diff options
author | Johan Gardsmark <johan.gardsmark@stericsson.com> | 2011-01-05 15:23:55 +0100 |
---|---|---|
committer | Jonas ABERG <jonas.aberg@stericsson.com> | 2011-02-22 15:58:55 +0100 |
commit | c780a508e42fa293e61eeadd9bbc570eac30c611 (patch) | |
tree | 74802e411c824104fe5eb4b2adbea87d6ed39922 | |
parent | c90bac6ee27f95669afba190089c47e72929a936 (diff) |
power: ab8500_bm: Add support for non-ab8500 chargersu8500-android-2.3_v0.19
Adds support to use non-ab8500 chargers in the ab8500 charging
algorithm. The charger specific functions are now stored in a
"sub class" charger structure with the power_supply as a
"base class".
ST-Ericsson ID: WP324917
Change-Id: I3c29c6b767209d750498ecd6b8a690d9fb073109
Signed-off-by: Johan Gardsmark <johan.gardsmark@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16416
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r-- | drivers/power/ab8500_chargalg.c | 91 | ||||
-rw-r--r-- | drivers/power/ab8500_charger.c | 147 | ||||
-rw-r--r-- | include/linux/mfd/ab8500/ab8500-bm.h | 9 | ||||
-rw-r--r-- | include/linux/mfd/ab8500/ux500_chargalg.h | 37 |
4 files changed, 194 insertions, 90 deletions
diff --git a/drivers/power/ab8500_chargalg.c b/drivers/power/ab8500_chargalg.c index d44f350aef6..96c20df02b8 100644 --- a/drivers/power/ab8500_chargalg.c +++ b/drivers/power/ab8500_chargalg.c @@ -20,6 +20,7 @@ #include <linux/workqueue.h> #include <linux/kobject.h> #include <linux/mfd/ab8500.h> +#include <linux/mfd/ab8500/ux500_chargalg.h> #include <linux/mfd/ab8500/ab8500-bm.h> #include <linux/mfd/ab8500/ab8500-gpadc.h> @@ -138,6 +139,7 @@ struct ab8500_chargalg_events { bool btemp_lowhigh; bool main_thermal_prot; bool usb_thermal_prot; + bool main_ovv; bool vbus_ovv; bool usbchargernotok; bool safety_timer_expired; @@ -185,6 +187,8 @@ struct ab8500_chargalg { struct ab8500_chargalg_platform_data *pdata; struct ab8500_bm_data *bat; struct power_supply chargalg_psy; + struct ux500_charger *ac_chg; + struct ux500_charger *usb_chg; struct ab8500_chargalg_events events; struct workqueue_struct *chargalg_wq; struct delayed_work chargalg_periodic_work; @@ -397,10 +401,15 @@ static void ab8500_chargalg_stop_maintenance_timer(struct ab8500_chargalg *di) */ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di) { - if (di->bat->charger_ops.kick_watchdog) - return di->bat->charger_ops.kick_watchdog(di->parent->charger); - else - return -ENXIO; + /* Check if charger exists and kick watchdog if charging */ + if (di->ac_chg && di->ac_chg->ops.kick_wd && + di->chg_info.online_chg & AC_CHG) + return di->ac_chg->ops.kick_wd(di->ac_chg); + else if (di->usb_chg && di->usb_chg->ops.kick_wd && + di->chg_info.online_chg & USB_CHG) + return di->usb_chg->ops.kick_wd(di->usb_chg); + + return -ENXIO; } /** @@ -416,11 +425,16 @@ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di) static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable, int vset, int iset) { - if (di->bat->charger_ops.ac_en) - return di->bat->charger_ops.ac_en(di->parent->charger, - enable, vset, iset); - else + if (!di->ac_chg || !di->ac_chg->ops.enable) return -ENXIO; + + /* Select maximum of what both the charger and the battery supports */ + if (di->ac_chg->max_out_volt) + vset = min(vset, di->ac_chg->max_out_volt); + if (di->ac_chg->max_out_curr) + iset = min(iset, di->ac_chg->max_out_curr); + + return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset); } /** @@ -436,11 +450,16 @@ static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable, static int ab8500_chargalg_usb_en(struct ab8500_chargalg *di, int enable, int vset, int iset) { - if (di->bat->charger_ops.usb_en) - return di->bat->charger_ops.usb_en(di->parent->charger, - enable, vset, iset); - else + if (!di->usb_chg || !di->usb_chg->ops.enable) return -ENXIO; + + /* Select maximum of what both the charger and the battery supports */ + if (di->usb_chg->max_out_volt) + vset = min(vset, di->usb_chg->max_out_volt); + if (di->usb_chg->max_out_curr) + iset = min(iset, di->usb_chg->max_out_curr); + + return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset); } /** @@ -614,6 +633,14 @@ static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) enum power_supply_property prop; prop = ext->properties[j]; + /* Initialize chargers if not already done */ + if (!di->ac_chg && + ext->type == POWER_SUPPLY_TYPE_MAINS) + di->ac_chg = psy_to_ux500_charger(ext); + else if (!di->usb_chg && + ext->type == POWER_SUPPLY_TYPE_USB) + di->usb_chg = psy_to_ux500_charger(ext); + switch (prop) { case POWER_SUPPLY_PROP_PRESENT: if (!ext->get_property(ext, @@ -736,6 +763,8 @@ static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) true; di->events.main_thermal_prot = false; + di->events.main_ovv = + false; di->events.ac_wd_expired = false; break; @@ -744,14 +773,28 @@ static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) true; di->events.mainextchnotok = false; + di->events.main_ovv = + false; di->events.main_thermal_prot = false; break; + case POWER_SUPPLY_HEALTH_COLD: case POWER_SUPPLY_HEALTH_OVERHEAT: di->events.main_thermal_prot = true; di->events.mainextchnotok = false; + di->events.main_ovv = + false; + di->events.ac_wd_expired = + false; + break; + case POWER_SUPPLY_HEALTH_OVERVOLTAGE: + di->events.main_ovv = true; + di->events.mainextchnotok = + false; + di->events.main_thermal_prot = + false; di->events.ac_wd_expired = false; break; @@ -760,6 +803,8 @@ static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) false; di->events.mainextchnotok = false; + di->events.main_ovv = + false; di->events.ac_wd_expired = false; break; @@ -788,6 +833,7 @@ static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) false; di->events.vbus_ovv = false; break; + case POWER_SUPPLY_HEALTH_COLD: case POWER_SUPPLY_HEALTH_OVERHEAT: di->events.usb_thermal_prot = true; @@ -1003,9 +1049,12 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) if (di->charge_state != STATE_CHG_NOT_OK) ab8500_chargalg_state_to(di, STATE_CHG_NOT_OK_INIT); } - /* VBUS or VBAT OVV. */ - else if (di->events.vbus_ovv || di->events.batt_ovv || - !di->chg_info.usb_chg_ok || !di->chg_info.ac_chg_ok) { + /* VBUS, Main or VBAT OVV. */ + else if (di->events.vbus_ovv || + di->events.main_ovv || + di->events.batt_ovv || + !di->chg_info.usb_chg_ok || + !di->chg_info.ac_chg_ok) { if (di->charge_state != STATE_OVV_PROTECT) ab8500_chargalg_state_to(di, STATE_OVV_PROTECT_INIT); } @@ -1112,8 +1161,11 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) /* Intentional fallthrough */ case STATE_OVV_PROTECT: - if (!di->events.vbus_ovv && !di->events.batt_ovv && - di->chg_info.usb_chg_ok && di->chg_info.ac_chg_ok) + if (!di->events.vbus_ovv && + !di->events.main_ovv && + !di->events.batt_ovv && + di->chg_info.usb_chg_ok && + di->chg_info.ac_chg_ok) ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); break; @@ -1281,12 +1333,15 @@ static void ab8500_chargalg_periodic_work(struct work_struct *work) */ static void ab8500_chargalg_wd_work(struct work_struct *work) { + int ret; struct ab8500_chargalg *di = container_of(work, struct ab8500_chargalg, chargalg_wd_work.work); dev_dbg(di->dev, "ab8500_chargalg_wd_work\n"); - ab8500_chargalg_kick_watchdog(di); + ret = ab8500_chargalg_kick_watchdog(di); + if (ret < 0) + dev_err(di->dev, "failed to kick watchdog\n"); queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, CHG_WD_INTERVAL); diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 9332f44500a..87c554e2c15 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -24,6 +24,7 @@ #include <linux/mfd/abx500.h> #include <linux/mfd/ab8500/ab8500-bm.h> #include <linux/mfd/ab8500/ab8500-gpadc.h> +#include <linux/mfd/ab8500/ux500_chargalg.h> /* Charger constants */ #define NO_PW_CONN 0 @@ -97,9 +98,9 @@ enum ab8500_usb_state { }; #define to_ab8500_charger_usb_device_info(x) container_of((x), \ - struct ab8500_charger, usb_psy); + struct ab8500_charger, usb_chg) #define to_ab8500_charger_ac_device_info(x) container_of((x), \ - struct ab8500_charger, ac_psy); + struct ab8500_charger, ac_chg) /** * struct ab8500_charger_interrupts - ab8500 interupts @@ -150,8 +151,8 @@ struct ab8500_charger_usb_state { * @bat: Pointer to the ab8500_bm platform data * @flags: Structure for information about events triggered * @usb_state: Structure for usb stack information - * @ac_psy: AC charger power supply - * @usb_psy: USB charger power supply + * @ac_chg: AC charger power supply + * @usb_chg: USB charger power supply * @ac: Structure that holds the AC charger properties * @usb: Structure that holds the USB charger properties * @charger_wq: Work queue for the IRQs and checking HW state @@ -181,8 +182,8 @@ struct ab8500_charger { struct ab8500_bm_data *bat; struct ab8500_charger_event_flags flags; struct ab8500_charger_usb_state usb_state; - struct power_supply ac_psy; - struct power_supply usb_psy; + struct ux500_charger ac_chg; + struct ux500_charger usb_chg; struct ab8500_charger_info ac; struct ab8500_charger_info usb; struct workqueue_struct *charger_wq; @@ -807,13 +808,15 @@ static int ab8500_charger_kick_main_wd(struct ab8500_charger *di) * Enable/Disable AC/Mains charging and turns on/off the charging led * respectively. **/ -static int ab8500_charger_ac_en(struct ab8500_charger *di, +static int ab8500_charger_ac_en(struct ux500_charger *charger, int enable, int vset, int iset) { int ret; int volt_index; int curr_index; + struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); + if (enable) { /* Check if AC is connected */ if (!di->ac.charger_connected) { @@ -942,7 +945,7 @@ static int ab8500_charger_ac_en(struct ab8500_charger *di, di->ac.wd_expired = false; dev_dbg(di->dev, "%s Disabled AC charging\n", __func__); } - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); return ret; @@ -999,13 +1002,15 @@ disable_charger: * Enable/Disable USB charging and turns on/off the charging led respectively. * Returns error code in case of failure else 0(on success) */ -static int ab8500_charger_usb_en(struct ab8500_charger *di, +static int ab8500_charger_usb_en(struct ux500_charger *charger, int enable, int vset, int ich_out) { int ret; int volt_index; int curr_index; + struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); + if (enable) { /* Check if USB is connected */ if (!di->usb.charger_connected) { @@ -1085,7 +1090,7 @@ static int ab8500_charger_usb_en(struct ab8500_charger *di, di->usb.wd_expired = false; dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); } - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); return ret; @@ -1106,9 +1111,17 @@ disable_charger: * Kick charger watchdog * Returns error code in case of failure else 0(on success) */ -static int ab8500_charger_watchdog_kick(struct ab8500_charger *di) +static int ab8500_charger_watchdog_kick(struct ux500_charger *charger) { int ret; + struct ab8500_charger *di; + + if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) + di = to_ab8500_charger_ac_device_info(charger); + else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) + di = to_ab8500_charger_usb_device_info(charger); + else + return -ENXIO; ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); @@ -1118,12 +1131,6 @@ static int ab8500_charger_watchdog_kick(struct ab8500_charger *di) return ret; } -static struct ab8500_charger_ops charger_ops = { - .ac_en = ab8500_charger_ac_en, - .usb_en = ab8500_charger_usb_en, - .kick_watchdog = ab8500_charger_watchdog_kick, -}; - /** * ab8500_charger_check_hw_failure_work() - check main charger failure * @work: pointer to the work_struct structure @@ -1148,7 +1155,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work) } if (!(reg_value & MAIN_CH_NOK)) { di->flags.mainextchnotok = false; - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); } } if (di->flags.vbus_ovv) { @@ -1161,7 +1168,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work) } if (!(reg_value & VBUS_OVV_TH)) { di->flags.vbus_ovv = false; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } } /* If we still have a failure, schedule a new check */ @@ -1231,7 +1238,7 @@ static void ab8500_charger_ac_work(struct work_struct *work) di->ac.charger_connected = 0; } - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); } /** @@ -1259,7 +1266,7 @@ void ab8500_charger_detect_usb_type_work(struct work_struct *work) if (!(ret & USB_PW_CONN)) { di->vbus_detected = 0; di->usb.charger_connected = 0; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } else { di->vbus_detected = 1; @@ -1269,7 +1276,7 @@ void ab8500_charger_detect_usb_type_work(struct work_struct *work) ret = ab8500_charger_detect_usb_type(di); if (!ret) { di->usb.charger_connected = 1; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } break; @@ -1286,7 +1293,7 @@ void ab8500_charger_detect_usb_type_work(struct work_struct *work) ret = ab8500_charger_detect_usb_type(di); if (!ret) { di->usb.charger_connected = 1; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } } break; @@ -1319,7 +1326,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) if (!(ret & USB_PW_CONN)) { di->vbus_detected = 0; di->usb.charger_connected = 0; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } else { di->vbus_detected = 1; ret = ab8500_charger_read_usb_type(di); @@ -1333,11 +1340,11 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) return; } di->usb.charger_connected = 1; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } else if (ret == -ENXIO) { /* No valid charger type detected */ di->usb.charger_connected = 0; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } } } @@ -1373,7 +1380,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work) case AB8500_BM_USB_STATE_SUSPEND: case AB8500_BM_USB_STATE_MAX: di->usb.charger_connected = 0; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); break; case AB8500_BM_USB_STATE_RESUME: @@ -1398,7 +1405,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work) return; } di->usb.charger_connected = 1; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } break; @@ -1433,7 +1440,7 @@ static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) else di->flags.usbchargernotok = false; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } /** @@ -1463,7 +1470,7 @@ static void ab8500_charger_check_main_thermal_prot_work( else di->flags.main_thermal_prot = false; - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); } /** @@ -1493,7 +1500,7 @@ static void ab8500_charger_check_usb_thermal_prot_work( else di->flags.usb_thermal_prot = false; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } /** @@ -1543,7 +1550,7 @@ static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di) dev_dbg(di->dev, "Main charger not ok\n"); di->flags.mainextchnotok = true; - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); /* Schedule a new HW failure check */ queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); @@ -1733,11 +1740,11 @@ static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) */ if (di->ac.charger_online) { di->ac.wd_expired = true; - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); } if (di->usb.charger_online) { di->usb.wd_expired = true; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); } return IRQ_HANDLED; @@ -1756,7 +1763,7 @@ static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di) dev_dbg(di->dev, "VBUS overvoltage detected\n"); di->flags.vbus_ovv = true; - power_supply_changed(&di->usb_psy); + power_supply_changed(&di->usb_chg.psy); /* Schedule a new HW failure check */ queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); @@ -1784,7 +1791,7 @@ static int ab8500_charger_ac_get_property(struct power_supply *psy, { struct ab8500_charger *di; - di = to_ab8500_charger_ac_device_info(psy); + di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); switch (psp) { case POWER_SUPPLY_PROP_HEALTH: @@ -1841,7 +1848,7 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy, { struct ab8500_charger *di; - di = to_ab8500_charger_usb_device_info(psy); + di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); switch (psp) { case POWER_SUPPLY_PROP_HEALTH: @@ -2080,10 +2087,10 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) int i, irq, ret; /* Disable AC charging */ - ab8500_charger_ac_en(di, false, 0, 0); + ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); /* Disable USB charging */ - ab8500_charger_usb_en(di, false, 0, 0); + ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); /* Disable interrupts */ for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { @@ -2101,8 +2108,8 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) destroy_workqueue(di->charger_wq); flush_scheduled_work(); - power_supply_unregister(&di->usb_psy); - power_supply_unregister(&di->ac_psy); + power_supply_unregister(&di->usb_chg.psy); + power_supply_unregister(&di->ac_chg.psy); platform_set_drvdata(pdev, NULL); kfree(di); @@ -2147,26 +2154,40 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) } di->bat = plat->battery; - /* Set up function pointers to be used by the charging algorithm */ - di->bat->charger_ops = charger_ops; - /* AC supply */ - di->ac_psy.name = "ab8500_ac"; - di->ac_psy.type = POWER_SUPPLY_TYPE_MAINS; - di->ac_psy.properties = ab8500_charger_ac_props; - di->ac_psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); - di->ac_psy.get_property = ab8500_charger_ac_get_property; - di->ac_psy.supplied_to = di->pdata->supplied_to; - di->ac_psy.num_supplicants = di->pdata->num_supplicants; + /* power_supply base class */ + di->ac_chg.psy.name = "ab8500_ac"; + di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS; + di->ac_chg.psy.properties = ab8500_charger_ac_props; + di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); + di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; + di->ac_chg.psy.supplied_to = di->pdata->supplied_to; + di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants; + /* ux500_charger sub-class */ + di->ac_chg.ops.enable = &ab8500_charger_ac_en; + di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; + di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ + ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; + di->ac_chg.max_out_curr = ab8500_charger_current_map[ + ARRAY_SIZE(ab8500_charger_current_map) - 1]; /* USB supply */ - di->usb_psy.name = "ab8500_usb"; - di->usb_psy.type = POWER_SUPPLY_TYPE_USB; - di->usb_psy.properties = ab8500_charger_usb_props; - di->usb_psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); - di->usb_psy.get_property = ab8500_charger_usb_get_property; - di->usb_psy.supplied_to = di->pdata->supplied_to; - di->usb_psy.num_supplicants = di->pdata->num_supplicants; + /* power_supply base class */ + di->usb_chg.psy.name = "ab8500_usb"; + di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB; + di->usb_chg.psy.properties = ab8500_charger_usb_props; + di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); + di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; + di->usb_chg.psy.supplied_to = di->pdata->supplied_to; + di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; + /* ux500_charger sub-class */ + di->usb_chg.ops.enable = &ab8500_charger_usb_en; + di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; + di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ + ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; + di->usb_chg.max_out_curr = ab8500_charger_current_map[ + ARRAY_SIZE(ab8500_charger_current_map) - 1]; + /* Create a work queue for the charger */ di->charger_wq = @@ -2227,14 +2248,14 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) } /* Register AC charger class */ - ret = power_supply_register(di->dev, &di->ac_psy); + ret = power_supply_register(di->dev, &di->ac_chg.psy); if (ret) { dev_err(di->dev, "failed to register AC charger\n"); goto free_charger_wq; } /* Register USB charger class */ - ret = power_supply_register(di->dev, &di->usb_psy); + ret = power_supply_register(di->dev, &di->usb_chg.psy); if (ret) { dev_err(di->dev, "failed to register USB charger\n"); goto free_ac; @@ -2245,7 +2266,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) if (charger_status & AC_PW_CONN) { di->ac.charger_connected = 1; di->ac_conn = true; - power_supply_changed(&di->ac_psy); + power_supply_changed(&di->ac_chg.psy); } if (charger_status & USB_PW_CONN) { @@ -2278,7 +2299,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) return ret; free_irq: - power_supply_unregister(&di->usb_psy); + power_supply_unregister(&di->usb_chg.psy); /* We also have to free all successfully registered irqs */ for (i = i - 1; i >= 0; i--) { @@ -2286,7 +2307,7 @@ free_irq: free_irq(irq, di); } free_ac: - power_supply_unregister(&di->ac_psy); + power_supply_unregister(&di->ac_chg.psy); free_charger_wq: destroy_workqueue(di->charger_wq); free_device_info: diff --git a/include/linux/mfd/ab8500/ab8500-bm.h b/include/linux/mfd/ab8500/ab8500-bm.h index 82a0c15ffda..d99a150f992 100644 --- a/include/linux/mfd/ab8500/ab8500-bm.h +++ b/include/linux/mfd/ab8500/ab8500-bm.h @@ -260,15 +260,8 @@ struct v_to_cap { }; /* Forward declaration */ -struct ab8500_charger; struct ab8500_fg; -struct ab8500_charger_ops { - int (*ac_en) (struct ab8500_charger *, int, int, int); - int (*usb_en) (struct ab8500_charger *, int, int, int); - int (*kick_watchdog) (struct ab8500_charger *); -}; - /** * struct ab8500_fg_parameters - Fuel gauge algorithm parameters, in seconds * if not specified @@ -394,7 +387,6 @@ struct ab8500_bm_charger_parameters { * @cap_levels capacity in percent for the different capacity levels * @pcb_ntc table with resistance to temp for PCB mounted NTC * @bat_type table of supported battery types - * @charger_ops pointers to the charger functions used by the algorithm * @chg_params charger parameters * @fg_params fuel gauge parameters */ @@ -416,7 +408,6 @@ struct ab8500_bm_data { struct ab8500_bm_capacity_levels *cap_levels; struct res_to_temp *pcb_ntc; struct battery_type *bat_type; - struct ab8500_charger_ops charger_ops; const struct ab8500_bm_charger_parameters *chg_params; const struct ab8500_fg_parameters *fg_params; }; diff --git a/include/linux/mfd/ab8500/ux500_chargalg.h b/include/linux/mfd/ab8500/ux500_chargalg.h new file mode 100644 index 00000000000..2048ab65c8f --- /dev/null +++ b/include/linux/mfd/ab8500/ux500_chargalg.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef _UX500_CHARGALG_H +#define _UX500_CHARGALG_H + +#include <linux/power_supply.h> + +#define psy_to_ux500_charger(x) container_of((x), \ + struct ux500_charger, psy) + +/* Forward declaration */ +struct ux500_charger; + +struct ux500_charger_ops { + int (*enable) (struct ux500_charger *, int, int, int); + int (*kick_wd) (struct ux500_charger *); +}; + +/** + * struct ux500_charger - power supply ux500 charger sub class + * @psy power supply base class + * @ops ux500 charger operations + * @max_out_volt maximum output charger voltage in mV + * @max_out_curr maximum output charger current in mA + */ +struct ux500_charger { + struct power_supply psy; + struct ux500_charger_ops ops; + int max_out_volt; + int max_out_curr; +}; + +#endif |