参考文件:arch/arm/mach-s5pv210/include/mach/gpio.h , /drivers/gpio/gpiolib.c , arch/arm/plat-s3c/include/plat/gpio-core.h , arch/arm/mach-s5pv210/gpio.c .

另外, documentation/gpio.txt 文档是重要参考!

通常, GPIO分成若干个group, 每个group包含几个io port. 访问某个port时要指明哪个group哪个port, 不方便. kernel处理方法是把所有io port整理成一个线性的空间, 即一组线性的数值, 每个io port对应于一个数值.  (注意: 这里port指1个pin哦)

一,每组GPIO的数目:

#define S5PV210_GPIO_A0_NR (8)
 #define S5PV210_GPIO_A1_NR (4)
 #define S5PV210_GPIO_B_NR (8)

......
 #define S5PV210_GPIO_ETC2_NR (8)
 #define S5PV210_GPIO_ETC4_NR (6)

二,每组GPIO的起始号码
 #define S5PV210_GPIO_NEXT(__gpio) /
  ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
        用##粘贴符号来运算的,以A组的0起始,依次加每组的GPIO个数.

如:S5PV210_GPIO_A1_START=S5PV210_GPIO_NEXT(S5PV210_GPIO_A0)=

S5PV210_GPIO_A0_START+S5PV210_GPIO_A0_NR+CONFIG_S3C_GPIO_SPACE + 1

全部的号码看这里:

enum s5p_gpio_number {
  S5PV210_GPIO_A0_START =0,
  S5PV210_GPIO_A1_START =S5PV210_GPIO_NEXT(S5PV210_GPIO_A0), /*0+8+1 = 9*/
  S5PV210_GPIO_B_START  = S5PV210_GPIO_NEXT(S5PV210_GPIO_A1), /*9+4+1 = 14*/

......

S5PV210_GPIO_ETC2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_ETC1),/*438+8+1 = 447*/
  S5PV210_GPIO_ETC4_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_ETC2),/*447+8+1 = 456*/
  /*总数是456+6+1 = 463*/
 };

三,单个GPIO脚的号码
     以单组的起始号
 #define S5PV210_GPA0(_nr) (S5PV210_GPIO_A0_START + (_nr))
 #define S5PV210_GPA1(_nr) (S5PV210_GPIO_A1_START + (_nr))
 #define S5PV210_GPB(_nr) (S5PV210_GPIO_B_START + (_nr))

......
 #define S5PV210_ETC2(_nr) (S5PV210_GPIO_ETC2_START + (_nr))
 #define S5PV210_ETC4(_nr) (S5PV210_GPIO_ETC4_START + (_nr))

四,判断GPIO是否有效

比如:if (gpio_is_valid(S5PV210_GPB(0)))
      static inline int gpio_is_valid(int number)    
      {                                              
            return ((unsigned)number) < ARCH_NR_GPIOS;  /*好象现在改成直接返回0了*/ 
      } 
      这是因为定义了:

#define ARCH_NR_GPIOS  (S5PV210_ETC4(S5PV210_GPIO_ETC4_NR) + CONFIG_SAMSUNG_GPIO_EXTRA + 1)

同样类似的范围定义有:S5PV210_GPIO_END ,S3C_GPIO_END.
   
五,申请分配GPIO -- 判断GPIO是否被占用, 若可用则占用它.
      比如:if(gpio_request(S5PV210_GPH0(2), "GPH0")),通过查看该port保存的记录标志是否为NULL来判断。gpio_desc[ARCH_NR_GPIOS]数值记录了每个io pin的情况.

注意: kernel代码的一个坏现象: 变量名与类型名经常取了相同的名字! 让人容易混淆.  比如, gpio_desc既是结构体名,又是变量名.

struct gpio_desc {
     struct gpio_chip *chip;    //该pin属于哪个gpio group? 此group的gpio_chip指针.
     unsigned long  flags;    //该pin各个状态之bit标志, 比如是否FLAG_REQUESTED, 等等.
     const char  *label;
};
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];

gpiochip_is_requested()仅判断port是否被占用?

六,释放GPIO
     比如:gpio_free(S5PV210_GPH3(15));就是把对应port的控制标志FLAG_REQUESTED清掉,之后可以再被request申请使用。

