Commit ea0ca3a843babd50c22dfbb5cf2d9a14df821b2b

Authored by Linus Torvalds

Merge git://git.infradead.org/battery-2.6

* git://git.infradead.org/battery-2.6:
  PXA: Use dev_pm_ops in z2_battery
  ds2760_battery: Fix rated capacity of the hx4700 1800mAh battery
  ds2760_battery: Fix indexing of the 4 active full EEPROM registers
  power: Make test_power driver more dynamic.
  bq27x00_battery: Name of cycle count property
  max8903_charger: Add GENERIC_HARDIRQS as a dependency (fixes S390 build)
  ARM: RX-51: Enable isp1704 power on/off
  isp1704_charger: Allow board specific powering routine
  gpio-charger: Add gpio_charger_resume
  power_supply: Add driver for MAX8903 charger

Showing 12 changed files Side-by-side Diff

arch/arm/mach-omap2/board-rx51-peripherals.c
... ... @@ -23,6 +23,7 @@
23 23 #include <linux/gpio.h>
24 24 #include <linux/gpio_keys.h>
25 25 #include <linux/mmc/host.h>
  26 +#include <linux/power/isp1704_charger.h>
26 27  
27 28 #include <plat/mcspi.h>
28 29 #include <plat/board.h>
... ... @@ -53,6 +54,8 @@
53 54 #define RX51_FMTX_RESET_GPIO 163
54 55 #define RX51_FMTX_IRQ 53
55 56  
  57 +#define RX51_USB_TRANSCEIVER_RST_GPIO 67
  58 +
56 59 /* list all spi devices here */
57 60 enum {
58 61 RX51_SPI_WL1251,
59 62  
60 63  
... ... @@ -111,10 +114,30 @@
111 114 },
112 115 };
113 116  
  117 +static void rx51_charger_set_power(bool on)
  118 +{
  119 + gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on);
  120 +}
  121 +
  122 +static struct isp1704_charger_data rx51_charger_data = {
  123 + .set_power = rx51_charger_set_power,
  124 +};
  125 +
114 126 static struct platform_device rx51_charger_device = {
115   - .name = "isp1704_charger",
  127 + .name = "isp1704_charger",
  128 + .dev = {
  129 + .platform_data = &rx51_charger_data,
  130 + },
116 131 };
117 132  
  133 +static void __init rx51_charger_init(void)
  134 +{
  135 + WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO,
  136 + GPIOF_OUT_INIT_LOW, "isp1704_reset"));
  137 +
  138 + platform_device_register(&rx51_charger_device);
  139 +}
  140 +
118 141 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
119 142  
120 143 #define RX51_GPIO_CAMERA_LENS_COVER 110
... ... @@ -961,6 +984,6 @@
961 984 if (partition)
962 985 omap2_hsmmc_init(mmc);
963 986  
964   - platform_device_register(&rx51_charger_device);
  987 + rx51_charger_init();
965 988 }
drivers/power/Kconfig
... ... @@ -210,6 +210,15 @@
210 210 Say Y to enable support for USB Charger Detection with
211 211 ISP1707/ISP1704 USB transceivers.
212 212  
  213 +config CHARGER_MAX8903
  214 + tristate "MAX8903 Battery DC-DC Charger for USB and Adapter Power"
  215 + depends on GENERIC_HARDIRQS
  216 + help
  217 + Say Y to enable support for the MAX8903 DC-DC charger and sysfs.
  218 + The driver supports controlling charger-enable and current-limit
  219 + pins based on the status of charger connections with interrupt
  220 + handlers.
  221 +
213 222 config CHARGER_TWL4030
214 223 tristate "OMAP TWL4030 BCI charger driver"
215 224 depends on TWL4030_CORE
drivers/power/Makefile
... ... @@ -33,6 +33,7 @@
33 33 obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
34 34 obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
35 35 obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
  36 +obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
36 37 obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
37 38 obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
drivers/power/bq27x00_battery.c
... ... @@ -4,6 +4,7 @@
4 4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
5 5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
6 6 * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
  7 + * Copyright (C) 2011 Pali Rohรกr <pali.rohar@gmail.com>
7 8 *
8 9 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
9 10 *
... ... @@ -76,7 +77,7 @@
76 77 int time_to_empty_avg;
77 78 int time_to_full;
78 79 int charge_full;
79   - int charge_counter;
  80 + int cycle_count;
80 81 int capacity;
81 82 int flags;
82 83  
... ... @@ -115,7 +116,7 @@
115 116 POWER_SUPPLY_PROP_CHARGE_FULL,
116 117 POWER_SUPPLY_PROP_CHARGE_NOW,
117 118 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
118   - POWER_SUPPLY_PROP_CHARGE_COUNTER,
  119 + POWER_SUPPLY_PROP_CYCLE_COUNT,
119 120 POWER_SUPPLY_PROP_ENERGY_NOW,
120 121 };
121 122  
... ... @@ -267,7 +268,7 @@
267 268 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
268 269 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
269 270 cache.charge_full = bq27x00_battery_read_lmd(di);
270   - cache.charge_counter = bq27x00_battery_read_cyct(di);
  271 + cache.cycle_count = bq27x00_battery_read_cyct(di);
