> ## 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.

# I2C

Inter-Integrated Circuit (I²C) is a bidirectional, two-wire serial bus for short-distance communication between integrated circuits, where devices communicate using assigned bus addresses.

## Overview

### Key Characteristics

* Bidirectional 2-wire serial bus (SDA + SCL)
* 7-bit or 10-bit target addressing
* Multi-controller mode support

### Operating Modes

| Mode            | Speed                      |
| --------------- | -------------------------- |
| Standard mode   | 100 kbps                   |
| Fast mode       | 400 kbps                   |
| Fast mode plus  | 1 Mbps (maximum supported) |
| High-speed mode | 3.4 MHz (not supported)    |

### Communication Sequence

<img src="https://mintcdn.com/qualcomm-prod/Bh7DlgudKfjY_3Wf/Linux/images/peripheral-interfaces/i2c_communication_sequence.png?fit=max&auto=format&n=Bh7DlgudKfjY_3Wf&q=85&s=5000635a0034efc2245dd6150b0e2708" width="1091" height="299" data-path="Linux/images/peripheral-interfaces/i2c_communication_sequence.png" />

<img src="https://mintcdn.com/qualcomm-prod/Bh7DlgudKfjY_3Wf/Linux/images/peripheral-interfaces/i2c_data_packet_format.png?fit=max&auto=format&n=Bh7DlgudKfjY_3Wf&q=85&s=1b75cb917455b3ef2cbcb36676ebdfde" width="1107" height="394" data-path="Linux/images/peripheral-interfaces/i2c_data_packet_format.png" />

**Packet structure:** Start → Address frame (7/10-bit) → R/W bit → ACK/NACK → Data frames (8-bit) → Stop

**Signal rules:**

* SCL HIGH: SDA must remain stable
* SCL LOW: SDA may change
* Exception: START and STOP sequences may change SDA when SCL is HIGH

### Transfer Modes by Subsystem

| Subsystem                     | Transfer Mode      | Bus Speeds                 |
| ----------------------------- | ------------------ | -------------------------- |
| **Linux**                     | FIFO, CPU DMA, GSI | 100 kHz, 400 kHz, 1000 kHz |
| **Boot**                      | FIFO               | 100 kHz, 400 kHz, 1000 kHz |
| **aDSP / Qualcomm TEE / SDC** | FIFO               | Standard                   |

## Interface Components

### Device Tree Sources

| Platform           | Device Tree File                        |
| ------------------ | --------------------------------------- |
| Dragonwing IQ-8275 | `arch/arm64/boot/dts/qcom/qcs8300.dtsi` |

### APIs

| Subsystem    | Header                                                |
| ------------ | ----------------------------------------------------- |
| Linux        | `include/linux/i2c.h`, `include/linux/i2c-dev.h`      |
| Boot         | `boot_images/boot/QcomPkg/Include/i2c_api.h`          |
| aDSP         | `adsp_proc/core/api/buses/i2c_api.h`                  |
| Qualcomm TEE | `trustzone_images/core/buses/api/i2c/qupv3/i2c_api.h` |

## Software Device Tree Configuration

### Linux Device Tree Example

```dts theme={null}
i2c21: i2c@b80000 {
   compatible = "qcom,geni-i2c";
   reg = <0x0 0xb80000 0x0 0x4000>;
   #address-cells = <1>;
   #size-cells = <0>;
   interrupts = <GIC_SPI 831 IRQ_TYPE_LEVEL_HIGH>;
   clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>;
   clock-names = "se";
   pinctrl-0 = <&qup_i2c21_default>;
   pinctrl-names = "default";
   power-domains = <&rpmhpd SA8295P_CX>;
   dmas = <&gpi_dma3 0 0 QCOM_GPI_I2C>,
          <&gpi_dma3 1 0 QCOM_GPI_I2C>;
   dma-names = "tx", "rx";
   status = "disabled";
};
```

