sky2: Factor out code to calculate packet sizes
[safe/jmp/linux-2.6] / drivers / power / wm8350_power.c
index 9c0a847..ad4f071 100644 (file)
@@ -44,7 +44,7 @@ static int wm8350_read_usb_uvolts(struct wm8350 *wm8350)
 
 static inline int wm8350_charge_time_min(struct wm8350 *wm8350, int min)
 {
-       if (wm8350->rev < WM8350_REV_G)
+       if (!wm8350->power.rev_g_coeff)
                return (((min - 30) / 15) & 0xf) << 8;
        else
                return (((min - 30) / 30) & 0xf) << 8;
@@ -184,28 +184,25 @@ static ssize_t charger_state_show(struct device *dev,
 
 static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL);
 
-static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data)
+static irqreturn_t wm8350_charger_handler(int irq, void *data)
 {
+       struct wm8350 *wm8350 = data;
        struct wm8350_power *power = &wm8350->power;
        struct wm8350_charger_policy *policy = power->policy;
 
        switch (irq) {
-       case WM8350_IRQ_CHG_BAT_HOT:
-               dev_err(wm8350->dev, "battery too hot\n");
-               break;
-       case WM8350_IRQ_CHG_BAT_COLD:
-               dev_err(wm8350->dev, "battery too cold\n");
-               break;
        case WM8350_IRQ_CHG_BAT_FAIL:
                dev_err(wm8350->dev, "battery failed\n");
                break;
        case WM8350_IRQ_CHG_TO:
                dev_err(wm8350->dev, "charger timeout\n");
-               break;
-       case WM8350_IRQ_CHG_END:
                power_supply_changed(&power->battery);
                break;
+
+       case WM8350_IRQ_CHG_BAT_HOT:
+       case WM8350_IRQ_CHG_BAT_COLD:
        case WM8350_IRQ_CHG_START:
+       case WM8350_IRQ_CHG_END:
                power_supply_changed(&power->battery);
                break;
 
@@ -242,6 +239,8 @@ static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data)
        default:
                dev_err(wm8350->dev, "Unknown interrupt %d\n", irq);
        }
+
+       return IRQ_HANDLED;
 }
 
 /*********************************************************************
@@ -308,6 +307,41 @@ static enum power_supply_property wm8350_usb_props[] = {
  *             Battery properties
  *********************************************************************/
 
+static int wm8350_bat_check_health(struct wm8350 *wm8350)
+{
+       u16 reg;
+
+       if (wm8350_read_battery_uvolts(wm8350) < 2850000)
+               return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+
+       reg = wm8350_reg_read(wm8350, WM8350_CHARGER_OVERRIDES);
+       if (reg & WM8350_CHG_BATT_HOT_OVRDE)
+               return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+       if (reg & WM8350_CHG_BATT_COLD_OVRDE)
+               return POWER_SUPPLY_HEALTH_COLD;
+
+       return POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int wm8350_bat_get_charge_type(struct wm8350 *wm8350)
+{
+       int state;
+
+       state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
+           WM8350_CHG_STS_MASK;
+       switch (state) {
+       case WM8350_CHG_STS_OFF:
+               return POWER_SUPPLY_CHARGE_TYPE_NONE;
+       case WM8350_CHG_STS_TRICKLE:
+               return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+       case WM8350_CHG_STS_FAST:
+               return POWER_SUPPLY_CHARGE_TYPE_FAST;
+       default:
+               return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+       }
+}
+
 static int wm8350_bat_get_property(struct power_supply *psy,
                                   enum power_supply_property psp,
                                   union power_supply_propval *val)
@@ -326,6 +360,12 @@ static int wm8350_bat_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                val->intval = wm8350_read_battery_uvolts(wm8350);
                break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               val->intval = wm8350_bat_check_health(wm8350);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               val->intval = wm8350_bat_get_charge_type(wm8350);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -338,6 +378,8 @@ static enum power_supply_property wm8350_bat_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
 };
 
 /*********************************************************************
@@ -348,73 +390,55 @@ static void wm8350_init_charger(struct wm8350 *wm8350)
 {
        /* register our interest in charger events */
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+                           wm8350_charger_handler, 0, "Battery hot", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+                           wm8350_charger_handler, 0, "Battery cold", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+                           wm8350_charger_handler, 0, "Battery fail", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO);
+                           wm8350_charger_handler, 0,
+                           "Charger timeout", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END);
+                           wm8350_charger_handler, 0,
+                           "Charge end", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START);
+                           wm8350_charger_handler, 0,
+                           "Charge start", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY);
+                           wm8350_charger_handler, 0,
+                           "Fast charge ready", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+                           wm8350_charger_handler, 0,
+                           "Battery <3.9V", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+                           wm8350_charger_handler, 0,
+                           "Battery <3.1V", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+                           wm8350_charger_handler, 0,
+                           "Battery <2.85V", wm8350);
 
        /* and supply change events */
        wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+                           wm8350_charger_handler, 0, "USB", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+                           wm8350_charger_handler, 0, "Wall", wm8350);
        wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
-                           wm8350_charger_handler, NULL);
-       wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+                           wm8350_charger_handler, 0, "Battery", wm8350);
 }
 
 static void free_charger_irq(struct wm8350 *wm8350)
 {
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
        wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
        wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
        wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
-       wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
        wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
 }