271 272  
272 273 if (!is_bq27500)
273 274 cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
... ... @@ -496,8 +497,8 @@
496 497 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
497 498 ret = bq27x00_simple_value(di->charge_design_full, val);
498 499 break;
499   - case POWER_SUPPLY_PROP_CHARGE_COUNTER:
500   - ret = bq27x00_simple_value(di->cache.charge_counter, val);
  500 + case POWER_SUPPLY_PROP_CYCLE_COUNT:
  501 + ret = bq27x00_simple_value(di->cache.cycle_count, val);
501 502 break;
502 503 case POWER_SUPPLY_PROP_ENERGY_NOW:
503 504 ret = bq27x00_battery_energy(di, val);
drivers/power/ds2760_battery.c
... ... @@ -86,7 +86,11 @@
86 86 920, /* NEC */
87 87 1440, /* Samsung */
88 88 1440, /* BYD */
  89 +#ifdef CONFIG_MACH_H4700
  90 + 1800, /* HP iPAQ hx4700 3.7V 1800mAh (359113-001) */
  91 +#else
89 92 1440, /* Lishen */
  93 +#endif
90 94 1440, /* NEC */
91 95 2880, /* Samsung */
92 96 2880, /* BYD */
... ... @@ -186,7 +190,7 @@
186 190  
187 191 scale[0] = di->full_active_uAh;
188 192 for (i = 1; i < 5; i++)
189   - scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
  193 + scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 1 + i];
190 194  
191 195 di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
192 196 di->full_active_uAh *= 1000; /* convert to ยตAh */
drivers/power/gpio-charger.c
... ... @@ -161,12 +161,27 @@
161 161 return 0;
162 162 }
163 163  
  164 +#ifdef CONFIG_PM_SLEEP
  165 +static int gpio_charger_resume(struct device *dev)
  166 +{
  167 + struct platform_device *pdev = to_platform_device(dev);
  168 + struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
  169 +
  170 + power_supply_changed(&gpio_charger->charger);
  171 +
  172 + return 0;
  173 +}
  174 +#endif
  175 +
  176 +static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
  177 +
164 178 static struct platform_driver gpio_charger_driver = {
165 179 .probe = gpio_charger_probe,
166 180 .remove = __devexit_p(gpio_charger_remove),
167 181 .driver = {
168 182 .name = "gpio-charger",
169 183 .owner = THIS_MODULE,
  184 + .pm = &gpio_charger_pm_ops,
170 185 },
171 186 };
172 187  
drivers/power/isp1704_charger.c
... ... @@ -33,6 +33,7 @@
33 33 #include <linux/usb/ulpi.h>
34 34 #include <linux/usb/ch9.h>
35 35 #include <linux/usb/gadget.h>
  36 +#include <linux/power/isp1704_charger.h>
36 37  
37 38 /* Vendor specific Power Control register */
38 39 #define ISP1704_PWR_CTRL 0x3d
... ... @@ -71,6 +72,18 @@
71 72 };
72 73  
73 74 /*
  75 + * Disable/enable the power from the isp1704 if a function for it
  76 + * has been provided with platform data.
  77 + */
  78 +static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
  79 +{
  80 + struct isp1704_charger_data *board = isp->dev->platform_data;
  81 +
  82 + if (board->set_power)
  83 + board->set_power(on);
  84 +}
  85 +
  86 +/*
74 87 * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB
75 88 * chargers).
76 89 *
... ... @@ -222,6 +235,9 @@
222 235  
223 236 mutex_lock(&lock);
224 237  
  238 + if (event != USB_EVENT_NONE)
  239 + isp1704_charger_set_power(isp, 1);
  240 +
225 241 switch (event) {
226 242 case USB_EVENT_VBUS:
227 243 isp->online = true;
... ... @@ -269,6 +285,8 @@
269 285 */
270 286 if (isp->otg->gadget)
271 287 usb_gadget_disconnect(isp->otg->gadget);
  288 +
  289 + isp1704_charger_set_power(isp, 0);
272 290 break;
273 291 case USB_EVENT_ENUMERATED:
274 292 if (isp->present)
... ... @@ -394,6 +412,8 @@
394 412 isp->dev = &pdev->dev;
395 413 platform_set_drvdata(pdev, isp);
396 414  
  415 + isp1704_charger_set_power(isp, 1);
  416 +
397 417 ret = isp1704_test_ulpi(isp);
398 418 if (ret < 0)
399 419 goto fail1;
... ... @@ -434,6 +454,7 @@
434 454  
435 455 /* Detect charger if VBUS is valid (the cable was already plugged). */
436 456 ret = otg_io_read(isp->otg, ULPI_USB_INT_STS);
  457 + isp1704_charger_set_power(isp, 0);