七,配置GPIO输入/输出方向
      比如:gpio_direction_output(S5PV210_GPH3(0), 1);  gpio_direction_input .

八,输出output电平/读取input电平 -- gpio基本使用
     比如输出一个高电平:gpio_set_value(S5PV210_GPH3(1), 1);

或者是得到输入的值:gpio_get_value(S5PV210_GPH3(8))

九,配置GPIO用途 -- 除in/out之外的其它功能
    由于GPIO多复用,所以不管是把它当作GPIO使用时,还是当作中断亦或通讯口,需要配置它的用途。

比如:s3c_gpio_cfgpin(S5PV210_GPB(0), 0x2); 设置S5PV210_GPB(0)口的function为2,function详情请参考芯片规格书。

API接口: s3c_gpio_cfgpin /s3c_gpio_setpull / s3c_gpio_setpin.  最终指向如下:

static struct s3c_gpio_cfg gpio_cfg = {
 .cfg_eint = 0xf,
 .set_config =>  .get_pull = s3c_gpio_getpull_updown,
 .set_pin    = s3c_gpio_setpin_updown
};

疑问: s3c_gpio_setpin功能与gpio_set_value重复, 感觉没必要!???

疑问: 还没有设置port驱动电流GPxDRV的函数???

十,上下拉

有的GPIO口可以内部配置成上拉或者下拉,这样就不需要外部再接电阻连线。配置成上拉时,驱动能力更强。配置上下拉对外部接口来说呈现的只是一种默认的电平,其本身可以对外输出高低由软件控制,就像I2C。
      比如:s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_DOWN);

十一,配置成外中断
   s3c_gpio_cfgpin(S5PV210_GPH1(5), S3C_GPIO_SFN(0xf));    //GPxCON 4-bit为0xF一般对应于INT功能. GPH1(5)对应EXT_INT[13].
   set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_BOTH);
   具体应用的话还需要用request_irq注册对应的中断处理函数。

内核gpio代码的数据结构:

** gpio_chip : 基本数据结构(gpiolib). A gpio_chip can help platforms abstract various sources of GPIOs so they can all be accessed through a common programing interface. Example sources would be SOC controllers, FPGAs, multifunction chips, dedicated GPIO expanders, and so on.

** s3c_gpio_chip : wrapper for specific implementation of gpio. This wrapper provides the necessary information for the Samsung specific gpios being registered with gpiolib.

* @chip: The chip structure to be exported via gpiolib.
     * @base: The base pointer to the gpio configuration registers.
     * @config: special function and pull-resistor control information.
     * @pm_save: Save information for suspend/resume support.

** GPIO implemention framework (OPTIONAL) -- gpiolib: 上述gpio_xxxx函数是对外的基本API函数.底层实现是s3c_gpiolib_xxxx : s3c_gpiolib_input, s3c_gpiolib_output, s3c_gpiolib_get, s3c_gpiolib_set.  其中s3c_gpiolib_input / s3c_gpiolib_output 是对应于s3c24xx芯片2-bits-per-port的GPxCON寄存器.  而PC110的GPxCON是4-bits-per-port, 故用samsung_gpiolib_4bit_input / samsung_gpiolib_4bit_output 实现.

** s3c_gpio_cfg : 除in/out之外其它功能的config函数, 比如: set_config, set_pullupdown. API接口为s3c_gpio_xxxx.

GPIO驱动代码流程

** core_initcall(s5pv210_gpiolib_init) 内核初始化call.

** s5pv210_gpiolib_init -> samsung_gpiolib_add_4bit & s3c_gpiolib_add 注册所有port的数据结构并关联API接口函数.

** 把API接口函数export出去. 比如EXPORT_SYMBOL_GPL(gpio_request), 等等.

**** S5PC110 GPIO 及特性 ****

