> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SPI

The Serial Peripheral Interface (SPI) is a synchronous, full-duplex, 4-wire serial bus.

<img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/spi_protocol.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=63ecd5562e3e2ab7f0b6c6aff479325f" width="724" height="426" data-path="Ubuntu/images/peripheral-interfaces/spi_protocol.png" />

## Signals

| Signal   | Description                                                 |
| -------- | ----------------------------------------------------------- |
| **MOSI** | Controller data output, target data input                   |
| **MISO** | Controller data input, target data output                   |
| **SCLK** | Clock generated by the controller                           |
| **CS**   | Chip-select (active low); up to 4 chip-select lines per bus |

## Transfer Modes by Subsystem

| Subsystem | Transfer Modes                | Max Speed | Notes                                       |
| --------- | ----------------------------- | --------- | ------------------------------------------- |
| **Linux** | FIFO, CPU DMA, GSI            | 50 MHz    | 4–32 bits per word; up to 4 CS              |
| **Boot**  | FIFO only                     | 50 MHz    | Polling mode; GSI not supported             |
| **aDSP**  | Full/half duplex, synchronous | 50 MHz    | Raw bit-level; no framing or error checking |

## Interface Components

### Device Tree Sources

| Platform           | File                                    |
| ------------------ | --------------------------------------- |
| Dragonwing IQ-9075 | `arch/arm64/boot/dts/qcom/sa8775p.dtsi` |

### APIs

| Subsystem | Header                                                       |
| --------- | ------------------------------------------------------------ |
| Linux     | `include/uapi/linux/spi/spidev.h`, `include/linux/spi/spi.h` |
| Boot      | `boot_images/boot/QcomPkg/Include/SpiApi.h`                  |
| aDSP      | `adsp_proc/core/api/buses/spi_api.h`                         |

## Software Configuration

### Linux Device Tree Example

```dts theme={null}
spi@a98000 {
    compatible = "qcom,geni-spi";
    reg = <0 0x00a98000 0 0x4000>;
    clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>;
    clock-names = "se";
    pinctrl-names = "default";
    pinctrl-0 = <&qup_spi14_data_clk>, <&qup_spi14_cs>;
    interrupts = <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>;
    #address-cells = <1>;
    #size-cells = <0>;
    power-domains = <&rpmhpd SC7280_CX>;
    interconnects = <&clk_virt MASTER_QUP_CORE_1 0 &clk_virt SLAVE_QUP_CORE_1 0>,
                    <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_QUP_1 0>;
    interconnect-names = "qup-core", "qup-config";
    dmas = <&gpi_dma1 0 6 QCOM_GPI_SPI>,
           <&gpi_dma1 1 6 QCOM_GPI_SPI>;
    dma-names = "tx", "rx";
    status = "disabled";
};
```

GPIO pinctrl:

```dts theme={null}
qup_spi14_data_clk: qup-spi14-data-clk-state {
    pins = "gpio56", "gpio57", "gpio58";
    function = "qup16";
};

qup_spi14_cs: qup-spi14-cs-state {
    pins = "gpio59";
    function = "qup16";
};
```

### QUPAC Access Control

```c theme={null}
{ QUPV3_0_SE3, QUPV3_PROTOCOL_SPI, QUPV3_MODE_FIFO, AC_HLOS, TRUE,  TRUE, FALSE }, // CAN SPI
{ QUPV3_1_SE3, QUPV3_PROTOCOL_SPI, QUPV3_MODE_FIFO, AC_HLOS, FALSE, TRUE, TRUE  }, // LS1 SPI
{ QUPV3_1_SE4, QUPV3_PROTOCOL_SPI, QUPV3_MODE_GSI,  AC_TZ,   FALSE, TRUE, TRUE  }, // NFC ESE
{ QUPV3_1_SE6, QUPV3_PROTOCOL_SPI, QUPV3_MODE_GSI,  AC_HLOS, FALSE, TRUE, FALSE }, // FP
```

## Configuration Steps

<Steps>
  <Step title="Enable kernel configurations">
    Edit `kernel_platform/kernel/arch/arm64/configs/qcom_defconfig`:

    ```
    CONFIG_QCOM_GENI_SE=y
    CONFIG_SPI_QCOM_GENI=m
    CONFIG_SPI_SPIDEV=m
    CONFIG_QCOM_GPI_DMA=m
    ```
  </Step>

  <Step title="Enable SPI node in device tree">
    ```dts theme={null}
    &spi1 {
        status = "okay";
    };
    ```
  </Step>

  <Step title="Compile and flash">
    Compile the kernel and device tree changes, then load images to the device.
  </Step>
