Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1598681
  • 博文数量: 204
  • 博客积分: 2215
  • 博客等级: 大尉
  • 技术积分: 4427
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-06 08:03
个人简介

气质,源于心灵的自信!

文章存档

2018年(1)

2017年(1)

2016年(1)

2015年(18)

2014年(20)

2013年(30)

2012年(119)

2011年(14)

分类: LINUX

2012-08-17 18:10:20

MSM8260中的设置中断唤醒的分析:
/*下面是设置的两个接口*/
static inline int enable_irq_wake(unsigned int irq)
{
    return set_irq_wake(irq, 1);
}

static inline int disable_irq_wake(unsigned int irq)
{
    return set_irq_wake(irq, 0);
}

/*上面的两个接口都调用如下函数*/
int set_irq_wake(unsigned int irq, unsigned int on)
{
    struct irq_desc *desc = irq_to_desc(irq);//由irq获得该irq的中断描述符
    unsigned long flags;
    int ret = 0;

    raw_spin_lock_irqsave(&desc->lock, flags);
    if (on) {//如果使能唤醒功能
        if (desc->wake_depth++ == 0) {//如果wake_depth为0,则执行真正的使能函数
            ret = set_irq_wake_real(irq, on);
            if (ret)
                desc->wake_depth = 0;
            else
                desc->status |= IRQ_WAKEUP;//如果使能成功,则置为IRQ_WAKEUP
        }
    } else {//如果去使能唤醒功能
        if (desc->wake_depth == 0) {
            WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
        } else if (--desc->wake_depth == 0) {//如果--为0则,走真正的去使能函数
            ret = set_irq_wake_real(irq, on);
            if (ret)
                desc->wake_depth = 1;
            else
                desc->status &= ~IRQ_WAKEUP;//如果使能成功,则清除IRQ_WAKEUP
        }
    }

    raw_spin_unlock_irqrestore(&desc->lock, flags);
    return ret;
}
EXPORT_SYMBOL(set_irq_wake);

/*上面的函数会调用如下函数*/
static int set_irq_wake_real(unsigned int irq, unsigned int on)
{
    struct irq_desc *desc = irq_to_desc(irq);
    int ret = -ENXIO;

    if (desc->chip->set_wake)//如果芯片的操作函数不为空,则调用该函数
        ret = desc->chip->set_wake(irq, on);

    return ret;
}

————————————————————————————————————————————————————————————————————————————————
下面分析该底层的操作函数
————————————————————————————————————————————————————————————————————————————————

/*底层的硬件操作函数*/
static struct irq_chip msm_gpio_irq_chip = {
    .name        = "msmgpio",
    .mask        = msm_gpio_irq_mask,
    .unmask    = msm_gpio_irq_unmask,
    .ack        = msm_gpio_irq_ack,
    .set_type    = msm_gpio_irq_set_type,
    .set_wake    = msm_gpio_irq_set_wake,//设置是否该irq有唤醒功能
    .disable    = msm_gpio_irq_disable,
};

/*唤醒回调函数的实现*/
#define GIC_SPI_START 32
#define TLMM_MSM_SUMMARY_IRQ            (GIC_SPI_START + 16)
#define NR_MSM_IRQS 256
#define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n))
static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
{
    return irq - MSM_GPIO_TO_INT(chip->base);//MSM_GPIO_TO_INT(0)
}


static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
{
    int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);

    if (on) {
        if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))//如果wake_irqs中都为空,则设置为1
            set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 1);
            set_bit(gpio, msm_gpio.wake_irqs);//设置相应的位为1
    } else {
        clear_bit(gpio, msm_gpio.wake_irqs);//设置相应的位为0
        if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))//如果wake_irqs中都为空,则设置为0
            set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 0);
    }

#ifdef CONFIG_MSM_RPM
    msm_mpm_set_irq_wake(irq, on);
#endif
    return 0;
}


/*下面是上面用到的结构体变量msm_gpio的定义*/
#define NR_GPIO_IRQS 173
#define NR_MSM_GPIOS NR_GPIO_IRQS
#define BITS_PER_BYTE        8
#define DIV_ROUND_UP(n,d)         (((n) + (d) - 1) / (d))
#define BITS_TO_LONGS(nr)           DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define DECLARE_BITMAP(name,bits)  unsigned long name[BITS_TO_LONGS(bits)]
struct msm_gpio_dev {
    struct gpio_chip gpio_chip;
    DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
    DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);//分配一个数组,向上取整,并且根据long的长度(可移植性),去分配数组成员的个数。
    DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
};

/*结构体变量*/
static struct msm_gpio_dev msm_gpio = {
    .gpio_chip = {
        .base             = 0,
        .ngpio            = NR_MSM_GPIOS,//173
        .direction_input  = msm_gpio_direction_input,
        .direction_output = msm_gpio_direction_output,
        .get              = msm_gpio_get,
        .set              = msm_gpio_set,
        .to_irq           = msm_gpio_to_irq,
        .request          = msm_gpio_request,
        .free             = msm_gpio_free,
    },
};

/*高通底层中断处理函数注册*/
static int __devinit msm_gpio_probe(struct sysdev_class *sysclass)
{
    .....................
    /*把msm_gpio里面的成员变量初始化为0*/
    bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
    bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
    bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
    msm_gpio.gpio_chip.label = sysclass->name;
    ret = gpiochip_add(&msm_gpio.gpio_chip);//注册一个chip结构
    ...................
    /*初始化中断体系结构的处理函数*/
    for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
        irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
        set_irq_chip(irq, &msm_gpio_irq_chip);//初始化芯片级操作函数
        set_irq_handler(irq, handle_level_irq);//初始化该irq处理函数的总入口
        set_irq_flags(irq, IRQF_VALID);//设置该irq可用
    }
    
    /*为总中断入口申请函数*/
    ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,IRQF_TRIGGER_HIGH, "msmgpio", NULL);
    return 0;
}
阅读(5821) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~