S5PC110 includes 237 multi-functional input/ output port pins and 142 memory port pins. There are 34 general port groups and 2 memory port groups as listed below:
 GPA0: 8 in/out port - 2xUART with flow control
 GPA1: 4 in/out port - 2xUART without flow control or 1xUART with flow control
 GPB: 8 in/out port - 2x SPI    --Fast I/O (3.3V I/O)
 GPC0: 5 in/out port - I2S, PCM, AC97
 GPC1: 5 in/out port - I2S, SPDIF, LCD_FRM
 GPD0: 4 in/out port - PWM
 GPD1: 6 in/out port - 3xI2C, PWM
 GPE0,1: 13 in/out port - Camera I/F
 GPF0,1,2,3: 30 in/out port - LCD I/F
 GPG0,1,2,3: 28 in/out port - 4xMMC channel (Channel 0 and 2 support 4-bit and 8-bit mode, but channel 1, and channel 3 support only 4-bit mode)   --Fast I/O (3.3V I/O)
 GPH0,1,2,3: 32 in/out port - Key pad, External Wake-up (up-to 32-bit). (GPH* groups are inAliveregion)
 GPI: Low Power I2S, PCM (in/out port is not used), PDN configuration for power down is controlled by AUDIO_SS PDN Register.
 GPJ0,1,2,3,4: 35 in/out port - Modem IF, CAMIF, CFCON, KEYPAD, SROM ADDR[22:16]
 MP0_1,2,3: 20 in/out port - Control signals of EBI (SROM, NF, OneNAND)
 MP0_4,5,6,7: 32 in/out memory port - EBI (For more information about EBI configuration, refer to Chapter 5, and 6)
 MP1_0~8: 71 DRAM1 ports (in/out port is not used)    --DRAM I/O (1.8V IO)
 MP2_0~8: 71 DRAM2 ports (in/out port is not used)    --DRAM I/O (1.8V IO)
 ETC0, ETC1, ETC2, ETC4: 28 in/out ETC ports - JTAG, Operating Mode, RESET, CLOCK (ETC3 is reserved)

** GPIO分成3个type: Normal I/O, Fast I/O, DRAM I/O.

** GPIO分成2个part: alive-part , off-part. 区别在于sleep mode时是否有power. alive-part的port可作wake -up信号.

** GPIO有多种I/O Control Type.

** GPIO有多种Pad Type.

** Each Port Group has 2 types of control registers. One works in normal mode, and the other works in power down mode (STOP, DEEP-STOP, SLEEP mode). Normal registers (For example, GPA0CON, GPA0DAT, GPA0PUD, and GPA0DRV) are the former, and power down registers (For example, GPA0CONPDN, and GPA0PUDPDN) are the latter.

gpio寄存器基本都是GPxCON, GPxDAT, GPxPUD, GPxDRV.  另外, power down mode下对应的GPxCONPDN, GPxPUDPDN.  另外, 中断对应的GPx_INT_CON, GPx_INT_FLTCONn, GPx_INT_MASK, GPx_INT_PEND,INT_PRIORITY.  另外, alive part对应的EXT_INT_x_CON, EXT_INT_x_FLTCON, EXT_INT_x_MASK, EXT_INT_x_PEND.  最后, powd down mode的PDNEN.

** GPIO Interrupt : In interrupt function, it is important to understand thefilteroperation. S5PC110 uses two types of filters to detect interrupt :delay filteranddigital filter. 改善稳定性. When you use interrupt function, set either delay or digital filter enabled in order to detect interrupt. GPIO Interrupt cannot use for wake-up source. For wake-up interrupt source, you can use External interrupt.

** External Interrupt : External Interrupt consists of 32 bits. EXT_INT[31:0] are used for wake-up source in Power down mode. In idle mode, all interrupts can be wake-up source; the other groups of external interrupts also can be the wake-up sources.  EXT_INT[0] can be used PS_HOLD_CONTROL.

详解s3c_gpio_cfgpin:

例子:

目的:设置GPH3_4口为KP_ROW[3]功能。

实现:s3c_gpio_cfgpin(S5PV210_GPH3(1), S3C_GPIO_SFN(3))

分析:

S5PV210_GPH3(1) = S5PV210_GPIO_H3_START + 1 = 155+1 = 156 ;/*其实不用算出来是多少,对应名字就好*/

S3C_GPIO_SFN(3)= 0xfffffff3;

所以执行的是:s3c_gpio_cfgpin(156,0xfffffff3)

/*arch/arm/plat-samsung/gpio-config.c*/

int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
{
 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin)  ;

