Pinctrl子系统
暴露到应用层
$ cat /sys/kernel/debug/gpio //查看gpio 暴露的调试信息
$ cat /sys/kernel/debug/tegra_pinctrl_reg
$ ls /sys/kernel/debug/pinctrl/
$ cat /sys/kernel/debug/pinctrl/pinctrl-handles //查看pinmux map对应的处理函数
GPIO当前配置情况
//注: gpio-79: 是内核gpio子系统里,对管脚的编号(是经过映射转化的)
// I2S0_SCLK : 是该管脚在电路图上的标号
gpiochip0: GPIOs 0-255, parent: platform/6000d000.gpio, tegra-gpio:
内核里编号 电路图标号 |当前使用者 输出 高电平
gpio-0 ( )
gpio-1 ( )
gpio-2 ( |pcie_wake ) in hi
gpio-3 ( )
...
gpio-6 ( |system-suspend-gpio ) out hi
...
gpio-11 ( )
gpio-12 (SPI1_MOSI )
gpio-13 (SPI1_MISO )
gpio-14 (SPI1_SCK )
gpio-15 (SPI1_CS0 )
gpio-16 (SPI0_MOSI )
gpio-17 (SPI0_MISO )
gpio-18 (SPI0_SCK )
gpio-19 (SPI0_CS0 )
gpio-20 (SPI0_CS1 )
...
gpio-38 (GPIO13 )
...
gpio-50 (UART1_RTS )
gpio-51 (UART1_CTS )
...
gpio-64 ( |i2c-mux-gpio ) out hi
...
gpio-76 (I2S0_FS )
gpio-77 (I2S0_DIN )
gpio-78 (I2S0_DOUT )
gpio-79 (I2S0_SCLK |? ) out hi
...
gpio-149 (GPIO01 )
gpio-150 ( )
gpio-151 ( |cam_reset_gpio ) out lo
...
gpio-168 (GPIO07 )
...
gpio-187 ( |? ) out hi
gpio-188 ( )
gpio-189 ( |Power ) in hi IRQ
gpio-190 ( |Forcerecovery ) in hi IRQ
...
gpio-194 (GPIO12 )
...
gpio-200 (GPIO11 )
gpio-201 ( |cd ) in lo IRQ
gpio-202 ( )
gpio-203 ( |vdd-3v3-sd ) out hi
...
gpio-216 (GPIO09 )
...
gpio-239 ( )
gpiochip1: GPIOs 504-511, parent: platform/max77620-gpio, max77620-gpio, can sleep:
gpio-505 ( |spmic-default-output) out hi
gpio-507 ( |vdd-3v3-sys ) out hi
gpio-510 ( |enable ) out lo
gpio-511 ( |avdd-io-edp-1v05 ) out lo
管脚复用寄存器的值
Bank: 1 Reg: 0x70003000 Val: 0x00003040 -> sdmmc1_clk_pm0
Bank: 1 Reg: 0x70003004 Val: 0x00003048 -> sdmmc1_cmd_pm1
Bank: 1 Reg: 0x70003008 Val: 0x00003048 -> sdmmc1_dat3_pm2
Bank: 1 Reg: 0x7000300c Val: 0x00003048 -> sdmmc1_dat2_pm3
Bank: 1 Reg: 0x70003010 Val: 0x00003048 -> sdmmc1_dat1_pm4
Bank: 1 Reg: 0x70003014 Val: 0x00003048 -> sdmmc1_dat0_pm5
Bank: 1 Reg: 0x700032b4 Val: 0x00000000 -> sdmmc2_clk
Bank: 1 Reg: 0x700032b8 Val: 0x00000000 -> sdmmc2_clkb
Bank: 1 Reg: 0x700032bc Val: 0x00000000 -> sdmmc2_cmd
Bank: 1 Reg: 0x70003294 Val: 0x00000000 -> sdmmc2_dat0
Bank: 1 Reg: 0x70003298 Val: 0x00000000 -> sdmmc2_dat1
Bank: 1 Reg: 0x7000329c Val: 0x00000000 -> sdmmc2_dat2
Bank: 1 Reg: 0x700032a0 Val: 0x00000000 -> sdmmc2_dat3
Bank: 1 Reg: 0x700032a4 Val: 0x00000000 -> sdmmc2_dat4
Bank: 1 Reg: 0x700032a8 Val: 0x00000000 -> sdmmc2_dat5
Bank: 1 Reg: 0x700032ac Val: 0x00000000 -> sdmmc2_dat6
Bank: 1 Reg: 0x700032b0 Val: 0x00000000 -> sdmmc2_dat7
Bank: 1 Reg: 0x700032c0 Val: 0x00000000 -> sdmmc2_dqs
Bank: 1 Reg: 0x700032c4 Val: 0x00000000 -> sdmmc2_dqsb
Bank: 1 Reg: 0x7000301c Val: 0x00002040 -> sdmmc3_clk_pp0
Bank: 1 Reg: 0x70003020 Val: 0x00002048 -> sdmmc3_cmd_pp1
Bank: 1 Reg: 0x70003024 Val: 0x00002048 -> sdmmc3_dat0_pp5
Bank: 1 Reg: 0x70003028 Val: 0x00002048 -> sdmmc3_dat1_pp4
Bank: 1 Reg: 0x7000302c Val: 0x00002048 -> sdmmc3_dat2_pp3
Bank: 1 Reg: 0x70003030 Val: 0x00002048 -> sdmmc3_dat3_pp2
Bank: 1 Reg: 0x70003038 Val: 0x00000400 -> pex_l0_rst_n_pa0
Bank: 1 Reg: 0x7000303c Val: 0x00000450 -> pex_l0_clkreq_n_pa1
Bank: 1 Reg: 0x70003040 Val: 0x00000440 -> pex_wake_n_pa2
Bank: 1 Reg: 0x70003044 Val: 0x00000400 -> pex_l1_rst_n_pa3
Bank: 1 Reg: 0x70003048 Val: 0x00000440 -> pex_l1_clkreq_n_pa4
Bank: 1 Reg: 0x7000304c Val: 0x00000049 -> sata_led_active_pa5
Bank: 1 Reg: 0x7000304c Val: 0x00000049 -> pa5
Bank: 1 Reg: 0x70003050 Val: 0x0000e015 -> spi1_mosi_pc0
Bank: 1 Reg: 0x70003054 Val: 0x0000e015 -> spi1_miso_pc1
Bank: 1 Reg: 0x70003058 Val: 0x0000e015 -> spi1_sck_pc2
Bank: 1 Reg: 0x7000305c Val: 0x0000e015 -> spi1_cs0_pc3
Bank: 1 Reg: 0x70003060 Val: 0x0000e015 -> spi1_cs1_pc4
Bank: 1 Reg: 0x70003064 Val: 0x00006016 -> spi2_mosi_pb4
Bank: 1 Reg: 0x70003068 Val: 0x00006016 -> spi2_miso_pb5
Bank: 1 Reg: 0x7000306c Val: 0x00006016 -> spi2_sck_pb6
Bank: 1 Reg: 0x70003070 Val: 0x00006016 -> spi2_cs0_pb7
Bank: 1 Reg: 0x70003074 Val: 0x00006015 -> spi2_cs1_pdd0
Bank: 1 Reg: 0x70003078 Val: 0x0000e015 -> spi4_mosi_pc7
Bank: 1 Reg: 0x7000307c Val: 0x0000e015 -> spi4_miso_pd0
Bank: 1 Reg: 0x70003080 Val: 0x0000e015 -> spi4_sck_pc5
Bank: 1 Reg: 0x70003084 Val: 0x0000e015 -> spi4_cs0_pc6
Bank: 1 Reg: 0x70003088 Val: 0x00002040 -> qspi_sck_pee0
Bank: 1 Reg: 0x7000308c Val: 0x00002000 -> qspi_cs_n_pee1
Bank: 1 Reg: 0x70003090 Val: 0x00002040 -> qspi_io0_pee2
Bank: 1 Reg: 0x70003094 Val: 0x00002040 -> qspi_io1_pee3
Bank: 1 Reg: 0x70003098 Val: 0x00002040 -> qspi_io2_pee4
Bank: 1 Reg: 0x7000309c Val: 0x00002040 -> qspi_io3_pee5
Bank: 1 Reg: 0x700030a4 Val: 0x00000041 -> dmic1_clk_pe0
Bank: 1 Reg: 0x700030a8 Val: 0x00000041 -> dmic1_dat_pe1
Bank: 1 Reg: 0x700030ac Val: 0x00000041 -> dmic2_clk_pe2
Bank: 1 Reg: 0x700030b0 Val: 0x00000041 -> dmic2_dat_pe3
Bank: 1 Reg: 0x700030b4 Val: 0x00000016 -> dmic3_clk_pe4
Bank: 1 Reg: 0x700030b8 Val: 0x00000016 -> dmic3_dat_pe5
Bank: 1 Reg: 0x700030bc Val: 0x00000440 -> gen1_i2c_scl_pj1
Bank: 1 Reg: 0x700030c0 Val: 0x00000440 -> gen1_i2c_sda_pj0
Bank: 1 Reg: 0x700030c4 Val: 0x00000440 -> gen2_i2c_scl_pj2
Bank: 1 Reg: 0x700030c8 Val: 0x00000440 -> gen2_i2c_sda_pj3
Bank: 1 Reg: 0x700030cc Val: 0x00000040 -> gen3_i2c_scl_pf0
Bank: 1 Reg: 0x700030d0 Val: 0x00000040 -> gen3_i2c_sda_pf1
Bank: 1 Reg: 0x700030d4 Val: 0x00000441 -> cam_i2c_scl_ps2
Bank: 1 Reg: 0x700030d8 Val: 0x00000441 -> cam_i2c_sda_ps3
Bank: 1 Reg: 0x700030dc Val: 0x00000040 -> pwr_i2c_scl_py3
Bank: 1 Reg: 0x700030e0 Val: 0x00000040 -> pwr_i2c_sda_py4
Bank: 1 Reg: 0x700030e4 Val: 0x00000000 -> uart1_tx_pu0
Bank: 1 Reg: 0x700030e8 Val: 0x00000040 -> uart1_rx_pu1
Bank: 1 Reg: 0x700030ec Val: 0x00000015 -> uart1_rts_pu2
Bank: 1 Reg: 0x700030f0 Val: 0x00000015 -> uart1_cts_pu3
Bank: 1 Reg: 0x700030f4 Val: 0x00000000 -> uart2_tx_pg0
Bank: 1 Reg: 0x700030f8 Val: 0x00000044 -> uart2_rx_pg1
Bank: 1 Reg: 0x700030fc Val: 0x00000016 -> uart2_rts_pg2
Bank: 1 Reg: 0x70003100 Val: 0x00000016 -> uart2_cts_pg3
Bank: 1 Reg: 0x70003104 Val: 0x00000000 -> uart3_tx_pd1
Bank: 1 Reg: 0x70003108 Val: 0x00000040 -> uart3_rx_pd2
Bank: 1 Reg: 0x7000310c Val: 0x00000008 -> uart3_rts_pd3
Bank: 1 Reg: 0x70003110 Val: 0x00000048 -> uart3_cts_pd4
Bank: 1 Reg: 0x70003114 Val: 0x00000000 -> uart4_tx_pi4
Bank: 1 Reg: 0x70003118 Val: 0x00000040 -> uart4_rx_pi5
Bank: 1 Reg: 0x7000311c Val: 0x00000000 -> uart4_rts_pi6
Bank: 1 Reg: 0x70003120 Val: 0x00000048 -> uart4_cts_pi7
Bank: 1 Reg: 0x70003124 Val: 0x00006015 -> dap1_fs_pb0
Bank: 1 Reg: 0x70003128 Val: 0x00006015 -> dap1_din_pb1
Bank: 1 Reg: 0x7000312c Val: 0x00006015 -> dap1_dout_pb2
Bank: 1 Reg: 0x70003130 Val: 0x00006015 -> dap1_sclk_pb3
Bank: 1 Reg: 0x70003134 Val: 0x00006040 -> dap2_fs_paa0
Bank: 1 Reg: 0x70003138 Val: 0x00006040 -> dap2_din_paa2
Bank: 1 Reg: 0x7000313c Val: 0x00006040 -> dap2_dout_paa3
Bank: 1 Reg: 0x70003140 Val: 0x00006040 -> dap2_sclk_paa1
Bank: 1 Reg: 0x70003144 Val: 0x00000015 -> dap4_fs_pj4
Bank: 1 Reg: 0x70003148 Val: 0x00000015 -> dap4_din_pj5
Bank: 1 Reg: 0x7000314c Val: 0x00000015 -> dap4_dout_pj6
Bank: 1 Reg: 0x70003150 Val: 0x00000005 -> dap4_sclk_pj7
Bank: 1 Reg: 0x70003154 Val: 0x00000000 -> cam1_mclk_ps0
Bank: 1 Reg: 0x70003158 Val: 0x00000000 -> cam2_mclk_ps1
Bank: 1 Reg: 0x7000315c Val: 0x00000000 -> jtag_rtck
Bank: 1 Reg: 0x70003160 Val: 0x00001000 -> clk_32k_in
Bank: 1 Reg: 0x70003164 Val: 0x00000048 -> clk_32k_out_py5
Bank: 1 Reg: 0x70003168 Val: 0x00000550 -> batt_bcl
Bank: 1 Reg: 0x7000316c Val: 0x00000004 -> clk_req
Bank: 1 Reg: 0x70003170 Val: 0x00000004 -> cpu_pwr_req
Bank: 1 Reg: 0x70003174 Val: 0x00000048 -> pwr_int_n
Bank: 1 Reg: 0x70003178 Val: 0x00000000 -> shutdown
Bank: 1 Reg: 0x7000317c Val: 0x00000000 -> core_pwr_req
Bank: 1 Reg: 0x70003180 Val: 0x00000015 -> aud_mclk_pbb0
Bank: 1 Reg: 0x70003184 Val: 0x00000001 -> dvfs_pwm_pbb1
Bank: 1 Reg: 0x70003188 Val: 0x00000014 -> dvfs_clk_pbb2
Bank: 1 Reg: 0x7000318c Val: 0x00000014 -> gpio_x1_aud_pbb3
Bank: 1 Reg: 0x70003190 Val: 0x00000014 -> gpio_x3_aud_pbb4
Bank: 1 Reg: 0x70003194 Val: 0x00000500 -> pcc7
Bank: 1 Reg: 0x70003198 Val: 0x00000540 -> hdmi_cec_pcc0
Bank: 1 Reg: 0x7000319c Val: 0x00000140 -> hdmi_int_dp_hpd_pcc1
Bank: 1 Reg: 0x700031a0 Val: 0x00000015 -> spdif_out_pcc2
Bank: 1 Reg: 0x700031a4 Val: 0x00000015 -> spdif_in_pcc3
Bank: 1 Reg: 0x700031a8 Val: 0x00000149 -> usb_vbus_en0_pcc4
Bank: 1 Reg: 0x700031ac Val: 0x00000115 -> usb_vbus_en1_pcc5
Bank: 1 Reg: 0x700031b0 Val: 0x00000040 -> dp_hpd0_pcc6
Bank: 1 Reg: 0x700031b4 Val: 0x00000000 -> wifi_en_ph0
Bank: 1 Reg: 0x700031b8 Val: 0x00000014 -> wifi_rst_ph1
Bank: 1 Reg: 0x700031bc Val: 0x00000044 -> wifi_wake_ap_ph2
Bank: 1 Reg: 0x700031c0 Val: 0x00000000 -> ap_wake_bt_ph3
Bank: 1 Reg: 0x700031c4 Val: 0x00000000 -> bt_rst_ph4
Bank: 1 Reg: 0x700031c8 Val: 0x00000048 -> bt_wake_ap_ph5
Bank: 1 Reg: 0x700031cc Val: 0x00000000 -> ap_wake_nfc_ph7
Bank: 1 Reg: 0x700031d0 Val: 0x00000000 -> nfc_en_pi0
Bank: 1 Reg: 0x700031d4 Val: 0x00000050 -> nfc_int_pi1
Bank: 1 Reg: 0x700031d8 Val: 0x00000000 -> gps_en_pi2
Bank: 1 Reg: 0x700031dc Val: 0x00000014 -> gps_rst_pi3
Bank: 1 Reg: 0x700031e0 Val: 0x00000015 -> cam_rst_ps4
Bank: 1 Reg: 0x700031e4 Val: 0x00000016 -> cam_af_en_ps5
Bank: 1 Reg: 0x700031e8 Val: 0x00000016 -> cam_flash_en_ps6
Bank: 1 Reg: 0x700031ec Val: 0x00000001 -> cam1_pwdn_ps7
Bank: 1 Reg: 0x700031f0 Val: 0x00000001 -> cam2_pwdn_pt0
Bank: 1 Reg: 0x700031f4 Val: 0x00000015 -> cam1_strobe_pt1
Bank: 1 Reg: 0x700031f8 Val: 0x00000015 -> lcd_te_py2
Bank: 1 Reg: 0x700031fc Val: 0x00000017 -> lcd_bl_pwm_pv0
Bank: 1 Reg: 0x70003200 Val: 0x00000040 -> lcd_bl_en_pv1
Bank: 1 Reg: 0x70003204 Val: 0x00000014 -> lcd_rst_pv2
Bank: 1 Reg: 0x70003208 Val: 0x00000015 -> lcd_gpio1_pv3
Bank: 1 Reg: 0x7000320c Val: 0x00000001 -> lcd_gpio2_pv4
Bank: 1 Reg: 0x70003210 Val: 0x00000014 -> ap_ready_pv5
Bank: 1 Reg: 0x70003214 Val: 0x00000014 -> touch_rst_pv6
Bank: 1 Reg: 0x70003218 Val: 0x00000015 -> touch_clk_pv7
Bank: 1 Reg: 0x7000321c Val: 0x00000014 -> modem_wake_ap_px0
Bank: 1 Reg: 0x70003220 Val: 0x00000014 -> touch_int_px1
Bank: 1 Reg: 0x70003224 Val: 0x00000014 -> motion_int_px2
Bank: 1 Reg: 0x70003228 Val: 0x00000000 -> als_prox_int_px3
Bank: 1 Reg: 0x7000322c Val: 0x00000048 -> temp_alert_px4
Bank: 1 Reg: 0x70003230 Val: 0x00000048 -> button_power_on_px5
Bank: 1 Reg: 0x70003234 Val: 0x00000048 -> button_vol_up_px6
Bank: 1 Reg: 0x70003238 Val: 0x00000014 -> button_vol_down_px7
Bank: 1 Reg: 0x7000323c Val: 0x00000014 -> button_slide_sw_py0
Bank: 1 Reg: 0x70003240 Val: 0x00000048 -> button_home_py1
Bank: 1 Reg: 0x70003244 Val: 0x00000001 -> pa6
Bank: 1 Reg: 0x70003248 Val: 0x00000014 -> pe6
Bank: 1 Reg: 0x7000324c Val: 0x00000002 -> pe7
Bank: 1 Reg: 0x70003250 Val: 0x00000048 -> ph6
Bank: 1 Reg: 0x70003254 Val: 0x00006016 -> pk0
Bank: 1 Reg: 0x70003258 Val: 0x00006016 -> pk1
Bank: 1 Reg: 0x7000325c Val: 0x00006016 -> pk2
Bank: 1 Reg: 0x70003260 Val: 0x00006016 -> pk3
Bank: 1 Reg: 0x70003264 Val: 0x00006015 -> pk4
Bank: 1 Reg: 0x70003268 Val: 0x00006015 -> pk5
Bank: 1 Reg: 0x7000326c Val: 0x00006015 -> pk6
Bank: 1 Reg: 0x70003270 Val: 0x00006015 -> pk7
Bank: 1 Reg: 0x70003274 Val: 0x00006014 -> pl0
Bank: 1 Reg: 0x70003278 Val: 0x00006015 -> pl1
Bank: 1 Reg: 0x7000327c Val: 0x00000015 -> pz0
Bank: 1 Reg: 0x70003280 Val: 0x00000049 -> pz1
Bank: 1 Reg: 0x70003284 Val: 0x0000004a -> pz2
Bank: 1 Reg: 0x70003288 Val: 0x00000001 -> pz3
Bank: 1 Reg: 0x7000328c Val: 0x00000015 -> pz4
Bank: 1 Reg: 0x70003290 Val: 0x00000048 -> pz5
Bank: 0 Reg: 0x700009c0 Val: 0x00000000 -> drive_pa6
Bank: 0 Reg: 0x700009c4 Val: 0x00000000 -> drive_pcc7
Bank: 0 Reg: 0x700009c8 Val: 0x00000000 -> drive_pe6
Bank: 0 Reg: 0x700009cc Val: 0x00000000 -> drive_pe7
Bank: 0 Reg: 0x700009d0 Val: 0x00000000 -> drive_ph6
Bank: 0 Reg: 0x700009d4 Val: 0x00000000 -> drive_pk0
Bank: 0 Reg: 0x700009d8 Val: 0x00000000 -> drive_pk1
Bank: 0 Reg: 0x700009dc Val: 0x00000000 -> drive_pk2
Bank: 0 Reg: 0x700009e0 Val: 0x00000000 -> drive_pk3
Bank: 0 Reg: 0x700009e4 Val: 0x00000000 -> drive_pk4
Bank: 0 Reg: 0x700009e8 Val: 0x00000000 -> drive_pk5
Bank: 0 Reg: 0x700009ec Val: 0x00000000 -> drive_pk6
Bank: 0 Reg: 0x700009f0 Val: 0x00000000 -> drive_pk7
Bank: 0 Reg: 0x700009f4 Val: 0x00000000 -> drive_pl0
Bank: 0 Reg: 0x700009f8 Val: 0x00000000 -> drive_pl1
Bank: 0 Reg: 0x700009fc Val: 0x01010000 -> drive_pz0
Bank: 0 Reg: 0x70000a00 Val: 0x01010000 -> drive_pz1
Bank: 0 Reg: 0x70000a04 Val: 0x00000000 -> drive_pz2
Bank: 0 Reg: 0x70000a08 Val: 0x00000000 -> drive_pz3
Bank: 0 Reg: 0x70000a0c Val: 0x00000000 -> drive_pz4
Bank: 0 Reg: 0x70000a10 Val: 0x00000000 -> drive_pz5
Bank: 0 Reg: 0x70000a98 Val: 0x51115000 -> drive_sdmmc1
Bank: 0 Reg: 0x70000a9c Val: 0x07ffd040 -> drive_sdmmc2
Bank: 0 Reg: 0x70000ab0 Val: 0x51212000 -> drive_sdmmc3
Bank: 0 Reg: 0x70000ab4 Val: 0x07ffd040 -> drive_sdmmc4
Bank: 0 Reg: 0x70000b70 Val: 0x00000001 -> drive_qspi_comp_control
Bank: 0 Reg: 0x70000b78 Val: 0x00000001 -> drive_qspi_lpbk_control
Bank: 0 Reg: 0x70000a78 Val: 0x00808000 -> drive_qspi_comp
管脚复用处理函数列表
和设备树里的配置一样,方便查看
//它设备树的pinmux@700008d4 被解析生效后 当下的管脚复用情况
Requested pin control handlers their pinmux maps:
device: 700008d4.pinmux current state: default //700008d4.pinmux控制器, 当前状态是default, 对应 pinctrl-names = "default"
state: default
type: MUX_GROUP controller 700008d4.pinmux group: dvfs_pwm_pbb1 (108) function: cldvfs (5)
//对应 nvidia,function = "cldvfs";
type: CONFIGS_GROUP controller 700008d4.pinmux group dvfs_pwm_pbb1 (108)
config pull=0 //对应 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
config tristate=1 //对应 nvidia,tristate = <TEGRA_PIN_ENABLE>;
config enable-input=0 //对应 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
type: MUX_GROUP controller 700008d4.pinmux group: dmic1_clk_pe0 (52) function: i2s3 (24)
type: CONFIGS_GROUP controller 700008d4.pinmux group dmic1_clk_pe0 (52)
config pull=0
config tristate=0
type: MUX_GROUP controller 700008d4.pinmux group: pe7 (158) function: pwm3 (39) 对应 nvidia,function = "pwm3";
type: CONFIGS_GROUP controller 700008d4.pinmux group pe7 (158)
config pull=0 //对应 nvidia,pull = <TEGRA_PIN_PULL_NONE>; 管脚内部不上拉
config tristate=0 //对应 nvidia,tristate = <TEGRA_PIN_DISABLE>; //禁用三态(高阻态),表示管脚与外界连通
config enable-input=0
type: MUX_GROUP controller 700008d4.pinmux group: lcd_gpio2_pv4 (142) function: pwm1 (37) 对应nvidia,function = "pwm1";
type: CONFIGS_GROUP controller 700008d4.pinmux group lcd_gpio2_pv4 (142)
config pull=0
config tristate=0
config enable-input=0
示例:点灯
$ cat /sys/kernel/debug/gpio |grep GPIO07 /* 查看电路图上 GPIO07标号的管脚的在内核里的gpio 编号
gpio-168 (GPIO07 )
*/
$ echo 168 > /sys/class/gpio/export //导出gpio管脚,进行控制
//成功可看到 /sys/class/gpio/gpio168 有生成
$ echo out > /sys/class/gpio/gpio168/direction //设置 为输出
$ echo 1 > /sys/class/gpio/gpio168/value //输出高电平 开灯
$ cat /sys/kernel/debug/gpio |grep GPIO07 /*查看管脚状态
内核里编号 电路图标号 |当前使用者(程序名) 输出 高电平
gpio-168 (GPIO07 |sysfs ) out hi
*/
$ echo 168 > /sys/class/gpio/unexport //取消导出(注:用完后,必须要释放,否则会导致别的程序访问不了)
示例: 管脚被占用问题
$ echo 79 > /sys/class/gpio/export //导出,申请79号(在内核里的编号,不是芯片手册电路图上的编号)管脚的使用
sh: write error: Device or resource busy //报错 资源被占用
$ cat /sys/kernel/debug/gpio |grep I2S0_SCLK /*查看电路图上 I2S0_SCLK标号(对应丝印12) 的状态
内核里编号 电路图标号 |当前使用者 输出 高电平
gpio-79 (I2S0_SCLK |? (未知) ) out hi
注: 如果当前使用者 有具体程序名,如 yhai_led , 可用kill -9 杀死
发现被未知的使用者占用 ,可采取屏蔽相应设备树, 或堆栈dump_stack 堆栈追踪方式
*/
堆栈追踪
- dump_stack(); //打印堆栈信息,跟踪
//drivers/pinctrl/core.c
int pinctrl_request_gpio(unsigned gpio)
{
if(79==gpio){
printk("pinctrl_request_gpio go\n");
dump_stack(); //打印堆栈信息,跟踪
}
}
# run distro_bootcmd
$ scp arch/arm64/boot/Image bbcen@192.168.10.237:/home/bbcen/
内核启动信息 /* 查看日志, 发现是gpio_led_probe 调用触发的 -> 字符串搜索 发现是 drivers/leds/leds-gpio.c
3.950363] pinctrl_request_gpio go
[ 3.953878] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.9.253 #43
[ 3.959959] Hardware name: NVIDIA Jetson Nano Developer Kit (DT)
[ 3.965951] Call trace:
[ 3.968409] [<ffffff800808bb80>] dump_backtrace+0x0/0x198
[ 3.973797] [<ffffff800808c144>] show_stack+0x24/0x30
[ 3.978846] [<ffffff8008f88ed8>] dump_stack+0xa0/0xc4
[ 3.983894] [<ffffff80084b9248>] pinctrl_request_gpio+0x1b0/0x1b8
[ 3.989978] [<ffffff80084d3164>] tegra_gpio_request+0x124/0x140
[ 3.994730] mmc0: SDHCI controller on sdhci-tegra.0 [sdhci-tegra.0] using ADMA 64-bit with 64 bit addr
[ 4.005168] [<ffffff80084c8aa8>] __gpiod_request+0xa0/0x158
[ 4.010729] [<ffffff80084cc210>] gpiod_request+0xd0/0x1e8
[ 4.016115] [<ffffff80084cc3ac>] fwnode_get_named_gpiod+0x84/0x118
[ 4.022284] [<ffffff80084c6ee0>] devm_get_gpiod_from_child+0x98/0x130
[ 4.028718] [<ffffff8008bf75f0>] gpio_led_probe+0x2e8/0x3d0 触发的驱动程序
[ 4.034286] [<ffffff800879b180>] platform_drv_probe+0x60/0xc0
[ 4.040020] [<ffffff8008798888>] driver_probe_device+0x298/0x448
[ 4.046014] [<ffffff8008798b14>] __driver_attach+0xdc/0x128
[ 4.051574] [<ffffff8008796144>] bus_for_each_dev+0x5c/0xa8
[ 4.057135] [<ffffff8008797ec8>] driver_attach+0x30/0x40
[ 4.062435] [<ffffff80087978fc>] bus_add_driver+0x20c/0x2a8
[ 4.067994] [<ffffff8008799b74>] driver_register+0x6c/0x110
[ 4.073554] [<ffffff800879b0bc>] __platform_driver_register+0x5c/0x68
[ 4.079987] [<ffffff8009682a90>] gpio_led_driver_init+0x18/0x20
[ 4.085896] [<ffffff8008083b64>] do_one_initcall+0x44/0x130
[ 4.091460] [<ffffff8009630e88>] kernel_init_freeable+0x1a0/0x268
[ 4.097541] [<ffffff8008f8bcc0>] kernel_init+0x18/0x148
[ 4.102754] [<ffffff80080838a0>] ret_from_fork+0x10/0x30
*/
//解决方法: 取消驱动的编译,或编译成模块,或屏蔽设备树节点,或在设备树节点中使用别的管脚
屏蔽设备树
//通过占用的驱动程序 drivers/leds/leds-gpio.c
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", }, //跟踪到设备树,然后屏蔽相应设备树节点
{},
};
//tegra210-p3448-0000-p3449-0000-b00.dts
/*屏蔽对应的设备节点,或使用另一个gpio管脚,或吧驱动编译成模块,不加载即可
yhai-gpio-led {
compatible = "gpio-leds";
led1{
gpios = <&gpio TEGRA_GPIO(J,7) GPIO_ACTIVE_HIGH>; //pJ7 对应79号,占用了管脚
};
};
*/
*设备树分析
帮助文档
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
基本配置
//tegra210-soc-base.dtsi cpu的基本配置
pinmux: pinmux@700008d4 {
compatible = "nvidia,tegra210-pinmux";
//定义pinmux 功能块的 寄存器资源(基地址 + 长度)
reg = <0x0 0x700008d4 0x0 0x2a5 /* Pad control registers 管脚配置寄存器,如上拉 三态 驱动能力*/
0x0 0x70003000 0x0 0x294>; /* Mux registers 复用设置寄存器*/
#gpio-range-cells = <3>; //声明 引用本节点,用 gpio-ranges 属性传参时 参数占3个单位
status = "disabled";
};
//位置: public_sources\hardware\nvidia\soc\t210\kernel-dts\tegra210-soc\
gpio: gpio@6000d000 {//gpio子节点
compatible = "nvidia,tegra210-gpio", "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
reg = <0x0 0x6000d000 0x0 0x1000>; //前2个数表示起始地址(由父节点的#address-cells = <2> 决定)
//后2个数表示长度范围(由父节点的#size-cells = <2> 决定)
#gpio-cells = <2>; //声明 引用本节点,用 gpios 属性传参时 参数占2个单位
gpio-controller; //声明本节点 是 GPIO 控制器
//gpio-ranges: 设置gpio number 与 pinctrl number的 映射范围
gpio-ranges = <&pinmux 0 0 246>; //设置管脚复用:通过引用pinmux节点,gpio-ranges属性传参的方式
// 参数占的3个单位 0 0 246,由pinmux里的 #gpio-range-cells = <3>;指定
//功用:设置 gpio 0~246 和 pinmux的 pin 0~246 的映射转换关系
//第一个0: 表示gpio 的 base number
//第二个0: 表示pinmux 的 base number
//246: 表示长度范围
//注:当gpio driver需要使用某一个gpio的时候,可以在gpiochip的request函数中,
//调用pinctrl core提供的pinctrl_request_gpio接口(参数是gpio编号),
//然后pinctrl core会查寻gpio ranges链表,将gpio编号转换成pin编号,
//然后调用pinctrl的相应接口(参数是pin编号),申请该pin的使用。
};
管脚复用状态的配置
pe7 {
nvidia,pins = "pe7"; //管脚名
nvidia,function = "pwm3"; //配置管脚为 pwm3功能
nvidia,pull = <TEGRA_PIN_PULL_NONE>; //管脚内部不上拉
nvidia,tristate = <TEGRA_PIN_DISABLE>; //禁用三态(高阻态),表示管脚与外界连通
nvidia,enable-input = <TEGRA_PIN_DISABLE>;//禁用输入功能
};
//tegra210-porg-pinmux-p3448-0000-b00.dtsi"
注 //当修改pinmux配置时,要修改当前的配置(状态1),
//如果修改别的状态下的配置可能不生效(只有在特殊状态下才会切换,如CPU省电睡眠时 )
//或通过专用的接口去申请改写,如GPIO子系统的申请。
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
pinmux: pinmux@700008d4 {
status = "okay";
pinctrl-names = "default", "drive", "unused"; //定制设备自己的三种管脚状态
//如无指定,默认用第一个设备状态的配置单
pinctrl-0 = <&pinmux_default>; //状态1(default) 对应的配置单(pinmux_default)
pinctrl-1 = <&drive_default>; //状态2(drive) 对应的配置单(drive_default)
pinctrl-2 = <&pinmux_unused_lowpower>;
pinmux_default: common { //默认的管脚复用,配置单
/* SFIO Pin Configuration */
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1"; //
nvidia,function = "cldvfs"; //配置当前管脚为cldvfs功能
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_ENABLE>; //开启三态(高阻),即断开了管脚与外界连接
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
dmic1_clk_pe0 {
nvidia,pins = "dmic1_clk_pe0";
nvidia,function = "i2s3";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
...
pe7 {
nvidia,pins = "pe7"; //管脚名
nvidia,function = "pwm3"; //配置管脚为 pwm3功能
nvidia,pull = <TEGRA_PIN_PULL_NONE>; //管脚内部不上拉
nvidia,tristate = <TEGRA_PIN_DISABLE>; //禁用三态(高阻态),表示管脚与外界连通
nvidia,enable-input = <TEGRA_PIN_DISABLE>;//禁用输入功能
};
...
};
pinmux_unused_lowpower: unused_lowpower { //803
lcd_bl_pwm_pv0 {
nvidia,pins = "lcd_bl_pwm_pv0";
nvidia,function = "rsvd3";
nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
/* GPIO Pin Configuration */
dap4_sclk_pj7 { // pj7的管脚配置(79号 led灯)
nvidia,pins = "dap4_sclk_pj7"; //指定管脚名
nvidia,function = "rsvd1"; //配置该管脚为 rsvd1 功能
nvidia,pull = <TEGRA_PIN_PULL_DOWN>; //管脚设为下拉
nvidia,tristate = <TEGRA_PIN_ENABLE>; //开启三态(高阻),即断开了管脚与外界连接
nvidia,enable-input = <TEGRA_PIN_DISABLE>;//输入禁止
};
}
drive_default: drive {
};
};
官方驱动分析
源码分析 //使用者角度: 从初始化入手,逐层调用到对象
//设计者角度: 从面向对象,到对外的接口
入口: 构建管脚配置列表
//drivers/pinctrl/tegra/pinctrl-tegra210.c
//所有管脚配置列表 -> 由设备树的 pinmux 去选择 《 重点
static struct tegra_pingroup tegra210_groups[] = {
// 管脚名 管脚复用:功能f0 f1 f2 f3
/* pg_name, f0, f1, f2, f3, r*/
PINGROUP(dvfs_pwm_pbb1, RSVD0, CLDVFS, SPI3, RSVD3, 0x3184),
PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000),
PINGROUP(dap4_sclk_pj7, I2S4B, RSVD1, RSVD2, RSVD3, 0x3150),
PINGROUP(pe7, RSVD0, I2S5A, PWM3, RSVD3, 0x324c),
PINGROUP(lcd_bl_pwm_pv0, DISPLAYA, PWM0, SOR0, RSVD3, 0x31fc),
PINGROUP(lcd_gpio2_pv4, DISPLAYB, PWM1, RSVD2, SOR1, 0x320c),
}
static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
.ngpios = NUM_GPIOS, //GPIO管脚个数
.pins = tegra210_pins, //管脚描述
.npins = ARRAY_SIZE(tegra210_pins), //管脚数
.functions = tegra210_functions, //功能列表
.nfunctions = ARRAY_SIZE(tegra210_functions),//功能数
.groups = tegra210_groups, //组列表
.ngroups = ARRAY_SIZE(tegra210_groups), //组数
};
static int tegra210_pinctrl_probe(struct platform_device *pdev) //探测初始化 pinctl设备信息
{
return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
}
static const struct of_device_id tegra210_pinctrl_of_match[] = {
{
.compatible = "nvidia,tegra210-pinmux",
.data = &tegra210_pinctrl_soc_data,
}
};
static struct platform_driver tegra210_pinctrl_driver = {
.driver = {
.name = "tegra210-pinctrl",
.of_match_table = tegra210_pinctrl_of_match, //在设备树中查找匹配的设备信息
},
.probe = tegra210_pinctrl_probe, //如果有匹配的,在调用初始化函数
};
static int __init tegra_pinctrl_init(void)
{
return platform_driver_register(&tegra210_pinctrl_driver);
}
postcore_initcall(tegra_pinctrl_init); //让模块在内核初始化时,被回调自动加载
初始化对象(属性和操作集)
//文件drivers/pinctrl/tegra/pinctrl-tegra.c
//定义 pinctl设备的类
struct tegra_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
const struct tegra_pinctrl_soc_data *soc;
const char **group_pins;
};
static struct tegra_pmx *pmx;
static const struct cfg_param { //配置参数 列表
const char *property;
enum tegra_pinconf_param param;
} cfg_params[] = {
{"nvidia,pull", TEGRA_PINCONF_PARAM_PULL},
{"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE},
{"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT},
{"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN},
{"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK},
{"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET},
{"nvidia,rcv-sel", TEGRA_PINCONF_PARAM_RCV_SEL},
{"nvidia,io-hv", TEGRA_PINCONF_PARAM_RCV_SEL},
{"nvidia,io-high-voltage", TEGRA_PINCONF_PARAM_E_IO_HV},
{"nvidia,loopback", TEGRA_PINCONF_PARAM_LOOPBACK},
{"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
{"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT},
{"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
{"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
{"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
{"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
{"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
{"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE},
{"nvidia,lpdr", TEGRA_PINCONF_PARAM_LPDR},
{"nvidia,pbias-buf", TEGRA_PINCONF_PARAM_PBIAS_BUF},
{"nvidia,preemp", TEGRA_PINCONF_PARAM_PREEMP},
{"nvidia,rfu-in", TEGRA_PINCONF_PARAM_RFU_IN},
{"nvidia,special-function", TEGRA_PINCONF_PARAM_GPIO_MODE},
{"nvidia,pad-power", TEGRA_PINCONF_PARAM_PAD_POWER},
{"nvidia,func", TEGRA_PINCONF_PARAM_FUNCTION},
};
static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map,
unsigned *reserved_maps,
unsigned *num_maps)
{
//解析设备树的属性
of_property_read_string(np, "nvidia,function", &function);
for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
ret = of_property_read_u32(np, cfg_params[i].property, &val);
}
of_property_count_strings(np, "nvidia,pins");
}
static const struct pinctrl_ops tegra_pinctrl_ops = { //pinctrl的操作函数集
.get_groups_count = tegra_pinctrl_get_groups_count,
.get_group_name = tegra_pinctrl_get_group_name,
.get_group_pins = tegra_pinctrl_get_group_pins,
.dt_node_to_map = tegra_pinctrl_dt_node_to_map, //解析映射设备树节点
//-> tegra_pinctrl_dt_subnode_to_map
.dt_free_map = pinctrl_utils_free_map,
};
static const struct pinmux_ops tegra_pinmux_ops = { //pinmux操作函数集
.set_mux = tegra_pinctrl_set_mux,
.gpio_request_enable = tegra_pinctrl_gpio_request_enable,
.gpio_disable_free = tegra_pinctrl_gpio_disable_free,
.gpio_set_direction = tegra_pinctrl_gpio_set_direction,
.gpio_save_config = tegra_pinctrl_gpio_save_config,
.gpio_restore_config = tegra_pinctrl_gpio_restore_config,
};
static struct pinctrl_desc tegra_pinctrl_desc = { //pinctrl 的操作描述(类似file_operations)
.pctlops = &tegra_pinctrl_ops, //管脚控制操作集
.pmxops = &tegra_pinmux_ops, //管脚复用操作集
.confops = &tegra_pinconf_ops, //管脚配置操作集
.owner = THIS_MODULE,
};
int tegra_pinctrl_probe(struct platform_device *pdev,
const struct tegra_pinctrl_soc_data *soc_data)
{
//-----初始是 对象(为结构体中各指针,分配实体,指向实体)
//分配device空间(以存储探测到的设备信息)
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
pmx->dev = &pdev->dev;
pmx->soc = soc_data;
res = platform_get_resource(pdev, IORESOURCE_MEM, i); //获取设备树中reg 属性的资源
pmx->reg_base[i] = res->start;
//注册pintrl设备
pmx->pctl = devm_pinctrl_register(&pdev->dev, &tegra_pinctrl_desc, pmx);
dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n");
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
对外接口
//include/linux/pinctrl/consumer.h 使用:对外常用接口(GPIO子系统 做pinctrl子系统的客户)
extern int pinctrl_request_gpio(unsigned gpio); //申请管脚做GPIO用途(使用管脚前,需申请,如被占用则申请失败)
extern void pinctrl_free_gpio(unsigned gpio); //释放控制
extern int pinctrl_gpio_direction_input(unsigned gpio); //设置管脚为输入
extern int pinctrl_gpio_direction_output(unsigned gpio); //设置管脚为输出
extern int pinctrl_gpio_save_config(unsigned gpio); //保存管脚配置
extern int pinctrl_gpio_restore_config(unsigned gpio); //重载管脚配置
extern void pinctrl_put(struct pinctrl *p);
extern struct pinctrl_state * __must_check pinctrl_lookup_state(
struct pinctrl *p,
const char *name);
extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s); //切换当前的复用状态
extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
extern void devm_pinctrl_put(struct pinctrl *p);