I am receiving a fatal error when attempting to load the Maxim MAX14830 SPI-to-QuadUART chip in a CentOS8 (x86_64) environment. The SPI controller in use is the Intel E3900 Atom, from which I am able to successfully mount and interact with using SPIDEV.
After reviewing several examples from the ARM world, I believe the issue lies in that I am not passing the "clocks" parameter to the max310x driver, but I have been unable to find a suitable example for describing a "phandle to the IC source clock" in ACPI.
The chip's clock input (Pin 45, XIN) is driven by a standard clock oscillator running at 7.3728 MHz.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clock-frequency", 7372800},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
The relevant output from dmesg is:
[ 1.974203] max310x spi-PRP0001:03: Cannot get clock
[ 1.975951] max310x: probe of spi-PRP0001:03 failed with error -22
The datasheet for the part can be found here: https://datasheets.maximintegrated.com/en/ds/MAX14830.pdf
Any guidance or relevant example link would be appreciated. Thanks!
EDIT: I found an example for how to reference another object at https://www.kernel.org/doc/html/latest/firmware-guide/acpi/dsd/leds.html; the following AML complied correctly, but resulted in a kernel panic. This discussion (https://lore.kernel.org/lkml/[email protected]/T/) leads me to believe that use of the common clock framework is not supported in ACPI, so any drivers that make use of it cannot be used with a ACPI + _DSD configuration.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (CLK1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim Clock Object")
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "fixed-clock"},
Package () {"clock-cells", 0},
Package () {"clock-frequency", 7372800},
}
})
}
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
100000, // 100 kHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clocks", ^CLK1},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
With the driver updates provided by 0andriy (https://lore.kernel.org/linux-serial/[email protected]/T/#u), I was able to get the /dev/ttyMAX devices to appear, although I needed to perform further modifications to force oscillator clocking; the driver was still dropping to the "Cannot get clock" error.
I modeled my AML after this example (https://github.com/westeri/meta-acpi/blob/master/recipes-bsp/acpi-tables/samples/edison/sc16is7xx.asl), which resulted in the following:
However, the driver was still failing in the devm_request_threaded_irq function:
Being a novice at C code, I wasn't able to find a way to correct the issue and ended up just commenting it out so that the mounts were not automatically torn down.
At this point, I am able to successfully query them with the setserial utility and access the devices with minicom.
I am handing the PCB back to the EE to verify the serial ports are actually working (it does not have easy test points exposed), and I will update this answer if it doesn't.
EDIT: We are able to send data while configured in this manner, but the receive path is not working, likely due to the IRQ issue. I will retest with a 5.11 kernel and report back. The current status is with LTS kernel version 5.4.70, with manual patching of the max310x driver.