437 458 if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) {
438 459 isp->event = USB_EVENT_VBUS;
439 460 schedule_work(&isp->work);
... ... @@ -459,6 +480,7 @@
459 480 otg_unregister_notifier(isp->otg, &isp->nb);
460 481 power_supply_unregister(&isp->psy);
461 482 otg_put_transceiver(isp->otg);
  483 + isp1704_charger_set_power(isp, 0);
462 484 kfree(isp);
463 485  
464 486 return 0;
drivers/power/max8903_charger.c
  1 +/*
  2 + * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver
  3 + *
  4 + * Copyright (C) 2011 Samsung Electronics
  5 + * MyungJoo Ham <myungjoo.ham@samsung.com>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + *
  21 + */
  22 +
  23 +#include <linux/gpio.h>
  24 +#include <linux/interrupt.h>
  25 +#include <linux/slab.h>
  26 +#include <linux/power_supply.h>
  27 +#include <linux/platform_device.h>
  28 +#include <linux/power/max8903_charger.h>
  29 +
  30 +struct max8903_data {
  31 + struct max8903_pdata *pdata;
  32 + struct device *dev;
  33 + struct power_supply psy;
  34 + bool fault;
  35 + bool usb_in;
  36 + bool ta_in;
  37 +};
  38 +
  39 +static enum power_supply_property max8903_charger_props[] = {
  40 + POWER_SUPPLY_PROP_STATUS, /* Charger status output */
  41 + POWER_SUPPLY_PROP_ONLINE, /* External power source */
  42 + POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */
  43 +};
  44 +
  45 +static int max8903_get_property(struct power_supply *psy,
  46 + enum power_supply_property psp,
  47 + union power_supply_propval *val)
  48 +{
  49 + struct max8903_data *data = container_of(psy,
  50 + struct max8903_data, psy);
  51 +
  52 + switch (psp) {
  53 + case POWER_SUPPLY_PROP_STATUS:
  54 + val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  55 + if (data->pdata->chg) {
  56 + if (gpio_get_value(data->pdata->chg) == 0)
  57 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
  58 + else if (data->usb_in || data->ta_in)
  59 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  60 + else
  61 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  62 + }
  63 + break;
  64 + case POWER_SUPPLY_PROP_ONLINE:
  65 + val->intval = 0;
  66 + if (data->usb_in || data->ta_in)
  67 + val->intval = 1;
  68 + break;
  69 + case POWER_SUPPLY_PROP_HEALTH:
  70 + val->intval = POWER_SUPPLY_HEALTH_GOOD;
  71 + if (data->fault)
  72 + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
  73 + break;
  74 + default:
  75 + return -EINVAL;
  76 + }
  77 + return 0;
  78 +}
  79 +
  80 +static irqreturn_t max8903_dcin(int irq, void *_data)
  81 +{
  82 + struct max8903_data *data = _data;
  83 + struct max8903_pdata *pdata = data->pdata;
  84 + bool ta_in;
  85 + enum power_supply_type old_type;
  86 +
  87 + ta_in = gpio_get_value(pdata->dok) ? false : true;
  88 +
  89 + if (ta_in == data->ta_in)
  90 + return IRQ_HANDLED;
  91 +
  92 + data->ta_in = ta_in;
  93 +
  94 + /* Set Current-Limit-Mode 1:DC 0:USB */
  95 + if (pdata->dcm)
  96 + gpio_set_value(pdata->dcm, ta_in ? 1 : 0);
  97 +
  98 + /* Charger Enable / Disable (cen is negated) */
  99 + if (pdata->cen)
  100 + gpio_set_value(pdata->cen, ta_in ? 0 :
  101 + (data->usb_in ? 0 : 1));
  102 +
  103 + dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
  104 + "Connected" : "Disconnected");
  105 +
  106 + old_type = data->psy.type;
  107 +
  108 + if (data->ta_in)
  109 + data->psy.type = POWER_SUPPLY_TYPE_MAINS;
  110 + else if (data->usb_in)
  111 + data->psy.type = POWER_SUPPLY_TYPE_USB;
  112 + else
  113 + data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
  114 +
  115 + if (old_type != data->psy.type)
  116 + power_supply_changed(&data->psy);
  117 +
  118 + return IRQ_HANDLED;
  119 +}
  120 +
  121 +static irqreturn_t max8903_usbin(int irq, void *_data)
  122 +{
  123 + struct max8903_data *data = _data;
  124 + struct max8903_pdata *pdata = data->pdata;
  125 + bool usb_in;
  126 + enum power_supply_type old_type;
  127 +
  128 + usb_in = gpio_get_value(pdata->uok) ? false : true;
  129 +
  130 + if (usb_in == data->usb_in)
  131 + return IRQ_HANDLED;
  132 +
  133 + data->usb_in = usb_in;
  134 +
  135 + /* Do not touch Current-Limit-Mode */
  136 +
  137 + /* Charger Enable / Disable (cen is negated) */
  138 + if (pdata->cen)
  139 + gpio_set_value(pdata->cen, usb_in ? 0 :
  140 + (data->ta_in ? 0 : 1));
  141 +
  142 + dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
  143 + "Connected" : "Disconnected");
  144 +
  145 + old_type = data->psy.type;
  146 +
  147 + if (data->ta_in)
  148 + data->psy.type = POWER_SUPPLY_TYPE_MAINS;
  149 + else if (data->usb_in)
  150 + data->psy.type = POWER_SUPPLY_TYPE_USB;
  151 + else
  152 + data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
  153 +
  154 + if (old_type != data->psy.type)
  155 + power_supply_changed(&data->psy);
  156 +
  157 + return IRQ_HANDLED;
  158 +}
  159 +
  160 +static irqreturn_t max8903_fault(int irq, void *_data)
  161 +{
  162 + struct max8903_data *data = _data;
  163 + struct max8903_pdata *pdata = data->pdata;
  164 + bool fault;
  165 +
  166 + fault = gpio_get_value(pdata->flt) ? false : true;
  167 +
  168 + if (fault == data->fault)
  169 + return IRQ_HANDLED;
  170 +
  171 + data->fault = fault;
  172 +
  173 + if (fault)
  174 + dev_err(data->dev, "Charger suffers a fault and stops.\n");
  175 + else
  176 + dev_err(data->dev, "Charger recovered from a fault.\n");
  177 +
  178 + return IRQ_HANDLED;
  179 +}
  180 +
  181 +static __devinit int max8903_probe(struct platform_device *pdev)
  182 +{
  183 + struct max8903_data *data;
  184 + struct device *dev = &pdev->dev;
  185 + struct max8903_pdata *pdata = pdev->dev.platform_data;
  186 + int ret = 0;
  187 + int gpio;
  188 + int ta_in = 0;
  189 + int usb_in = 0;
  190 +
  191 + data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL);
  192 + if (data == NULL) {
  193 + dev_err(dev, "Cannot allocate memory.\n");
  194 + return -ENOMEM;
  195 + }
  196 + data->pdata = pdata;
  197 + data->dev = dev;
  198 + platform_set_drvdata(pdev, data);
  199 +
  200 + if (pdata->dc_valid == false && pdata->usb_valid == false) {
  201 + dev_err(dev, "No valid power sources.\n");
  202 + ret = -EINVAL;
  203 + goto err;
  204 + }
  205 +
  206 + if (pdata->dc_valid) {
  207 + if (pdata->dok && gpio_is_valid(pdata->dok) &&
  208 + pdata->dcm && gpio_is_valid(pdata->dcm)) {
  209 + gpio = pdata->dok; /* PULL_UPed Interrupt */
  210 + ta_in = gpio_get_value(gpio) ? 0 : 1;
  211 +
  212 + gpio = pdata->dcm; /* Output */
  213 + gpio_set_value(gpio, ta_in);
  214 + } else {
  215 + dev_err(dev, "When DC is wired, DOK and DCM should"
  216 + " be wired as well.\n");
  217 + ret = -EINVAL;
  218 + goto err;
  219 + }
  220 + } else {
  221 + if (pdata->dcm) {
  222 + if (gpio_is_valid(pdata->dcm))
  223 + gpio_set_value(pdata->dcm, 0);
  224 + else {
  225 + dev_err(dev, "Invalid pin: dcm.\n");
  226 + ret = -EINVAL;
  227 + goto err;
  228 + }
  229 + }
  230 + }
  231 +
  232 + if (pdata->usb_valid) {
  233 + if (pdata->uok && gpio_is_valid(pdata->uok)) {
  234 + gpio = pdata->uok;
  235 + usb_in = gpio_get_value(gpio) ? 0 : 1;
  236 + } else {
  237 + dev_err(dev, "When USB is wired, UOK should be wired."
  238 + "as well.\n");
  239 + ret = -EINVAL;
  240 + goto err;
  241 + }
  242 + }
  243 +
  244 + if (pdata->cen) {
  245 + if (gpio_is_valid(pdata->cen)) {
  246 + gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
  247 + } else {
  248 + dev_err(dev, "Invalid pin: cen.\n");
  249 + ret = -EINVAL;
  250 + goto err;
  251 + }
  252 + }
  253 +
  254 + if (pdata->chg) {
  255 + if (!gpio_is_valid(pdata->chg)) {
  256 + dev_err(dev, "Invalid pin: chg.\n");
  257 + ret = -EINVAL;
  258 + goto err;
  259 + }
  260 + }
  261 +
  262 + if (pdata->flt) {
  263 + if (!gpio_is_valid(pdata->flt)) {
  264 + dev_err(dev, "Invalid pin: flt.\n");
  265 + ret = -EINVAL;
  266 + goto err;
  267 + }
  268 + }
  269 +
  270 + if (pdata->usus) {
  271 + if (!gpio_is_valid(pdata->usus)) {
  272 + dev_err(dev, "Invalid pin: usus.\n");
  273 + ret = -EINVAL;
  274 + goto err;
  275 + }
  276 + }
  277 +
  278 + data->fault = false;
  279 + data->ta_in = ta_in;
  280 + data->usb_in = usb_in;
  281 +
  282 + data->psy.name = "max8903_charger";
  283 + data->psy.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS :
  284 + ((usb_in) ? POWER_SUPPLY_TYPE_USB :
  285 + POWER_SUPPLY_TYPE_BATTERY);
  286 + data->psy.get_property = max8903_get_property;
  287 + data->psy.properties = max8903_charger_props;
  288 + data->psy.num_properties = ARRAY_SIZE(max8903_charger_props);
  289 +
  290 + ret = power_supply_register(dev, &data->psy);
  291 + if (ret) {
  292 + dev_err(dev, "failed: power supply register.\n");
  293 + goto err;
  294 + }
  295 +
  296 + if (pdata->dc_valid) {
  297 + ret = request_threaded_irq(gpio_to_irq(pdata->dok),
  298 + NULL, max8903_dcin,
  299 + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
  300 + "MAX8903 DC IN", data);
  301 + if (ret) {
  302 + dev_err(dev, "Cannot request irq %d for DC (%d)\n",
  303 + gpio_to_irq(pdata->dok), ret);
  304 + goto err_psy;
  305 + }
  306 + }
  307 +
  308 + if (pdata->usb_valid) {
  309 + ret = request_threaded_irq(gpio_to_irq(pdata->uok),
  310 + NULL, max8903_usbin,
  311 + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
  312 + "MAX8903 USB IN", data);
  313 + if (ret) {
  314 + dev_err(dev, "Cannot request irq %d for USB (%d)\n",
  315 + gpio_to_irq(pdata->uok), ret);
  316 + goto err_dc_irq;
  317 + }
  318 + }
  319 +
  320 + if (pdata->flt) {
  321 + ret = request_threaded_irq(gpio_to_irq(pdata->flt),
  322 + NULL, max8903_fault,
  323 + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
  324 + "MAX8903 Fault", data);
  325 + if (ret) {
  326 + dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
  327 + gpio_to_irq(pdata->flt), ret);
  328 + goto err_usb_irq;
  329 + }
  330 + }
  331 +
  332 + return 0;
  333 +
  334 +err_usb_irq:
  335 + if (pdata->usb_valid)
  336 + free_irq(gpio_to_irq(pdata->uok), data);
  337 +err_dc_irq:
  338 + if (pdata->dc_valid)
  339 + free_irq(gpio_to_irq(pdata->dok), data);
  340 +err_psy:
  341 + power_supply_unregister(&data->psy);
  342 +err:
  343 + kfree(data);
  344 + return ret;
  345 +}
  346 +
  347 +static __devexit int max8903_remove(struct platform_device *pdev)
  348 +{
  349 + struct max8903_data *data = platform_get_drvdata(pdev);
  350 +
  351 + if (data) {
  352 + struct max8903_pdata *pdata = data->pdata;
  353 +
  354 + if (pdata->flt)
  355 + free_irq(gpio_to_irq(pdata->flt), data);
  356 + if (pdata->usb_valid)
  357 + free_irq(gpio_to_irq(pdata->uok), data);
  358 + if (pdata->dc_valid)
  359 + free_irq(gpio_to_irq(pdata->dok), data);
  360 + power_supply_unregister(&data->psy);
  361 + kfree(data);
  362 + }
  363 +
  364 + return 0;
  365 +}
  366 +
  367 +static struct platform_driver max8903_driver = {
  368 + .probe = max8903_probe,
  369 + .remove = __devexit_p(max8903_remove),
  370 + .driver = {
  371 + .name = "max8903-charger",
  372 + .owner = THIS_MODULE,
  373 + },
  374 +};
  375 +
  376 +static int __init max8903_init(void)
  377 +{
  378 + return platform_driver_register(&max8903_driver);
  379 +}
  380 +module_init(max8903_init);
  381 +
  382 +static void __exit max8903_exit(void)
  383 +{
  384 + platform_driver_unregister(&max8903_driver);
  385 +}
  386 +module_exit(max8903_exit);
  387 +
  388 +MODULE_LICENSE("GPL");
  389 +MODULE_DESCRIPTION("MAX8903 Charger Driver");
  390 +MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
  391 +MODULE_ALIAS("max8903-charger");