### QUPAC Access Control

Ensure the correct protocol is set in `QUPAC_Access.c`:

```c theme={null}
{ QUPV3_0_SE0, QUPV3_PROTOCOL_I2C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE },
{ QUPV3_1_SE5, QUPV3_PROTOCOL_I2C, QUPV3_MODE_GSI,  AC_HLOS, FALSE, TRUE, FALSE },
```

## Configuration Steps

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

    ```
    CONFIG_QCOM_GENI_SE=y
    CONFIG_I2C_QCOM_GENI=m
    CONFIG_I2C_CHARDEV=m
    CONFIG_QCOM_GPI_DMA=m
    ```
  </Step>

  <Step title="Enable I2C node in device tree">
    ```diff theme={null}
    +&i2c1 {
    +    status = "okay";
    +};
    ```
  </Step>

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

## Verification

### Check Device Nodes

```bash theme={null}
ls /dev/i2c*
# Expected: /dev/i2c-0  /dev/i2c-1  /dev/i2c-16
```

### Use i2c-tools

```bash theme={null}
# push tools using SCP or similar tools.
scp i2cdetect root@<IP address>:/usr

#Assign permission to execute
chmod 777 i2cdetect								
# Scan bus		  
i2cdetect -y -r 0
# Dump device registers					   
i2cdump -r 0-0xff 0 0x2b b
# Read register			   
i2cget -y 0 0x2b 0x04
# Write register				
i2cset -y 0 0x2b 0x04 0xFF
```

## Debugging

### Enable Debug Logs

```bash theme={null}
mount -t debugfs none /sys/kernel/debug
echo -n "file i2c-qcom-geni.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file i2c-core-base.c +p" > /sys/kernel/debug/dynamic_debug/control
echo -n "file gpi.c +p" > /sys/kernel/debug/dynamic_debug/control
dmesg | grep i2c
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="I2C Device Not Detected">
    ```bash theme={null}
    cat /proc/device-tree/soc@0/geniqup@*/i2c*/status
    lsmod | grep i2c_qcom_geni
    modprobe i2c_qcom_geni
    cat /sys/kernel/debug/clk/gcc_qupv3_wrap0_s1_clk/clk_enable_count
    ```
  </Accordion>

  <Accordion title="I2C Transfer Timeout">
    **Causes:** No pull-up resistors, slave not responding, wrong clock frequency, bus stuck low.

    Add 4.7 kΩ pull-ups on SDA/SCL; adjust `clock-frequency` in device tree.
  </Accordion>

  <Accordion title="Invalid Protocol Error">
    **Symptom:** `geni_i2c a94000.i2c: Invalid proto 1`

    Verify `QUPAC_Access.c` sets `QUPV3_PROTOCOL_I2C`, `AC_HLOS`, `bAllowFifo=TRUE`, `bLoad=TRUE`.
  </Accordion>

  <Accordion title="DMA Transfer Failures">
    Verify `CONFIG_QCOM_GPI_DMA=m`; check `dmas` and `dma-names` in device tree.

    To test without DMA:

    ```dts theme={null}
    &i2c1 {
        /delete-property/ dmas;
        /delete-property/ dma-names;
    };
    ```
  </Accordion>
</AccordionGroup>

## Quick Diagnostic Commands

```bash theme={null}
ls -l /dev/i2c*
i2cdetect -y -r 0
dmesg | grep -i i2c
cat /sys/kernel/debug/clk/clk_summary | grep -i qup
lsmod | grep i2c
```

## Resources

* [I2C Bus Specification](https://www.i2c-bus.org/fileadmin/ftp/i2c_bus_specification_1995.pdf)
* [Linux I2C Subsystem](https://www.kernel.org/doc/html/latest/i2c/index.html)
* [Device Tree Bindings](https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/i2c/qcom%2Ci2c-geni-qcom.yaml)
* [i2c-tools](https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/)
