Linux内核移植 part3:pinctrl和gpio驱动
来源:互联网 发布:算法流程图 编辑:程序博客网 时间:2024/06/07 21:45
世上最快乐的事,莫过于为理想而奋斗。 —— 苏格拉底
谨送给自己和所有在路上的朋友。
exynos 4412平台有很多模块穿插了gpio的控制,譬如usb phy需要gpio来控制提供vbus,sdmmc的所有管脚都和gpio复用。gpio作为管脚的一种,现在融合到了pinctrl驱动中,这篇文章就介绍一下Linux 4.1版本内核是如何管理gpio的。
一 设备树和平台编码的配合
设备树负责组织gpio,但是关于每个bank有多少个gpio口,每个口的地址偏移是多少,内核把这些信息硬编码进了内核(我觉得后面可能还会调整)。
1.1 pinctrl框架
平台对应的驱动位于drivers/pinctrl/samsung文件夹中,配置都在pinctrl-exynos.c中。
const struct samsung_pin_ctrl exynos4x12_pin_ctrl[] __initconst = { { /* pin-controller instance 0 data */ .pin_banks = exynos4x12_pin_banks0, .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks0), .eint_gpio_init = exynos_eint_gpio_init, .suspend = exynos_pinctrl_suspend, .resume = exynos_pinctrl_resume, }, { /* pin-controller instance 1 data */ .pin_banks = exynos4x12_pin_banks1, .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks1), .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, .suspend = exynos_pinctrl_suspend, .resume = exynos_pinctrl_resume, }, { /* pin-controller instance 2 data */ .pin_banks = exynos4x12_pin_banks2, .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks2), .eint_gpio_init = exynos_eint_gpio_init, .suspend = exynos_pinctrl_suspend, .resume = exynos_pinctrl_resume, }, { /* pin-controller instance 3 data */ .pin_banks = exynos4x12_pin_banks3, .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks3), .eint_gpio_init = exynos_eint_gpio_init, .suspend = exynos_pinctrl_suspend, .resume = exynos_pinctrl_resume, },};
匹配的id号定义在pinctrl-samsung.c中。
static const struct of_device_id samsung_pinctrl_dt_match[] = {#ifdef CONFIG_PINCTRL_EXYNOS { .compatible = "samsung,exynos3250-pinctrl", .data = (void *)exynos3250_pin_ctrl }, { .compatible = "samsung,exynos4210-pinctrl", .data = (void *)exynos4210_pin_ctrl }, { .compatible = "samsung,exynos4x12-pinctrl", .data = (void *)exynos4x12_pin_ctrl }, { .compatible = "samsung,exynos4415-pinctrl", .data = (void *)exynos4415_pin_ctrl }, { .compatible = "samsung,exynos5250-pinctrl", .data = (void *)exynos5250_pin_ctrl }, { .compatible = "samsung,exynos5260-pinctrl", .data = (void *)exynos5260_pin_ctrl }, { .compatible = "samsung,exynos5420-pinctrl", .data = (void *)exynos5420_pin_ctrl }, { .compatible = "samsung,exynos5433-pinctrl", .data = (void *)exynos5433_pin_ctrl }, { .compatible = "samsung,s5pv210-pinctrl", .data = (void *)s5pv210_pin_ctrl }, { .compatible = "samsung,exynos7-pinctrl", .data = (void *)exynos7_pin_ctrl },#endif#ifdef CONFIG_PINCTRL_S3C64XX { .compatible = "samsung,s3c64xx-pinctrl", .data = s3c64xx_pin_ctrl },#endif#ifdef CONFIG_PINCTRL_S3C24XX { .compatible = "samsung,s3c2412-pinctrl", .data = s3c2412_pin_ctrl }, { .compatible = "samsung,s3c2416-pinctrl", .data = s3c2416_pin_ctrl }, { .compatible = "samsung,s3c2440-pinctrl", .data = s3c2440_pin_ctrl }, { .compatible = "samsung,s3c2450-pinctrl", .data = s3c2450_pin_ctrl },#endif {},};MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
关键数据结构就是这两个了。下面说明一下gpio信息是如何硬编码进内核的。
1.2 gpio编码
gpio的编码信息都保存在这样的结构中。从Exynos4412用户手册中可以看到所有的gpio分为四个部分,每个部分目前就对应这样一个结构。
/* pin banks of exynos4x12 pin-controller 0 */static const struct samsung_pin_bank_data exynos4x12_pin_banks0[] __initconst = { // 该组gpio管脚数量+该组gpio偏移地址+名字+相对于eint配置寄存器(0x700)的偏移 EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14), EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18), EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30), EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34), EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38), EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c), EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40), EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44),};
至于gpio的操作等都很简单,查看一下手册立马就知道了。如果刚更新到新版内核,可能要稍微琢磨一下上面这些结构体是怎么编码的。所以就在这里记录一下吧。希望看到的人能尽快上手。
二 gpio调试
关于gpio的知识应该是所有模块最简单的了,基本上熟悉了内核中的驱动框架之后就不会有什么难点了,遇到具体问题去翻一下手册就很容易解决。这里再记录一下内核中调试gpio的几种方法。
debugfs
驱动中把gpio相关信息注册进了debugfs,所以我们可以通过挂载debugfs来查看gpio配置。内核配置:
然后mount debugfs,就可以查看管脚映射了。
host # mount -t debugfs none home/debugfshost # ls home/debugfs/gpio106e0000.pinctrl 11400000.pinctrl pinctrl-devices pinctrl-maps11000000.pinctrl 3860000.pinctrl pinctrl-handles
sysfs
也可以sysfs查看gpio配置,首先也要配置内核。然后就可以在/sys/class/gpio/目录下看到相关信息了。
host # ls /sys/class/gpioexport gpiochip14 gpiochip188 gpiochip244 gpiochip36 gpiochip83gpiochip0 gpiochip143 gpiochip196 gpiochip251 gpiochip40 gpiochip90gpiochip104 gpiochip148 gpiochip204 gpiochip259 gpiochip48 gpiochip97gpiochip111 gpiochip156 gpiochip212 gpiochip267 gpiochip56 unexportgpiochip118 gpiochip164 gpiochip22 gpiochip27 gpiochip64gpiochip120 gpiochip170 gpiochip220 gpiochip275 gpiochip70gpiochip128 gpiochip174 gpiochip228 gpiochip283 gpiochip78gpiochip136 gpiochip180 gpiochip236 gpiochip32 gpiochip8
现在我们想要点个灯看一下效果,可以这样操作,查看itop Exynos4412硬件原理图可以知道,GPL2[0]对应LED2。GPL[2]在内核中对应gpiochip120(可以通过搜索字符串gpl2或者直接查看源代码知道)。
host # echo 120 > exporthost # echo "out" > gpio120/direction host # echo 1 > gpio120/value
可以看到LED2亮了。可以通过
host # echo 120 > unexport
取消映射。
三 总结
gpio可以说是最简单的硬件了,如果要对代码进行良好的抽象,保证实用性和可扩展性,却不见得是个简单的东西。总之,有现成的框架,遇到问题多看看手册自然就能迎刃而解。
- Linux内核移植 part3:pinctrl和gpio驱动
- Linux芯片级移植与底层驱动(基于3.7.4内核)(GPIO&&pinctrl&&clk)
- Linux内核移植 part3:串口驱动
- Linux内核移植 part3:usb host驱动
- Linux内核移植 part3:sdmmc驱动
- Linux内核移植 part3:Exynos4412内核编译
- Linux内核移植 part3:Exynos4412 Linux Kernel移植
- linux pinctrl驱动
- 内核移植之Part3
- Linux内核中的GPIO驱动
- Linux驱动编译进内核-GPIO驱动
- Linux 内核设备驱动之GPIO驱动之GPIO API
- gpio子系统和pinctrl子系统(一)
- gpio子系统和pinctrl子系统(二)
- gpio子系统和pinctrl子系统(三)
- gpio子系统和pinctrl子系统(上)
- gpio子系统和pinctrl子系统(上)
- Linux 内核设备驱动之GPIO驱动之GPIO GPIO描述符到GPIO号
- Tensorflow学习笔记
- 归并排序
- LeetCode之453. Minimum Moves to Equal Array Elements
- JAVA多线程的内存可见性
- Android Studio 项目目录简介
- Linux内核移植 part3:pinctrl和gpio驱动
- Framework7学习总结
- 罗马数字转换成阿拉伯数字以及递归的简单运用
- Android中Okhttp进行get和post提交及数据请求的基本使用
- redis与spring整合
- My First Blog
- Android混淆总结篇(一)
- 通过Samba让Windows访问Linux文件
- Python ConfigParser 注意事项