/****************************************************************************************************

s3c_gpiolib_getchip也就是去查找s3c_gpios[chip] ,

s3c_gpios这个数组的来源:

s5pv210_gpiolib_init时,执行samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit,ARRAY_SIZE(s5pv210_gpio_4bit));

其中执行了s3c_gpiolib_track(s5pv210_gpio_4bit),在这里将s5pv210_gpio_4bit数组的内容,按照每个对应ngpio的大小,重新分配给s3c_gpios。

===>这个方法不好,s3c_gpios依赖于CONFIG_S3C_GPIO_TRACK宏, 若未定义则麻烦!???
所以s3c_gpios相当于s5pv210_gpio_4bit,在这个数组里找到S5PV210_GPH3(0)  对应的部分:

.base = S5PV210_GPH3_BASE,
  .config = &gpio_cfg_noint,
  .chip = {
   .base = S5PV210_GPH3(0),
   .ngpio = S5PV210_GPIO_H3_NR,
   .label = "GPH3",

****************************************************************************************************/
 unsigned long flags;
 int offset;
 int ret;

if (!chip)
  return -EINVAL;

offset = pin - chip->chip.base; /*S5PV210_GPH3(1)-S5PV210_GPH3(0)= 1*/

local_irq_save(flags);
 ret = s3c_gpio_do_setcfg(chip, offset, config);/*(chip, 1, 0xfffffff3)*/

/****************************************************************************************************

(chip->config->set_config)(chip, off, config);

找到对应的是arch/arm/mach-s5pv210/gpio.c

static struct s3c_gpio_cfg gpio_cfg = {
 .cfg_eint = 0xf,
 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
 .set_pull = s3c_gpio_setpull_updown,
 .get_pull = s3c_gpio_getpull_updown,
 .set_pin    = s3c_gpio_setpin_updown
};

所以:

(chip->config->set_config)(chip, off, config);

就是

s3c_gpio_setcfg_s3c64xx_4bit(chip, off, config); /*(chip, 1, 0xfffffff3)*/

看文件arch/arm/plat-samsung/gpio-config.c

int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
     unsigned int off, unsigned int cfg)

{
 void __iomem *reg = chip->base;/*reg的地址为S5PV210_GPH3_BASE = 0xE0200C60*/
 unsigned int shift = (off & 7) * 4; /*(1&7)*4 = 4*/
 u32 con;

if (off < 8 && chip->chip.ngpio > 8)/*由于当前base寄存器只可能设置8个GPIO,所以如果ngpio大于8则当前寄存器减4*/
  reg -= 4;

if (s3c_gpio_is_cfg_special(cfg)) {/*看一下cfg有没有超出范围*/ ==> 此check没实际意义???
  cfg &= 0xf;
  cfg <<= shift;      /*cfg = 3<<4 = 0x30*/
 }

con = __raw_readl(reg);
 con &= ~(0xf << shift);  /*与上0xffffff0f*/
 con |= cfg;       /*或上0x30*/
 __raw_writel(con, reg);

return 0;
}

此处执行的结果是:

将0xE0200C60寄存器的[7..4]赋值3,

也即设置GPH3_4口为KP_ROW[3]功能。

****************************************************************************************************/

local_irq_restore(flags);

return ret;

原文链接:http://blog.csdn.net/bmbm546/article/details/6928003

