phonepad:fix alarm lose intterupt problem
authorlw@rock-chips.com <lw@rock-chips.com>
Sat, 11 Aug 2012 03:37:28 +0000 (11:37 +0800)
committerlw <lw@rock-chips.com>
Sat, 11 Aug 2012 03:37:55 +0000 (11:37 +0800)
drivers/mfd/tps65910-irq.c
drivers/rtc/rtc-tps65910.c
include/linux/mfd/tps65910.h

index bcec38371c9455c6cf743f106442edb010647543..1b781bfc93e56e1faa71b04fb52aa5e56b3aa059 100755 (executable)
@@ -22,6 +22,8 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/mfd/tps65910.h>
+#include <linux/wakelock.h>
+#include <linux/kthread.h>
 
 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, &reg);
        irq_sts = reg;
        tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
@@ -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, &reg);
        }
-
+       wake_unlock(&tps65910->irq_wake);
        return IRQ_HANDLED;
 }
 
@@ -188,14 +194,17 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
        tps65910->write(tps65910, TPS65910_INT_STS2, 1, &reg);
        tps65910->read(tps65910, TPS65910_INT_STS3, 1, &reg);
        tps65910->write(tps65910, TPS65910_INT_STS3, 1, &reg);
+       tps65910->read(tps65910, TPS65910_RTC_STATUS, 1, &reg); 
+       tps65910->write(tps65910, TPS65910_RTC_STATUS, 1, &reg);//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;
-
+       
        switch (tps65910_chip_id(tps65910)) {
        case TPS65910:
                tps65910->irq_num = TPS65910_NUM_IRQ;
index f6a8693cabcfd4a43ef2e478889c4130ede4c969..50eba3a7db48dd72066dd3ae60a46d61ad898677 100755 (executable)
@@ -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;
 }
 
index c093c477477b4db31c64212a077e4865f6eb25e2..c098040c72562790a974d831bfe34513f8d1cfd6 100755 (executable)
@@ -18,6 +18,7 @@
 #define __LINUX_MFD_TPS65910_H
 
 #include <linux/gpio.h>
+#include <linux/wakelock.h>
 
 /* 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);