#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
return 0;
}
如果针对GPX情况
int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
unsigned int off, unsigned int cfg)
{
void __iomem *reg = chip->base;
unsigned int shift = off * 2; // 每个GPX对应2位
u32 con;
if (s3c_gpio_is_cfg_special(cfg)) {
cfg &= 0xf;
if (cfg > 3)
return -EINVAL;
cfg <<= shift; // 将cfg的0,1两位左移offset
}
con = __raw_readl(reg); // 读对应的GPXCON值
con &= ~(0x3 << shift); // 将GPXCON(pin)的两bits请0
con |= cfg; // 设置config值
__raw_writel(con, reg); // 写入新的GPXCON
return 0;
}
return ret;
} // end s3c_gpio_cfgpin
这里涉及到了一个重要的数据结构,s3c_gpio_chip,此数据结构比较复杂,我贴出这个数据结构的结构图:
、
这个重要的数据结构中可以记录每个GPIO所需要的所有数据,后面会遇到的s3c24xx_gpios[]结构体就是该结构体的集合,描述了芯片中所有的GPIO端口,之后我们需要时时回头看看这个结构。
我们先来看s3c_gpiolib_getchip ,它实现了返回对应pin值的GPIO结构体首指针的功能
#include
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 NULL
return NULL;
chip = &s3c24xx_gpios[pin/32]; //根据偏移,计算出对应pin的GPIO结构体指针
return ((pin - chip->chip.base) < chip->chip.ngpio) chip : NULL;
// 这里验证,如果pin偏移超过了GPIO的个数,说明出错了,否则就返回该GPIO的结构体指针
}
回想以下之前s3c2410_gpio_cfgpin中,我们传入的参数是led_table[i]和 led_cfg_table[i],
/* 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
* 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)
S3C24XX_PA_UART相当于(0x15000000)
#define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
#define S3C_ADDR_BASE 0xF6000000
#ifndef __ASSEMBLY__
#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
#else
#define S3C_ADDR(x) (S3C_ADDR_BASE + (x))
#endif
0x15600000-15000000+F7000000 这里的S3C2410_GPACON应该怎么算?
.pm = __gpio_pm(&s3c_gpio_pm_1bit),
.config = &s3c24xx_gpiocfg_banka, // 设置GPIO的函数指针
static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
.set_config = s3c_gpio_setcfg_s3c24xx_a,
.get_config = s3c_gpio_getcfg_s3c24xx_a,
};
.chip = {
.base = S3C2410_GPA(0), //基地址,也是偏移量
.owner = THIS_MODULE,
.label = "GPIOA",
.ngpio = 24,
.direction_input = s3c24xx_gpiolib_banka_input,
.direction_output = s3c24xx_gpiolib_banka_output,
},
},
[1] = {
.base = S3C2410_GPBCON,
.pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPB(0),
.owner = THIS_MODULE,
.label = "GPIOB",
.ngpio = 16,
},
},
[2] = {
.base = S3C2410_GPCCON,
.pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPC(0),
.owner = THIS_MODULE,
.label = "GPIOC",
.ngpio = 16,
},
},
[3] = {
.base = S3C2410_GPDCON,
.pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_