电子说
下面截取gpio0的设备树,复制自:linux_5.10/arch/riscv/boot/dts/cvitek/cv180x_base.dtsi
gpio0: gpio@03020000 {
compatible = "snps,dw-apb-gpio";
reg = < 0x0 0x03020000 0x0 0x1000 >;
#address-cells = < 1 >;
#size-cells = < 0 >;
porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
bank-name = "porta";
gpio-controller;
#gpio-cells = < 2 >;
snps,nr-gpios = < 32 >;
reg = < 0 >;
};
};
以下是复制自:linux_5.10/arch/riscv/boot/dts/cvitek/cv180x_base_riscv.dtsi
gpio0: gpio@03020000 {
porta: gpio-controller@0 {
interrupt-controller;
interrupts = < 60 IRQ_TYPE_LEVEL_HIGH >;
interrupt-parent = < &plic0 >;
};
};
cv180x的GPIO控制器用到是dw-apb-gpio控制器驱动,驱动代码位于:linux_5.10/drivers/gpio/gpio-dwapb.c
#define DWAPB_DRIVER_NAME "gpio-dwapb"
// 省略其他代码
static struct platform_driver dwapb_gpio_driver = {
.driver = {
.name = DWAPB_DRIVER_NAME,
.pm = &dwapb_gpio_pm_ops,
.of_match_table = dwapb_of_match,
.acpi_match_table = dwapb_acpi_match,
},
.probe = dwapb_gpio_probe,
};
module_platform_driver(dwapb_gpio_driver);
关键函数是probe函数
// drivers/gpio/gpio-dwapb.c
dwapb_gpio_probe:
dwapb_gpio_get_pdata(dev)
device_for_each_child_node(dev, fwnode) { //遍历设备树节点
fwnode_property_read_u32(fwnode, "snps,nr-gpios", &pp- >ngpio)
fwnode_property_read_u32(fwnode, "reg", &pp- >idx)
}
dwapb_gpio_add_port
devm_gpiochip_add_data
devm_gpiochip_add_data_with_key
gpiochip_add_data_with_key //注册到gpiolib的gpio_devices中
// drivers/gpio/gpiolib.c
struct gpio_desc *gpio_to_desc(unsigned gpio) //从gpio_devices获取gpio_desc
// include/asm-generic/gpio.h
// drivers/gpio/gpiolib-sysfs.c
gpio_export:
gpiod_export(gpio_to_desc(gpio), direction_may_change)
device_create_with_groups
device_create_groups_vargs
device_add
kobject_add //添加到相关的设备模型子系统
device_create_file //创建/sys下的设备属性文件
... //其他相关设置
通过上面的3块,就实现了/sys/class/gpio/export导出gpio的过程即对gpio的操作。
关于gpio的相关操作函数就在gpiolib.c里面。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !