字符设备驱动(1)代码分析---之gpio_to_irq

时间:2022-04-15 17:55:04
 
 
/**************************************************************
gpio_to_irq(S5PV210_GPH2(0))
**************************************************************/
 4 #define gpio_to_irq      __gpio_to_irq
 5 
 6 int __gpio_to_irq(unsigned gpio)
 7 {
 8     struct gpio_chip    *chip;
 9     chip = gpio_to_chip(S5PV210_GPH2(0));
static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
{
    return gpio_desc[S5PV210_GPH2(0)].chip; 
    //参考gpio-s5pv210.c中
    //samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips)函数
    //gpio_desc[id].chip = chip;
}
10     return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
11     //s5pv210_gpio_4bit
12 }
int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
{
//获得gpio_chip结构体所在的父结构体s3c_gpio_chip的指针 
struct s3c_gpio_chip *s3c_chip = container_of(chip,struct s3c_gpio_chip, chip);
//获取虚拟映射机制中定义的终端号
return s3c_chip->irq_base + offset;

字符设备驱动(1)代码分析---之gpio_to_irq字符设备驱动(1)代码分析---之gpio_to_irq
#define IRQ_EINT(x)        ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
                    : ((x) - 16 + S5P_EINT_BASE2))
#define S5P_EINT_BASE2        (IRQ_VIC_END + 1)
#define IRQ_VIC_END        S5P_IRQ_VIC3(31)
#define S5P_IRQ_VIC3(x)        (S5P_VIC3_BASE + (x))
#define S5P_VIC3_BASE        S5P_IRQ(96)
#define S5P_IRQ(x)        ((x) + S5P_IRQ_OFFSET)
#define S5P_IRQ_OFFSET        (32)

#define S5P_EINT_BASE1        (S5P_IRQ_VIC0(0))
#define S5P_IRQ_VIC0(x)        (S5P_VIC0_BASE + (x))
#define S5P_VIC0_BASE        S5P_IRQ(0)
IRQ_EINT(16)
 
  
}

 

字符设备驱动(1)代码分析---之gpio_to_irq字符设备驱动(1)代码分析---之gpio_to_irq
static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
    
    {
        .chip    = {
            .base    = S5PV210_GPA0(0),
            .ngpio    = S5PV210_GPIO_A0_NR,
            .label    = "GPA0",
        },
    }, 
    ...............
    ...............
    {
     .base    = (S5P_VA_GPIO + 0xC40),
     .config    = &gpio_cfg_noint,
     .irq_base = IRQ_EINT(16),
     .chip    = {
        .base    = S5PV210_GPH2(0),
        .ngpio    = S5PV210_GPIO_H2_NR,
        .label    = "GPH2",
        .to_irq = samsung_gpiolib_to_irq,
        },
    }, 
    
    {
        .base    = (S5P_VA_GPIO + 0xC60),
        .config    = &gpio_cfg_noint,
        .irq_base = IRQ_EINT(24),
        .chip    = {
            .base    = S5PV210_GPH3(0),
            .ngpio    = S5PV210_GPIO_H3_NR,
            .label    = "GPH3",
            .to_irq = samsung_gpiolib_to_irq,
        },
    },
};
static struct s3c_gpio_chip s5pv210_gpio_4bit[]
 1 static __init int s5pv210_gpiolib_init(void)
 2 {
 3     struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
 4     int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
字符设备驱动(1)代码分析---之gpio_to_irq字符设备驱动(1)代码分析---之gpio_to_irq
for (i = 0; i < nr_chips; i++, chip++) {
        if (chip->config == NULL) {
            chip->config = &gpio_cfg;
            chip->group = gpioint_group++;
        }
        if (chip->base == NULL)
            chip->base = S5PV210_BANK_BASE(i);
    }
View Code

 

 6     samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
void  __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
                       int nr_chips)
{
        for (; nr_chips > 0; nr_chips--, chip++)
        {
            samsung_gpiolib_add_4bit(chip);
字符设备驱动(1)代码分析---之gpio_to_irq字符设备驱动(1)代码分析---之gpio_to_irq
void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
            {
                    chip->chip.direction_input = samsung_gpiolib_4bit_input;
                    chip->chip.direction_output = samsung_gpiolib_4bit_output;
                    chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
            }
View Code
 s3c_gpiolib_add(chip); 
 __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
            {
          //将s3c_gpio_chip 结构体变量s5pv210_gpio_4bit数组中的每一个数组变量 ".chip"传递给gpio_chip结构体指针gc
          struct gpio_chip *gc = &chip->chip; 
         
//gc = { // .base = S5PV210_GPH2(0), // .ngpio = S5PV210_GPIO_H2_NR, // .label = "GPH2", // .to_irq = samsung_gpiolib_to_irq, // }, int ret; spin_lock_init(&chip->lock);
          //给gc结构体指针其他结构体成员赋值
if (!gc->direction_input) gc->direction_input = s3c_gpiolib_input; if (!gc->direction_output) gc->direction_output = s3c_gpiolib_output; if (!gc->set) gc->set = s3c_gpiolib_set; if (!gc->get) gc->get = s3c_gpiolib_get; #ifdef CONFIG_PM if (chip->pm != NULL) { if (!chip->pm->save || !chip->pm->resume) printk(KERN_ERR "gpio: %s has missing PM functions\n", gc->label); } else printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); #endif // gpiochip_add() prints own failure message on error. ret = gpiochip_add(gc);
 
    
int gpiochip_add(struct gpio_chip *chip){ 
unsigned long flags;
int status = 0; unsigned id;
int base = chip->base; //base = S5PV210_GPH2(0)   //查看获得的gpio_chip结构体指针基址和范围是否在有效范围之内 if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1)) && base >= 0) { status = -EINVAL; goto fail; } spin_lock_irqsave(&gpio_lock, flags); if (base < 0) { base = gpiochip_find_base(chip->ngpio); if (base < 0) { status = base; goto unlock; } chip->base = base; } //these GPIO numbers must not be managed by another gpio_chip 
//遍历某个GPIO端口组的所有IO,如:S5PV210_GPH2端口组的8个IO口
S5PV210_GPH2(0)~(7)
 
  for (id = base; id < base + chip->ngpio; id++)
  {
   //正常状态gpio_desc[base].chip未被初始化,所以各个成员为NULL
    if (gpio_desc[id].chip != NULL) { status = -EBUSY; break; } } if (status == 0) { for (id = base; id < base + chip->ngpio; id++) { gpio_desc[id].chip = chip;
//至此完成gpio_desc[S5PV210_GPH2(0)].chip的赋值,作为返回值在gpio_to_chip()中返回
// REVISIT: most hardware initializes GPIOs as * inputs (often with pullups enabled) so power * usage is minimized. Linux code should set the * gpio direction first thing; but until it does, * we may expose the wrong direction in sysfs. gpio_desc[id].flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0; } } of_gpiochip_add(chip); unlock: spin_unlock_irqrestore(&gpio_lock, flags); if (status) goto fail; status = gpiochip_export(chip); if (status) goto fail; return 0; fail: //failures here can mean systems won't boot... pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; }
 
   

 

if (ret >= 0)
                    s3c_gpiolib_track(chip)
            }
        }
}
 
 

 

 7     s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 8 
 9     return 0;
10 }