1、GPIO 驱动相关笔记2011-03-27 22:54 529 人阅读 评论(2) 收藏 举报打算跟着友善之臂的mini2440 linux 移植开发指南来做个 LED 驱动,虽然 LED 的原理简单得不能再简单了,但是要把 kernel 中针对于s3c24*的 GPIO 的一些数据结构,还有函数搞清楚也不是那么轻松的事,所以本文主要简单地说明下 LED 驱动中的相关数据结构以及函数/宏的定义,并对驱动加以验证* 注意:在/arch/arm/mach-s3c2410/include/mach/gpio-fns.h 源代码中有如下说明:16/* These functions are in th
2、e to-be-removed category and it is strongly17 * encouraged not to use these in new code. They will be marked deprecated18 * very soon.19 *20 * Most of the functionality can be either replaced by the gpiocfg calls21 * for the s3c platform or by the generic GPIOlib API.22 *23 * As of 2.6.35-rc, these
3、will be removed, with the few drivers using them24 * either replaced or given a wrapper until the calls can be removed.25*/该头文件包括:static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)该函数直接使用linux/arch/arm/plat-s3c/gpio-config.c 中的int s3c_gpio_cfgpin(unsigned int pin, unsigned in
4、t config)即可 * 首先看一下设备初始化程序:85 /*86 * 设备初始化87 */88 static int _init dev_init(void)89 90 int ret;91 int i;92 for (i = 0; i 结束后,四个 LED 应该是全部都是发光96 状态97 s3c2410_gpio_setpin(led_tablei, 0);98 99 ret = misc_register( /注册设备100 printk (DEVICE_NAME“/tinitialized/n“); /打印初始化信息101 return ret;102 可以看到,这里涉及到两个函数
5、,分别是 s3c2410_gpio_cfgpin,s3c2410_gpio_setpin,这两个函数分别对四个 LED 进行配置,从函数名来看,cfgpin 对引脚寄存器状态进行配置,而 setpin 应该是对寄存器数据值进行配置,我们在分析函数之前先弄清楚传入的参数到底是什么。led_tablei28 /LED 对应的 GPIO 端口列表29 static unsigned long led_table = 30 S3C2410_GPB(5),31 S3C2410_GPB(6),32 S3C2410_GPB(7),33 S3C2410_GPB(8),34 ;这里 S3C2410_GPB 宏定
6、义在 mach/gpio-nrs.h 中 /* GPIO bank sizes */#define S3C2410_GPIO_A_NR (32)#define S3C2410_GPIO_B_NR (32)#define S3C2410_GPIO_C_NR (32)#define S3C2410_GPIO_D_NR (32)#define S3C2410_GPIO_E_NR (32)#define S3C2410_GPIO_F_NR (32)#define S3C2410_GPIO_G_NR (32)#define S3C2410_GPIO_H_NR (32)#define S3C2410_GP
7、IO_J_NR (32) /* technically 16. */#define S3C2410_GPIO_K_NR (32) /* technically 16. */#define S3C2410_GPIO_L_NR (32) /* technically 15. */#define S3C2410_GPIO_M_NR (32) /* technically 2. */#if CONFIG_S3C_GPIO_SPACE != 0#error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment#endif #define S3C2410_G
8、PIO_NEXT(_gpio) /(_gpio#_START) + (_gpio#_NR) + CONFIG_S3C_GPIO_SPACE + 0)/这里的 CONFIG_S3C_GPIO_SPAC 是内核配置选项,在.config 中可以找到,我的配置为:CONFIG_S3C_GPIO_SPACE = 0 enum s3c_gpio_number S3C2410_GPIO_A_START = 0,S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A),S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S
9、3C2410_GPIO_B),S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C),S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D),S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E),S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F),S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G),
10、S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H),S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J),S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K),S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_L),;#define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr) 因此,以 S3C2410_GPB
11、(5)为例,其宏展开为:S3C2410_GPIO_NEXT(S3C2410_GPIO_A) +5 = (S3C2410_GPIO_A_START + S3C2410_GPIO_A_NR + CONFIG_S3C_GPIO_SPACE + 0) + 5 =很显然, S3C2410_GPB(5)就是从 GPA 的首地址+GPA 个数+GPB 的 offset 就是当前 GPB 的 IO 偏移量,即0+32+5=37, 同理S3C2410_GPB(0) 相当于 3230 S3C2410_GPB(5) 相当于 3731 S3C2410_GPB(6) 相当于 3832 S3C2410_GPB(7) 相当
12、于 3933 S3C2410_GPB(8) 相当于 40* led_cfg_tablei36 /LED 对应端口将要输出的状态列表37 static unsigned int led_cfg_table = 38 S3C2410_GPIO_OUTPUT,39 S3C2410_GPIO_OUTPUT,40 S3C2410_GPIO_OUTPUT,41 S3C2410_GPIO_OUTPUT,42 ;S3C2410_GPIO_OUTPUT 定义在 mach/regs-gpio.h#define S3C2410_GPIO_LEAVE (0xFFFFFFFF) / 最后两位是设置,11 表示 RESE
13、RVE#define S3C2410_GPIO_INPUT (0xFFFFFFF0) /* not available on A */ / 最后两位是设置,00 表示INPUT#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1) / 最后两位是设置,01 表示OUTPUT#define S3C2410_GPIO_IRQ (0xFFFFFFF2) /* not available for all */#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* bank A = addr/cs/nand */#define S3C2410_GPI
14、O_SFN3 (0xFFFFFFF3) /* not available on A */* 根据前面的分析,s3c2410 传入了当前 GPIO 的偏移地址,以及 OUTPUT 状态现在我们深入前面的两个函数:定义在 linux/arch/arm/plat-s3c/gpio-config.cint s3c_gpio_cfgpin(unsigned int pin, unsigned int config)struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); /得到对应 GPIO 结构体首指针,里面包含了该GPIO 的各种参数unsigne
15、d long flags;int offset;int ret;if (!chip)return -EINVAL; / 没找到的话,返回 invalidoffset = pin - chip-chip.base; / 否则 offset 等于该 GPIO 引脚相对于 GPX(0)的偏移量,每个偏移1s3c_gpio_lock(chip, flags); / 自旋锁锁住该 GPIO,通过 chip 指针指向 lock,看下面的 define 和图ret = s3c_gpio_do_setcfg(chip, offset, config); /设置该 GPIO 状态寄存器的数值为 configs3
16、c_gpio_unlock(chip, flags); / 解锁/ 自旋锁操作/* locking wrappers to deal with multiple access to the same gpio bank */#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(/这里的 set_config 是一个函数指针,由后面的分析知道,如果针对 GPA,该函数指针指向s3c_gpio_setcfg_s3c24xx_a , 如果针对 GPX 应该是指向 s3c_gpio_setcfg_s3c24xx但发现,如果是其他 GPX,根本没有定义 se
17、t_config! (这个问题已经解决,见后文 s3c24xx_gpiolib_init 函数,事实上,其余的 config 的确指向s3c_gpio_do_setcfg 函数)struct s3c_gpio_cfg s3c24xx_gpiocfg_default = .set_config = s3c_gpio_setcfg_s3c24xx,.get_config = s3c_gpio_getcfg_s3c24xx,;int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, unsigned int off, unsigned int
18、 cfg)void _iomem *reg = chip-base; / GPXCON 的物理基地址unsigned int shift = off; / 每个 GPA 对应一位u32 con;if (s3c_gpio_is_cfg_special(cfg) /OUTPUT 状态是否为(0xfffffffX),是,返回 1cfg / cfg = 0xX/* Map output to 0, and SFN2 to 1 */ 本实验不会运行到这cfg -= 1;if (cfg 1)return -EINVAL;cfg base;unsigned int shift = off * 2; / 每个
19、 GPX 对应 2 位u32 con;if (s3c_gpio_is_cfg_special(cfg) cfg if (cfg 3)return -EINVAL;cfg static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)struct s3c_gpio_chip *chip;if (pin S3C_GPIO_END) /如果超过 GPJ(32)就 return NULLreturn NULL;chip = /根据偏移,计算出对应 pin 的 GPIO 结构体指针return (pin - chip-c
20、hip.base) chip.ngpio) ? chip : NULL;/ 这里验证,如果 pin 偏移超过了 GPIO 的个数,说明出错了,否则就返回该 GPIO 的结构体指针回想以下之前 s3c2410_gpio_cfgpin 中,我们传入的参数是 led_tablei和 led_cfg_tablei,/* GPIO sizes for various SoCs:* 2442* 2410 2412 2440 2443 2416* - - - - -* A 23 22 25 16 25* B 11 11 11 11 9* C 16 15 16 16 16* D 16 16 16 16 16*
21、 E 16 16 16 16 16* F 8 8 8 8 8* G16 16 16 16 8* H 11 11 9 15 15* J - - 13 16 -* K - - - - 16* L - - - 15 7* M - - - 2 2*/ struct s3c_gpio_chip s3c24xx_gpios = 0 = .base = S3C2410_GPACON, / datasheet 上地址为 0x56000000/#define S3C2410_GPACON S3C2410_GPIOREG(0x00)#define S3C2410_GPIOREG(x) (x) + S3C24XX_VA_GPIO) #define S3C24XX_VA_GPIO (S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)S3C24XX_PA_GPIO 相当于(0x15600000)
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。