From: 张晴 Date: Sat, 11 Aug 2012 08:40:07 +0000 (+0800) Subject: rk2928:fix alarm lose intterupt problem X-Git-Tag: firefly_0821_release~8912^2~8 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=13da9d54f5617551e07e5d25d225d7edec673995;p=firefly-linux-kernel-4.4.55.git rk2928:fix alarm lose intterupt problem --- diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c index bcec38371c94..8b53c05be689 100755 --- a/drivers/mfd/tps65910-irq.c +++ b/drivers/mfd/tps65910-irq.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include static inline int irq_to_tps65910_irq(struct tps65910 *tps65910, int irq) @@ -46,6 +48,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data) u8 reg; int i; + wake_lock(&tps65910->irq_wake); tps65910->read(tps65910, TPS65910_INT_STS, 1, ®); irq_sts = reg; tps65910->read(tps65910, TPS65910_INT_STS2, 1, ®); @@ -69,7 +72,10 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data) irq_sts &= ~irq_mask; if (!irq_sts) + { + wake_unlock(&tps65910->irq_wake); return IRQ_NONE; + } for (i = 0; i < tps65910->irq_num; i++) { @@ -90,7 +96,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data) reg = irq_sts >> 8; tps65910->write(tps65910, TPS65910_INT_STS3, 1, ®); } - + wake_unlock(&tps65910->irq_wake); return IRQ_HANDLED; } @@ -188,11 +194,14 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq, tps65910->write(tps65910, TPS65910_INT_STS2, 1, ®); tps65910->read(tps65910, TPS65910_INT_STS3, 1, ®); tps65910->write(tps65910, TPS65910_INT_STS3, 1, ®); + tps65910->read(tps65910, TPS65910_RTC_STATUS, 1, ®); + tps65910->write(tps65910, TPS65910_RTC_STATUS, 1, ®);//clear alarm and timer interrupt /* Mask top level interrupts */ tps65910->irq_mask = 0xFFFFFF; - mutex_init(&tps65910->irq_lock); + mutex_init(&tps65910->irq_lock); + wake_lock_init(&tps65910->irq_wake, WAKE_LOCK_SUSPEND, "tps65910_irq_wake"); tps65910->chip_irq = irq; tps65910->irq_base = pdata->irq_base; diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index f6a8693cabcf..50eba3a7db48 100755 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -350,21 +350,43 @@ static int tps65910_rtc_irq_set_freq(struct device *dev, int freq) return ret; } - - static irqreturn_t tps65910_alm_irq(int irq, void *data) { struct tps65910_rtc *tps65910_rtc = data; + int ret; + u8 rtc_ctl; + /*Dummy read -- mandatory for status register*/ + ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_STATUS); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + + ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_STATUS); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + rtc_ctl = ret&0xff; + + //The alarm interrupt keeps its low level, until the micro-controller write 1 in the ALARM bit of the RTC_STATUS_REG register. + ret = tps65910_reg_write(tps65910_rtc->tps65910, TPS65910_RTC_STATUS,rtc_ctl); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_AF); + printk("%s:irq=%d,rtc_ctl=0x%x\n",__func__,irq,rtc_ctl); return IRQ_HANDLED; } static irqreturn_t tps65910_per_irq(int irq, void *data) { struct tps65910_rtc *tps65910_rtc = data; - + rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_UF); //printk("%s:irq=%d\n",__func__,irq); @@ -558,6 +580,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev) //tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS, // BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + enable_irq_wake(alm_irq); // so tps65910 alarm irq can wake up system g_pdev = pdev; printk("%s:ok\n",__func__); @@ -610,6 +633,8 @@ static ssize_t rtc_tps65910_test_write(struct file *file, int nr = 0, ret; struct platform_device *pdev; struct rtc_time tm; + struct rtc_wkalrm alrm; + struct tps65910_rtc *tps65910_rtc; if(count > 3) return -EFAULT; @@ -618,7 +643,7 @@ static ssize_t rtc_tps65910_test_write(struct file *file, return -EFAULT; sscanf(nr_buf, "%d", &nr); - if(nr >= 2 || nr < 0) + if(nr > 5 || nr < 0) { printk("%s:data is error\n",__func__); return -EFAULT; @@ -629,6 +654,10 @@ static ssize_t rtc_tps65910_test_write(struct file *file, else pdev = g_pdev; + + tps65910_rtc = dev_get_drvdata(&pdev->dev); + + //test rtc time if(nr == 0) { tm.tm_wday = 6; @@ -662,6 +691,56 @@ static ssize_t rtc_tps65910_test_write(struct file *file, else printk("%s:error\n",__func__); + + //test rtc alarm + if(nr == 2) + { + //2000-01-01 00:00:30 + if(tm.tm_sec < 30) + { + alrm.time.tm_sec = tm.tm_sec+30; + alrm.time.tm_min = tm.tm_min; + } + else + { + alrm.time.tm_sec = tm.tm_sec-30; + alrm.time.tm_min = tm.tm_min+1; + } + alrm.time.tm_hour = tm.tm_hour; + alrm.time.tm_mday = tm.tm_mday; + alrm.time.tm_mon = tm.tm_mon; + alrm.time.tm_year = tm.tm_year; + tps65910_rtc_alarm_irq_enable(&pdev->dev, 1); + tps65910_rtc_setalarm(&pdev->dev, &alrm); + + dev_info(&pdev->dev, "Set alarm %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm.time.tm_year, alrm.time.tm_mon + 1, alrm.time.tm_mday, alrm.time.tm_wday, + alrm.time.tm_hour, alrm.time.tm_min, alrm.time.tm_sec); + } + + + if(nr == 3) + { + ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_STATUS); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + printk("%s:ret=0x%x\n",__func__,ret&0xff); + + ret = tps65910_reg_write(tps65910_rtc->tps65910, TPS65910_RTC_STATUS, ret&0xff); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + } + + if(nr == 4) + tps65910_rtc_update_irq_enable(&pdev->dev, 1); + + if(nr == 5) + tps65910_rtc_update_irq_enable(&pdev->dev, 0); + return count; } diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index c093c477477b..c098040c7256 100755 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -18,6 +18,7 @@ #define __LINUX_MFD_TPS65910_H #include +#include /* TPS chip id list */ #define TPS65910 0 @@ -802,6 +803,7 @@ struct tps65910 { struct i2c_client *i2c_client; struct regmap *regmap; struct mutex io_mutex; + struct wake_lock irq_wake; unsigned int id; int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest); int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src);