</Steps>

## Verification

<Steps>
  <Step title="Transfer spidev_test to device">
    ```bash theme={null}
    scp spidev_test ubuntu@<device_ip>:/bin
    chmod 777 /bin/spidev_test
    ```
  </Step>

  <Step title="Run test">
    ```bash theme={null}
    ./spidev_test -D /dev/spidev1.0
    ./spidev_test -D /dev/spidev3.0
    ```

    **Expected output:**

    ```
    spi mode: 0x0
    bits per word: 8
    max speed: 500000 Hz (500 KHz)
    ```
  </Step>
</Steps>

## Debugging

### Enable Debug Logs

```bash theme={null}
sudo su
mount -t debugfs none /sys/kernel/debug

echo -n "file spi-geni-qcom.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file qcom-geni-se.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file spidev.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file gpi.c +p" > /sys/kernel/debug/dynamic_debug/control
```

To disable:

```bash theme={null}
echo -n "file spi-geni-qcom.c -p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file spidev.c -p" > /sys/kernel/debug/dynamic_debug/control
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="SPI Device Not Detected (/dev/spidev* missing)">
    ```bash theme={null}
    # Check kernel config
    cat /boot/config-$(uname -r) | grep -i spi
    # Expect: CONFIG_SPI_QCOM_GENI=m, CONFIG_SPI_SPIDEV=m

    # Check kernel logs
    dmesg | grep -i spi
    dmesg | grep -i geni
    ```

    * Verify SPI node status is `"okay"` in device tree
    * Verify `QUPAC_Access.c` sets `QUPV3_PROTOCOL_SPI`, `AC_HLOS`, `bLoad=TRUE`
  </Accordion>

  <Accordion title="SPI Transfer Failures / Data Corruption">
    ```bash theme={null}
    # Test at lower speed
    ./spidev_test -D /dev/spidev1.0 -s 1000000

    # Test different clock modes
    ./spidev_test -D /dev/spidev1.0 -H   # CPHA
    ./spidev_test -D /dev/spidev1.0 -O   # CPOL
    ```

    * Check GPIO drive strength and pull configuration in pinctrl
    * Verify clock phase and polarity match the target device
    * Use oscilloscope to check signal integrity
  </Accordion>

  <Accordion title="GSI/DMA Mode Not Working">
    ```bash theme={null}
    lsmod | grep gpi
    echo -n "file gpi.c +p" > /sys/kernel/debug/dynamic_debug/control
    ```

    * Verify `CONFIG_QCOM_GPI_DMA=m` is enabled
    * Check `dmas` and `dma-names` properties in device tree
    * Verify `QUPAC_Access.c` sets `QUPV3_MODE_GSI` and `bAllowFifo=FALSE`
  </Accordion>

  <Accordion title="Multiple Chip Select Issues">
    Verify all CS pins are configured in pinctrl. Check device tree `reg` property:

    ```dts theme={null}
    spidev@0 { reg = <0>; };  /* CS0 */
    spidev@1 { reg = <1>; };  /* CS1 */
    ```

    Test explicitly:

    ```bash theme={null}
    ./spidev_test -D /dev/spidev1.0   # CS0
    ./spidev_test -D /dev/spidev1.1   # CS1
    ```
  </Accordion>

  <Accordion title="Boot Subsystem SPI Not Working">
    * Verify QUP wrapper node status is `"okay"` and serial engine node is `"disabled"`
    * Confirm `FIFO_MODE = /bits/ 8 <1>` (GSI not supported in boot)
    * Check `protocol_supported` includes `SPI_SUPPORTED`
    * Verify `QUPAC_Access.c` settings match boot requirements
  </Accordion>
</AccordionGroup>

### Quick Diagnostic Commands

```bash theme={null}
ls /dev/spi*                          # Check SPI device nodes
dmesg | grep -i spi                   # Kernel SPI messages
dmesg | grep -i geni                  # GENI driver messages
lsmod | grep spi                      # Loaded SPI modules
lsmod | grep gpi                      # GPI DMA module
```

## Resources

* [SPI Driver Source](https://github.com/torvalds/linux/blob/master/drivers/spi/spi-geni-qcom.c)
* [SPI Device Tree Bindings](https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/spi/qcom%2Cspi-geni-qcom.yaml)
* [SPI User API](https://github.com/torvalds/linux/blob/master/include/uapi/linux/spi/spidev.h)
* [SPI Tools](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/spi)