GPIO驱动分析 GPIO使用方法--S5PC110和S5PC210相关推荐

  1. Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

    文章目录 全系列传送门 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找 2. 在设备树配置文件中添加设备节点定义以及其引脚定义 3. 修改设备树文件添加配置 4. d ...

  2. openharmony GPIO 驱动开发

    openharmony GPIO 驱动开发 GPIO 基础知识 GPIO 基础知识--概念 GPIO 基础知识--IO 复用 GPIO 基础知识--GPIO 分组和编号 GPIO 基础知识--用户态测 ...

  3. 树莓派linux下gpio驱动,树莓派官方自带gpio驱动bcm2708_gpio.c原理分析 linux gpio架构 gpio子系统...

    对树莓派gpio的操作有好多方法,比如mmap映射cpu内存,编写内核驱动模块等.这里推荐一篇文章外链网址已屏蔽 其实树莓派官方使用linux内核gpio驱动框架内置了一个驱动,让我们可以直接使用标准 ...

  4. 【嵌入式开发】LED 驱动 ( LED发光二极管原理 | 底板原理图分析 | 核心板原理图分析 | GPIO | 裸板程序烧写流程 )

    文章目录 开发板 的 LED 灯 作用 : 嵌入式软件的开发初期, 如 开发 BootLoader 代码 或者 Kernel 内核代码 过程中, 有效的调试方法有限, 此时通常使用 开发板上的 LED ...

  5. 我的内核学习笔记10:Intel GPIO驱动源码分析

    本文对Intel e3800的GPIO驱动源码进行分析. 一.概述 1.1 内核配置 Intel e3800的GPIO在Linux内核中使用的驱动名为gpio_ich(为了行文方便,将对应的设备称为& ...

  6. 树莓派GPIO驱动原理

    1.前言 最近认真学习了树莓派,从浅到深认真分析了wiringPi实现代码,借助树莓派学习linux收获颇丰.深入学习linux一段时间后发现它非常有魅力,一个简单的IO口输出操作尽有那么多的&quo ...

  7. 高通驱动实现 GPIO 中断上报键值

    高通驱动实现 GPIO 中断上报键值 一. 确认keycode值,同步修改上层键值映射表 Tips 1: 选择一个好的键值的好处 Tips 2: 如何确认驱动代是否ok 二. 驱动代码编写 三.代码调 ...

  8. Davinci DM6446开发攻略——LINUX GPIO驱动源码移植

    一.             DM6446 GPIO的介绍 说到LINUX 驱动移植,没有移植过的朋友,或刚刚进入LINUX领域的朋友,最好去看看<LINUX 设备驱动程序>第三版,有个理 ...

  9. android gpio驱动实例,Android/Linux 驱动层对GPIO口的操作方法和相关代码

    实例: unsigned int otg_en_pin=952; ----->高通的gpio的基础值为902,这里我们时间的gpio为50,即这里定义值是要设置为952. //young.yan ...

最新文章

  1. 《JavaScript高级程序设计》读书笔记(十一):内置对象Global
  2. HashMap与ConcurrentHashMap的区别
  3. ffmpeg将sdp转发_ffmpeg常用命令
  4. 基于Canvas和HTML+CSS3构建JavaScript弹幕库
  5. 2020年mac上最值得使用的五大录屏软件
  6. 回撤率 python 平台_python夏普率、最大回撤计算
  7. SharePoint 使用 CMOS 上传、下载、删除文件,新增文件夹
  8. # 慢东周记(第 1 期):【本周话题】真正的投资者应该是寻找到长期、稳定、持续的正期望收益机会且重仓
  9. 时尚亲民的发烧耳机,无需焊接的模块化设计,小蝙蝠M0体验
  10. 简述计算机领域最高国际奖是什么奖,清华大学团队蝉联高性能计算应用领域国际最高奖...
  11. part3_模块五作业
  12. 高性能PC机与服务器的真正区别
  13. 学习商业汇票 ---- 银承汇票业务
  14. A7139射频模块wor配置解析
  15. python datetime strftime_datetime.strftime时间输出转换
  16. Java判断Long类型相等问题
  17. 六个SEO关键词分析工具
  18. C语言学生信息管理系统(结构体数组,文件)
  19. kindeditor上传图片后自动缩放尺寸
  20. Oracle删除链接用户

热门文章

  1. 训练实录 | 2021牛客暑期多校训练营2
  2. 20210326-ds18b20负温度理解
  3. 手把手教你如何免ROOT卸载Flyme7系统自带APP
  4. 2022化工自动化控制仪表考试练习题模拟考试平台操作
  5. mysql8设置用户权限报错You have an error in your SQL syntax;right syntax to use near ‘IDENTIFIED BY
  6. oracle数据库实例的账号密码,正确修改Oracle数据库的默认账号密码的方法
  7. Onedrive android 乱码,最后一个盘符总是出现很多乱码文件夹
  8. QT web 开发 -- 笔记
  9. 31岁做副市长,面试了4000多顶尖CEO,她总结了一套职场好运真经|72问
  10. Ericsson-LG 5G无线测试下载速率达26.3Gbps