twl4030_charger: ack and ratelimit monitoring events
[pandora-kernel.git] / drivers / power / twl4030_charger.c
index 92c16e1..a7259c5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/power_supply.h>
 #include <linux/notifier.h>
 #include <linux/usb/otg.h>
+#include <linux/ratelimit.h>
 
 #define TWL4030_BCIMSTATEC     0x02
 #define TWL4030_BCIICHG                0x08
@@ -61,8 +62,8 @@
 #define TWL4030_MSTATEC_COMPLETE1      0x0b
 #define TWL4030_MSTATEC_COMPLETE4      0x0e
 
-static bool allow_usb;
-module_param(allow_usb, bool, 1);
+static bool allow_usb = 1;
+module_param(allow_usb, bool, 0644);
 MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
 
 struct twl4030_bci {
@@ -76,6 +77,7 @@ struct twl4030_bci {
        int                     irq_bci;
 
        unsigned long           event;
+       struct ratelimit_state  ratelimit;
 };
 
 /*
@@ -243,21 +245,28 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
        }
 
        /* various monitoring events, for now we just log them here */
-       if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
+       if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1) &&
+                       __ratelimit(&bci->ratelimit))
                dev_warn(bci->dev, "battery temperature out of range\n");
 
-       if (irqs1 & TWL4030_BATSTS)
+       if (irqs1 & TWL4030_BATSTS && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "battery disconnected\n");
 
-       if (irqs2 & TWL4030_VBATOV)
+       if (irqs2 & TWL4030_VBATOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "VBAT overvoltage\n");
 
-       if (irqs2 & TWL4030_VBUSOV)
+       if (irqs2 & TWL4030_VBUSOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "VBUS overvoltage\n");
 
-       if (irqs2 & TWL4030_ACCHGOV)
+       if (irqs2 & TWL4030_ACCHGOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "Ac charger overvoltage\n");
 
+       /* ack the interrupts */
+       twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, irqs1,
+                        TWL4030_INTERRUPTS_BCIISR1A);
+       twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, irqs2,
+                        TWL4030_INTERRUPTS_BCIISR2A);
+
        return IRQ_HANDLED;
 }
 
@@ -425,7 +434,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 {
        struct twl4030_bci *bci;
        int ret;
-       int reg;
+       u32 reg;
 
        bci = kzalloc(sizeof(*bci), GFP_KERNEL);
        if (bci == NULL)
@@ -437,6 +446,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, bci);
 
+       ratelimit_state_init(&bci->ratelimit, HZ, 2);
+
        bci->ac.name = "twl4030_ac";
        bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
        bci->ac.properties = twl4030_charger_props;
@@ -486,7 +497,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        }
 
        /* Enable interrupts now. */
-       reg = ~(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
+       reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
                TWL4030_TBATOR1 | TWL4030_BATSTS);
        ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                               TWL4030_INTERRUPTS_BCIIMR1A);
@@ -495,7 +506,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
                goto fail_unmask_interrupts;
        }
 
-       reg = ~(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
+       reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
        ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                               TWL4030_INTERRUPTS_BCIIMR2A);
        if (ret < 0)
@@ -572,7 +583,7 @@ static void __exit twl4030_bci_exit(void)
 }
 module_exit(twl4030_bci_exit);
 
-MODULE_AUTHOR("Gražydas Ignotas");
+MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:twl4030_bci");