Skip to content

Peripheral Porting

This document describes how to adapt the I2C/SPI peripheral interfaces, including node inspection, hardware information, and device tree modification examples.

I2C

On the Rhino Pi A1R board, four groups of I2C are in use. You can check the nodes corresponding to these I2C buses with the following command:

bash
ls -l /sys/bus/i2c/devices/i2c*

Example command output:

text
lrwxrwxrwx 1 root root 0 Jan  1  1970 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/platform/soc@0/9c0000.geniqup/980000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Jan  1  1970 /sys/bus/i2c/devices/i2c-13 -> ../../../devices/platform/soc@0/ac0000.geniqup/a94000.i2c/i2c-13

The corresponding hardware information is as follows:

I2C nodeBase addressGPIO pinsHardware node
i2c-09880000/1qupv3_id_0-i2c0
i2c-13a9400052/53qupv3_id_1-i2c13

Modification Example: RTC Chip INS5830B

The I2C pins used by the RTC chip INS5830B are GPIO0 and GPIO1.

The I2C mux for these two pins is configured in sc7280.dtsi:

text
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/sc7280.dtsi
dts
i2c0: i2c@980000 {
    compatible = "qcom,geni-i2c";
    reg = <0 0x00980000 0 0x4000>;
    clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
    clock-names = "se";
    pinctrl-names = "default";
    pinctrl-0 = <&qup_i2c0_data_clk>;
    interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
    #address-cells = <1>;
    #size-cells = <0>;
    interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
                    <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_QUP_0 0>,
                    <&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
    interconnect-names = "qup-core", "qup-config", "qup-memory";
    power-domains = <&rpmhpd SC7280_CX>;
    required-opps = <&rpmhpd_opp_low_svs>;
    dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
           <&gpi_dma0 1 0 QCOM_GPI_I2C>;
    dma-names = "tx", "rx";
    status = "disabled";
};

qup_i2c0_data_clk: qup-i2c0-data-clk-state {
    pins = "gpio0", "gpio1";
    function = "qup00";
};

In qcm6490-addons-idp.dts, the RTC device tree node is configured under qupv3_hub_i2c2:

text
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/qcm6490-addons-idp.dts
dts
&i2c0 {
    clock-frequency = <100000>;
    status = "okay";

    qps615_switch: pcie-switch@77 {
        compatible = "qcom,switch-i2c";
        reg = <0x77>;
        vdda-supply = <&qps615_rsex_vreg>;
        status = "okay";
    };

    ins5830b: ins5830b@32 {
        compatible = "dptel,rtc-ins5830b";
        reg = <0x32>;
        pinctrl-names = "default";
        pinctrl-0 = <&ins5830b_int_default>;
        interrupt-parent = <&tlmm>;
        interrupts = <104 IRQ_TYPE_EDGE_FALLING>;
        status = "okay";
    };
};

SPI

On the Rhino Pi A1R board, four groups of SPI are in use. You can check the nodes corresponding to these SPI buses with the following command:

bash
ls -l /sys/bus/spi/devices/

Example command output:

text
total 0
lrwxrwxrwx 1 root root 0 Aug 18 09:24 spi12.0 -> ../../../devices/platform/soc@0/ac0000.geniqup/a90000.spi/spi_master/spi12/spi12.0
lrwxrwxrwx 1 root root 0 Aug 18 09:24 spi14.0 -> ../../../devices/platform/soc@0/ac0000.geniqup/a98000.spi/spi_master/spi14/spi14.0
lrwxrwxrwx 1 root root 0 Aug 18 09:24 spi3.0 -> ../../../devices/platform/soc@0/9c0000.geniqup/98c000.spi/spi_master/spi3/spi3.0
lrwxrwxrwx 1 root root 0 Aug 18 09:24 spi6.0 -> ../../../devices/platform/soc@0/9c0000.geniqup/998000.spi/spi_master/spi6/spi6.0

The corresponding hardware information is as follows:

SPI nodeBase addressGPIO pinsHardware node
spi3.098c00012/13/14/15qupv3_id_0-spi3
spi6.099800024/25/26/27qupv3_id_0-spi6
spi12.0a9000048/49/50/51qupv3_id_1-spi12
spi14.0a9800056/57/58/59qupv3_id_1-spi14

Modification Example: CAN Chip MCP2518

The SPI pins used by the CAN chip MCP2518 are GPIO48 to GPIO51.

The QUP mux for these pins is configured in sc7280.dtsi (the QUP type of SE1 is configured as SPI in TZ):

text
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/sc7280.dtsi
dts
spi12: spi@a90000 {
    compatible = "qcom,geni-spi";
    reg = <0 0x00a90000 0 0x4000>;
    clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
    clock-names = "se";
    pinctrl-names = "default";
    pinctrl-0 = <&qup_spi12_data_clk>, <&qup_spi12_cs>;
    interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
    #address-cells = <1>;
    #size-cells = <0>;
    power-domains = <&rpmhpd SC7280_CX>;
    operating-points-v2 = <&qup_opp_table>;
    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 4 QCOM_GPI_SPI>,
           <&gpi_dma1 1 4 QCOM_GPI_SPI>;
    dma-names = "tx", "rx";
    status = "disabled";
};

qup_spi12_data_clk: qup-spi12-data-clk-state {
    pins = "gpio48", "gpio49", "gpio50";
    function = "qup14";
};

qup_spi12_cs: qup-spi12-cs-state {
    pins = "gpio51";
    function = "qup14";
};

In qcm6490-addons-idp.dts, the spi12 device tree node is configured using the pinctrl above:

text
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/qcm6490-addons-idp.dts
dts
&spi12 {
    status = "okay";
    can@0 {
        compatible = "microchip,mcp2518fd";
        reg = <0>;
        clock-frequency = <40000000>;
        interrupt-parent = <&tlmm>;
        interrupts = <41 0>;
        interrupt-names = "can_irq";
        spi-max-frequency = <10000000>;
        gpio-controller;
        pinctrl-names = "default";
        pinctrl-0 = <&can0_int>;
        status = "ok";
    };
};