Use GPIO as chip select for SPI ACPI overlay

950 Views Asked by At

I want to use a GPIO pin as a new chip select for SPI on an Up Squared board. The Up squared uses an Intel Pentium N4200, so it's a x86 machine. I have managed to this on a Raspberry Pi by using Device Tree Overlays but as this is an x86 machine I may have to use ACPI overlays.

The Up squared has two spi available and they propose here to use ACPI overlays, this repo, which actually works very well. Below one of the asl files they use

/*
 * This ASL can be used to declare a spidev device on SPI0 CS0
 */
DefinitionBlock ("", "SSDT", 5, "INTEL", "SPIDEV0", 1)
{
    External (_SB_.PCI0.SPI1, DeviceObj)

    Scope (\_SB.PCI0.SPI1)
    {
        Device (TP0) {
            Name (_HID, "SPT0001")
            Name (_DDN, "SPI test device connected to CS0")
            Name (_CRS, ResourceTemplate () {
                SpiSerialBus (
                    0,                      // Chip select
                    PolarityLow,            // Chip select is active low
                    FourWireMode,           // Full duplex
                    8,                      // Bits per word is 8 (byte)
                    ControllerInitiated,    // Don't care
                    1000000,                // 10 MHz
                    ClockPolarityLow,       // SPI mode 0
                    ClockPhaseFirst,        // SPI mode 0
                    "\\_SB.PCI0.SPI1",      // SPI host controller
                    0                       // Must be 0
                )
            })
        }
    }
}

I compiled this file using

$ sudo iasl spidev1.0.asl > /dev/null
$ sudo mv spidev1.0.asl /lib/firmware/acpi-upgrades
$ sudo update-initramfs -u -k all

Then I reboot an I can see a device and communicate through it.

up@up:~$ ls /dev/spi*
/dev/spidev1.0

Thus, I decided to write my own overlay based on themeta-acpi samples from intel and I wrote this:

/*
 * This ASL can be used to declare a spidev device on SPI0 CS2
 */
DefinitionBlock ("", "SSDT", 5, "INTEL", "SPIDEV2", 1)
{
    External (_SB_.PCI0.SPI1, DeviceObj)
    External (_SB_.PCI0.GIP0.GPO, DeviceObj)

    Scope (\_SB.PCI0.SPI1)
    {

        Name (_CRS, ResourceTemplate () {
            GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
                "\\_SB.PCI0.GIP0.GPO", 0) {
                    22 // pin 22 is BCM25 or 402 in linux
                } 
        })

        Name (_DSD, Package() {
            ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package () {
                Package () { "compatible", "spidev" }, // not sure if this is needed
                Package () {
                    "cs-gpios", Package () {
                        0,
                        0,
                        ^SPI1, 0, 0, 0, // index 0 in _CRS -> pin 22
                    }
                },
            }
        })

        Device (TP2) {
            Name (_HID, "SPT0001")
            Name (_DDN, "SPI test device connected to CS2")
            Name (_CRS, ResourceTemplate () {
                SpiSerialBus (
                    2,                      // Chip select
                    PolarityLow,            // Chip select is active low
                    FourWireMode,           // Full duplex
                    8,                      // Bits per word is 8 (byte)
                    ControllerInitiated,    // Don't care
                    1000000,                // 10 MHz
                    ClockPolarityLow,       // SPI mode 0
                    ClockPhaseFirst,        // SPI mode 0
                    "\\_SB.PCI0.SPI1",      // SPI host controller
                    0                       // Must be 0
                )
            })
        }
    }
}

But I cannot see the new device. What am I missing?

Edit: I have modified the code with a code which actually worked. I can see now a device on /dev/spidev1.2.

However, the CS on pin 22 is low all the time which shouldn't be the case. is the number of the pin correct? I'm using pin numbering from here

Edit 2:

Here is the output of my kernel version

Linux up 5.4.65-rt38+ #1 SMP PREEMPT_RT Mon Feb 28 13:42:31 CET 2022 x86_64 x86_64 x86_64 GNU/Linux

I compiled this up linux repository with the RT patch for the right kernel version.

I also installed the upboard-extras package and I'm actually able to communicate through spi for devices /dev/spidev1.0 and /dev/spidev1.1. So I think I have configured the up squared correctly.

There is nongpio file under /sys/class/gpio

up@up:~/aru$ ls /sys/class/gpio
export  gpiochip0  gpiochip267  gpiochip310  gpiochip357  gpiochip434  unexport

I can set the GPIO to 1 or 0 and I can see the output on a multimeter, so I think I have right permissions for GPIO.

Edit 3:

Please find in this link the .dat result from acpidump -o up2-tables.dat

1

There are 1 best solutions below

9
On

I assume that you are using this board. To be able to use I/O pins(i2c, spi etc.), you need to enable them firstly. Easy way to check you already enabled them or not is that typing in terminal:

uname -a

Output of this will be look like:

 Linux upxtreme-UP-WHL01 5.4.0-1-generic #2~upboard2-Ubuntu SMP Thu Jul 25 13:35:27 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

In here #2~upboard2-Ubuntu part can be changed accordingto your board type. However if you don't see a similar result, then you didn't configure your board yet. Otherway to check it, go to folder: /sys/class/gpio and check the ngpio file. Inside it, there should be written 28.

To use any I/O pins(i2c, spi etc.), you don't need to change anything on BIOS side, because its coming to you defaultly enabled.

Please check the up-wiki page, and update your board kernel after linux installation. Then your I/O configurations will be enabled. Up-wiki main page.