1 From cb7ab7ce6ad690be5f71bde73a9369d3640985e8 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Wed, 16 Jul 2008 14:44:11 +0100
4 Subject: [PATCH] gta01-pcf50606.patch
5 This is a NXP PCF50606 power management unit driver.
7 The PCF50606 is used in the FIC/OpenMoko Neo1973 GTA01 GSM phone.
9 Signed-off-by: Harald Welte <laforge@openmoko.org>
11 drivers/i2c/chips/Kconfig | 11 +
12 drivers/i2c/chips/Makefile | 1 +
13 drivers/i2c/chips/pcf50606.c | 1945 ++++++++++++++++++++++++++++++++++++++++++
14 drivers/i2c/chips/pcf50606.h | 302 +++++++
15 include/linux/i2c-id.h | 1 +
16 include/linux/pcf50606.h | 108 +++
17 6 files changed, 2368 insertions(+), 0 deletions(-)
18 create mode 100644 drivers/i2c/chips/pcf50606.c
19 create mode 100644 drivers/i2c/chips/pcf50606.h
20 create mode 100644 include/linux/pcf50606.h
22 diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
23 index 2da2edf..e8e64aa 100644
24 --- a/drivers/i2c/chips/Kconfig
25 +++ b/drivers/i2c/chips/Kconfig
26 @@ -25,6 +25,17 @@ config SENSORS_EEPROM
27 This driver can also be built as a module. If so, the module
28 will be called eeprom.
30 +config SENSORS_PCF50606
31 + tristate "Philips/NXP PCF50606"
34 + If you say yes here you get support for Philips/NXP PCF50606
35 + PMU (Power Management Unit) chips.
37 + This driver can also be built as a module. If so, the module
38 + will be called pcf50606.
41 config SENSORS_PCF8574
42 tristate "Philips PCF8574 and PCF8574A"
43 depends on EXPERIMENTAL
44 diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
45 index e47aca0..60d3d5a 100644
46 --- a/drivers/i2c/chips/Makefile
47 +++ b/drivers/i2c/chips/Makefile
48 @@ -13,6 +13,7 @@ obj-$(CONFIG_DS1682) += ds1682.o
49 obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
50 obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
51 obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
52 +obj-$(CONFIG_SENSORS_PCF50606) += pcf50606.o
53 obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
54 obj-$(CONFIG_PCF8575) += pcf8575.o
55 obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
56 diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c
58 index 0000000..6626c68
60 +++ b/drivers/i2c/chips/pcf50606.c
62 +/* Philips/NXP PCF50606 Power Management Unit (PMU) driver
64 + * (C) 2006-2007 by OpenMoko, Inc.
65 + * Authors: Harald Welte <laforge@openmoko.org>,
66 + * Matt Hsu <matt@openmoko.org>
67 + * All rights reserved.
69 + * This program is free software; you can redistribute it and/or
70 + * modify it under the terms of the GNU General Public License as
71 + * published by the Free Software Foundation; either version 2 of
72 + * the License, or (at your option) any later version.
74 + * This program is distributed in the hope that it will be useful,
75 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
76 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77 + * GNU General Public License for more details.
79 + * You should have received a copy of the GNU General Public License
80 + * along with this program; if not, write to the Free Software
81 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
84 + * This driver is a monster ;) It provides the following features
85 + * - voltage control for a dozen different voltage domains
86 + * - charging control for main and backup battery
89 + * - adc driver (hw_sensors like)
95 +#include <linux/module.h>
96 +#include <linux/init.h>
97 +#include <linux/i2c.h>
98 +#include <linux/types.h>
99 +#include <linux/interrupt.h>
100 +#include <linux/irq.h>
101 +#include <linux/workqueue.h>
102 +#include <linux/rtc.h>
103 +#include <linux/bcd.h>
104 +#include <linux/watchdog.h>
105 +#include <linux/miscdevice.h>
106 +#include <linux/input.h>
107 +#include <linux/fb.h>
108 +#include <linux/backlight.h>
109 +#include <linux/sched.h>
110 +#include <linux/platform_device.h>
111 +#include <linux/pcf50606.h>
112 +#include <linux/apm-emulation.h>
114 +#include <asm/mach-types.h>
115 +#include <asm/arch/gta01.h>
117 +#include "pcf50606.h"
119 +/* we use dev_dbg() throughout the code, but sometimes don't want to
120 + * write an entire line of debug related information. This DEBUGPC
121 + * macro is a continuation for dev_dbg() */
123 +#define DEBUGPC(x, args ...) printk(x, ## args)
125 +#define DEBUGPC(x, args ...)
128 +/***********************************************************************
129 + * Static data / structures
130 + ***********************************************************************/
132 +static unsigned short normal_i2c[] = { 0x08, I2C_CLIENT_END };
134 +I2C_CLIENT_INSMOD_1(pcf50606);
136 +#define PCF50606_F_CHG_FAST 0x00000001 /* Charger Fast allowed */
137 +#define PCF50606_F_CHG_PRESENT 0x00000002 /* Charger present */
138 +#define PCF50606_F_CHG_FOK 0x00000004 /* Fast OK for battery */
139 +#define PCF50606_F_CHG_ERR 0x00000008 /* Charger Error */
140 +#define PCF50606_F_CHG_PROT 0x00000010 /* Charger Protection */
141 +#define PCF50606_F_CHG_READY 0x00000020 /* Charging completed */
142 +#define PCF50606_F_CHG_MASK 0x000000fc
144 +#define PCF50606_F_PWR_PRESSED 0x00000100
145 +#define PCF50606_F_RTC_SECOND 0x00000200
149 + CLOSE_STATE_ALLOW = 0x2342,
152 +struct pcf50606_data {
153 + struct i2c_client client;
154 + struct pcf50606_platform_data *pdata;
155 + struct backlight_device *backlight;
157 + unsigned int flags;
158 + unsigned int working;
159 + struct mutex working_lock;
160 + struct work_struct work;
161 + struct rtc_device *rtc;
162 + struct input_dev *input_dev;
168 + u_int8_t dcdc1, dcdc2;
176 + u_int8_t adcc1, adcc2;
178 + u_int8_t int1m, int2m, int3m;
183 +static struct i2c_driver pcf50606_driver;
185 +/* This is an ugly construct on how to access the (currently single/global)
186 + * pcf50606 handle from other code in the kernel. I didn't really come up with
187 + * a more decent method of dynamically resolving this */
188 +struct pcf50606_data *pcf50606_global;
189 +EXPORT_SYMBOL_GPL(pcf50606_global);
191 +static struct platform_device *pcf50606_pdev;
193 +/* This is a 10k, B=3370 NTC Thermistor -10..79 centigrade */
194 +/* Table entries are offset by +0.5C so a properly rounded value is generated */
195 +static const u_int16_t ntc_table_10k_3370B[] = {
197 + 43888, 41819, 39862, 38010, 36257, 34596, 33024, 31534, 30121, 28781,
198 + 27510, 26304, 25159, 24071, 23038, 22056, 21122, 20234, 19390, 18586,
199 + 17821, 17093, 16399, 15738, 15107, 14506, 13933, 13387, 12865, 12367,
200 + 11891, 11437, 11003, 10588, 10192, 9813, 9450, 9103, 8771, 8453,
201 + 8149, 7857, 7578, 7310, 7054, 6808, 6572, 6346, 6129, 5920,
202 + 5720, 5528, 5344, 5167, 4996, 4833, 4675, 4524, 4379, 4239,
203 + 4104, 3975, 3850, 3730, 3614, 3503, 3396, 3292, 3193, 3097,
204 + 3004, 2915, 2829, 2745, 2665, 2588, 2513, 2441, 2371, 2304,
205 + 2239, 2176, 2116, 2057, 2000, 1945, 1892, 1841, 1791, 1743,
209 +/***********************************************************************
210 + * Low-Level routines
211 + ***********************************************************************/
213 +static inline int __reg_write(struct pcf50606_data *pcf, u_int8_t reg,
216 + return i2c_smbus_write_byte_data(&pcf->client, reg, val);
219 +static int reg_write(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
223 + mutex_lock(&pcf->lock);
224 + ret = __reg_write(pcf, reg, val);
225 + mutex_unlock(&pcf->lock);
230 +static inline int32_t __reg_read(struct pcf50606_data *pcf, u_int8_t reg)
234 + ret = i2c_smbus_read_byte_data(&pcf->client, reg);
239 +static u_int8_t reg_read(struct pcf50606_data *pcf, u_int8_t reg)
243 + mutex_lock(&pcf->lock);
244 + ret = __reg_read(pcf, reg);
245 + mutex_unlock(&pcf->lock);
250 +static int reg_set_bit_mask(struct pcf50606_data *pcf,
251 + u_int8_t reg, u_int8_t mask, u_int8_t val)
258 + mutex_lock(&pcf->lock);
260 + tmp = __reg_read(pcf, reg);
263 + ret = __reg_write(pcf, reg, tmp);
265 + mutex_unlock(&pcf->lock);
270 +static int reg_clear_bits(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
275 + mutex_lock(&pcf->lock);
277 + tmp = __reg_read(pcf, reg);
279 + ret = __reg_write(pcf, reg, tmp);
281 + mutex_unlock(&pcf->lock);
286 +/* synchronously read one ADC channel (busy-wait for result to be complete) */
287 +static u_int16_t adc_read(struct pcf50606_data *pcf, int channel,
290 + u_int8_t adcs2, adcs1;
293 + dev_dbg(&pcf->client.dev, "entering (pcf=%p, channel=%u, data2=%p)\n",
294 + pcf, channel, data2);
296 + channel &= PCF50606_ADCC2_ADCMUX_MASK;
298 + mutex_lock(&pcf->lock);
300 + /* start ADC conversion of selected channel */
301 + __reg_write(pcf, PCF50606_REG_ADCC2, channel |
302 + PCF50606_ADCC2_ADCSTART | PCF50606_ADCC2_RES_10BIT);
305 + adcs2 = __reg_read(pcf, PCF50606_REG_ADCS2);
306 + } while (!(adcs2 & PCF50606_ADCS2_ADCRDY));
308 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS1);
309 + ret = (adcs1 << 2) | (adcs2 & 0x03);
312 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS3);
313 + *data2 = (adcs1 << 2) | ((adcs2 & 0x0c) >> 2);
316 + mutex_unlock(&pcf->lock);
318 + dev_dbg(&pcf->client.dev, "returning %u %u\n", ret,
319 + data2 ? *data2 : 0);
324 +/***********************************************************************
326 + ***********************************************************************/
328 +static u_int8_t dcudc_voltage(unsigned int millivolts)
330 + if (millivolts < 900)
332 + if (millivolts > 5500)
334 + if (millivolts <= 3300) {
336 + return millivolts/300;
338 + if (millivolts < 4000)
341 + millivolts -= 4000;
342 + return millivolts/100;
346 +static unsigned int dcudc_2voltage(u_int8_t bits)
350 + return 900 + bits * 300;
351 + else if (bits < 0x10)
354 + return 4000 + bits * 100;
357 +static u_int8_t dcdec_voltage(unsigned int millivolts)
359 + if (millivolts < 900)
361 + else if (millivolts > 3300)
365 + return millivolts/300;
368 +static unsigned int dcdec_2voltage(u_int8_t bits)
371 + return 900 + bits*300;
374 +static u_int8_t dcdc_voltage(unsigned int millivolts)
376 + if (millivolts < 900)
378 + else if (millivolts > 3600)
381 + if (millivolts < 1500) {
383 + return millivolts/25;
385 + millivolts -= 1500;
386 + return 0x18 + millivolts/300;
390 +static unsigned int dcdc_2voltage(u_int8_t bits)
393 + if ((bits & 0x18) == 0x18)
394 + return 1500 + ((bits & 0x7) * 300);
396 + return 900 + (bits * 25);
399 +static u_int8_t dx_voltage(unsigned int millivolts)
401 + if (millivolts < 900)
403 + else if (millivolts > 3300)
407 + return millivolts/100;
410 +static unsigned int dx_2voltage(u_int8_t bits)
413 + return 900 + (bits * 100);
416 +static const u_int8_t regulator_registers[__NUM_PCF50606_REGULATORS] = {
417 + [PCF50606_REGULATOR_DCD] = PCF50606_REG_DCDC1,
418 + [PCF50606_REGULATOR_DCDE] = PCF50606_REG_DCDEC1,
419 + [PCF50606_REGULATOR_DCUD] = PCF50606_REG_DCUDC1,
420 + [PCF50606_REGULATOR_D1REG] = PCF50606_REG_D1REGC1,
421 + [PCF50606_REGULATOR_D2REG] = PCF50606_REG_D2REGC1,
422 + [PCF50606_REGULATOR_D3REG] = PCF50606_REG_D3REGC1,
423 + [PCF50606_REGULATOR_LPREG] = PCF50606_REG_LPREGC1,
424 + [PCF50606_REGULATOR_IOREG] = PCF50606_REG_IOREGC,
427 +int pcf50606_onoff_set(struct pcf50606_data *pcf,
428 + enum pcf50606_regulator_id reg, int on)
432 + if (reg >= __NUM_PCF50606_REGULATORS)
435 + /* IOREG cannot be powered off since it powers the PMU I2C */
436 + if (reg == PCF50606_REGULATOR_IOREG)
439 + addr = regulator_registers[reg];
442 + reg_set_bit_mask(pcf, addr, 0xe0, 0x00);
444 + reg_set_bit_mask(pcf, addr, 0xe0, 0xe0);
448 +EXPORT_SYMBOL_GPL(pcf50606_onoff_set);
450 +int pcf50606_onoff_get(struct pcf50606_data *pcf,
451 + enum pcf50606_regulator_id reg)
453 + u_int8_t val, addr;
455 + if (reg >= __NUM_PCF50606_REGULATORS)
458 + addr = regulator_registers[reg];
459 + val = (reg_read(pcf, addr) & 0xe0) >> 5;
461 + /* PWREN1 = 1, PWREN2 = 1, see table 16 of datasheet */
470 +EXPORT_SYMBOL_GPL(pcf50606_onoff_get);
472 +int pcf50606_voltage_set(struct pcf50606_data *pcf,
473 + enum pcf50606_regulator_id reg,
474 + unsigned int millivolts)
476 + u_int8_t volt_bits;
480 + dev_dbg(&pcf->client.dev, "pcf=%p, reg=%d, mvolts=%d\n", pcf, reg,
483 + if (reg >= __NUM_PCF50606_REGULATORS)
486 + if (millivolts > pcf->pdata->rails[reg].voltage.max)
490 + case PCF50606_REGULATOR_DCD:
491 + volt_bits = dcdc_voltage(millivolts);
492 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDC1, 0x1f,
495 + case PCF50606_REGULATOR_DCDE:
496 + volt_bits = dcdec_voltage(millivolts);
497 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDEC1, 0x0f,
500 + case PCF50606_REGULATOR_DCUD:
501 + volt_bits = dcudc_voltage(millivolts);
502 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCUDC1, 0x1f,
505 + case PCF50606_REGULATOR_D1REG:
506 + case PCF50606_REGULATOR_D2REG:
507 + case PCF50606_REGULATOR_D3REG:
508 + regnr = PCF50606_REG_D1REGC1 + (reg - PCF50606_REGULATOR_D1REG);
509 + volt_bits = dx_voltage(millivolts);
510 + rc = reg_set_bit_mask(pcf, regnr, 0x1f, volt_bits);
512 + case PCF50606_REGULATOR_LPREG:
513 + volt_bits = dx_voltage(millivolts);
514 + rc = reg_set_bit_mask(pcf, PCF50606_REG_LPREGC1, 0x1f,
517 + case PCF50606_REGULATOR_IOREG:
518 + if (millivolts < 1800)
520 + volt_bits = dx_voltage(millivolts);
521 + rc = reg_set_bit_mask(pcf, PCF50606_REG_IOREGC, 0x1f,
530 +EXPORT_SYMBOL_GPL(pcf50606_voltage_set);
532 +unsigned int pcf50606_voltage_get(struct pcf50606_data *pcf,
533 + enum pcf50606_regulator_id reg)
535 + u_int8_t volt_bits;
537 + unsigned int rc = 0;
539 + if (reg >= __NUM_PCF50606_REGULATORS)
543 + case PCF50606_REGULATOR_DCD:
544 + volt_bits = reg_read(pcf, PCF50606_REG_DCDC1) & 0x1f;
545 + rc = dcdc_2voltage(volt_bits);
547 + case PCF50606_REGULATOR_DCDE:
548 + volt_bits = reg_read(pcf, PCF50606_REG_DCDEC1) & 0x0f;
549 + rc = dcdec_2voltage(volt_bits);
551 + case PCF50606_REGULATOR_DCUD:
552 + volt_bits = reg_read(pcf, PCF50606_REG_DCUDC1) & 0x1f;
553 + rc = dcudc_2voltage(volt_bits);
555 + case PCF50606_REGULATOR_D1REG:
556 + case PCF50606_REGULATOR_D2REG:
557 + case PCF50606_REGULATOR_D3REG:
558 + regnr = PCF50606_REG_D1REGC1 + (reg - PCF50606_REGULATOR_D1REG);
559 + volt_bits = reg_read(pcf, regnr) & 0x1f;
560 + if (volt_bits > 0x18)
562 + rc = dx_2voltage(volt_bits);
564 + case PCF50606_REGULATOR_LPREG:
565 + volt_bits = reg_read(pcf, PCF50606_REG_LPREGC1) & 0x1f;
566 + if (volt_bits > 0x18)
568 + rc = dx_2voltage(volt_bits);
570 + case PCF50606_REGULATOR_IOREG:
571 + volt_bits = reg_read(pcf, PCF50606_REG_IOREGC) & 0x1f;
572 + if (volt_bits > 0x18)
574 + rc = dx_2voltage(volt_bits);
582 +EXPORT_SYMBOL_GPL(pcf50606_voltage_get);
584 +/* go into 'STANDBY' mode, i.e. power off the main CPU and peripherals */
585 +void pcf50606_go_standby(void)
587 + reg_write(pcf50606_global, PCF50606_REG_OOCC1,
588 + PCF50606_OOCC1_GOSTDBY);
590 +EXPORT_SYMBOL_GPL(pcf50606_go_standby);
592 +void pcf50606_gpo0_set(struct pcf50606_data *pcf, int on)
601 + reg_set_bit_mask(pcf, PCF50606_REG_GPOC1, 0x0f, val);
603 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_set);
605 +int pcf50606_gpo0_get(struct pcf50606_data *pcf)
607 + u_int8_t reg = reg_read(pcf, PCF50606_REG_GPOC1) & 0x0f;
609 + if (reg == 0x07 || reg == 0x08)
614 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_get);
616 +static void pcf50606_work(struct work_struct *work)
618 + struct pcf50606_data *pcf =
619 + container_of(work, struct pcf50606_data, work);
620 + u_int8_t pcfirq[3];
623 + mutex_lock(&pcf->working_lock);
626 + * p35 pcf50606 datasheet rev 2.2:
627 + * ''The system controller shall read all interrupt registers in
628 + * one I2C read action''
629 + * because if you don't INT# gets stuck asserted forever after a
632 + ret = i2c_smbus_read_i2c_block_data(&pcf->client, PCF50606_REG_INT1, 3,
635 + DEBUGPC("Oh crap PMU IRQ register read failed %d\n", ret);
637 + dev_dbg(&pcf->client.dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x:",
638 + pcfirq[0], pcfirq[1], pcfirq[2]);
640 + if (pcfirq[0] & PCF50606_INT1_ONKEYF) {
641 + /* ONKEY falling edge (start of button press) */
642 + DEBUGPC("ONKEYF ");
643 + pcf->flags |= PCF50606_F_PWR_PRESSED;
644 + input_report_key(pcf->input_dev, KEY_POWER, 1);
646 + if (pcfirq[0] & PCF50606_INT1_ONKEY1S) {
647 + /* ONKEY pressed for more than 1 second */
648 + pcf->onkey_seconds = 0;
649 + DEBUGPC("ONKEY1S ");
650 + /* Tell PMU we are taking care of this */
651 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
652 + PCF50606_OOCC1_TOTRST,
653 + PCF50606_OOCC1_TOTRST);
654 + /* enable SECOND interrupt (hz tick) */
655 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
657 + if (pcfirq[0] & PCF50606_INT1_ONKEYR) {
658 + /* ONKEY rising edge (end of button press) */
659 + DEBUGPC("ONKEYR ");
660 + pcf->flags &= ~PCF50606_F_PWR_PRESSED;
661 + pcf->onkey_seconds = -1;
662 + input_report_key(pcf->input_dev, KEY_POWER, 0);
663 + /* disable SECOND interrupt in case RTC didn't
665 + if (!(pcf->flags & PCF50606_F_RTC_SECOND))
666 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M,
667 + PCF50606_INT1_SECOND,
668 + PCF50606_INT1_SECOND);
670 + if (pcfirq[0] & PCF50606_INT1_EXTONR) {
671 + DEBUGPC("EXTONR ");
672 + input_report_key(pcf->input_dev, KEY_POWER2, 1);
674 + if (pcfirq[0] & PCF50606_INT1_EXTONF) {
675 + DEBUGPC("EXTONF ");
676 + input_report_key(pcf->input_dev, KEY_POWER2, 0);
678 + if (pcfirq[0] & PCF50606_INT1_SECOND) {
679 + DEBUGPC("SECOND ");
680 + if (pcf->flags & PCF50606_F_RTC_SECOND)
681 + rtc_update_irq(pcf->rtc, 1,
682 + RTC_PF | RTC_IRQF);
684 + if (pcf->onkey_seconds >= 0 &&
685 + pcf->flags & PCF50606_F_PWR_PRESSED) {
686 + DEBUGPC("ONKEY_SECONDS(%u, OOCC1=0x%02x) ",
687 + pcf->onkey_seconds,
688 + reg_read(pcf, PCF50606_REG_OOCC1));
689 + pcf->onkey_seconds++;
690 + if (pcf->onkey_seconds >=
691 + pcf->pdata->onkey_seconds_required) {
692 + /* Ask init to do 'ctrlaltdel' */
693 + DEBUGPC("SIGINT(init) ");
694 + kill_proc(1, SIGINT, 1);
695 + /* FIXME: what to do if userspace doesn't
696 + * shut down? Do we want to force it? */
700 + if (pcfirq[0] & PCF50606_INT1_ALARM) {
702 + if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
703 + rtc_update_irq(pcf->rtc, 1,
704 + RTC_AF | RTC_IRQF);
707 + if (pcfirq[1] & PCF50606_INT2_CHGINS) {
708 + /* Charger inserted */
709 + DEBUGPC("CHGINS ");
710 + input_report_key(pcf->input_dev, KEY_BATTERY, 1);
711 + apm_queue_event(APM_POWER_STATUS_CHANGE);
712 + pcf->flags |= PCF50606_F_CHG_PRESENT;
713 + if (pcf->pdata->cb)
714 + pcf->pdata->cb(&pcf->client.dev,
715 + PCF50606_FEAT_MBC, PMU_EVT_INSERT);
716 + /* FIXME: how to signal this to userspace */
718 + if (pcfirq[1] & PCF50606_INT2_CHGRM) {
719 + /* Charger removed */
721 + input_report_key(pcf->input_dev, KEY_BATTERY, 0);
722 + apm_queue_event(APM_POWER_STATUS_CHANGE);
723 + pcf->flags &= ~(PCF50606_F_CHG_MASK|PCF50606_F_CHG_PRESENT);
724 + if (pcf->pdata->cb)
725 + pcf->pdata->cb(&pcf->client.dev,
726 + PCF50606_FEAT_MBC, PMU_EVT_INSERT);
727 + /* FIXME: how signal this to userspace */
729 + if (pcfirq[1] & PCF50606_INT2_CHGFOK) {
730 + /* Battery ready for fast charging */
731 + DEBUGPC("CHGFOK ");
732 + pcf->flags |= PCF50606_F_CHG_FOK;
733 + /* FIXME: how to signal this to userspace */
735 + if (pcfirq[1] & PCF50606_INT2_CHGERR) {
736 + /* Error in charge mode */
737 + DEBUGPC("CHGERR ");
738 + pcf->flags |= PCF50606_F_CHG_ERR;
739 + pcf->flags &= ~(PCF50606_F_CHG_FOK|PCF50606_F_CHG_READY);
740 + /* FIXME: how to signal this to userspace */
742 + if (pcfirq[1] & PCF50606_INT2_CHGFRDY) {
743 + /* Fast charge completed */
744 + DEBUGPC("CHGFRDY ");
745 + pcf->flags |= PCF50606_F_CHG_READY;
746 + pcf->flags &= ~PCF50606_F_CHG_FOK;
747 + /* FIXME: how to signal this to userspace */
749 + if (pcfirq[1] & PCF50606_INT2_CHGPROT) {
750 + /* Charging protection interrupt */
751 + DEBUGPC("CHGPROT ");
752 + pcf->flags &= ~(PCF50606_F_CHG_FOK|PCF50606_F_CHG_READY);
753 + /* FIXME: signal this to userspace */
755 + if (pcfirq[1] & PCF50606_INT2_CHGWD10S) {
756 + /* Charger watchdog will expire in 10 seconds */
757 + DEBUGPC("CHGWD10S ");
758 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
759 + PCF50606_OOCC1_WDTRST,
760 + PCF50606_OOCC1_WDTRST);
762 + if (pcfirq[1] & PCF50606_INT2_CHGWDEXP) {
763 + /* Charger watchdog expires */
764 + DEBUGPC("CHGWDEXP ");
765 + /* FIXME: how to signal this to userspace */
768 + if (pcfirq[2] & PCF50606_INT3_ADCRDY) {
769 + /* ADC result ready */
770 + DEBUGPC("ADCRDY ");
772 + if (pcfirq[2] & PCF50606_INT3_ACDINS) {
773 + /* Accessory insertion detected */
774 + DEBUGPC("ACDINS ");
775 + if (pcf->pdata->cb)
776 + pcf->pdata->cb(&pcf->client.dev,
777 + PCF50606_FEAT_ACD, PMU_EVT_INSERT);
779 + if (pcfirq[2] & PCF50606_INT3_ACDREM) {
780 + /* Accessory removal detected */
781 + DEBUGPC("ACDREM ");
782 + if (pcf->pdata->cb)
783 + pcf->pdata->cb(&pcf->client.dev,
784 + PCF50606_FEAT_ACD, PMU_EVT_REMOVE);
786 + /* FIXME: TSCPRES */
787 + if (pcfirq[2] & PCF50606_INT3_LOWBAT) {
788 + /* Really low battery voltage, we have 8 seconds left */
789 + DEBUGPC("LOWBAT ");
790 + apm_queue_event(APM_LOW_BATTERY);
791 + DEBUGPC("SIGPWR(init) ");
792 + kill_proc(1, SIGPWR, 1);
793 + /* Tell PMU we are taking care of this */
794 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
795 + PCF50606_OOCC1_TOTRST,
796 + PCF50606_OOCC1_TOTRST);
798 + if (pcfirq[2] & PCF50606_INT3_HIGHTMP) {
799 + /* High temperature */
800 + DEBUGPC("HIGHTMP ");
801 + apm_queue_event(APM_CRITICAL_SUSPEND);
807 + input_sync(pcf->input_dev);
808 + put_device(&pcf->client.dev);
809 + mutex_unlock(&pcf->working_lock);
812 +static irqreturn_t pcf50606_irq(int irq, void *_pcf)
814 + struct pcf50606_data *pcf = _pcf;
816 + dev_dbg(&pcf->client.dev, "entering(irq=%u, pcf=%p): scheduling work\n",
818 + get_device(&pcf->client.dev);
819 + if (!schedule_work(&pcf->work) && !pcf->working)
820 + dev_dbg(&pcf->client.dev, "work item may be lost\n");
822 + return IRQ_HANDLED;
825 +static u_int16_t adc_to_batt_millivolts(u_int16_t adc)
829 + mvolts = (adc * 6000) / 1024;
834 +#define BATTVOLT_SCALE_START 2800
835 +#define BATTVOLT_SCALE_END 4200
836 +#define BATTVOLT_SCALE_DIVIDER ((BATTVOLT_SCALE_END - BATTVOLT_SCALE_START)/100)
838 +static u_int8_t battvolt_scale(u_int16_t battvolt)
840 + /* FIXME: this linear scale is completely bogus */
841 + u_int16_t battvolt_relative = battvolt - BATTVOLT_SCALE_START;
842 + unsigned int percent = battvolt_relative / BATTVOLT_SCALE_DIVIDER;
847 +u_int16_t pcf50606_battvolt(struct pcf50606_data *pcf)
850 + adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_RES, NULL);
852 + return adc_to_batt_millivolts(adc);
854 +EXPORT_SYMBOL_GPL(pcf50606_battvolt);
856 +static ssize_t show_battvolt(struct device *dev, struct device_attribute *attr,
859 + struct i2c_client *client = to_i2c_client(dev);
860 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
862 + return sprintf(buf, "%u\n", pcf50606_battvolt(pcf));
864 +static DEVICE_ATTR(battvolt, S_IRUGO | S_IWUSR, show_battvolt, NULL);
866 +static int reg_id_by_name(const char *name)
870 + if (!strcmp(name, "voltage_dcd"))
871 + reg_id = PCF50606_REGULATOR_DCD;
872 + else if (!strcmp(name, "voltage_dcde"))
873 + reg_id = PCF50606_REGULATOR_DCDE;
874 + else if (!strcmp(name, "voltage_dcud"))
875 + reg_id = PCF50606_REGULATOR_DCUD;
876 + else if (!strcmp(name, "voltage_d1reg"))
877 + reg_id = PCF50606_REGULATOR_D1REG;
878 + else if (!strcmp(name, "voltage_d2reg"))
879 + reg_id = PCF50606_REGULATOR_D2REG;
880 + else if (!strcmp(name, "voltage_d3reg"))
881 + reg_id = PCF50606_REGULATOR_D3REG;
882 + else if (!strcmp(name, "voltage_lpreg"))
883 + reg_id = PCF50606_REGULATOR_LPREG;
884 + else if (!strcmp(name, "voltage_ioreg"))
885 + reg_id = PCF50606_REGULATOR_IOREG;
892 +static ssize_t show_vreg(struct device *dev, struct device_attribute *attr,
895 + struct i2c_client *client = to_i2c_client(dev);
896 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
897 + unsigned int reg_id;
899 + reg_id = reg_id_by_name(attr->attr.name);
903 + if (pcf50606_onoff_get(pcf, reg_id) > 0)
904 + return sprintf(buf, "%u\n", pcf50606_voltage_get(pcf, reg_id));
906 + return strlcpy(buf, "0\n", PAGE_SIZE);
909 +static ssize_t set_vreg(struct device *dev, struct device_attribute *attr,
910 + const char *buf, size_t count)
912 + struct i2c_client *client = to_i2c_client(dev);
913 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
914 + unsigned long mvolts = simple_strtoul(buf, NULL, 10);
915 + unsigned int reg_id;
917 + reg_id = reg_id_by_name(attr->attr.name);
921 + dev_dbg(dev, "attempting to set %s(%d) to %lu mvolts\n",
922 + attr->attr.name, reg_id, mvolts);
925 + pcf50606_onoff_set(pcf, reg_id, 0);
927 + if (pcf50606_voltage_set(pcf, reg_id, mvolts) < 0) {
928 + dev_warn(dev, "refusing to set %s(%d) to %lu mvolts "
929 + "(max=%u)\n", attr->attr.name, reg_id, mvolts,
930 + pcf->pdata->rails[reg_id].voltage.max);
933 + pcf50606_onoff_set(pcf, reg_id, 1);
939 +static DEVICE_ATTR(voltage_dcd, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
940 +static DEVICE_ATTR(voltage_dcde, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
941 +static DEVICE_ATTR(voltage_dcud, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
942 +static DEVICE_ATTR(voltage_d1reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
943 +static DEVICE_ATTR(voltage_d2reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
944 +static DEVICE_ATTR(voltage_d3reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
945 +static DEVICE_ATTR(voltage_lpreg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
946 +static DEVICE_ATTR(voltage_ioreg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
948 +/***********************************************************************
950 + ***********************************************************************/
952 +/* Enable/disable fast charging (500mA in the GTA01) */
953 +void pcf50606_charge_fast(struct pcf50606_data *pcf, int on)
955 + if (!(pcf->pdata->used_features & PCF50606_FEAT_MBC))
959 + /* We can allow PCF to automatically charge
961 + pcf->flags |= PCF50606_F_CHG_FAST;
962 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
963 + PCF50606_MBCC1_AUTOFST,
964 + PCF50606_MBCC1_AUTOFST);
966 + pcf->flags &= ~PCF50606_F_CHG_FAST;
967 + /* disable automatic fast-charge */
968 + reg_clear_bits(pcf, PCF50606_REG_MBCC1,
969 + PCF50606_MBCC1_AUTOFST);
970 + /* switch to idle mode to abort existing charge
972 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
973 + PCF50606_MBCC1_CHGMOD_MASK,
974 + PCF50606_MBCC1_CHGMOD_IDLE);
977 +EXPORT_SYMBOL_GPL(pcf50606_charge_fast);
979 +static inline u_int16_t adc_to_rntc(struct pcf50606_data *pcf, u_int16_t adc)
981 + u_int32_t r_ntc = (adc * (u_int32_t)pcf->pdata->r_fix_batt) / (1023 - adc);
986 +static inline int16_t rntc_to_temp(u_int16_t rntc)
990 + for (i = 0; i < ARRAY_SIZE(ntc_table_10k_3370B); i++) {
991 + if (rntc > ntc_table_10k_3370B[i])
992 + return i - 10; /* First element is -10 */
994 + return -99; /* Below our range */
997 +static ssize_t show_battemp(struct device *dev, struct device_attribute *attr,
1000 + struct i2c_client *client = to_i2c_client(dev);
1001 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1004 + adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL);
1006 + return sprintf(buf, "%d\n", rntc_to_temp(adc_to_rntc(pcf, adc)));
1008 +static DEVICE_ATTR(battemp, S_IRUGO | S_IWUSR, show_battemp, NULL);
1010 +static inline int16_t adc_to_chg_milliamps(struct pcf50606_data *pcf,
1011 + u_int16_t adc_adcin1,
1012 + u_int16_t adc_batvolt)
1014 + int32_t res = (adc_adcin1 - adc_batvolt) * 2400;
1015 + return (res * 1000) / (pcf->pdata->r_sense_milli * 1024);
1018 +static ssize_t show_chgcur(struct device *dev, struct device_attribute *attr,
1021 + struct i2c_client *client = to_i2c_client(dev);
1022 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1023 + u_int16_t adc_batvolt, adc_adcin1;
1026 + adc_batvolt = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1,
1028 + ma = adc_to_chg_milliamps(pcf, adc_adcin1, adc_batvolt);
1030 + return sprintf(buf, "%d\n", ma);
1032 +static DEVICE_ATTR(chgcur, S_IRUGO | S_IWUSR, show_chgcur, NULL);
1034 +static const char *chgmode_names[] = {
1035 + [PCF50606_MBCC1_CHGMOD_QUAL] = "qualification",
1036 + [PCF50606_MBCC1_CHGMOD_PRE] = "pre",
1037 + [PCF50606_MBCC1_CHGMOD_TRICKLE] = "trickle",
1038 + [PCF50606_MBCC1_CHGMOD_FAST_CCCV] = "fast_cccv",
1039 + [PCF50606_MBCC1_CHGMOD_FAST_NOCC] = "fast_nocc",
1040 + [PCF50606_MBCC1_CHGMOD_FAST_NOCV] = "fast_nocv",
1041 + [PCF50606_MBCC1_CHGMOD_FAST_SW] = "fast_switch",
1042 + [PCF50606_MBCC1_CHGMOD_IDLE] = "idle",
1045 +static ssize_t show_chgmode(struct device *dev, struct device_attribute *attr,
1048 + struct i2c_client *client = to_i2c_client(dev);
1049 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1050 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
1051 + u_int8_t chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
1053 + return sprintf(buf, "%s\n", chgmode_names[chgmod]);
1056 +static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
1057 + const char *buf, size_t count)
1059 + struct i2c_client *client = to_i2c_client(dev);
1060 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1061 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
1063 + mbcc1 &= ~PCF50606_MBCC1_CHGMOD_MASK;
1065 + if (!strcmp(buf, "qualification"))
1066 + mbcc1 |= PCF50606_MBCC1_CHGMOD_QUAL;
1067 + else if (!strcmp(buf, "pre"))
1068 + mbcc1 |= PCF50606_MBCC1_CHGMOD_PRE;
1069 + else if (!strcmp(buf, "trickle"))
1070 + mbcc1 |= PCF50606_MBCC1_CHGMOD_TRICKLE;
1071 + else if (!strcmp(buf, "fast_cccv"))
1072 + mbcc1 |= PCF50606_MBCC1_CHGMOD_FAST_CCCV;
1073 + /* We don't allow the other fast modes for security reasons */
1074 + else if (!strcmp(buf, "idle"))
1075 + mbcc1 |= PCF50606_MBCC1_CHGMOD_IDLE;
1079 + reg_write(pcf, PCF50606_REG_MBCC1, mbcc1);
1084 +static DEVICE_ATTR(chgmode, S_IRUGO | S_IWUSR, show_chgmode, set_chgmode);
1086 +static const char *chgstate_names[] = {
1087 + [PCF50606_F_CHG_FAST] = "fast_enabled",
1088 + [PCF50606_F_CHG_PRESENT] = "present",
1089 + [PCF50606_F_CHG_FOK] = "fast_ok",
1090 + [PCF50606_F_CHG_ERR] = "error",
1091 + [PCF50606_F_CHG_PROT] = "protection",
1092 + [PCF50606_F_CHG_READY] = "ready",
1095 +static ssize_t show_chgstate(struct device *dev, struct device_attribute *attr,
1098 + struct i2c_client *client = to_i2c_client(dev);
1099 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1103 + for (i = 0; i < 32; i++)
1104 + if (pcf->flags & (1 << i) && i < ARRAY_SIZE(chgstate_names))
1105 + b += sprintf(b, "%s ", chgstate_names[i]);
1108 + b += sprintf(b, "\n");
1112 +static DEVICE_ATTR(chgstate, S_IRUGO | S_IWUSR, show_chgstate, NULL);
1114 +/***********************************************************************
1116 + ***********************************************************************/
1118 +static void pcf50606_get_power_status(struct apm_power_info *info)
1120 + struct pcf50606_data *pcf = pcf50606_global;
1121 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
1122 + u_int8_t chgmod = mbcc1 & PCF50606_MBCC1_CHGMOD_MASK;
1123 + u_int16_t battvolt = pcf50606_battvolt(pcf);
1125 + if (reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON)
1126 + info->ac_line_status = APM_AC_ONLINE;
1128 + info->ac_line_status = APM_AC_OFFLINE;
1131 + case PCF50606_MBCC1_CHGMOD_QUAL:
1132 + case PCF50606_MBCC1_CHGMOD_PRE:
1133 + case PCF50606_MBCC1_CHGMOD_IDLE:
1134 + info->battery_life = battvolt_scale(battvolt);
1137 + info->battery_status = APM_BATTERY_STATUS_CHARGING;
1138 + info->battery_flag = APM_BATTERY_FLAG_CHARGING;
1143 +/***********************************************************************
1145 + ***********************************************************************/
1147 +struct pcf50606_time {
1157 +static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50606_time *pcf)
1159 + rtc->tm_sec = BCD2BIN(pcf->sec);
1160 + rtc->tm_min = BCD2BIN(pcf->min);
1161 + rtc->tm_hour = BCD2BIN(pcf->hour);
1162 + rtc->tm_wday = BCD2BIN(pcf->wkday);
1163 + rtc->tm_mday = BCD2BIN(pcf->day);
1164 + rtc->tm_mon = BCD2BIN(pcf->month);
1165 + rtc->tm_year = BCD2BIN(pcf->year) + 100;
1168 +static void rtc2pcf_time(struct pcf50606_time *pcf, struct rtc_time *rtc)
1170 + pcf->sec = BIN2BCD(rtc->tm_sec);
1171 + pcf->min = BIN2BCD(rtc->tm_min);
1172 + pcf->hour = BIN2BCD(rtc->tm_hour);
1173 + pcf->wkday = BIN2BCD(rtc->tm_wday);
1174 + pcf->day = BIN2BCD(rtc->tm_mday);
1175 + pcf->month = BIN2BCD(rtc->tm_mon);
1176 + pcf->year = BIN2BCD(rtc->tm_year - 100);
1179 +static int pcf50606_rtc_ioctl(struct device *dev, unsigned int cmd,
1180 + unsigned long arg)
1182 + struct i2c_client *client = to_i2c_client(dev);
1183 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1186 + /* disable periodic interrupt (hz tick) */
1187 + pcf->flags &= ~PCF50606_F_RTC_SECOND;
1188 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M,
1189 + PCF50606_INT1_SECOND, PCF50606_INT1_SECOND);
1192 + /* ensable periodic interrupt (hz tick) */
1193 + pcf->flags |= PCF50606_F_RTC_SECOND;
1194 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
1197 + return -ENOIOCTLCMD;
1200 +static int pcf50606_rtc_read_time(struct device *dev, struct rtc_time *tm)
1202 + struct i2c_client *client = to_i2c_client(dev);
1203 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1204 + struct pcf50606_time pcf_tm;
1206 + mutex_lock(&pcf->lock);
1207 + pcf_tm.sec = __reg_read(pcf, PCF50606_REG_RTCSC);
1208 + pcf_tm.min = __reg_read(pcf, PCF50606_REG_RTCMN);
1209 + pcf_tm.hour = __reg_read(pcf, PCF50606_REG_RTCHR);
1210 + pcf_tm.wkday = __reg_read(pcf, PCF50606_REG_RTCWD);
1211 + pcf_tm.day = __reg_read(pcf, PCF50606_REG_RTCDT);
1212 + pcf_tm.month = __reg_read(pcf, PCF50606_REG_RTCMT);
1213 + pcf_tm.year = __reg_read(pcf, PCF50606_REG_RTCYR);
1214 + mutex_unlock(&pcf->lock);
1216 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
1217 + pcf_tm.day, pcf_tm.month, pcf_tm.year,
1218 + pcf_tm.hour, pcf_tm.min, pcf_tm.sec);
1220 + pcf2rtc_time(tm, &pcf_tm);
1222 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
1223 + tm->tm_mday, tm->tm_mon, tm->tm_year,
1224 + tm->tm_hour, tm->tm_min, tm->tm_sec);
1229 +static int pcf50606_rtc_set_time(struct device *dev, struct rtc_time *tm)
1231 + struct i2c_client *client = to_i2c_client(dev);
1232 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1233 + struct pcf50606_time pcf_tm;
1236 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
1237 + tm->tm_mday, tm->tm_mon, tm->tm_year,
1238 + tm->tm_hour, tm->tm_min, tm->tm_sec);
1239 + rtc2pcf_time(&pcf_tm, tm);
1240 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
1241 + pcf_tm.day, pcf_tm.month, pcf_tm.year,
1242 + pcf_tm.hour, pcf_tm.min, pcf_tm.sec);
1244 + mutex_lock(&pcf->lock);
1246 + /* disable SECOND interrupt */
1247 + int1m = __reg_read(pcf, PCF50606_REG_INT1M);
1248 + __reg_write(pcf, PCF50606_REG_INT1M, int1m | PCF50606_INT1_SECOND);
1250 + __reg_write(pcf, PCF50606_REG_RTCSC, pcf_tm.sec);
1251 + __reg_write(pcf, PCF50606_REG_RTCMN, pcf_tm.min);
1252 + __reg_write(pcf, PCF50606_REG_RTCHR, pcf_tm.hour);
1253 + __reg_write(pcf, PCF50606_REG_RTCWD, pcf_tm.wkday);
1254 + __reg_write(pcf, PCF50606_REG_RTCDT, pcf_tm.day);
1255 + __reg_write(pcf, PCF50606_REG_RTCMT, pcf_tm.month);
1256 + __reg_write(pcf, PCF50606_REG_RTCYR, pcf_tm.year);
1258 + /* restore INT1M, potentially re-enable SECOND interrupt */
1259 + __reg_write(pcf, PCF50606_REG_INT1M, int1m);
1261 + mutex_unlock(&pcf->lock);
1266 +static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
1268 + struct i2c_client *client = to_i2c_client(dev);
1269 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1270 + struct pcf50606_time pcf_tm;
1272 + mutex_lock(&pcf->lock);
1274 + __reg_read(pcf, PCF50606_REG_INT1M) & PCF50606_INT1_ALARM ? 0 : 1;
1275 + pcf_tm.sec = __reg_read(pcf, PCF50606_REG_RTCSCA);
1276 + pcf_tm.min = __reg_read(pcf, PCF50606_REG_RTCMNA);
1277 + pcf_tm.hour = __reg_read(pcf, PCF50606_REG_RTCHRA);
1278 + pcf_tm.wkday = __reg_read(pcf, PCF50606_REG_RTCWDA);
1279 + pcf_tm.day = __reg_read(pcf, PCF50606_REG_RTCDTA);
1280 + pcf_tm.month = __reg_read(pcf, PCF50606_REG_RTCMTA);
1281 + pcf_tm.year = __reg_read(pcf, PCF50606_REG_RTCYRA);
1282 + mutex_unlock(&pcf->lock);
1284 + pcf2rtc_time(&alrm->time, &pcf_tm);
1289 +static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
1291 + struct i2c_client *client = to_i2c_client(dev);
1292 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1293 + struct pcf50606_time pcf_tm;
1296 + rtc2pcf_time(&pcf_tm, &alrm->time);
1298 + mutex_lock(&pcf->lock);
1300 + /* disable alarm interrupt */
1301 + irqmask = __reg_read(pcf, PCF50606_REG_INT1M);
1302 + irqmask |= PCF50606_INT1_ALARM;
1303 + __reg_write(pcf, PCF50606_REG_INT1M, irqmask);
1305 + __reg_write(pcf, PCF50606_REG_RTCSCA, pcf_tm.sec);
1306 + __reg_write(pcf, PCF50606_REG_RTCMNA, pcf_tm.min);
1307 + __reg_write(pcf, PCF50606_REG_RTCHRA, pcf_tm.hour);
1308 + __reg_write(pcf, PCF50606_REG_RTCWDA, pcf_tm.wkday);
1309 + __reg_write(pcf, PCF50606_REG_RTCDTA, pcf_tm.day);
1310 + __reg_write(pcf, PCF50606_REG_RTCMTA, pcf_tm.month);
1311 + __reg_write(pcf, PCF50606_REG_RTCYRA, pcf_tm.year);
1313 + if (alrm->enabled) {
1314 + /* (re-)enaable alarm interrupt */
1315 + irqmask = __reg_read(pcf, PCF50606_REG_INT1M);
1316 + irqmask &= ~PCF50606_INT1_ALARM;
1317 + __reg_write(pcf, PCF50606_REG_INT1M, irqmask);
1320 + mutex_unlock(&pcf->lock);
1326 +static struct rtc_class_ops pcf50606_rtc_ops = {
1327 + .ioctl = pcf50606_rtc_ioctl,
1328 + .read_time = pcf50606_rtc_read_time,
1329 + .set_time = pcf50606_rtc_set_time,
1330 + .read_alarm = pcf50606_rtc_read_alarm,
1331 + .set_alarm = pcf50606_rtc_set_alarm,
1334 +/***********************************************************************
1336 + ***********************************************************************/
1338 +static void pcf50606_wdt_start(struct pcf50606_data *pcf)
1340 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1, PCF50606_OOCC1_WDTRST,
1341 + PCF50606_OOCC1_WDTRST);
1344 +static void pcf50606_wdt_stop(struct pcf50606_data *pcf)
1346 + reg_clear_bits(pcf, PCF50606_REG_OOCS, PCF50606_OOCS_WDTEXP);
1349 +static void pcf50606_wdt_keepalive(struct pcf50606_data *pcf)
1351 + pcf50606_wdt_start(pcf);
1354 +static int pcf50606_wdt_open(struct inode *inode, struct file *file)
1356 + struct pcf50606_data *pcf = pcf50606_global;
1358 + file->private_data = pcf;
1360 + /* start the timer */
1361 + pcf50606_wdt_start(pcf);
1363 + return nonseekable_open(inode, file);
1366 +static int pcf50606_wdt_release(struct inode *inode, struct file *file)
1368 + struct pcf50606_data *pcf = file->private_data;
1370 + if (pcf->allow_close == CLOSE_STATE_ALLOW)
1371 + pcf50606_wdt_stop(pcf);
1373 + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
1374 + pcf50606_wdt_keepalive(pcf);
1377 + pcf->allow_close = CLOSE_STATE_NOT;
1382 +static ssize_t pcf50606_wdt_write(struct file *file, const char __user *data,
1383 + size_t len, loff_t *ppos)
1385 + struct pcf50606_data *pcf = file->private_data;
1389 + for (i = 0; i != len; i++) {
1391 + if (get_user(c, data + i))
1394 + pcf->allow_close = CLOSE_STATE_ALLOW;
1396 + pcf50606_wdt_keepalive(pcf);
1402 +static struct watchdog_info pcf50606_wdt_ident = {
1403 + .options = WDIOF_MAGICCLOSE,
1404 + .firmware_version = 0,
1405 + .identity = "PCF50606 Watchdog",
1408 +static int pcf50606_wdt_ioctl(struct inode *inode, struct file *file,
1409 + unsigned int cmd, unsigned long arg)
1411 + struct pcf50606_data *pcf = file->private_data;
1412 + void __user *argp = (void __user *)arg;
1413 + int __user *p = argp;
1416 + case WDIOC_GETSUPPORT:
1417 + return copy_to_user(argp, &pcf50606_wdt_ident,
1418 + sizeof(pcf50606_wdt_ident)) ? -EFAULT : 0;
1420 + case WDIOC_GETSTATUS:
1421 + case WDIOC_GETBOOTSTATUS:
1422 + return put_user(0, p);
1423 + case WDIOC_KEEPALIVE:
1424 + pcf50606_wdt_keepalive(pcf);
1426 + case WDIOC_GETTIMEOUT:
1427 + return put_user(8, p);
1429 + return -ENOIOCTLCMD;
1433 +static struct file_operations pcf50606_wdt_fops = {
1434 + .owner = THIS_MODULE,
1435 + .llseek = no_llseek,
1436 + .write = &pcf50606_wdt_write,
1437 + .ioctl = &pcf50606_wdt_ioctl,
1438 + .open = &pcf50606_wdt_open,
1439 + .release = &pcf50606_wdt_release,
1442 +static struct miscdevice pcf50606_wdt_miscdev = {
1443 + .minor = WATCHDOG_MINOR,
1444 + .name = "watchdog",
1445 + .fops = &pcf50606_wdt_fops,
1448 +/***********************************************************************
1450 + ***********************************************************************/
1452 +static const char *pwm_dc_table[] = {
1453 + "0/16", "1/16", "2/16", "3/16",
1454 + "4/16", "5/16", "6/16", "7/16",
1455 + "8/16", "9/16", "10/16", "11/16",
1456 + "12/16", "13/16", "14/16", "15/16",
1459 +static ssize_t show_pwm_dc(struct device *dev, struct device_attribute *attr,
1462 + struct i2c_client *client = to_i2c_client(dev);
1463 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1466 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_DC_SHIFT;
1469 + return sprintf(buf, "%s\n", pwm_dc_table[val]);
1472 +static ssize_t set_pwm_dc(struct device *dev, struct device_attribute *attr,
1473 + const char *buf, size_t count)
1475 + struct i2c_client *client = to_i2c_client(dev);
1476 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1479 + for (i = 0; i < ARRAY_SIZE(pwm_dc_table); i++) {
1480 + if (!strncmp(buf, pwm_dc_table[i], strlen(pwm_dc_table[i]))) {
1481 + dev_dbg(dev, "setting pwm dc %s\n\r", pwm_dc_table[i]);
1482 + reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
1483 + (i << PCF50606_PWMC1_DC_SHIFT));
1489 +static DEVICE_ATTR(pwm_dc, S_IRUGO | S_IWUSR, show_pwm_dc, set_pwm_dc);
1491 +static const char *pwm_clk_table[] = {
1492 + "512", "256", "128", "64",
1493 + "56300", "28100", "14100", "7000",
1496 +static ssize_t show_pwm_clk(struct device *dev, struct device_attribute *attr,
1499 + struct i2c_client *client = to_i2c_client(dev);
1500 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1503 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_CLK_SHIFT;
1506 + return sprintf(buf, "%s\n", pwm_clk_table[val]);
1509 +static ssize_t set_pwm_clk(struct device *dev, struct device_attribute *attr,
1510 + const char *buf, size_t count)
1512 + struct i2c_client *client = to_i2c_client(dev);
1513 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1516 + for (i = 0; i < ARRAY_SIZE(pwm_clk_table); i++) {
1517 + if (!strncmp(buf, pwm_clk_table[i], strlen(pwm_clk_table[i]))) {
1518 + dev_dbg(dev, "setting pwm clk %s\n\r",
1519 + pwm_clk_table[i]);
1520 + reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0xe0,
1521 + (i << PCF50606_PWMC1_CLK_SHIFT));
1527 +static DEVICE_ATTR(pwm_clk, S_IRUGO | S_IWUSR, show_pwm_clk, set_pwm_clk);
1529 +static int pcf50606bl_get_intensity(struct backlight_device *bd)
1531 + struct pcf50606_data *pcf = bl_get_data(bd);
1532 + int intensity = reg_read(pcf, PCF50606_REG_PWMC1);
1533 + intensity = (intensity >> PCF50606_PWMC1_DC_SHIFT);
1535 + return intensity & 0xf;
1538 +static int pcf50606bl_set_intensity(struct backlight_device *bd)
1540 + struct pcf50606_data *pcf = bl_get_data(bd);
1541 + int intensity = bd->props.brightness;
1543 + if (bd->props.power != FB_BLANK_UNBLANK)
1545 + if (bd->props.fb_blank != FB_BLANK_UNBLANK)
1548 + return reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
1549 + (intensity << PCF50606_PWMC1_DC_SHIFT));
1552 +static struct backlight_ops pcf50606bl_ops = {
1553 + .get_brightness = pcf50606bl_get_intensity,
1554 + .update_status = pcf50606bl_set_intensity,
1557 +/***********************************************************************
1558 + * Driver initialization
1559 + ***********************************************************************/
1561 +#ifdef CONFIG_MACH_NEO1973_GTA01
1562 +/* We currently place those platform devices here to make sure the device
1563 + * suspend/resume order is correct */
1564 +static struct platform_device gta01_pm_gps_dev = {
1565 + .name = "neo1973-pm-gps",
1568 +static struct platform_device gta01_pm_bt_dev = {
1569 + .name = "neo1973-pm-bt",
1573 +static struct attribute *pcf_sysfs_entries[16] = {
1574 + &dev_attr_voltage_dcd.attr,
1575 + &dev_attr_voltage_dcde.attr,
1576 + &dev_attr_voltage_dcud.attr,
1577 + &dev_attr_voltage_d1reg.attr,
1578 + &dev_attr_voltage_d2reg.attr,
1579 + &dev_attr_voltage_d3reg.attr,
1580 + &dev_attr_voltage_lpreg.attr,
1581 + &dev_attr_voltage_ioreg.attr,
1585 +static struct attribute_group pcf_attr_group = {
1586 + .name = NULL, /* put in device directory */
1587 + .attrs = pcf_sysfs_entries,
1590 +static void populate_sysfs_group(struct pcf50606_data *pcf)
1593 + struct attribute **attr;
1595 + for (attr = pcf_sysfs_entries; *attr; attr++)
1598 + if (pcf->pdata->used_features & PCF50606_FEAT_MBC) {
1599 + pcf_sysfs_entries[i++] = &dev_attr_chgstate.attr;
1600 + pcf_sysfs_entries[i++] = &dev_attr_chgmode.attr;
1603 + if (pcf->pdata->used_features & PCF50606_FEAT_CHGCUR)
1604 + pcf_sysfs_entries[i++] = &dev_attr_chgcur.attr;
1606 + if (pcf->pdata->used_features & PCF50606_FEAT_BATVOLT)
1607 + pcf_sysfs_entries[i++] = &dev_attr_battvolt.attr;
1609 + if (pcf->pdata->used_features & PCF50606_FEAT_BATTEMP)
1610 + pcf_sysfs_entries[i++] = &dev_attr_battemp.attr;
1612 + if (pcf->pdata->used_features & PCF50606_FEAT_PWM) {
1613 + pcf_sysfs_entries[i++] = &dev_attr_pwm_dc.attr;
1614 + pcf_sysfs_entries[i++] = &dev_attr_pwm_clk.attr;
1618 +static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
1620 + struct i2c_client *new_client;
1621 + struct pcf50606_data *data;
1625 + if (!pcf50606_pdev) {
1626 + printk(KERN_ERR "pcf50606: driver needs a platform_device!\n");
1630 + irq = platform_get_irq(pcf50606_pdev, 0);
1632 + dev_err(&pcf50606_pdev->dev, "no irq in platform resources!\n");
1636 + /* At the moment, we only support one PCF50606 in a system */
1637 + if (pcf50606_global) {
1638 + dev_err(&pcf50606_pdev->dev,
1639 + "currently only one chip supported\n");
1643 + data = kzalloc(sizeof(*data), GFP_KERNEL);
1647 + mutex_init(&data->lock);
1648 + mutex_init(&data->working_lock);
1649 + INIT_WORK(&data->work, pcf50606_work);
1651 + data->working = 0;
1652 + data->onkey_seconds = -1;
1653 + data->pdata = pcf50606_pdev->dev.platform_data;
1655 + new_client = &data->client;
1656 + i2c_set_clientdata(new_client, data);
1657 + new_client->addr = address;
1658 + new_client->adapter = adapter;
1659 + new_client->driver = &pcf50606_driver;
1660 + new_client->flags = 0;
1661 + strlcpy(new_client->name, "pcf50606", I2C_NAME_SIZE);
1663 + /* now we try to detect the chip */
1665 + /* register with i2c core */
1666 + err = i2c_attach_client(new_client);
1668 + dev_err(&new_client->dev,
1669 + "error during i2c_attach_client()\n");
1673 + populate_sysfs_group(data);
1675 + err = sysfs_create_group(&new_client->dev.kobj, &pcf_attr_group);
1677 + dev_err(&new_client->dev, "error creating sysfs group\n");
1681 + /* create virtual charger 'device' */
1683 + /* input device registration */
1684 + data->input_dev = input_allocate_device();
1685 + if (!data->input_dev)
1688 + data->input_dev->name = "FIC Neo1973 PMU events";
1689 + data->input_dev->phys = "I2C";
1690 + data->input_dev->id.bustype = BUS_I2C;
1691 + data->input_dev->cdev.dev = &new_client->dev;
1693 + data->input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
1694 + set_bit(KEY_POWER, data->input_dev->keybit);
1695 + set_bit(KEY_POWER2, data->input_dev->keybit);
1696 + set_bit(KEY_BATTERY, data->input_dev->keybit);
1698 + err = input_register_device(data->input_dev);
1702 + /* register power off handler with core power management */
1703 + pm_power_off = &pcf50606_go_standby;
1705 + /* configure interrupt mask */
1706 + reg_write(data, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
1707 + reg_write(data, PCF50606_REG_INT2M, 0x00);
1708 + reg_write(data, PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES);
1710 + err = request_irq(irq, pcf50606_irq, IRQF_TRIGGER_FALLING,
1711 + "pcf50606", data);
1715 + if (enable_irq_wake(irq) < 0)
1716 + dev_err(&new_client->dev, "IRQ %u cannot be enabled as wake-up"
1717 + "source in this hardware revision!", irq);
1719 + pcf50606_global = data;
1721 + if (data->pdata->used_features & PCF50606_FEAT_RTC) {
1722 + data->rtc = rtc_device_register("pcf50606", &new_client->dev,
1723 + &pcf50606_rtc_ops, THIS_MODULE);
1724 + if (IS_ERR(data->rtc)) {
1725 + err = PTR_ERR(data->rtc);
1730 + if (data->pdata->used_features & PCF50606_FEAT_WDT) {
1731 + err = misc_register(&pcf50606_wdt_miscdev);
1733 + dev_err(&new_client->dev, "cannot register miscdev on "
1734 + "minor=%d (%d)\n", WATCHDOG_MINOR, err);
1739 + if (data->pdata->used_features & PCF50606_FEAT_PWM) {
1740 + /* enable PWM controller */
1741 + reg_set_bit_mask(data, PCF50606_REG_PWMC1,
1742 + PCF50606_PWMC1_ACTSET,
1743 + PCF50606_PWMC1_ACTSET);
1746 + if (data->pdata->used_features & PCF50606_FEAT_PWM_BL) {
1747 + data->backlight = backlight_device_register("pcf50606-bl",
1751 + if (!data->backlight)
1753 + data->backlight->props.max_brightness = 16;
1754 + data->backlight->props.power = FB_BLANK_UNBLANK;
1755 + data->backlight->props.brightness =
1756 + data->pdata->init_brightness;
1757 + backlight_update_status(data->backlight);
1760 + apm_get_power_status = pcf50606_get_power_status;
1762 +#ifdef CONFIG_MACH_NEO1973_GTA01
1763 + if (machine_is_neo1973_gta01()) {
1764 + gta01_pm_gps_dev.dev.parent = &new_client->dev;
1765 + switch (system_rev) {
1766 + case GTA01Bv2_SYSTEM_REV:
1767 + case GTA01Bv3_SYSTEM_REV:
1768 + case GTA01Bv4_SYSTEM_REV:
1769 + gta01_pm_bt_dev.dev.parent = &new_client->dev;
1770 + platform_device_register(>a01_pm_bt_dev);
1773 + platform_device_register(>a01_pm_gps_dev);
1774 + /* a link for gllin compatibility */
1775 + err = sysfs_create_link(&platform_bus_type.devices.kobj,
1776 + >a01_pm_gps_dev.dev.kobj, "gta01-pm-gps.0");
1779 + "sysfs_create_link (gta01-pm-gps.0): %d\n", err);
1783 + if (data->pdata->used_features & PCF50606_FEAT_ACD)
1784 + reg_set_bit_mask(data, PCF50606_REG_ACDC1,
1785 + PCF50606_ACDC1_ACDAPE, PCF50606_ACDC1_ACDAPE);
1787 + reg_clear_bits(data, PCF50606_REG_ACDC1,
1788 + PCF50606_ACDC1_ACDAPE);
1793 + if (data->pdata->used_features & PCF50606_FEAT_WDT)
1794 + misc_deregister(&pcf50606_wdt_miscdev);
1796 + if (data->pdata->used_features & PCF50606_FEAT_RTC)
1797 + rtc_device_unregister(pcf50606_global->rtc);
1799 + free_irq(pcf50606_global->irq, pcf50606_global);
1800 + pcf50606_global = NULL;
1802 + pm_power_off = NULL;
1803 + input_unregister_device(data->input_dev);
1805 + sysfs_remove_group(&new_client->dev.kobj, &pcf_attr_group);
1807 + i2c_detach_client(new_client);
1813 +static int pcf50606_attach_adapter(struct i2c_adapter *adapter)
1815 + return i2c_probe(adapter, &addr_data, &pcf50606_detect);
1818 +static int pcf50606_detach_client(struct i2c_client *client)
1820 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1822 + apm_get_power_status = NULL;
1823 + input_unregister_device(pcf->input_dev);
1825 + if (pcf->pdata->used_features & PCF50606_FEAT_PWM_BL)
1826 + backlight_device_unregister(pcf->backlight);
1828 + if (pcf->pdata->used_features & PCF50606_FEAT_WDT)
1829 + misc_deregister(&pcf50606_wdt_miscdev);
1831 + if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
1832 + rtc_device_unregister(pcf->rtc);
1834 + free_irq(pcf->irq, pcf);
1836 + sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
1838 + pm_power_off = NULL;
1846 +#define INT1M_RESUMERS (PCF50606_INT1_ALARM | \
1847 + PCF50606_INT1_ONKEYF | \
1848 + PCF50606_INT1_EXTONR)
1849 +#define INT2M_RESUMERS (PCF50606_INT2_CHGWD10S | \
1850 + PCF50606_INT2_CHGPROT | \
1851 + PCF50606_INT2_CHGERR)
1852 +#define INT3M_RESUMERS (PCF50606_INT3_LOWBAT | \
1853 + PCF50606_INT3_HIGHTMP | \
1854 + PCF50606_INT3_ACDINS)
1855 +static int pcf50606_suspend(struct device *dev, pm_message_t state)
1857 + struct i2c_client *client = to_i2c_client(dev);
1858 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1861 + /* The general idea is to power down all unused power supplies,
1862 + * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF
1865 + mutex_lock(&pcf->lock);
1867 + /* Save all registers that don't "survive" standby state */
1868 + pcf->standby_regs.dcdc1 = __reg_read(pcf, PCF50606_REG_DCDC1);
1869 + pcf->standby_regs.dcdc2 = __reg_read(pcf, PCF50606_REG_DCDC2);
1870 + pcf->standby_regs.dcdec1 = __reg_read(pcf, PCF50606_REG_DCDEC1);
1871 + pcf->standby_regs.dcudc1 = __reg_read(pcf, PCF50606_REG_DCUDC1);
1872 + pcf->standby_regs.ioregc = __reg_read(pcf, PCF50606_REG_IOREGC);
1873 + pcf->standby_regs.d1regc1 = __reg_read(pcf, PCF50606_REG_D1REGC1);
1874 + pcf->standby_regs.d2regc1 = __reg_read(pcf, PCF50606_REG_D2REGC1);
1875 + pcf->standby_regs.d3regc1 = __reg_read(pcf, PCF50606_REG_D3REGC1);
1876 + pcf->standby_regs.lpregc1 = __reg_read(pcf, PCF50606_REG_LPREGC1);
1877 + pcf->standby_regs.adcc1 = __reg_read(pcf, PCF50606_REG_ADCC1);
1878 + pcf->standby_regs.adcc2 = __reg_read(pcf, PCF50606_REG_ADCC2);
1879 + pcf->standby_regs.pwmc1 = __reg_read(pcf, PCF50606_REG_PWMC1);
1881 + /* switch off power supplies that are not needed during suspend */
1882 + for (i = 0; i < __NUM_PCF50606_REGULATORS; i++) {
1883 + if (!(pcf->pdata->rails[i].flags & PMU_VRAIL_F_SUSPEND_ON)) {
1886 + /* IOREG powers the I@C interface so we cannot switch
1888 + if (i == PCF50606_REGULATOR_IOREG)
1891 + dev_dbg(dev, "disabling pcf50606 regulator %u\n", i);
1892 + /* we cannot use pcf50606_onoff_set() because we're
1893 + * already under the mutex */
1894 + tmp = __reg_read(pcf, regulator_registers[i]);
1896 + __reg_write(pcf, regulator_registers[i], tmp);
1900 + pcf->standby_regs.int1m = __reg_read(pcf, PCF50606_REG_INT1M);
1901 + pcf->standby_regs.int2m = __reg_read(pcf, PCF50606_REG_INT2M);
1902 + pcf->standby_regs.int3m = __reg_read(pcf, PCF50606_REG_INT3M);
1903 + __reg_write(pcf, PCF50606_REG_INT1M, ~INT1M_RESUMERS & 0xff);
1904 + __reg_write(pcf, PCF50606_REG_INT2M, ~INT2M_RESUMERS & 0xff);
1905 + __reg_write(pcf, PCF50606_REG_INT3M, ~INT3M_RESUMERS & 0xff);
1907 + mutex_unlock(&pcf->lock);
1912 +static int pcf50606_resume(struct device *dev)
1914 + struct i2c_client *client = to_i2c_client(dev);
1915 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
1917 + mutex_lock(&pcf->lock);
1919 + /* Resume all saved registers that don't "survive" standby state */
1920 + __reg_write(pcf, PCF50606_REG_INT1M, pcf->standby_regs.int1m);
1921 + __reg_write(pcf, PCF50606_REG_INT2M, pcf->standby_regs.int2m);
1922 + __reg_write(pcf, PCF50606_REG_INT3M, pcf->standby_regs.int3m);
1924 + __reg_write(pcf, PCF50606_REG_DCDC1, pcf->standby_regs.dcdc1);
1925 + __reg_write(pcf, PCF50606_REG_DCDC2, pcf->standby_regs.dcdc2);
1926 + __reg_write(pcf, PCF50606_REG_DCDEC1, pcf->standby_regs.dcdec1);
1927 + __reg_write(pcf, PCF50606_REG_DCUDC1, pcf->standby_regs.dcudc1);
1928 + __reg_write(pcf, PCF50606_REG_IOREGC, pcf->standby_regs.ioregc);
1929 + __reg_write(pcf, PCF50606_REG_D1REGC1, pcf->standby_regs.d1regc1);
1930 + __reg_write(pcf, PCF50606_REG_D2REGC1, pcf->standby_regs.d2regc1);
1931 + __reg_write(pcf, PCF50606_REG_D3REGC1, pcf->standby_regs.d3regc1);
1932 + __reg_write(pcf, PCF50606_REG_LPREGC1, pcf->standby_regs.lpregc1);
1933 + __reg_write(pcf, PCF50606_REG_ADCC1, pcf->standby_regs.adcc1);
1934 + __reg_write(pcf, PCF50606_REG_ADCC2, pcf->standby_regs.adcc2);
1935 + __reg_write(pcf, PCF50606_REG_PWMC1, pcf->standby_regs.pwmc1);
1937 + mutex_unlock(&pcf->lock);
1942 +#define pcf50606_suspend NULL
1943 +#define pcf50606_resume NULL
1946 +static struct i2c_driver pcf50606_driver = {
1948 + .name = "pcf50606",
1949 + .suspend = pcf50606_suspend,
1950 + .resume = pcf50606_resume,
1952 + .id = I2C_DRIVERID_PCF50606,
1953 + .attach_adapter = pcf50606_attach_adapter,
1954 + .detach_client = pcf50606_detach_client,
1957 +/* platform driver, since i2c devices don't have platform_data */
1958 +static int __init pcf50606_plat_probe(struct platform_device *pdev)
1960 + struct pcf50606_platform_data *pdata = pdev->dev.platform_data;
1965 + pcf50606_pdev = pdev;
1970 +static int pcf50606_plat_remove(struct platform_device *pdev)
1975 +static struct platform_driver pcf50606_plat_driver = {
1976 + .probe = pcf50606_plat_probe,
1977 + .remove = pcf50606_plat_remove,
1979 + .owner = THIS_MODULE,
1980 + .name = "pcf50606",
1984 +static int __init pcf50606_init(void)
1988 + rc = platform_driver_register(&pcf50606_plat_driver);
1990 + rc = i2c_add_driver(&pcf50606_driver);
1995 +static void pcf50606_exit(void)
1997 + i2c_del_driver(&pcf50606_driver);
1998 + platform_driver_unregister(&pcf50606_plat_driver);
2001 +MODULE_DESCRIPTION("I2C chip driver for NXP PCF50606 power management unit");
2002 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
2003 +MODULE_LICENSE("GPL");
2005 +module_init(pcf50606_init);
2006 +module_exit(pcf50606_exit);
2007 diff --git a/drivers/i2c/chips/pcf50606.h b/drivers/i2c/chips/pcf50606.h
2008 new file mode 100644
2009 index 0000000..15b350f
2011 +++ b/drivers/i2c/chips/pcf50606.h
2013 +#ifndef _PCF50606_H
2014 +#define _PCF50606_H
2016 +/* Philips PCF50606 Power Managemnt Unit (PMU) driver
2017 + * (C) 2006-2007 by OpenMoko, Inc.
2018 + * Author: Harald Welte <laforge@openmoko.org>
2022 +enum pfc50606_regs {
2023 + PCF50606_REG_ID = 0x00,
2024 + PCF50606_REG_OOCS = 0x01,
2025 + PCF50606_REG_INT1 = 0x02, /* Interrupt Status */
2026 + PCF50606_REG_INT2 = 0x03, /* Interrupt Status */
2027 + PCF50606_REG_INT3 = 0x04, /* Interrupt Status */
2028 + PCF50606_REG_INT1M = 0x05, /* Interrupt Mask */
2029 + PCF50606_REG_INT2M = 0x06, /* Interrupt Mask */
2030 + PCF50606_REG_INT3M = 0x07, /* Interrupt Mask */
2031 + PCF50606_REG_OOCC1 = 0x08,
2032 + PCF50606_REG_OOCC2 = 0x09,
2033 + PCF50606_REG_RTCSC = 0x0a, /* Second */
2034 + PCF50606_REG_RTCMN = 0x0b, /* Minute */
2035 + PCF50606_REG_RTCHR = 0x0c, /* Hour */
2036 + PCF50606_REG_RTCWD = 0x0d, /* Weekday */
2037 + PCF50606_REG_RTCDT = 0x0e, /* Day */
2038 + PCF50606_REG_RTCMT = 0x0f, /* Month */
2039 + PCF50606_REG_RTCYR = 0x10, /* Year */
2040 + PCF50606_REG_RTCSCA = 0x11, /* Alarm Second */
2041 + PCF50606_REG_RTCMNA = 0x12, /* Alarm Minute */
2042 + PCF50606_REG_RTCHRA = 0x13, /* Alarm Hour */
2043 + PCF50606_REG_RTCWDA = 0x14, /* Alarm Weekday */
2044 + PCF50606_REG_RTCDTA = 0x15, /* Alarm Day */
2045 + PCF50606_REG_RTCMTA = 0x16, /* Alarm Month */
2046 + PCF50606_REG_RTCYRA = 0x17, /* Alarm Year */
2047 + PCF50606_REG_PSSC = 0x18, /* Power sequencing */
2048 + PCF50606_REG_PWROKM = 0x19, /* PWROK mask */
2049 + PCF50606_REG_PWROKS = 0x1a, /* PWROK status */
2050 + PCF50606_REG_DCDC1 = 0x1b,
2051 + PCF50606_REG_DCDC2 = 0x1c,
2052 + PCF50606_REG_DCDC3 = 0x1d,
2053 + PCF50606_REG_DCDC4 = 0x1e,
2054 + PCF50606_REG_DCDEC1 = 0x1f,
2055 + PCF50606_REG_DCDEC2 = 0x20,
2056 + PCF50606_REG_DCUDC1 = 0x21,
2057 + PCF50606_REG_DCUDC2 = 0x22,
2058 + PCF50606_REG_IOREGC = 0x23,
2059 + PCF50606_REG_D1REGC1 = 0x24,
2060 + PCF50606_REG_D2REGC1 = 0x25,
2061 + PCF50606_REG_D3REGC1 = 0x26,
2062 + PCF50606_REG_LPREGC1 = 0x27,
2063 + PCF50606_REG_LPREGC2 = 0x28,
2064 + PCF50606_REG_MBCC1 = 0x29,
2065 + PCF50606_REG_MBCC2 = 0x2a,
2066 + PCF50606_REG_MBCC3 = 0x2b,
2067 + PCF50606_REG_MBCS1 = 0x2c,
2068 + PCF50606_REG_BBCC = 0x2d,
2069 + PCF50606_REG_ADCC1 = 0x2e,
2070 + PCF50606_REG_ADCC2 = 0x2f,
2071 + PCF50606_REG_ADCS1 = 0x30,
2072 + PCF50606_REG_ADCS2 = 0x31,
2073 + PCF50606_REG_ADCS3 = 0x32,
2074 + PCF50606_REG_ACDC1 = 0x33,
2075 + PCF50606_REG_BVMC = 0x34,
2076 + PCF50606_REG_PWMC1 = 0x35,
2077 + PCF50606_REG_LEDC1 = 0x36,
2078 + PCF50606_REG_LEDC2 = 0x37,
2079 + PCF50606_REG_GPOC1 = 0x38,
2080 + PCF50606_REG_GPOC2 = 0x39,
2081 + PCF50606_REG_GPOC3 = 0x3a,
2082 + PCF50606_REG_GPOC4 = 0x3b,
2083 + PCF50606_REG_GPOC5 = 0x3c,
2084 + __NUM_PCF50606_REGS
2087 +enum pcf50606_reg_oocs {
2088 + PFC50606_OOCS_ONKEY = 0x01,
2089 + PCF50606_OOCS_EXTON = 0x02,
2090 + PCF50606_OOCS_PWROKRST = 0x04,
2091 + PCF50606_OOCS_BATOK = 0x08,
2092 + PCF50606_OOCS_BACKOK = 0x10,
2093 + PCF50606_OOCS_CHGOK = 0x20,
2094 + PCF50606_OOCS_TEMPOK = 0x40,
2095 + PCF50606_OOCS_WDTEXP = 0x80,
2098 +enum pcf50606_reg_oocc1 {
2099 + PCF50606_OOCC1_GOSTDBY = 0x01,
2100 + PCF50606_OOCC1_TOTRST = 0x02,
2101 + PCF50606_OOCC1_CLK32ON = 0x04,
2102 + PCF50606_OOCC1_WDTRST = 0x08,
2103 + PCF50606_OOCC1_RTCWAK = 0x10,
2104 + PCF50606_OOCC1_CHGWAK = 0x20,
2105 + PCF50606_OOCC1_EXTONWAK_HIGH = 0x40,
2106 + PCF50606_OOCC1_EXTONWAK_LOW = 0x80,
2109 +enum pcf50606_reg_oocc2 {
2110 + PCF50606_OOCC2_ONKEYDB_NONE = 0x00,
2111 + PCF50606_OOCC2_ONKEYDB_14ms = 0x01,
2112 + PCF50606_OOCC2_ONKEYDB_62ms = 0x02,
2113 + PCF50606_OOCC2_ONKEYDB_500ms = 0x03,
2114 + PCF50606_OOCC2_EXTONDB_NONE = 0x00,
2115 + PCF50606_OOCC2_EXTONDB_14ms = 0x04,
2116 + PCF50606_OOCC2_EXTONDB_62ms = 0x08,
2117 + PCF50606_OOCC2_EXTONDB_500ms = 0x0c,
2120 +enum pcf50606_reg_int1 {
2121 + PCF50606_INT1_ONKEYR = 0x01, /* ONKEY rising edge */
2122 + PCF50606_INT1_ONKEYF = 0x02, /* ONKEY falling edge */
2123 + PCF50606_INT1_ONKEY1S = 0x04, /* OMKEY at least 1sec low */
2124 + PCF50606_INT1_EXTONR = 0x08, /* EXTON rising edge */
2125 + PCF50606_INT1_EXTONF = 0x10, /* EXTON falling edge */
2126 + PCF50606_INT1_SECOND = 0x40, /* RTC periodic second interrupt */
2127 + PCF50606_INT1_ALARM = 0x80, /* RTC alarm time is reached */
2130 +enum pcf50606_reg_int2 {
2131 + PCF50606_INT2_CHGINS = 0x01, /* Charger inserted */
2132 + PCF50606_INT2_CHGRM = 0x02, /* Charger removed */
2133 + PCF50606_INT2_CHGFOK = 0x04, /* Fast charging OK */
2134 + PCF50606_INT2_CHGERR = 0x08, /* Error in charging mode */
2135 + PCF50606_INT2_CHGFRDY = 0x10, /* Fast charge completed */
2136 + PCF50606_INT2_CHGPROT = 0x20, /* Charging protection interrupt */
2137 + PCF50606_INT2_CHGWD10S = 0x40, /* Charger watchdig expires in 10s */
2138 + PCF50606_INT2_CHGWDEXP = 0x80, /* Charger watchdog expires */
2141 +enum pcf50606_reg_int3 {
2142 + PCF50606_INT3_ADCRDY = 0x01, /* ADC conversion finished */
2143 + PCF50606_INT3_ACDINS = 0x02, /* Accessory inserted */
2144 + PCF50606_INT3_ACDREM = 0x04, /* Accessory removed */
2145 + PCF50606_INT3_TSCPRES = 0x08, /* Touch screen pressed */
2146 + PCF50606_INT3_LOWBAT = 0x40, /* Low battery voltage */
2147 + PCF50606_INT3_HIGHTMP = 0x80, /* High temperature */
2150 +/* used by PSSC, PWROKM, PWROKS, */
2151 +enum pcf50606_regu {
2152 + PCF50606_REGU_DCD = 0x01, /* DCD in phase 2 */
2153 + PCF50606_REGU_DCDE = 0x02, /* DCDE in phase 2 */
2154 + PCF50606_REGU_DCUD = 0x04, /* DCDU in phase 2 */
2155 + PCF50606_REGU_IO = 0x08, /* IO in phase 2 */
2156 + PCF50606_REGU_D1 = 0x10, /* D1 in phase 2 */
2157 + PCF50606_REGU_D2 = 0x20, /* D2 in phase 2 */
2158 + PCF50606_REGU_D3 = 0x40, /* D3 in phase 2 */
2159 + PCF50606_REGU_LP = 0x80, /* LP in phase 2 */
2162 +enum pcf50606_reg_dcdc4 {
2163 + PCF50606_DCDC4_MODE_AUTO = 0x00,
2164 + PCF50606_DCDC4_MODE_PWM = 0x01,
2165 + PCF50606_DCDC4_MODE_PCF = 0x02,
2166 + PCF50606_DCDC4_OFF_FLOAT = 0x00,
2167 + PCF50606_DCDC4_OFF_BYPASS = 0x04,
2168 + PCF50606_DCDC4_OFF_PULLDOWN = 0x08,
2169 + PCF50606_DCDC4_CURLIM_500mA = 0x00,
2170 + PCF50606_DCDC4_CURLIM_750mA = 0x10,
2171 + PCF50606_DCDC4_CURLIM_1000mA = 0x20,
2172 + PCF50606_DCDC4_CURLIM_1250mA = 0x30,
2173 + PCF50606_DCDC4_TOGGLE = 0x40,
2174 + PCF50606_DCDC4_REGSEL_DCDC2 = 0x80,
2177 +enum pcf50606_reg_dcdec2 {
2178 + PCF50606_DCDEC2_MODE_AUTO = 0x00,
2179 + PCF50606_DCDEC2_MODE_PWM = 0x01,
2180 + PCF50606_DCDEC2_MODE_PCF = 0x02,
2181 + PCF50606_DCDEC2_OFF_FLOAT = 0x00,
2182 + PCF50606_DCDEC2_OFF_BYPASS = 0x04,
2185 +enum pcf50606_reg_dcudc2 {
2186 + PCF50606_DCUDC2_MODE_AUTO = 0x00,
2187 + PCF50606_DCUDC2_MODE_PWM = 0x01,
2188 + PCF50606_DCUDC2_MODE_PCF = 0x02,
2189 + PCF50606_DCUDC2_OFF_FLOAT = 0x00,
2190 + PCF50606_DCUDC2_OFF_BYPASS = 0x04,
2193 +enum pcf50606_reg_adcc1 {
2194 + PCF50606_ADCC1_TSCMODACT = 0x01,
2195 + PCF50606_ADCC1_TSCMODSTB = 0x02,
2196 + PCF50606_ADCC1_TRATSET = 0x04,
2197 + PCF50606_ADCC1_NTCSWAPE = 0x08,
2198 + PCF50606_ADCC1_NTCSWAOFF = 0x10,
2199 + PCF50606_ADCC1_EXTSYNCBREAK = 0x20,
2201 + PCF50606_ADCC1_TSCINT = 0x80,
2204 +enum pcf50606_reg_adcc2 {
2205 + PCF50606_ADCC2_ADCSTART = 0x01,
2206 + /* see enum pcf50606_adcc2_adcmux */
2207 + PCF50606_ADCC2_SYNC_NONE = 0x00,
2208 + PCF50606_ADCC2_SYNC_TXON = 0x20,
2209 + PCF50606_ADCC2_SYNC_PWREN1 = 0x40,
2210 + PCF50606_ADCC2_SYNC_PWREN2 = 0x60,
2211 + PCF50606_ADCC2_RES_10BIT = 0x00,
2212 + PCF50606_ADCC2_RES_8BIT = 0x80,
2215 +#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
2217 +#define ADCMUX_SHIFT 1
2218 +enum pcf50606_adcc2_adcmux {
2219 + PCF50606_ADCMUX_BATVOLT_RES = 0x0 << ADCMUX_SHIFT,
2220 + PCF50606_ADCMUX_BATVOLT_SUBTR = 0x1 << ADCMUX_SHIFT,
2221 + PCF50606_ADCMUX_ADCIN1_RES = 0x2 << ADCMUX_SHIFT,
2222 + PCF50606_ADCMUX_ADCIN1_SUBTR = 0x3 << ADCMUX_SHIFT,
2223 + PCF50606_ADCMUX_BATTEMP = 0x4 << ADCMUX_SHIFT,
2224 + PCF50606_ADCMUX_ADCIN2 = 0x5 << ADCMUX_SHIFT,
2225 + PCF50606_ADCMUX_ADCIN3 = 0x6 << ADCMUX_SHIFT,
2226 + PCF50606_ADCMUX_ADCIN3_RATIO = 0x7 << ADCMUX_SHIFT,
2227 + PCF50606_ADCMUX_XPOS = 0x8 << ADCMUX_SHIFT,
2228 + PCF50606_ADCMUX_YPOS = 0x9 << ADCMUX_SHIFT,
2229 + PCF50606_ADCMUX_P1 = 0xa << ADCMUX_SHIFT,
2230 + PCF50606_ADCMUX_P2 = 0xb << ADCMUX_SHIFT,
2231 + PCF50606_ADCMUX_BATVOLT_ADCIN1 = 0xc << ADCMUX_SHIFT,
2232 + PCF50606_ADCMUX_XY_SEQUENCE = 0xe << ADCMUX_SHIFT,
2233 + PCF50606_P1_P2_RESISTANCE = 0xf << ADCMUX_SHIFT,
2236 +enum pcf50606_adcs2 {
2237 + PCF50606_ADCS2_ADCRDY = 0x80,
2240 +enum pcf50606_reg_mbcc1 {
2241 + PCF50606_MBCC1_CHGAPE = 0x01,
2242 + PCF50606_MBCC1_AUTOFST = 0x02,
2243 +#define PCF50606_MBCC1_CHGMOD_MASK 0x1c
2244 +#define PCF50606_MBCC1_CHGMOD_SHIFT 2
2245 + PCF50606_MBCC1_CHGMOD_QUAL = 0x00,
2246 + PCF50606_MBCC1_CHGMOD_PRE = 0x04,
2247 + PCF50606_MBCC1_CHGMOD_TRICKLE = 0x08,
2248 + PCF50606_MBCC1_CHGMOD_FAST_CCCV = 0x0c,
2249 + PCF50606_MBCC1_CHGMOD_FAST_NOCC = 0x10,
2250 + PCF50606_MBCC1_CHGMOD_FAST_NOCV = 0x14,
2251 + PCF50606_MBCC1_CHGMOD_FAST_SW = 0x18,
2252 + PCF50606_MBCC1_CHGMOD_IDLE = 0x1c,
2253 + PCF50606_MBCC1_DETMOD_LOWCHG = 0x20,
2254 + PCF50606_MBCC1_DETMOD_WDRST = 0x40,
2257 +enum pcf50606_reg_acdc1 {
2258 + PCF50606_ACDC1_ACDDET = 0x01,
2259 + PCF50606_ACDC1_THRSHLD_1V0 = 0x00,
2260 + PCF50606_ACDC1_THRSHLD_1V2 = 0x02,
2261 + PCF50606_ACDC1_THRSHLD_1V4 = 0x04,
2262 + PCF50606_ACDC1_THRSHLD_1V6 = 0x06,
2263 + PCF50606_ACDC1_THRSHLD_1V8 = 0x08,
2264 + PCF50606_ACDC1_THRSHLD_2V0 = 0x0a,
2265 + PCF50606_ACDC1_THRSHLD_2V2 = 0x0c,
2266 + PCF50606_ACDC1_THRSHLD_2V4 = 0x0e,
2267 + PCF50606_ACDC1_DISDB = 0x10,
2268 + PCF50606_ACDC1_ACDAPE = 0x80,
2271 +enum pcf50606_reg_bvmc {
2272 + PCF50606_BVMC_LOWBAT = 0x01,
2273 + PCF50606_BVMC_THRSHLD_NULL = 0x00,
2274 + PCF50606_BVMC_THRSHLD_2V8 = 0x02,
2275 + PCF50606_BVMC_THRSHLD_2V9 = 0x04,
2276 + PCF50606_BVMC_THRSHLD_3V = 0x08,
2277 + PCF50606_BVMC_THRSHLD_3V1 = 0x08,
2278 + PCF50606_BVMC_THRSHLD_3V2 = 0x0a,
2279 + PCF50606_BVMC_THRSHLD_3V3 = 0x0c,
2280 + PCF50606_BVMC_THRSHLD_3V4 = 0x0e,
2281 + PCF50606_BVMC_DISDB = 0x10,
2284 +enum pcf50606_reg_pwmc1 {
2285 + PCF50606_PWMC1_ACTSET = 0x01,
2286 + PCF50606_PWMC1_PWMDC_0_16 = 0x00,
2287 + PCF50606_PWMC1_PWMDC_1_16 = 0x02,
2288 + PCF50606_PWMC1_PWMDC_2_16 = 0x04,
2289 + PCF50606_PWMC1_PWMDC_3_16 = 0x06,
2290 + PCF50606_PWMC1_PWMDC_4_16 = 0x08,
2291 + PCF50606_PWMC1_PWMDC_5_16 = 0x0a,
2292 + PCF50606_PWMC1_PWMDC_6_16 = 0x0c,
2293 + PCF50606_PWMC1_PWMDC_7_16 = 0x0e,
2294 + PCF50606_PWMC1_PWMDC_8_16 = 0x10,
2295 + PCF50606_PWMC1_PWMDC_9_16 = 0x12,
2296 + PCF50606_PWMC1_PWMDC_10_16 = 0x14,
2297 + PCF50606_PWMC1_PWMDC_11_16 = 0x16,
2298 + PCF50606_PWMC1_PWMDC_12_16 = 0x18,
2299 + PCF50606_PWMC1_PWMDC_13_16 = 0x1a,
2300 + PCF50606_PWMC1_PWMDC_14_16 = 0x1c,
2301 + PCF50606_PWMC1_PWMDC_15_16 = 0x1e,
2302 + PCF50606_PWMC1_PRESC_512Hz = 0x20,
2303 + PCF50606_PWMC1_PRESC_256Hz = 0x40,
2304 + PCF50606_PWMC1_PRESC_64Hz = 0x60,
2305 + PCF50606_PWMC1_PRESC_56kHz = 0x80,
2306 + PCF50606_PWMC1_PRESC_28kHz = 0xa0,
2307 + PCF50606_PWMC1_PRESC_14kHz = 0xc0,
2308 + PCF50606_PWMC1_PRESC_7kHz = 0xe0,
2310 +#define PCF50606_PWMC1_CLK_SHIFT 5
2311 +#define PCF50606_PWMC1_DC_SHIFT 1
2313 +#endif /* _PCF50606_H */
2315 diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
2316 index 580acc9..2cda699 100644
2317 --- a/include/linux/i2c-id.h
2318 +++ b/include/linux/i2c-id.h
2320 #define I2C_DRIVERID_I2CDEV 900
2322 #define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */
2323 +#define I2C_DRIVERID_PCF50606 1049
2326 * ---- Adapter types ----------------------------------------------------
2327 diff --git a/include/linux/pcf50606.h b/include/linux/pcf50606.h
2328 new file mode 100644
2329 index 0000000..bc98e47
2331 +++ b/include/linux/pcf50606.h
2333 +#ifndef _LINUX_PCF50606_H
2334 +#define _LINUX_PCF50606_H
2336 +/* public in-kernel pcf50606 api */
2337 +enum pcf50606_regulator_id {
2338 + PCF50606_REGULATOR_DCD,
2339 + PCF50606_REGULATOR_DCDE,
2340 + PCF50606_REGULATOR_DCUD,
2341 + PCF50606_REGULATOR_D1REG,
2342 + PCF50606_REGULATOR_D2REG,
2343 + PCF50606_REGULATOR_D3REG,
2344 + PCF50606_REGULATOR_LPREG,
2345 + PCF50606_REGULATOR_IOREG,
2346 + __NUM_PCF50606_REGULATORS
2349 +struct pcf50606_data;
2351 +/* This is an ugly construct on how to access the (currently single/global)
2352 + * pcf50606 handle from other code in the kernel. I didn't really come up with
2353 + * a more decent method of dynamically resolving this */
2354 +extern struct pcf50606_data *pcf50606_global;
2357 +pcf50606_go_standby(void);
2360 +pcf50606_gpo0_set(struct pcf50606_data *pcf, int on);
2363 +pcf50606_gpo0_get(struct pcf50606_data *pcf);
2366 +pcf50606_voltage_set(struct pcf50606_data *pcf,
2367 + enum pcf50606_regulator_id reg,
2368 + unsigned int millivolts);
2369 +extern unsigned int
2370 +pcf50606_voltage_get(struct pcf50606_data *pcf,
2371 + enum pcf50606_regulator_id reg);
2373 +pcf50606_onoff_get(struct pcf50606_data *pcf,
2374 + enum pcf50606_regulator_id reg);
2377 +pcf50606_onoff_set(struct pcf50606_data *pcf,
2378 + enum pcf50606_regulator_id reg, int on);
2381 +pcf50606_charge_fast(struct pcf50606_data *pcf, int on);
2383 +#define PMU_VRAIL_F_SUSPEND_ON 0x00000001 /* Remains on during suspend */
2384 +#define PMU_VRAIL_F_UNUSED 0x00000002 /* This rail is not used */
2385 +struct pmu_voltage_rail {
2387 + unsigned int flags;
2389 + unsigned int init;
2401 +typedef int pmu_cb(struct device *dev, unsigned int feature,
2402 + enum pmu_event event);
2404 +#define PCF50606_FEAT_EXTON 0x00000001 /* not yet supported */
2405 +#define PCF50606_FEAT_MBC 0x00000002
2406 +#define PCF50606_FEAT_BBC 0x00000004 /* not yet supported */
2407 +#define PCF50606_FEAT_TSC 0x00000008 /* not yet supported */
2408 +#define PCF50606_FEAT_WDT 0x00000010
2409 +#define PCF50606_FEAT_ACD 0x00000020
2410 +#define PCF50606_FEAT_RTC 0x00000040
2411 +#define PCF50606_FEAT_PWM 0x00000080
2412 +#define PCF50606_FEAT_CHGCUR 0x00000100
2413 +#define PCF50606_FEAT_BATVOLT 0x00000200
2414 +#define PCF50606_FEAT_BATTEMP 0x00000400
2415 +#define PCF50606_FEAT_PWM_BL 0x00000800
2417 +struct pcf50606_platform_data {
2419 + unsigned int used_features;
2420 + unsigned int onkey_seconds_required;
2422 + /* voltage regulator related */
2423 + struct pmu_voltage_rail rails[__NUM_PCF50606_REGULATORS];
2424 + unsigned int used_regulators;
2426 + /* charger related */
2427 + unsigned int r_fix_batt;
2428 + unsigned int r_fix_batt_par;
2429 + unsigned int r_sense_milli;
2431 + /* backlight related */
2432 + unsigned int init_brightness;
2435 + u_int8_t mbcc3; /* charger voltage / current */