歡迎轉載,轉載時需保留做者信息,謝謝。linux
郵箱:tangzhongp@163.comios
博客園地址:http://www.cnblogs.com/embedded-tzp數組
Csdn博客地址:http://blog.csdn.net/xiayulewa數據結構
是平時本身word離線作筆記的,當發在網上才發現寫的太宏觀,不怎麼容易看懂,從此作筆記會注意多貼代碼。函數
如上所述:spa
#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART).net
由於UART的物理地址和虛擬地址映射肯定了,因此其它寄存器如GPIO映射關係也能夠肯定了orm
static struct map_desc s3c_iodesc[] __initdata = {對象
IODESC_ENT(GPIO),blog
IODESC_ENT(IRQ),
IODESC_ENT(MEMCTRL),
IODESC_ENT(UART)
};
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT))
#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT)
#define PAGE_SHIFT 12
根據上述定義:gpio虛擬地址分配(S3C24XX_VA_GPIO)流程:MACHINE_START中mini2440_map_io→s3c24xx_init_io →iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
上圖能夠看出,根據gpio_desc數組,還能夠經過container_of還原出struct samsung_gpio_chip, 該結構體裏面的base成員即爲虛擬地址,在s3c24xx_gpiolib_add_chips中被賦值。最右邊的.chip成員還有struct gpio_desc *desc;成員,其被賦值爲chip->desc = &gpio_desc[chip->base]; 所以,經過gpio號能夠索引到數組gpio_desc的成員,而後索引到.chip,進而索引全部gpio對象。
主要結構體:Gpiolib.c (src\drivers\gpio): struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; // 每個gpio管腳對應一個gpio_desc,gpio_desc的索引爲linux虛擬的。
gpio_desc初始化:Gpio-samsung.c (src\drivers\gpio):core_initcall(samsung_gpiolib_init);(見MACHINE_START處理)
→ s3c24xx_gpiolib_add_chips(s3c24xx_gpios, ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO)→ gpiochip_add, 因此最後gpio_desc內容與s3c24xx_gpios相關,同時在該函數中有chip->base = base + ((i) * 0x10); 對base賦值爲虛擬地址,根據第一節gpio的虛擬地址和物理地址創建的映射,即可訪問到物理地址。
struct samsung_gpio_chip s3c24xx_gpios[] = {
#ifdef CONFIG_PLAT_S3C24XX
{
.config = &s3c24xx_gpiocfg_banka,
.chip = {
.base = S3C2410_GPA(0),
.owner = THIS_MODULE,
.label = "GPIOA",
.ngpio = 24,
.direction_input = s3c24xx_gpiolib_banka_input,
.direction_output = s3c24xx_gpiolib_banka_output,
},
}, {
.chip = {
.base = S3C2410_GPB(0),
.owner = THIS_MODULE,
.label = "GPIOB",
.ngpio = 16,
},
},
.........................................
};
以gpio_direction_input爲例說明 gpio驅動:
gpio_direction_input(unsigned gpio) → gpiod_direction_input(gpio_to_desc(gpio)); → chip = desc->chip; chip->direction_input(chip, offset); 在上述gpio_desc初始化或者s3c24xx_gpios結構體變量定義中,該函數被賦值,以samsung_gpiolib_2bit_input爲例,最終執行
struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
void __iomem *base = ourchip->base; // base 爲該gpio寄存器的虛擬地址。
....
con = __raw_readl(base + 0x00); //操縱實際寄存器
....
chip->direction_input,direction_output, get, set在s3c24xx_gpiolib_add_chips中被賦值。
gpio_direction_output→ Chip->direction_output 進行實際寄存器操縱。
gpio_request
gpio_free
gpio_get_direction
gpio_direction_input
gpio_direction_output
gpio_set_value
gpio_get_value
gpio_set_debounce
gpio_to_irq
gpiolib_dbg_show
根據上述討論,經過gpio號能夠索引到gpio全部相關對象(數據和函數),如S3C2410_GPA(0)
gpio_request(S3C2410_GPA(0), "KEY_UP");
gpio_direction_input(S3C2410_GPA(0)); /*2.配置爲輸入*/