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


    
    
    /**************************************************************
    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;

    #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)
    
    
    }
    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);
    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);
    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 ", gc->label); } else printk(KERN_ERR "gpio: %s has no PM function ", 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 ", 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 }
  • 相关阅读:
    【Java】Swing-LookAndFeel 初解
    【软件】软件发布版本号说明
    【Gradle】Gradle compile 运用
    【Java】String,StringBuilder,StringBuffer 区别与实现
    Java面试题
    java面向对象_抽象类和接口
    Java学习_int和Integer的区别+包装类
    PHP-格式标签
    PHP+Zend 输出时中文乱码问题
    JSP学习
  • 原文地址:https://www.cnblogs.com/embeded-linux/p/11055279.html
Copyright © 2020-2023  润新知