diff options
-rw-r--r-- | drivers/power/Kconfig | 6 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/ds2782_battery.c | 3 | ||||
-rw-r--r-- | drivers/power/pda_power.c | 10 | ||||
-rw-r--r-- | drivers/power/wm831x_power.c | 33 | ||||
-rw-r--r-- | drivers/power/z2_battery.c | 328 | ||||
-rw-r--r-- | include/linux/pda_power.h | 2 | ||||
-rw-r--r-- | include/linux/z2_battery.h | 17 |
8 files changed, 380 insertions, 20 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index faaa9b4d0d07..22f2fa912127 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -125,6 +125,12 @@ config BATTERY_MAX17040 | |||
125 | in handheld and portable equipment. The MAX17040 is configured | 125 | in handheld and portable equipment. The MAX17040 is configured |
126 | to operate with a single lithium cell | 126 | to operate with a single lithium cell |
127 | 127 | ||
128 | config BATTERY_Z2 | ||
129 | tristate "Z2 battery driver" | ||
130 | depends on I2C && MACH_ZIPIT2 | ||
131 | help | ||
132 | Say Y to include support for the battery on the Zipit Z2. | ||
133 | |||
128 | config CHARGER_PCF50633 | 134 | config CHARGER_PCF50633 |
129 | tristate "NXP PCF50633 MBC" | 135 | tristate "NXP PCF50633 MBC" |
130 | depends on MFD_PCF50633 | 136 | depends on MFD_PCF50633 |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index a2ba7c85c97a..a82f292e5c94 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -31,4 +31,5 @@ obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o | |||
31 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | 31 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o |
32 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 32 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
33 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o | 33 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o |
34 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o | ||
34 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | 35 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o |
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 99c89976a902..ba1bd1a545be 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c | |||
@@ -237,8 +237,6 @@ static int ds2782_battery_remove(struct i2c_client *client) | |||
237 | idr_remove(&battery_id, info->id); | 237 | idr_remove(&battery_id, info->id); |
238 | mutex_unlock(&battery_lock); | 238 | mutex_unlock(&battery_lock); |
239 | 239 | ||
240 | i2c_set_clientdata(client, info); | ||
241 | |||
242 | kfree(info); | 240 | kfree(info); |
243 | return 0; | 241 | return 0; |
244 | } | 242 | } |
@@ -290,7 +288,6 @@ static int ds2782_battery_probe(struct i2c_client *client, | |||
290 | fail_register: | 288 | fail_register: |
291 | kfree(info->battery.name); | 289 | kfree(info->battery.name); |
292 | fail_name: | 290 | fail_name: |
293 | i2c_set_clientdata(client, info); | ||
294 | kfree(info); | 291 | kfree(info); |
295 | fail_info: | 292 | fail_info: |
296 | mutex_lock(&battery_lock); | 293 | mutex_lock(&battery_lock); |
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index a232de6a5703..69f8aa3a6a4b 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c | |||
@@ -404,6 +404,13 @@ static int usb_wakeup_enabled; | |||
404 | 404 | ||
405 | static int pda_power_suspend(struct platform_device *pdev, pm_message_t state) | 405 | static int pda_power_suspend(struct platform_device *pdev, pm_message_t state) |
406 | { | 406 | { |
407 | if (pdata->suspend) { | ||
408 | int ret = pdata->suspend(state); | ||
409 | |||
410 | if (ret) | ||
411 | return ret; | ||
412 | } | ||
413 | |||
407 | if (device_may_wakeup(&pdev->dev)) { | 414 | if (device_may_wakeup(&pdev->dev)) { |
408 | if (ac_irq) | 415 | if (ac_irq) |
409 | ac_wakeup_enabled = !enable_irq_wake(ac_irq->start); | 416 | ac_wakeup_enabled = !enable_irq_wake(ac_irq->start); |
@@ -423,6 +430,9 @@ static int pda_power_resume(struct platform_device *pdev) | |||
423 | disable_irq_wake(ac_irq->start); | 430 | disable_irq_wake(ac_irq->start); |
424 | } | 431 | } |
425 | 432 | ||
433 | if (pdata->resume) | ||
434 | return pdata->resume(); | ||
435 | |||
426 | return 0; | 436 | return 0; |
427 | } | 437 | } |
428 | #else | 438 | #else |
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 875c4d0f776b..fbcc36dae470 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -537,9 +537,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
537 | goto err_battery; | 537 | goto err_battery; |
538 | 538 | ||
539 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 539 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
540 | ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, | 540 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, |
541 | IRQF_TRIGGER_RISING, "SYSLO", | 541 | IRQF_TRIGGER_RISING, "System power low", |
542 | power); | 542 | power); |
543 | if (ret != 0) { | 543 | if (ret != 0) { |
544 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", | 544 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", |
545 | irq, ret); | 545 | irq, ret); |
@@ -547,9 +547,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
547 | } | 547 | } |
548 | 548 | ||
549 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 549 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
550 | ret = wm831x_request_irq(wm831x, irq, wm831x_pwr_src_irq, | 550 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, |
551 | IRQF_TRIGGER_RISING, "Power source", | 551 | IRQF_TRIGGER_RISING, "Power source", |
552 | power); | 552 | power); |
553 | if (ret != 0) { | 553 | if (ret != 0) { |
554 | dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", | 554 | dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", |
555 | irq, ret); | 555 | irq, ret); |
@@ -558,10 +558,10 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
558 | 558 | ||
559 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 559 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
560 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 560 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
561 | ret = wm831x_request_irq(wm831x, irq, wm831x_bat_irq, | 561 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, |
562 | IRQF_TRIGGER_RISING, | 562 | IRQF_TRIGGER_RISING, |
563 | wm831x_bat_irqs[i], | 563 | wm831x_bat_irqs[i], |
564 | power); | 564 | power); |
565 | if (ret != 0) { | 565 | if (ret != 0) { |
566 | dev_err(&pdev->dev, | 566 | dev_err(&pdev->dev, |
567 | "Failed to request %s IRQ %d: %d\n", | 567 | "Failed to request %s IRQ %d: %d\n", |
@@ -575,13 +575,13 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
575 | err_bat_irq: | 575 | err_bat_irq: |
576 | for (; i >= 0; i--) { | 576 | for (; i >= 0; i--) { |
577 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 577 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
578 | wm831x_free_irq(wm831x, irq, power); | 578 | free_irq(irq, power); |
579 | } | 579 | } |
580 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 580 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
581 | wm831x_free_irq(wm831x, irq, power); | 581 | free_irq(irq, power); |
582 | err_syslo: | 582 | err_syslo: |
583 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 583 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
584 | wm831x_free_irq(wm831x, irq, power); | 584 | free_irq(irq, power); |
585 | err_usb: | 585 | err_usb: |
586 | power_supply_unregister(usb); | 586 | power_supply_unregister(usb); |
587 | err_battery: | 587 | err_battery: |
@@ -596,19 +596,18 @@ err_kmalloc: | |||
596 | static __devexit int wm831x_power_remove(struct platform_device *pdev) | 596 | static __devexit int wm831x_power_remove(struct platform_device *pdev) |
597 | { | 597 | { |
598 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); | 598 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); |
599 | struct wm831x *wm831x = wm831x_power->wm831x; | ||
600 | int irq, i; | 599 | int irq, i; |
601 | 600 | ||
602 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 601 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
603 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 602 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
604 | wm831x_free_irq(wm831x, irq, wm831x_power); | 603 | free_irq(irq, wm831x_power); |
605 | } | 604 | } |
606 | 605 | ||
607 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 606 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
608 | wm831x_free_irq(wm831x, irq, wm831x_power); | 607 | free_irq(irq, wm831x_power); |
609 | 608 | ||
610 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 609 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
611 | wm831x_free_irq(wm831x, irq, wm831x_power); | 610 | free_irq(irq, wm831x_power); |
612 | 611 | ||
613 | power_supply_unregister(&wm831x_power->battery); | 612 | power_supply_unregister(&wm831x_power->battery); |
614 | power_supply_unregister(&wm831x_power->wall); | 613 | power_supply_unregister(&wm831x_power->wall); |
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c new file mode 100644 index 000000000000..9cca465436e3 --- /dev/null +++ b/drivers/power/z2_battery.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Battery measurement code for Zipit Z2 | ||
3 | * | ||
4 | * Copyright (C) 2009 Peter Edwards <sweetlilmre@gmail.com> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/power_supply.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/mach/irq.h> | ||
25 | #include <linux/z2_battery.h> | ||
26 | |||
27 | #define Z2_DEFAULT_NAME "Z2" | ||
28 | |||
29 | struct z2_charger { | ||
30 | struct z2_battery_info *info; | ||
31 | int bat_status; | ||
32 | struct i2c_client *client; | ||
33 | struct power_supply batt_ps; | ||
34 | struct mutex work_lock; | ||
35 | struct work_struct bat_work; | ||
36 | }; | ||
37 | |||
38 | static unsigned long z2_read_bat(struct z2_charger *charger) | ||
39 | { | ||
40 | int data; | ||
41 | data = i2c_smbus_read_byte_data(charger->client, | ||
42 | charger->info->batt_I2C_reg); | ||
43 | if (data < 0) | ||
44 | return 0; | ||
45 | |||
46 | return data * charger->info->batt_mult / charger->info->batt_div; | ||
47 | } | ||
48 | |||
49 | static int z2_batt_get_property(struct power_supply *batt_ps, | ||
50 | enum power_supply_property psp, | ||
51 | union power_supply_propval *val) | ||
52 | { | ||
53 | struct z2_charger *charger = container_of(batt_ps, struct z2_charger, | ||
54 | batt_ps); | ||
55 | struct z2_battery_info *info = charger->info; | ||
56 | |||
57 | switch (psp) { | ||
58 | case POWER_SUPPLY_PROP_STATUS: | ||
59 | val->intval = charger->bat_status; | ||
60 | break; | ||
61 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
62 | val->intval = info->batt_tech; | ||
63 | break; | ||
64 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
65 | if (info->batt_I2C_reg >= 0) | ||
66 | val->intval = z2_read_bat(charger); | ||
67 | else | ||
68 | return -EINVAL; | ||
69 | break; | ||
70 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | ||
71 | if (info->max_voltage >= 0) | ||
72 | val->intval = info->max_voltage; | ||
73 | else | ||
74 | return -EINVAL; | ||
75 | break; | ||
76 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: | ||
77 | if (info->min_voltage >= 0) | ||
78 | val->intval = info->min_voltage; | ||
79 | else | ||
80 | return -EINVAL; | ||
81 | break; | ||
82 | case POWER_SUPPLY_PROP_PRESENT: | ||
83 | val->intval = 1; | ||
84 | break; | ||
85 | default: | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static void z2_batt_ext_power_changed(struct power_supply *batt_ps) | ||
93 | { | ||
94 | struct z2_charger *charger = container_of(batt_ps, struct z2_charger, | ||
95 | batt_ps); | ||
96 | schedule_work(&charger->bat_work); | ||
97 | } | ||
98 | |||
99 | static void z2_batt_update(struct z2_charger *charger) | ||
100 | { | ||
101 | int old_status = charger->bat_status; | ||
102 | struct z2_battery_info *info; | ||
103 | |||
104 | info = charger->info; | ||
105 | |||
106 | mutex_lock(&charger->work_lock); | ||
107 | |||
108 | charger->bat_status = (info->charge_gpio >= 0) ? | ||
109 | (gpio_get_value(info->charge_gpio) ? | ||
110 | POWER_SUPPLY_STATUS_CHARGING : | ||
111 | POWER_SUPPLY_STATUS_DISCHARGING) : | ||
112 | POWER_SUPPLY_STATUS_UNKNOWN; | ||
113 | |||
114 | if (old_status != charger->bat_status) { | ||
115 | pr_debug("%s: %i -> %i\n", charger->batt_ps.name, old_status, | ||
116 | charger->bat_status); | ||
117 | power_supply_changed(&charger->batt_ps); | ||
118 | } | ||
119 | |||
120 | mutex_unlock(&charger->work_lock); | ||
121 | } | ||
122 | |||
123 | static void z2_batt_work(struct work_struct *work) | ||
124 | { | ||
125 | struct z2_charger *charger; | ||
126 | charger = container_of(work, struct z2_charger, bat_work); | ||
127 | z2_batt_update(charger); | ||
128 | } | ||
129 | |||
130 | static irqreturn_t z2_charge_switch_irq(int irq, void *devid) | ||
131 | { | ||
132 | struct z2_charger *charger = devid; | ||
133 | schedule_work(&charger->bat_work); | ||
134 | return IRQ_HANDLED; | ||
135 | } | ||
136 | |||
137 | static int z2_batt_ps_init(struct z2_charger *charger, int props) | ||
138 | { | ||
139 | int i = 0; | ||
140 | enum power_supply_property *prop; | ||
141 | struct z2_battery_info *info = charger->info; | ||
142 | |||
143 | if (info->batt_tech >= 0) | ||
144 | props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */ | ||
145 | if (info->batt_I2C_reg >= 0) | ||
146 | props++; /* POWER_SUPPLY_PROP_VOLTAGE_NOW */ | ||
147 | if (info->max_voltage >= 0) | ||
148 | props++; /* POWER_SUPPLY_PROP_VOLTAGE_MAX */ | ||
149 | if (info->min_voltage >= 0) | ||
150 | props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ | ||
151 | |||
152 | prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); | ||
153 | if (!prop) | ||
154 | return -ENOMEM; | ||
155 | |||
156 | prop[i++] = POWER_SUPPLY_PROP_PRESENT; | ||
157 | if (info->charge_gpio >= 0) | ||
158 | prop[i++] = POWER_SUPPLY_PROP_STATUS; | ||
159 | if (info->batt_tech >= 0) | ||
160 | prop[i++] = POWER_SUPPLY_PROP_TECHNOLOGY; | ||
161 | if (info->batt_I2C_reg >= 0) | ||
162 | prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_NOW; | ||
163 | if (info->max_voltage >= 0) | ||
164 | prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MAX; | ||
165 | if (info->min_voltage >= 0) | ||
166 | prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MIN; | ||
167 | |||
168 | if (!info->batt_name) { | ||
169 | dev_info(&charger->client->dev, | ||
170 | "Please consider setting proper battery " | ||
171 | "name in platform definition file, falling " | ||
172 | "back to name \" Z2_DEFAULT_NAME \"\n"); | ||
173 | charger->batt_ps.name = Z2_DEFAULT_NAME; | ||
174 | } else | ||
175 | charger->batt_ps.name = info->batt_name; | ||
176 | |||
177 | charger->batt_ps.properties = prop; | ||
178 | charger->batt_ps.num_properties = props; | ||
179 | charger->batt_ps.type = POWER_SUPPLY_TYPE_BATTERY; | ||
180 | charger->batt_ps.get_property = z2_batt_get_property; | ||
181 | charger->batt_ps.external_power_changed = z2_batt_ext_power_changed; | ||
182 | charger->batt_ps.use_for_apm = 1; | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int __devinit z2_batt_probe(struct i2c_client *client, | ||
188 | const struct i2c_device_id *id) | ||
189 | { | ||
190 | int ret = 0; | ||
191 | int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ | ||
192 | struct z2_charger *charger; | ||
193 | struct z2_battery_info *info = client->dev.platform_data; | ||
194 | |||
195 | if (info == NULL) { | ||
196 | dev_err(&client->dev, | ||
197 | "Please set platform device platform_data" | ||
198 | " to a valid z2_battery_info pointer!\n"); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | |||
202 | charger = kzalloc(sizeof(*charger), GFP_KERNEL); | ||
203 | if (charger == NULL) | ||
204 | return -ENOMEM; | ||
205 | |||
206 | charger->bat_status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
207 | charger->info = info; | ||
208 | charger->client = client; | ||
209 | i2c_set_clientdata(client, charger); | ||
210 | |||
211 | mutex_init(&charger->work_lock); | ||
212 | |||
213 | if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { | ||
214 | ret = gpio_request(info->charge_gpio, "BATT CHRG"); | ||
215 | if (ret) | ||
216 | goto err; | ||
217 | |||
218 | ret = gpio_direction_input(info->charge_gpio); | ||
219 | if (ret) | ||
220 | goto err2; | ||
221 | |||
222 | set_irq_type(gpio_to_irq(info->charge_gpio), | ||
223 | IRQ_TYPE_EDGE_BOTH); | ||
224 | ret = request_irq(gpio_to_irq(info->charge_gpio), | ||
225 | z2_charge_switch_irq, IRQF_DISABLED, | ||
226 | "AC Detect", charger); | ||
227 | if (ret) | ||
228 | goto err3; | ||
229 | } | ||
230 | |||
231 | ret = z2_batt_ps_init(charger, props); | ||
232 | if (ret) | ||
233 | goto err3; | ||
234 | |||
235 | INIT_WORK(&charger->bat_work, z2_batt_work); | ||
236 | |||
237 | ret = power_supply_register(&client->dev, &charger->batt_ps); | ||
238 | if (ret) | ||
239 | goto err4; | ||
240 | |||
241 | schedule_work(&charger->bat_work); | ||
242 | |||
243 | return 0; | ||
244 | |||
245 | err4: | ||
246 | kfree(charger->batt_ps.properties); | ||
247 | err3: | ||
248 | if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) | ||
249 | free_irq(gpio_to_irq(info->charge_gpio), charger); | ||
250 | err2: | ||
251 | if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) | ||
252 | gpio_free(info->charge_gpio); | ||
253 | err: | ||
254 | kfree(charger); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static int __devexit z2_batt_remove(struct i2c_client *client) | ||
259 | { | ||
260 | struct z2_charger *charger = i2c_get_clientdata(client); | ||
261 | struct z2_battery_info *info = charger->info; | ||
262 | |||
263 | flush_scheduled_work(); | ||
264 | power_supply_unregister(&charger->batt_ps); | ||
265 | |||
266 | kfree(charger->batt_ps.properties); | ||
267 | if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { | ||
268 | free_irq(gpio_to_irq(info->charge_gpio), charger); | ||
269 | gpio_free(info->charge_gpio); | ||
270 | } | ||
271 | |||
272 | kfree(charger); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | #ifdef CONFIG_PM | ||
278 | static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) | ||
279 | { | ||
280 | flush_scheduled_work(); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int z2_batt_resume(struct i2c_client *client) | ||
285 | { | ||
286 | struct z2_charger *charger = i2c_get_clientdata(client); | ||
287 | |||
288 | schedule_work(&charger->bat_work); | ||
289 | return 0; | ||
290 | } | ||
291 | #else | ||
292 | #define z2_batt_suspend NULL | ||
293 | #define z2_batt_resume NULL | ||
294 | #endif | ||
295 | |||
296 | static const struct i2c_device_id z2_batt_id[] = { | ||
297 | { "aer915", 0 }, | ||
298 | { } | ||
299 | }; | ||
300 | |||
301 | static struct i2c_driver z2_batt_driver = { | ||
302 | .driver = { | ||
303 | .name = "z2-battery", | ||
304 | .owner = THIS_MODULE, | ||
305 | }, | ||
306 | .probe = z2_batt_probe, | ||
307 | .remove = z2_batt_remove, | ||
308 | .suspend = z2_batt_suspend, | ||
309 | .resume = z2_batt_resume, | ||
310 | .id_table = z2_batt_id, | ||
311 | }; | ||
312 | |||
313 | static int __init z2_batt_init(void) | ||
314 | { | ||
315 | return i2c_add_driver(&z2_batt_driver); | ||
316 | } | ||
317 | |||
318 | static void __exit z2_batt_exit(void) | ||
319 | { | ||
320 | i2c_del_driver(&z2_batt_driver); | ||
321 | } | ||
322 | |||
323 | module_init(z2_batt_init); | ||
324 | module_exit(z2_batt_exit); | ||
325 | |||
326 | MODULE_LICENSE("GPL"); | ||
327 | MODULE_AUTHOR("Peter Edwards <sweetlilmre@gmail.com>"); | ||
328 | MODULE_DESCRIPTION("Zipit Z2 battery driver"); | ||
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h index d4cf7a2ceb3e..c9e4d814ff77 100644 --- a/include/linux/pda_power.h +++ b/include/linux/pda_power.h | |||
@@ -24,6 +24,8 @@ struct pda_power_pdata { | |||
24 | int (*is_usb_online)(void); | 24 | int (*is_usb_online)(void); |
25 | void (*set_charge)(int flags); | 25 | void (*set_charge)(int flags); |
26 | void (*exit)(struct device *dev); | 26 | void (*exit)(struct device *dev); |
27 | int (*suspend)(pm_message_t state); | ||
28 | int (*resume)(void); | ||
27 | 29 | ||
28 | char **supplied_to; | 30 | char **supplied_to; |
29 | size_t num_supplicants; | 31 | size_t num_supplicants; |
diff --git a/include/linux/z2_battery.h b/include/linux/z2_battery.h new file mode 100644 index 000000000000..7b9750404d22 --- /dev/null +++ b/include/linux/z2_battery.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef _LINUX_Z2_BATTERY_H | ||
2 | #define _LINUX_Z2_BATTERY_H | ||
3 | |||
4 | struct z2_battery_info { | ||
5 | int batt_I2C_bus; | ||
6 | int batt_I2C_addr; | ||
7 | int batt_I2C_reg; | ||
8 | int charge_gpio; | ||
9 | int min_voltage; | ||
10 | int max_voltage; | ||
11 | int batt_div; | ||
12 | int batt_mult; | ||
13 | int batt_tech; | ||
14 | char *batt_name; | ||
15 | }; | ||
16 | |||
17 | #endif | ||