drivers/power/test_power.c
... ... @@ -3,6 +3,12 @@
3 3 *
4 4 * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com>
5 5 *
  6 + * Dynamic module parameter code from the Virtual Battery Driver
  7 + * Copyright (C) 2008 Pylone, Inc.
  8 + * By: Masashi YOKOTA <yokota@pylone.jp>
  9 + * Originally found here:
  10 + * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2
  11 + *
6 12 * This program is free software; you can redistribute it and/or modify
7 13 * it under the terms of the GNU General Public License version 2 as
8 14 * published by the Free Software Foundation.
... ... @@ -15,8 +21,12 @@
15 21 #include <linux/delay.h>
16 22 #include <linux/vermagic.h>
17 23  
18   -static int test_power_ac_online = 1;
19   -static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING;
  24 +static int ac_online = 1;
  25 +static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
  26 +static int battery_health = POWER_SUPPLY_HEALTH_GOOD;
  27 +static int battery_present = 1; /* true */
  28 +static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION;
  29 +static int battery_capacity = 50;
20 30  
21 31 static int test_power_get_ac_property(struct power_supply *psy,
22 32 enum power_supply_property psp,
... ... @@ -24,7 +34,7 @@
24 34 {
25 35 switch (psp) {
26 36 case POWER_SUPPLY_PROP_ONLINE:
27   - val->intval = test_power_ac_online;
  37 + val->intval = ac_online;
28 38 break;
29 39 default:
30 40 return -EINVAL;
31 41  
32 42  
33 43  
34 44  
35 45  
... ... @@ -47,23 +57,31 @@
47 57 val->strval = UTS_RELEASE;
48 58 break;
49 59 case POWER_SUPPLY_PROP_STATUS:
50   - val->intval = test_power_battery_status;
  60 + val->intval = battery_status;
51 61 break;
52 62 case POWER_SUPPLY_PROP_CHARGE_TYPE:
53 63 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
54 64 break;
55 65 case POWER_SUPPLY_PROP_HEALTH:
56   - val->intval = POWER_SUPPLY_HEALTH_GOOD;
  66 + val->intval = battery_health;
57 67 break;
  68 + case POWER_SUPPLY_PROP_PRESENT:
  69 + val->intval = battery_present;
  70 + break;
58 71 case POWER_SUPPLY_PROP_TECHNOLOGY:
59   - val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
  72 + val->intval = battery_technology;
60 73 break;
61 74 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
62 75 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
63 76 break;
64 77 case POWER_SUPPLY_PROP_CAPACITY:
65   - val->intval = 50;
  78 + case POWER_SUPPLY_PROP_CHARGE_NOW:
  79 + val->intval = battery_capacity;
66 80 break;
  81 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  82 + case POWER_SUPPLY_PROP_CHARGE_FULL:
  83 + val->intval = 100;
  84 + break;
67 85 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
68 86 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
69 87 val->intval = 3600;
70 88  
71 89  
... ... @@ -84,9 +102,11 @@
84 102 POWER_SUPPLY_PROP_STATUS,
85 103 POWER_SUPPLY_PROP_CHARGE_TYPE,
86 104 POWER_SUPPLY_PROP_HEALTH,
  105 + POWER_SUPPLY_PROP_PRESENT,
87 106 POWER_SUPPLY_PROP_TECHNOLOGY,
  107 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
88 108 POWER_SUPPLY_PROP_CHARGE_FULL,
89   - POWER_SUPPLY_PROP_CHARGE_EMPTY,
  109 + POWER_SUPPLY_PROP_CHARGE_NOW,
90 110 POWER_SUPPLY_PROP_CAPACITY,
91 111 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
92 112 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
... ... @@ -118,6 +138,7 @@
118 138 },
119 139 };
120 140  
  141 +
121 142 static int __init test_power_init(void)
122 143 {
123 144 int i;
... ... @@ -145,8 +166,8 @@
145 166 int i;
146 167  
147 168 /* Let's see how we handle changes... */
148   - test_power_ac_online = 0;
149   - test_power_battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
  169 + ac_online = 0;
  170 + battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
150 171 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
151 172 power_supply_changed(&test_power_supplies[i]);
152 173 pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
... ... @@ -157,6 +178,241 @@
157 178 power_supply_unregister(&test_power_supplies[i]);
158 179 }
159 180 module_exit(test_power_exit);
  181 +
  182 +
  183 +
  184 +#define MAX_KEYLENGTH 256
  185 +struct battery_property_map {
  186 + int value;
  187 + char const *key;
  188 +};
  189 +
  190 +static struct battery_property_map map_ac_online[] = {
  191 + { 0, "on" },
  192 + { 1, "off" },
  193 + { -1, NULL },
  194 +};
  195 +
  196 +static struct battery_property_map map_status[] = {
  197 + { POWER_SUPPLY_STATUS_CHARGING, "charging" },
  198 + { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" },
  199 + { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" },
  200 + { POWER_SUPPLY_STATUS_FULL, "full" },
  201 + { -1, NULL },
  202 +};
  203 +
  204 +static struct battery_property_map map_health[] = {
  205 + { POWER_SUPPLY_HEALTH_GOOD, "good" },
  206 + { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" },
  207 + { POWER_SUPPLY_HEALTH_DEAD, "dead" },
  208 + { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" },
  209 + { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" },
  210 + { -1, NULL },
  211 +};
  212 +
  213 +static struct battery_property_map map_present[] = {
  214 + { 0, "false" },
  215 + { 1, "true" },
  216 + { -1, NULL },
  217 +};
  218 +
  219 +static struct battery_property_map map_technology[] = {
  220 + { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" },
  221 + { POWER_SUPPLY_TECHNOLOGY_LION, "LION" },
  222 + { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" },
  223 + { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" },
  224 + { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" },
  225 + { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" },
  226 + { -1, NULL },
  227 +};
  228 +
  229 +
  230 +static int map_get_value(struct battery_property_map *map, const char *key,
  231 + int def_val)
  232 +{
  233 + char buf[MAX_KEYLENGTH];
  234 + int cr;
  235 +
  236 + strncpy(buf, key, MAX_KEYLENGTH);
  237 + buf[MAX_KEYLENGTH-1] = '\0';
  238 +
  239 + cr = strnlen(buf, MAX_KEYLENGTH) - 1;
  240 + if (buf[cr] == '\n')
  241 + buf[cr] = '\0';
  242 +
  243 + while (map->key) {
  244 + if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0)
  245 + return map->value;
  246 + map++;
  247 + }
  248 +
  249 + return def_val;
  250 +}
  251 +
  252 +
  253 +static const char *map_get_key(struct battery_property_map *map, int value,
  254 + const char *def_key)
  255 +{
  256 + while (map->key) {
  257 + if (map->value == value)
  258 + return map->key;
  259 + map++;
  260 + }
  261 +
  262 + return def_key;
  263 +}
  264 +
  265 +static int param_set_ac_online(const char *key, const struct kernel_param *kp)
  266 +{
  267 + ac_online = map_get_value(map_ac_online, key, ac_online);
  268 + power_supply_changed(&test_power_supplies[0]);
  269 + return 0;
  270 +}
  271 +
  272 +static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
  273 +{
  274 + strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown"));
  275 + return strlen(buffer);
  276 +}
  277 +
  278 +static int param_set_battery_status(const char *key,
  279 + const struct kernel_param *kp)
  280 +{
  281 + battery_status = map_get_value(map_status, key, battery_status);
  282 + power_supply_changed(&test_power_supplies[1]);
  283 + return 0;
  284 +}
  285 +
  286 +static int param_get_battery_status(char *buffer, const struct kernel_param *kp)
  287 +{
  288 + strcpy(buffer, map_get_key(map_status, battery_status, "unknown"));
  289 + return strlen(buffer);
  290 +}
  291 +
  292 +static int param_set_battery_health(const char *key,
  293 + const struct kernel_param *kp)
  294 +{
  295 + battery_health = map_get_value(map_health, key, battery_health);
  296 + power_supply_changed(&test_power_supplies[1]);
  297 + return 0;
  298 +}
  299 +
  300 +static int param_get_battery_health(char *buffer, const struct kernel_param *kp)
  301 +{
  302 + strcpy(buffer, map_get_key(map_health, battery_health, "unknown"));
  303 + return strlen(buffer);
  304 +}
  305 +
  306 +static int param_set_battery_present(const char *key,
  307 + const struct kernel_param *kp)
  308 +{
  309 + battery_present = map_get_value(map_present, key, battery_present);
  310 + power_supply_changed(&test_power_supplies[0]);
  311 + return 0;
  312 +}
  313 +
  314 +static int param_get_battery_present(char *buffer,
  315 + const struct kernel_param *kp)
  316 +{
  317 + strcpy(buffer, map_get_key(map_present, battery_present, "unknown"));
  318 + return strlen(buffer);
  319 +}
  320 +
  321 +static int param_set_battery_technology(const char *key,
  322 + const struct kernel_param *kp)
  323 +{
  324 + battery_technology = map_get_value(map_technology, key,
  325 + battery_technology);
  326 + power_supply_changed(&test_power_supplies[1]);
  327 + return 0;
  328 +}
  329 +
  330 +static int param_get_battery_technology(char *buffer,
  331 + const struct kernel_param *kp)
  332 +{
  333 + strcpy(buffer,
  334 + map_get_key(map_technology, battery_technology, "unknown"));
  335 + return strlen(buffer);
  336 +}
  337 +
  338 +static int param_set_battery_capacity(const char *key,
  339 + const struct kernel_param *kp)
  340 +{
  341 + int tmp;
  342 +
  343 + if (1 != sscanf(key, "%d", &tmp))
  344 + return -EINVAL;
  345 +
  346 + battery_capacity = tmp;
  347 + power_supply_changed(&test_power_supplies[1]);
  348 + return 0;
  349 +}
  350 +
  351 +#define param_get_battery_capacity param_get_int
  352 +
  353 +
  354 +
  355 +static struct kernel_param_ops param_ops_ac_online = {
  356 + .set = param_set_ac_online,
  357 + .get = param_get_ac_online,
  358 +};
  359 +
  360 +static struct kernel_param_ops param_ops_battery_status = {
  361 + .set = param_set_battery_status,
  362 + .get = param_get_battery_status,
  363 +};
  364 +
  365 +static struct kernel_param_ops param_ops_battery_present = {
  366 + .set = param_set_battery_present,
  367 + .get = param_get_battery_present,
  368 +};
  369 +
  370 +static struct kernel_param_ops param_ops_battery_technology = {
  371 + .set = param_set_battery_technology,
  372 + .get = param_get_battery_technology,
  373 +};
  374 +
  375 +static struct kernel_param_ops param_ops_battery_health = {
  376 + .set = param_set_battery_health,
  377 + .get = param_get_battery_health,
  378 +};
  379 +
  380 +static struct kernel_param_ops param_ops_battery_capacity = {
  381 + .set = param_set_battery_capacity,
  382 + .get = param_get_battery_capacity,
  383 +};
  384 +
  385 +
  386 +#define param_check_ac_online(name, p) __param_check(name, p, void);
  387 +#define param_check_battery_status(name, p) __param_check(name, p, void);
  388 +#define param_check_battery_present(name, p) __param_check(name, p, void);
  389 +#define param_check_battery_technology(name, p) __param_check(name, p, void);
  390 +#define param_check_battery_health(name, p) __param_check(name, p, void);
  391 +#define param_check_battery_capacity(name, p) __param_check(name, p, void);
  392 +
  393 +
  394 +module_param(ac_online, ac_online, 0644);
  395 +MODULE_PARM_DESC(ac_online, "AC charging state <on|off>");
  396 +
  397 +module_param(battery_status, battery_status, 0644);
  398 +MODULE_PARM_DESC(battery_status,
  399 + "battery status <charging|discharging|not-charging|full>");
  400 +
  401 +module_param(battery_present, battery_present, 0644);
  402 +MODULE_PARM_DESC(battery_present,
  403 + "battery presence state <good|overheat|dead|overvoltage|failure>");
  404 +
  405 +module_param(battery_technology, battery_technology, 0644);
  406 +MODULE_PARM_DESC(battery_technology,
  407 + "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
  408 +
  409 +module_param(battery_health, battery_health, 0644);
  410 +MODULE_PARM_DESC(battery_health,
  411 + "battery health state <good|overheat|dead|overvoltage|failure>");
  412 +
  413 +module_param(battery_capacity, battery_capacity, 0644);
  414 +MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)");
  415 +
160 416  
161 417 MODULE_DESCRIPTION("Power supply driver for testing");
162 418 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
drivers/power/z2_battery.c
... ... @@ -271,24 +271,33 @@
271 271 }
272 272  
273 273 #ifdef CONFIG_PM
274   -static int z2_batt_suspend(struct i2c_client *client, pm_message_t state)
  274 +static int z2_batt_suspend(struct device *dev)
275 275 {
  276 + struct i2c_client *client = to_i2c_client(dev);
276 277 struct z2_charger *charger = i2c_get_clientdata(client);
277 278  
278 279 flush_work_sync(&charger->bat_work);
279 280 return 0;
280 281 }
281 282  
282   -static int z2_batt_resume(struct i2c_client *client)
  283 +static int z2_batt_resume(struct device *dev)
283 284 {
  285 + struct i2c_client *client = to_i2c_client(dev);
284 286 struct z2_charger *charger = i2c_get_clientdata(client);
285 287  
286 288 schedule_work(&charger->bat_work);
287 289 return 0;
288 290 }
  291 +
  292 +static const struct dev_pm_ops z2_battery_pm_ops = {
  293 + .suspend = z2_batt_suspend,
  294 + .resume = z2_batt_resume,
  295 +};
  296 +
  297 +#define Z2_BATTERY_PM_OPS (&z2_battery_pm_ops)
  298 +
289 299 #else
290   -#define z2_batt_suspend NULL
291   -#define z2_batt_resume NULL
  300 +#define Z2_BATTERY_PM_OPS (NULL)
292 301 #endif
293 302  
294 303 static const struct i2c_device_id z2_batt_id[] = {
295 304  
... ... @@ -301,11 +310,10 @@
301 310 .driver = {
302 311 .name = "z2-battery",
303 312 .owner = THIS_MODULE,
  313 + .pm = Z2_BATTERY_PM_OPS
304 314 },
305 315 .probe = z2_batt_probe,
306 316 .remove = z2_batt_remove,
307   - .suspend = z2_batt_suspend,
308   - .resume = z2_batt_resume,
309 317 .id_table = z2_batt_id,
310 318 };
311 319  
include/linux/power/isp1704_charger.h
  1 +/*
  2 + * ISP1704 USB Charger Detection driver
  3 + *
  4 + * Copyright (C) 2011 Nokia Corporation
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +
  21 +
  22 +#ifndef __ISP1704_CHARGER_H
  23 +#define __ISP1704_CHARGER_H
  24 +
  25 +struct isp1704_charger_data {
  26 + void (*set_power)(bool on);
  27 +};
  28 +
  29 +#endif
include/linux/power/max8903_charger.h
  1 +/*
  2 + * max8903_charger.h - Maxim 8903 USB/Adapter Charger Driver
  3 + *
  4 + * Copyright (C) 2011 Samsung Electronics
  5 + * MyungJoo Ham <myungjoo.ham@samsung.com>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + *
  21 + */
  22 +
  23 +#ifndef __MAX8903_CHARGER_H__
  24 +#define __MAX8903_CHARGER_H__
  25 +
  26 +struct max8903_pdata {
  27 + /*
  28 + * GPIOs
  29 + * cen, chg, flt, and usus are optional.
  30 + * dok, dcm, and uok are not optional depending on the status of
  31 + * dc_valid and usb_valid.
  32 + */
  33 + int cen; /* Charger Enable input */
  34 + int dok; /* DC(Adapter) Power OK output */
  35 + int uok; /* USB Power OK output */
  36 + int chg; /* Charger status output */
  37 + int flt; /* Fault output */
  38 + int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */
  39 + int usus; /* USB Suspend Input (1: suspended) */
  40 +
  41 + /*
  42 + * DC(Adapter/TA) is wired
  43 + * When dc_valid is true,
  44 + * dok and dcm should be valid.
  45 + *
  46 + * At least one of dc_valid or usb_valid should be true.
  47 + */
  48 + bool dc_valid;
  49 + /*
  50 + * USB is wired
  51 + * When usb_valid is true,
  52 + * uok should be valid.
  53 + */
  54 + bool usb_valid;
  55 +};
  56 +
  57 +#endif /* __MAX8903_CHARGER_H__ */