至此,我们可以比较清晰看到GPIO被静态映射的过程,由于我们在前面的静态映射中已经做好了GPIO的映射,也就是我们写GPIO相关驱动的时候可以如下配置引脚的原因:
s3c2410_gpio_cfgpin(xxx,xxx);
其实,s3c2410_gpio_cfgpin定义如下:
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB) {
mask = 1 << S3C2410_GPIO_OFFSET(pin);
} else {
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
}
local_irq_save(flags);
con = __raw_readl(base + 0x00);
con &= ~mask;
con |= function;
__raw_writel(con, base + 0x00);
local_irq_restore(flags);
}
其中,比较关键的一个地方:
void __iomem *base = S3C2410_GPIO_BASE(pin);
这一行中,S3C2410_GPIO_BASE定义如下:
#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
至此,GPIO的静态映射就看得很明白了。
下面来看其他外设的静态映射:
在s3c24xx_init_io()函数中,除了iotable_init()以为,还会在最后调用,
(CPU->map_io)(mach_desc, size);
而CPU的这个map_io在arch/arm/mach-s3c2410/cpu.c里面定义如下:
static struct cpu_table cpu_ids[] __initdata = {
{
.idcode = 0x32410000,
.idmask = 0xffffffff,
.map_io = s3c2410_map_io,
.init_clocks = s3c2410_init_clocks,
.init_uarts = s3c2410_init_uarts,
.init = s3c2410_init,
.name = name_s3c2410
},
...
}
再查看s3c2410_map_io(),函数代码如下:
void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
{
/* register our io-tables */
iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
iotable_init(mach_desc, mach_size);
}
接下来看结构s3c2410_iodesc [arch/arm/mach-s3c2410/s3c2410.c],代码如下,
/* Initial IO mappings */
static struct map_desc s3c2410_iodesc[] __initdata = {
IODESC_ENT(USBHOST),
IODESC_ENT(USBDEV),
IODESC_ENT(CLKPWR),
IODESC_ENT(LCD),
IODESC_ENT(TIMER),
IODESC_ENT(ADC),
IODESC_ENT(WATCHDOG),
};
赫然发现IODESC_ENT(TIMER)这一行,结合之前GPIO的类似分析,IODESC_ENT宏如下:
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
至此,TIMER, USBHOST,USBDEV,lcd,adc,watchdog等的静态映射都看得很明白了。
[1] [2] [3]
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。