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:
ls -l /sys/bus/i2c/devices/i2c*Example command output:
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-13The corresponding hardware information is as follows:
| I2C node | Base address | GPIO pins | Hardware node |
|---|---|---|---|
i2c-0 | 988000 | 0/1 | qupv3_id_0-i2c0 |
i2c-13 | a94000 | 52/53 | qupv3_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:
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/sc7280.dtsii2c0: 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:
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/qcm6490-addons-idp.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:
ls -l /sys/bus/spi/devices/Example command output:
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.0The corresponding hardware information is as follows:
| SPI node | Base address | GPIO pins | Hardware node |
|---|---|---|---|
spi3.0 | 98c000 | 12/13/14/15 | qupv3_id_0-spi3 |
spi6.0 | 998000 | 24/25/26/27 | qupv3_id_0-spi6 |
spi12.0 | a90000 | 48/49/50/51 | qupv3_id_1-spi12 |
spi14.0 | a98000 | 56/57/58/59 | qupv3_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):
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/sc7280.dtsispi12: 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:
layers/meta-qcom-hwe/recipes-kernel/linux/linux-qcom-custom/kernel-source/arch/arm64/boot/dts/qcom/qcm6490-addons-idp.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";
};
};