LAN966x GPIO
LAN966x GPIO
SoC Resources
LAN966x GPIO controller supports 78 gpio pins. Most of the GPIO pins have alternate functions which will be handled by linux driver.
Kernel configurations
Following kernel config options should be enabled to use LAN966x GPIO Controller:
-
CONFIG_PINCTRL_OCELOT
- GPIO controller config option.
Devicetree Configuration
To use GPIO pins of a specific peripheral, configure following properties in device tree:
-
compatible
string must be set tomicrochip,lan966x-pinctrl
. -
reg
property must be set with<0xe2004064 0xb4>
and<0xe2010024 0x138>
. -
gpio-controller
property must be added. -
#gpio-cells
property must be set to 2 -
gpio-ranges
property must be set to<&gpio 0 0 78>
-
interrupts
property must be set with GPIO block interrupt details as<GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>
.
Peripheral | Shared Peripheral Interrupt | CPU INTR |
---|---|---|
gpio |
49 |
17 |
- Note
-
Shared peripheral interrupt lines start at index ID32. So, CPU INTR must be calculated as [Shared peripheral interrupt number - 32].
-
pins
must be set with list of GPIO pins required. For example for mcan0, it should be set as"GPIO_35", "GPIO_36"
. -
function
must be set to function name corresponding to GPIO pins and the peripheral we are trying to enable. Refer below table for function names:
-
GPIO Pin | FUNC1 | FUNC2 | FUNC3 | FUNC4 | FUNC5 | FUNC6 |
---|---|---|---|---|---|---|
0 |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
2 |
- |
- |
- |
- |
- |
- |
3 |
- |
- |
- |
- |
- |
- |
4 |
- |
- |
- |
- |
- |
- |
5 |
- |
- |
- |
- |
- |
- |
6 |
- |
- |
- |
- |
- |
- |
7 |
- |
- |
- |
- |
- |
- |
8 |
fc0_a |
usb_host_b |
- |
usb_slave_b |
- |
- |
9 |
fc0_a |
usb_host_b |
- |
- |
- |
- |
10 |
fc0_a |
- |
- |
- |
- |
- |
11 |
fc1_a |
- |
- |
- |
- |
- |
12 |
fc1_a |
- |
- |
- |
- |
- |
13 |
fc1_a |
- |
- |
- |
- |
- |
14 |
fc2_a |
- |
- |
- |
- |
- |
15 |
fc2_a |
- |
- |
- |
- |
- |
16 |
fc2_a |
ib_trig_a |
- |
ob_trig_a |
irq_in_c |
irq_out_c |
17 |
fc3_a |
ib_trig_a |
- |
ob_trig_a |
irq_in_c |
irq_out_c |
18 |
fc3_a |
ib_trig_a |
- |
ob_trig_a |
irq_in_c |
irq_out_c |
19 |
fc3_a |
ib_trig_a |
- |
ob_trig_a |
irq_in_c |
irq_out_c |
20 |
fc4_a |
ib_trig_a |
- |
ob_trig_a |
irq_in_c |
- |
21 |
fc4_a |
- |
- |
ob_trig_a |
- |
- |
22 |
fc4_a |
- |
- |
ob_trig_a |
- |
- |
23 |
- |
- |
- |
ob_trig_a |
- |
- |
24 |
fc0_b |
ib_trig_a |
usb_host_c |
ob_trig_a |
irq_in_c |
tacho_a |
25 |
fc0_b |
ib_trig_a |
usb_host_c |
ob_trig_a |
irq_out_c |
sfp_sd |
26 |
fc0_b |
ib_trig_a |
usb_slave_c |
ob_trig_a |
can0_a |
sfp_sd |
27 |
- |
- |
- |
ob_trig_a |
can0_a |
- |
28 |
miim_a |
- |
- |
ob_trig_a |
irq_out_c |
sfp_sd |
29 |
miim_a |
- |
- |
ob_trig_a |
- |
- |
30 |
fc3_c |
can1 |
- |
ob_trig |
reco_b |
- |
31 |
fc3_c |
can1 |
- |
ob_trig |
reco_b |
- |
32 |
fc3_c |
- |
sgpio_a |
- |
miim_slave_a |
- |
33 |
fc1_b |
- |
sgpio_a |
- |
miim_slave_a |
miim_b |
34 |
fc1_b |
- |
sgpio_a |
- |
miim_slave_a |
miim_b |
35 |
fc1_b |
ptpsync_0 |
sgpio_a |
can0_b |
- |
- |
36 |
- |
ptpsync_1 |
- |
can0_b |
- |
- |
37 |
fc_shrd0 |
ptpsync_2 |
twi_slc_gate_ad |
- |
- |
- |
38 |
- |
ptpsync_3 |
- |
- |
- |
- |
39 |
- |
ptpsync_4 |
- |
- |
- |
- |
40 |
fc_shrd1 |
ptpsync_5 |
- |
- |
- |
- |
41 |
fc_shrd2 |
ptpsync_6 |
twi_slc_gate_ad |
- |
- |
- |
42 |
fc_shrd3 |
ptpsync_7 |
twi_slc_gate_ad |
- |
- |
- |
43 |
fc2_b |
ob_trig_b |
ib_trig_b |
irq_out_a |
reco_a |
irq_in_a |
44 |
fc2_b |
ob_trig_b |
ib_trig_b |
irq_out_a |
reco_a |
irq_in_a |
45 |
fc2_b |
ob_trig_b |
ib_trig_b |
irq_out_a |
- |
irq_in_a |
46 |
fc1_c |
ob_trig_b |
ib_trig_b |
irq_out_a |
fc_shrd4 |
irq_in_a |
47 |
fc1_c |
ob_trig_b |
ib_trig_b |
irq_out_a |
fc_shrd5 |
irq_in_a |
48 |
fc1_c |
ob_trig_b |
ib_trig_b |
irq_out_a |
fc_shrd6 |
irq_in_a |
49 |
fc_shrd7 |
ob_trig_b |
ib_trig_b |
irq_out_a |
twi_slc_gate |
irq_in_a |
50 |
fc_shrd16 |
ob_trig_b |
ib_trig_b |
irq_out_a |
twi_slc_gate |
- |
51 |
fc3_b |
ob_trig_b |
ib_trig_c |
irq_out_b |
- |
irq_in_b |
52 |
fc3_b |
ob_trig_b |
ib_trig_c |
irq_out_b |
tacho_b |
irq_in_b |
53 |
fc3_b |
ob_trig_b |
ib_trig_c |
irq_out_b |
- |
irq_in_b |
54 |
fc_shrd8 |
ob_trig_b |
ib_trig_c |
irq_out_b |
twi_slc_gate |
irq_in_b |
55 |
fc_shrd9 |
ob_trig_b |
ib_trig_c |
irq_out_b |
twi_slc_gate |
irq_in_b |
56 |
fc4_b |
ob_trig_b |
ib_trig_c |
irq_out_b |
fc_shrd10 |
irq_in_b |
57 |
fc4_b |
twi_slc_gate |
ib_trig_c |
irq_out_b |
fc_shrd11 |
irq_in_b |
58 |
fc4_b |
twi_slc_gate |
ib_trig_c |
irq_out_b |
fc_shrd12 |
irq_in_b |
59 |
qspi1 |
miim_c |
- |
- |
miim_slaveb |
- |
60 |
qspi1 |
miim_c |
- |
- |
miim_slaveb |
- |
61 |
qspi1 |
- |
sgpio_b |
fc0_c |
miim_slaveb |
- |
62 |
qspi1 |
fc_shrd13 |
sgpio_b |
fc0_c |
twi_slc_gate |
sfp_sd |
63 |
qspi1 |
fc_shrd14 |
sgpio_b |
fc0_c |
twi_slc_gate |
sfp_sd |
64 |
qspi1 |
fc4_c |
sgpio_b |
fc_shrd15 |
twi_slc_gate |
sfp_sd |
65 |
usb_host_a |
fc4_c |
- |
irq_out_c |
twi_slc_gate_ad |
- |
66 |
usb_host_a |
fc4_c |
usb_slave_a |
irq_out_c |
irq_in_c |
- |
67 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
68 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
69 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
70 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
71 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
72 |
emmc_sd |
- |
qspi2 |
- |
- |
- |
73 |
emmc |
- |
- |
sd |
- |
- |
74 |
emmc |
- |
fc_shrd17 |
sd |
twi_slc_gate |
- |
75 |
emmc |
- |
fc_shrd18 |
sd |
twi_slc_gate |
- |
76 |
emmc |
- |
fc_shrd19 |
sd |
twi_slc_gate |
- |
77 |
emmc_sd |
- |
fc_shrd20 |
- |
twi_slc_gate |
- |
- Note
-
LAN966x GPIO controller supports 8 Alternate functions. FUNC0 is GPIO mode and FUNC7 is Reserved. Function names for FUNC1-FUNC6 alternate modes are listed above.
Example
Following example shows how a GPIO controller should be defined in DT to enable GPIO pins for eMMC interface:
dtsi file:
gpio: pinctrl@e2004070 { compatible = "microchip,lan966x-pinctrl"; reg = <GCB_GPIO_ADDR GCB_GPIO_SIZE>, <CHIP_TOP_GPIO_CFG_ADDR CHIP_TOP_GPIO_CFG_SIZE>; gpio-controller; #gpio-cells = <2>; gpio-ranges = <&gpio 0 0 78>; interrupt-controller; interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; #interrupt-cells = <2>; emmc_sd_pins: emmc-sd-pins { /* eMMC_SD - CMD, CLK, D0, D1, D2, D3, RSTN */ pins = "GPIO_67", "GPIO_68", "GPIO_69", "GPIO_70", "GPIO_71", "GPIO_72", "GPIO_77"; function = "emmc_sd"; }; emmc_pins: emmc-pins { /* eMMC - D4, D5, D6, D7 */ pins = "GPIO_73", "GPIO_74", "GPIO_75", "GPIO_76"; function = "emmc"; }; };
dts file changes:
&sdmmc0 { bus-width = <8>; cap-mmc-highspeed; cap-mmc-hw-reset; non-removable; pinctrl-0 = <&emmc_sd_pins>, <&emmc_pins>; pinctrl-names = "default"; no-1-8-v; tx-phase = <0>; /* 180 degrees phase shift */ status = "okay"; };
UserSpace
Confirm instances are created
-
Check if pinctrl driver is registered and respective peripheral is up or not.
Example on how to use
Checking if the pinctrl driver is registered and respective
peripheral(here emmc
with above dt example) is created or not.
# dmesg | grep pinctrl [ 0.014851] pinctrl core: initialized pinctrl subsystem [ 0.109830] gpio gpiochip0: (ocelot-gpio): created GPIO range 0->77 ==> e2004064.pinctrl PIN 0->77 [ 0.111131] pinctrl-ocelot e2004064.pinctrl: driver registered # dmesg | grep mmc [ 0.722586] mmc0: SDHCI controller on e0830000.sdio-host [e0830000.sdio-host] using ADMA [ 2.373076] mmc0: new high speed MMC card at address 0001 [ 2.378776] mmcblk0: mmc0:0001 IS004G 3.64 GiB [ 2.387639] mmcblk0: [ 2.388324] mmcblk0boot0: mmc0:0001 IS004G 2.00 MiB [ 2.399663] mmcblk0boot1: mmc0:0001 IS004G 2.00 MiB [ 2.410084] mmcblk0rpmb: mmc0:0001 IS004G 512 KiB, chardev (247:0) # mount -t debugfs none /sys/kernel/debug/ cat /sys/kernel/debug/mmc0/ios# cat /sys/kernel/debug/mmc0/ios clock: 46000000 Hz actual clock: 46000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 3 (8 bits) timing spec: 1 (mmc high-speed) signal voltage: 0 (3.30 V) driver type: 0 (driver type B)
Configuring GPIO pin using Sysfs interface
- Mounting Sysfs
-
The root file system being used may not have sysfs mounted and it cannot be used if it’s not mounted. The directory /sys is also needed to mount the sysfs on. The root file system must be writable to do the following steps.
- Identify the GPIO chips
-
Use command
ls /sys/class/gpio/
to list all the gpio chips. - Steps to configure a GPIO pin
-
-
Export a GPIO pin using command
echo X > /sys/class/gpio/export
. -
Read direction and value from GPIO pin using command
cat /sys/class/gpio/gpioX/direction
for direction andcat /sys/class/gpio/gpioX/value
for value, where X is pin number. -
If direction of a pin is
out
, we can write0
or1
to value file of pin and also can read its value. -
If direction of a pin is
in
, we can only read its value but cannot write to it, we would get an error because it is not valid to set the value of an input pin. -
Unexport a GPIO pin using command
echo X > /sys/class/gpio/unexport
.
-
Following example configures GPIO pin 51(physical pin number 32) and validates voltage on pin using a multimeter:
# ls /sys/class/gpio/ export gpiochip0 unexport
Export GPIO pin 51:
# echo 51 > /sys/class/gpio/export # ls /sys/class/gpio/ export gpio51 gpiochip0 unexport
Check default direction and value:
# cat /sys/class/gpio/gpio51/value 1 # # cat /sys/class/gpio/gpio51/direction in #
Now, measure voltage on physical pin number 32 and you should see voltage of approximately 3.3v.
Change direction of GPIO pin 51 to out
and set value to zero:
# echo out > /sys/class/gpio/gpio51/direction # # # cat /sys/class/gpio/gpio51/value 0 #
Again measure voltage on physical pin number 32 and you should see voltage close to zero.