拿到新开发板代码分析入口和gpiolib库

来源:互联网 发布:阿里云 按流量收费 编辑:程序博客网 时间:2024/05/01 08:17
☆ 程序分析入口
   ==>拿个一个新的开发板,一般分析的入口的文件路径(x210为例,分析makefile得出) /kernel/arch/arm/mach-s5pv210/mach-x210.c,
   为进一步确定可先编译一下看看这个文件是不是被编译称为.o文件
   ==>分析mach-x210.c从文件最下面的MACHINE_START宏处入手
#ifdef CONFIG_MACH_SMDKC110
MACHINE_START(SMDKC110, "SMDKC110")
#elif CONFIG_MACH_SMDKV210
MACHINE_START(SMDKV210, "SMDKV210")
#endif
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
//.fixup = smdkv210_fixup,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
.timer = &s5p_systimer,
MACHINE_END
展开后得到
static const struct machine_desc __mach_desc_SMDKV210 __used
__attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_SMDKV210,
.name = SMDKV210,
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
.timer = &s5p_systimer,

};
内核会根据相应的配置找到这个结构体并调用其中的函数,这个下一节来分析,每个新的开发板
只需要提供相应的函数即可


☆  gpiolib的创建是x210开发板移植人员做的,其调用流程为
    __mach_desc_SMDKV210.map_io
smdkc110_map_io
s5pv210_gpiolib_init();
☆  先分析s5pv210的GPIOLIB设计到的结构体:
==>struct s3c_gpio_chip {
struct gpio_chipchip;
struct s3c_gpio_cfg*config;
struct s3c_gpio_pm*pm;
void __iomem *base;   //这个base会被赋值为真正的gpio虚拟地址
int eint_offset;
spinlock_t lock;
#ifdef CONFIG_PM
u32 pm_save[7];
#endif
};
==>struct gpio_chip {
const char *label;
struct device *dev;
struct module *owner;
.....一系列函数......
int base;         //这个base要和上面的base区别开,base是基编号
u16 ngpio;
const char *const *names;
unsigned can_sleep:1;
unsigned exported:1;
};
    ==>struct gpio_desc {
struct gpio_chip*chip;
unsigned long flags;
#ifdef CONFIG_DEBUG_FS
const char *label;
#endif
};
☆  分析s5pv210_gpiolib_init()函数:
    ==> 结构体数组s5pv210_gpio_4bit描述了 
.base这里如果某GPIO特殊也可以在这里赋值,不然后面会统一赋值
.chip.base  基地址,属于一个相对地址
.chip.ngpio 代表每个GPIO(A/B/C/D......)有效的端口数量
.chip.label 名称
.chip.to_irq 对应的中断号
==> 如果.base为NULL,调用S5PV210_BANK_BASE(i) 赋值gpio的虚拟地址(注意和.chip.base区分)
==> samsung_gpiolib_add_4bit_chips 根据s3c_gpio_chip结构体的成员 挨个调用下面两个函数
■samsung_gpiolib_add_4bit(chip); 里指明了部分GPIO的部分控制操作(不想用默认的就在这里设置)
■s3c_gpiolib_add(chip); --先是指明了GPIO的控制操作(如果amsung_gpiolib_add_4bit没有定义这里就赋值为默认值,
--然后调用gpiochip_add把gpio_chip(也就是s3c_gpio_chip里的chip)和gpio_desc关联在一起

==>gpiochip_add函数把gpio_desc结构体数组 和 gpio_chip结构体数组的关联主要是下面的for循环
  base = chip->base;
  for (id = base; id < base + chip->ngpio; id++) {
gpio_desc[id].chip = chip;
gpio_desc[id].flags = !chip->direction_input
? (1 << FLAG_IS_OUT)
: 0;
}
执行完之后,gpio_desc[0]~[7]的chip就是  s3c_gpio_chip的GPIOA
gpio_desc[9]~[12]的chip就是 s3c_gpio_chip的GPIOB
.............
以后通过gpio_desc[i] 就能找到GPIOX的y口



==> 其他地方调用gpio_request就会去gpio_desc获得对应的 gpio_chip结构体然后将其做个标志标志已被申请一次
  举个例子:gpio_request(S5PV210_GPH0(6), "GPH06");
  
  S5PV210_GPH0(6) --> S5PV210_GPIO_H0_START+6 -->  S5PV210_GPIO_NEXT(S5PV210_GPIO_G3) + 6 -->
  S5PV210_GPIO_G3_START + S5PV210_GPIO_G3_NR + CONFIG_S3C_GPIO_SPACE + 1 -->
  S5PV210_GPIO_G3_START + 7 + CONFIG_S3C_GPIO_SPACE + 1
  然后把S5PV210_GPIO_G3_START 宏继续展开可以一直得到 CONFIG_S3C_GPIO_SPACE + 1 + 某一个整数
  这个意思就是gpiolib把所有的gpio进行了一个编号,S5PV210_GPA0(0)就是0,S5PV210_GPA0(1)就是1
  而CONFIG_S3C_GPIO_SPACE 宏就是定了GPIOA,GPIOB,GPIOC编号的空白距离,例如 GPIOA8和 GPIOB0 
  的编号差CONFIG_S3C_GPIO_SPACE + 1

==> 其他地方调用gpio_direction_output就会去gpio_desc获得对应的 gpio_chip结构体,
然后gpio -= chip->base;gpio值就是相对于基址的偏移值
再调用direction_output(chip, gpio, value);
        也就是前面赋值的samsung_gpiolib_4bit_output(struct gpio_chip *chip,unsigned int offset, int value)

==>其他函数调用类似,经常被调用的接口有
  gpio_request(unsigned gpio, const char *label)
  gpio_free(unsigned gpio)
  gpio_direction_input(unsigned gpio)
  gpio_direction_output(unsigned gpio, int value)
  __gpio_get_value(unsigned gpio)
  __gpio_set_value(unsigned gpio, int value)
  __gpio_to_irq(unsigned gpio)
==> 重点说下__gpio_to_irq(unsigned gpio)
  gpio_to_irq()返回的中断编号可以传给request_irq()和free_irq()。 
  
关于中断下一节来说明



0 0
原创粉丝点击