单片机
返回首页

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

2025-01-07 来源:cnblogs


/**************************************************************

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)


}


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,

        },

    },

};


 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);

    }


 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);

            }


            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 functionsn',

                               gc->label);

                } else

                    printk(KERN_ERR 'gpio: %s has no PM functionn', 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 registern',

        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 }


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 设计汽车集群电源

  • 6晶体管H桥

  • USB自供电声卡

  • AVR LCD温度计—LM35

  • AVR PC步进电机驱动器

  • AVR温度计TCN75

    相关电子头条文章