aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQiao Zhou <zhouqiao@marvell.com>2012-07-09 02:37:32 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-07-09 09:12:51 -0400
commit70c6cce040661204986ebbf22224cb24bd77ea71 (patch)
treefe60851749c386e65735818e397850f2b3bd7d3e
parent49003a68926e073fc71062d210c6f9febc8665a2 (diff)
mfd: Support 88pm80x in 80x driver
88PM800 and 88PM805 are two discrete chips used for power management. Hardware designer can use them together or only one of them according to requirement. 88pm80x.c provides common i2c driver handling for both 800 and 805, such as i2c_driver init, regmap init, read/write api etc. 88pm800.c handles specifically for 800, such as chip init, irq init/handle, mfd device register, including rtc, onkey, regulator( to be add later) etc. besides that, 800 has three i2c device, one regular i2c client, two other i2c dummy for gpadc and power purpose. 88pm805.c handles specifically for 805, such as chip init, irq init/handle, mfd device register, including codec, headset/mic detect etc. the i2c operation of both 800 and 805 are via regmap, and 88pm80x-i2c exported a group of r/w bulk r/w and bits set API for facility. Signed-off-by: Qiao Zhou <zhouqiao@marvell.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/88pm800.c593
-rw-r--r--drivers/mfd/88pm805.c299
-rw-r--r--drivers/mfd/88pm80x.c116
-rw-r--r--drivers/mfd/Kconfig24
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--include/linux/mfd/88pm80x.h368
6 files changed, 1402 insertions, 0 deletions
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
new file mode 100644
index 000000000000..fe479ccfaa19
--- /dev/null
+++ b/drivers/mfd/88pm800.c
@@ -0,0 +1,593 @@
1/*
2 * Base driver for Marvell 88PM800
3 *
4 * Copyright (C) 2012 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * Joseph(Yossi) Hanin <yhanin@marvell.com>
7 * Qiao Zhou <zhouqiao@marvell.com>
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/i2c.h>
26#include <linux/mfd/core.h>
27#include <linux/mfd/88pm80x.h>
28#include <linux/slab.h>
29
30#define PM800_CHIP_ID (0x00)
31
32/* Interrupt Registers */
33#define PM800_INT_STATUS1 (0x05)
34#define PM800_ONKEY_INT_STS1 (1 << 0)
35#define PM800_EXTON_INT_STS1 (1 << 1)
36#define PM800_CHG_INT_STS1 (1 << 2)
37#define PM800_BAT_INT_STS1 (1 << 3)
38#define PM800_RTC_INT_STS1 (1 << 4)
39#define PM800_CLASSD_OC_INT_STS1 (1 << 5)
40
41#define PM800_INT_STATUS2 (0x06)
42#define PM800_VBAT_INT_STS2 (1 << 0)
43#define PM800_VSYS_INT_STS2 (1 << 1)
44#define PM800_VCHG_INT_STS2 (1 << 2)
45#define PM800_TINT_INT_STS2 (1 << 3)
46#define PM800_GPADC0_INT_STS2 (1 << 4)
47#define PM800_TBAT_INT_STS2 (1 << 5)
48#define PM800_GPADC2_INT_STS2 (1 << 6)
49#define PM800_GPADC3_INT_STS2 (1 << 7)
50
51#define PM800_INT_STATUS3 (0x07)
52
53#define PM800_INT_STATUS4 (0x08)
54#define PM800_GPIO0_INT_STS4 (1 << 0)
55#define PM800_GPIO1_INT_STS4 (1 << 1)
56#define PM800_GPIO2_INT_STS4 (1 << 2)
57#define PM800_GPIO3_INT_STS4 (1 << 3)
58#define PM800_GPIO4_INT_STS4 (1 << 4)
59
60#define PM800_INT_ENA_1 (0x09)
61#define PM800_ONKEY_INT_ENA1 (1 << 0)
62#define PM800_EXTON_INT_ENA1 (1 << 1)
63#define PM800_CHG_INT_ENA1 (1 << 2)
64#define PM800_BAT_INT_ENA1 (1 << 3)
65#define PM800_RTC_INT_ENA1 (1 << 4)
66#define PM800_CLASSD_OC_INT_ENA1 (1 << 5)
67
68#define PM800_INT_ENA_2 (0x0A)
69#define PM800_VBAT_INT_ENA2 (1 << 0)
70#define PM800_VSYS_INT_ENA2 (1 << 1)
71#define PM800_VCHG_INT_ENA2 (1 << 2)
72#define PM800_TINT_INT_ENA2 (1 << 3)
73
74#define PM800_INT_ENA_3 (0x0B)
75#define PM800_GPADC0_INT_ENA3 (1 << 0)
76#define PM800_GPADC1_INT_ENA3 (1 << 1)
77#define PM800_GPADC2_INT_ENA3 (1 << 2)
78#define PM800_GPADC3_INT_ENA3 (1 << 3)
79#define PM800_GPADC4_INT_ENA3 (1 << 4)
80
81#define PM800_INT_ENA_4 (0x0C)
82#define PM800_GPIO0_INT_ENA4 (1 << 0)
83#define PM800_GPIO1_INT_ENA4 (1 << 1)
84#define PM800_GPIO2_INT_ENA4 (1 << 2)
85#define PM800_GPIO3_INT_ENA4 (1 << 3)
86#define PM800_GPIO4_INT_ENA4 (1 << 4)
87
88/* number of INT_ENA & INT_STATUS regs */
89#define PM800_INT_REG_NUM (4)
90
91/* Interrupt Number in 88PM800 */
92enum {
93 PM800_IRQ_ONKEY, /*EN1b0 *//*0 */
94 PM800_IRQ_EXTON, /*EN1b1 */
95 PM800_IRQ_CHG, /*EN1b2 */
96 PM800_IRQ_BAT, /*EN1b3 */
97 PM800_IRQ_RTC, /*EN1b4 */
98 PM800_IRQ_CLASSD, /*EN1b5 *//*5 */
99 PM800_IRQ_VBAT, /*EN2b0 */
100 PM800_IRQ_VSYS, /*EN2b1 */
101 PM800_IRQ_VCHG, /*EN2b2 */
102 PM800_IRQ_TINT, /*EN2b3 */
103 PM800_IRQ_GPADC0, /*EN3b0 *//*10 */
104 PM800_IRQ_GPADC1, /*EN3b1 */
105 PM800_IRQ_GPADC2, /*EN3b2 */
106 PM800_IRQ_GPADC3, /*EN3b3 */
107 PM800_IRQ_GPADC4, /*EN3b4 */
108 PM800_IRQ_GPIO0, /*EN4b0 *//*15 */
109 PM800_IRQ_GPIO1, /*EN4b1 */
110 PM800_IRQ_GPIO2, /*EN4b2 */
111 PM800_IRQ_GPIO3, /*EN4b3 */
112 PM800_IRQ_GPIO4, /*EN4b4 *//*19 */
113 PM800_MAX_IRQ,
114};
115
116enum {
117 /* Procida */
118 PM800_CHIP_A0 = 0x60,
119 PM800_CHIP_A1 = 0x61,
120 PM800_CHIP_B0 = 0x62,
121 PM800_CHIP_C0 = 0x63,
122 PM800_CHIP_END = PM800_CHIP_C0,
123
124 /* Make sure to update this to the last stepping */
125 PM8XXX_CHIP_END = PM800_CHIP_END
126};
127
128static const struct i2c_device_id pm80x_id_table[] = {
129 {"88PM800", CHIP_PM800},
130};
131MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
132
133static struct resource rtc_resources[] = {
134 {
135 .name = "88pm80x-rtc",
136 .start = PM800_IRQ_RTC,
137 .end = PM800_IRQ_RTC,
138 .flags = IORESOURCE_IRQ,
139 },
140};
141
142static struct mfd_cell rtc_devs[] = {
143 {
144 .name = "88pm80x-rtc",
145 .num_resources = ARRAY_SIZE(rtc_resources),
146 .resources = &rtc_resources[0],
147 .id = -1,
148 },
149};
150
151static struct resource onkey_resources[] = {
152 {
153 .name = "88pm80x-onkey",
154 .start = PM800_IRQ_ONKEY,
155 .end = PM800_IRQ_ONKEY,
156 .flags = IORESOURCE_IRQ,
157 },
158};
159
160static struct mfd_cell onkey_devs[] = {
161 {
162 .name = "88pm80x-onkey",
163 .num_resources = 1,
164 .resources = &onkey_resources[0],
165 .id = -1,
166 },
167};
168
169static const struct regmap_irq pm800_irqs[] = {
170 /* INT0 */
171 [PM800_IRQ_ONKEY] = {
172 .mask = PM800_ONKEY_INT_ENA1,
173 },
174 [PM800_IRQ_EXTON] = {
175 .mask = PM800_EXTON_INT_ENA1,
176 },
177 [PM800_IRQ_CHG] = {
178 .mask = PM800_CHG_INT_ENA1,
179 },
180 [PM800_IRQ_BAT] = {
181 .mask = PM800_BAT_INT_ENA1,
182 },
183 [PM800_IRQ_RTC] = {
184 .mask = PM800_RTC_INT_ENA1,
185 },
186 [PM800_IRQ_CLASSD] = {
187 .mask = PM800_CLASSD_OC_INT_ENA1,
188 },
189 /* INT1 */
190 [PM800_IRQ_VBAT] = {
191 .reg_offset = 1,
192 .mask = PM800_VBAT_INT_ENA2,
193 },
194 [PM800_IRQ_VSYS] = {
195 .reg_offset = 1,
196 .mask = PM800_VSYS_INT_ENA2,
197 },
198 [PM800_IRQ_VCHG] = {
199 .reg_offset = 1,
200 .mask = PM800_VCHG_INT_ENA2,
201 },
202 [PM800_IRQ_TINT] = {
203 .reg_offset = 1,
204 .mask = PM800_TINT_INT_ENA2,
205 },
206 /* INT2 */
207 [PM800_IRQ_GPADC0] = {
208 .reg_offset = 2,
209 .mask = PM800_GPADC0_INT_ENA3,
210 },
211 [PM800_IRQ_GPADC1] = {
212 .reg_offset = 2,
213 .mask = PM800_GPADC1_INT_ENA3,
214 },
215 [PM800_IRQ_GPADC2] = {
216 .reg_offset = 2,
217 .mask = PM800_GPADC2_INT_ENA3,
218 },
219 [PM800_IRQ_GPADC3] = {
220 .reg_offset = 2,
221 .mask = PM800_GPADC3_INT_ENA3,
222 },
223 [PM800_IRQ_GPADC4] = {
224 .reg_offset = 2,
225 .mask = PM800_GPADC4_INT_ENA3,
226 },
227 /* INT3 */
228 [PM800_IRQ_GPIO0] = {
229 .reg_offset = 3,
230 .mask = PM800_GPIO0_INT_ENA4,
231 },
232 [PM800_IRQ_GPIO1] = {
233 .reg_offset = 3,
234 .mask = PM800_GPIO1_INT_ENA4,
235 },
236 [PM800_IRQ_GPIO2] = {
237 .reg_offset = 3,
238 .mask = PM800_GPIO2_INT_ENA4,
239 },
240 [PM800_IRQ_GPIO3] = {
241 .reg_offset = 3,
242 .mask = PM800_GPIO3_INT_ENA4,
243 },
244 [PM800_IRQ_GPIO4] = {
245 .reg_offset = 3,
246 .mask = PM800_GPIO4_INT_ENA4,
247 },
248};
249
250static int __devinit device_gpadc_init(struct pm80x_chip *chip,
251 struct pm80x_platform_data *pdata)
252{
253 struct pm80x_subchip *subchip = chip->subchip;
254 struct regmap *map = subchip->regmap_gpadc;
255 int data = 0, mask = 0, ret = 0;
256
257 if (!map) {
258 dev_warn(chip->dev,
259 "Warning: gpadc regmap is not available!\n");
260 return -EINVAL;
261 }
262 /*
263 * initialize GPADC without activating it turn on GPADC
264 * measurments
265 */
266 ret = regmap_update_bits(map,
267 PM800_GPADC_MISC_CONFIG2,
268 PM800_GPADC_MISC_GPFSM_EN,
269 PM800_GPADC_MISC_GPFSM_EN);
270 if (ret < 0)
271 goto out;
272 /*
273 * This function configures the ADC as requires for
274 * CP implementation.CP does not "own" the ADC configuration
275 * registers and relies on AP.
276 * Reason: enable automatic ADC measurements needed
277 * for CP to get VBAT and RF temperature readings.
278 */
279 ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN1,
280 PM800_MEAS_EN1_VBAT, PM800_MEAS_EN1_VBAT);
281 if (ret < 0)
282 goto out;
283 ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN2,
284 (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN),
285 (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN));
286 if (ret < 0)
287 goto out;
288
289 /*
290 * the defult of PM800 is GPADC operates at 100Ks/s rate
291 * and Number of GPADC slots with active current bias prior
292 * to GPADC sampling = 1 slot for all GPADCs set for
293 * Temprature mesurmants
294 */
295 mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
296 PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);
297
298 if (pdata && (pdata->batt_det == 0))
299 data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
300 PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);
301 else
302 data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN2 |
303 PM800_GPADC_GP_BIAS_EN3);
304
305 ret = regmap_update_bits(map, PM800_GP_BIAS_ENA1, mask, data);
306 if (ret < 0)
307 goto out;
308
309 dev_info(chip->dev, "pm800 device_gpadc_init: Done\n");
310 return 0;
311
312out:
313 dev_info(chip->dev, "pm800 device_gpadc_init: Failed!\n");
314 return ret;
315}
316
317static int __devinit device_irq_init_800(struct pm80x_chip *chip)
318{
319 struct regmap *map = chip->regmap;
320 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
321 int data, mask, ret = -EINVAL;
322
323 if (!map || !chip->irq) {
324 dev_err(chip->dev, "incorrect parameters\n");
325 return -EINVAL;
326 }
327
328 /*
329 * irq_mode defines the way of clearing interrupt. it's read-clear by
330 * default.
331 */
332 mask =
333 PM800_WAKEUP2_INV_INT | PM800_WAKEUP2_INT_CLEAR |
334 PM800_WAKEUP2_INT_MASK;
335
336 data = PM800_WAKEUP2_INT_CLEAR;
337 ret = regmap_update_bits(map, PM800_WAKEUP2, mask, data);
338
339 if (ret < 0)
340 goto out;
341
342 ret =
343 regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1,
344 chip->regmap_irq_chip, &chip->irq_data);
345
346out:
347 return ret;
348}
349
350static void device_irq_exit_800(struct pm80x_chip *chip)
351{
352 regmap_del_irq_chip(chip->irq, chip->irq_data);
353}
354
355static struct regmap_irq_chip pm800_irq_chip = {
356 .name = "88pm800",
357 .irqs = pm800_irqs,
358 .num_irqs = ARRAY_SIZE(pm800_irqs),
359
360 .num_regs = 4,
361 .status_base = PM800_INT_STATUS1,
362 .mask_base = PM800_INT_ENA_1,
363 .ack_base = PM800_INT_STATUS1,
364};
365
366static int pm800_pages_init(struct pm80x_chip *chip)
367{
368 struct pm80x_subchip *subchip;
369 struct i2c_client *client = chip->client;
370
371 subchip = chip->subchip;
372 /* PM800 block power: i2c addr 0x31 */
373 if (subchip->power_page_addr) {
374 subchip->power_page =
375 i2c_new_dummy(client->adapter, subchip->power_page_addr);
376 subchip->regmap_power =
377 devm_regmap_init_i2c(subchip->power_page,
378 &pm80x_regmap_config);
379 i2c_set_clientdata(subchip->power_page, chip);
380 } else
381 dev_info(chip->dev,
382 "PM800 block power 0x31: No power_page_addr\n");
383
384 /* PM800 block GPADC: i2c addr 0x32 */
385 if (subchip->gpadc_page_addr) {
386 subchip->gpadc_page = i2c_new_dummy(client->adapter,
387 subchip->gpadc_page_addr);
388 subchip->regmap_gpadc =
389 devm_regmap_init_i2c(subchip->gpadc_page,
390 &pm80x_regmap_config);
391 i2c_set_clientdata(subchip->gpadc_page, chip);
392 } else
393 dev_info(chip->dev,
394 "PM800 block GPADC 0x32: No gpadc_page_addr\n");
395
396 return 0;
397}
398
399static void pm800_pages_exit(struct pm80x_chip *chip)
400{
401 struct pm80x_subchip *subchip;
402
403 regmap_exit(chip->regmap);
404 i2c_unregister_device(chip->client);
405
406 subchip = chip->subchip;
407 if (subchip->power_page) {
408 regmap_exit(subchip->regmap_power);
409 i2c_unregister_device(subchip->power_page);
410 }
411 if (subchip->gpadc_page) {
412 regmap_exit(subchip->regmap_gpadc);
413 i2c_unregister_device(subchip->gpadc_page);
414 }
415}
416
417static int __devinit device_800_init(struct pm80x_chip *chip,
418 struct pm80x_platform_data *pdata)
419{
420 int ret, pmic_id;
421
422 regmap_read(chip->regmap, PM800_CHIP_ID, &ret);
423 if (ret < 0) {
424 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
425 goto out;
426 }
427
428 pmic_id = ret & PM80X_VERSION_MASK;
429
430 if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) {
431 chip->version = ret;
432 dev_info(chip->dev,
433 "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", ret);
434 } else {
435 dev_err(chip->dev,
436 "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", ret);
437 goto out;
438 }
439
440 /*
441 * alarm wake up bit will be clear in device_irq_init(),
442 * read before that
443 */
444 regmap_read(chip->regmap, PM800_RTC_CONTROL, &ret);
445 if (ret < 0) {
446 dev_err(chip->dev, "Failed to read RTC register: %d\n", ret);
447 goto out;
448 }
449 if (ret & PM800_ALARM_WAKEUP) {
450 if (pdata && pdata->rtc)
451 pdata->rtc->rtc_wakeup = 1;
452 }
453
454 ret = device_gpadc_init(chip, pdata);
455 if (ret < 0) {
456 dev_err(chip->dev, "[%s]Failed to init gpadc\n", __func__);
457 goto out;
458 }
459
460 chip->regmap_irq_chip = &pm800_irq_chip;
461
462 ret = device_irq_init_800(chip);
463 if (ret < 0) {
464 dev_err(chip->dev, "[%s]Failed to init pm800 irq\n", __func__);
465 goto out;
466 }
467
468 ret =
469 mfd_add_devices(chip->dev, 0, &onkey_devs[0],
470 ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0);
471 if (ret < 0) {
472 dev_err(chip->dev, "Failed to add onkey subdev\n");
473 goto out_dev;
474 } else
475 dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__);
476
477 if (pdata && pdata->rtc) {
478 rtc_devs[0].platform_data = pdata->rtc;
479 rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
480 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
481 ARRAY_SIZE(rtc_devs), NULL, 0);
482 if (ret < 0) {
483 dev_err(chip->dev, "Failed to add rtc subdev\n");
484 goto out_dev;
485 } else
486 dev_info(chip->dev,
487 "[%s]:Added mfd rtc_devs\n", __func__);
488 }
489
490 return 0;
491out_dev:
492 mfd_remove_devices(chip->dev);
493 device_irq_exit_800(chip);
494out:
495 return ret;
496}
497
498static int __devinit pm800_probe(struct i2c_client *client,
499 const struct i2c_device_id *id)
500{
501 int ret = 0;
502 struct pm80x_chip *chip;
503 struct pm80x_platform_data *pdata = client->dev.platform_data;
504 struct pm80x_subchip *subchip;
505
506 ret = pm80x_init(client, id);
507 if (ret) {
508 dev_err(&client->dev, "pm800_init fail\n");
509 goto out_init;
510 }
511
512 chip = i2c_get_clientdata(client);
513
514 /* init subchip for PM800 */
515 subchip =
516 devm_kzalloc(&client->dev, sizeof(struct pm80x_subchip),
517 GFP_KERNEL);
518 if (!subchip) {
519 ret = -ENOMEM;
520 goto err_subchip_alloc;
521 }
522
523 subchip->power_page_addr = pdata->power_page_addr;
524 subchip->gpadc_page_addr = pdata->gpadc_page_addr;
525 chip->subchip = subchip;
526
527 ret = device_800_init(chip, pdata);
528 if (ret) {
529 dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
530 goto err_800_init;
531 }
532
533 ret = pm800_pages_init(chip);
534 if (ret) {
535 dev_err(&client->dev, "pm800_pages_init failed!\n");
536 goto err_page_init;
537 }
538
539 if (pdata->plat_config)
540 pdata->plat_config(chip, pdata);
541
542err_page_init:
543 mfd_remove_devices(chip->dev);
544 device_irq_exit_800(chip);
545err_800_init:
546 devm_kfree(&client->dev, subchip);
547err_subchip_alloc:
548 pm80x_deinit(client);
549out_init:
550 return ret;
551}
552
553static int __devexit pm800_remove(struct i2c_client *client)
554{
555 struct pm80x_chip *chip = i2c_get_clientdata(client);
556
557 mfd_remove_devices(chip->dev);
558 device_irq_exit_800(chip);
559
560 pm800_pages_exit(chip);
561 devm_kfree(&client->dev, chip->subchip);
562
563 pm80x_deinit(client);
564
565 return 0;
566}
567
568static struct i2c_driver pm800_driver = {
569 .driver = {
570 .name = "88PM80X",
571 .owner = THIS_MODULE,
572 .pm = &pm80x_pm_ops,
573 },
574 .probe = pm800_probe,
575 .remove = __devexit_p(pm800_remove),
576 .id_table = pm80x_id_table,
577};
578
579static int __init pm800_i2c_init(void)
580{
581 return i2c_add_driver(&pm800_driver);
582}
583subsys_initcall(pm800_i2c_init);
584
585static void __exit pm800_i2c_exit(void)
586{
587 i2c_del_driver(&pm800_driver);
588}
589module_exit(pm800_i2c_exit);
590
591MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM800");
592MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");
593MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
new file mode 100644
index 000000000000..d93c3091cb9f
--- /dev/null
+++ b/drivers/mfd/88pm805.c
@@ -0,0 +1,299 @@
1/*
2 * Base driver for Marvell 88PM805
3 *
4 * Copyright (C) 2012 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * Joseph(Yossi) Hanin <yhanin@marvell.com>
7 * Qiao Zhou <zhouqiao@marvell.com>
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/i2c.h>
26#include <linux/irq.h>
27#include <linux/mfd/core.h>
28#include <linux/mfd/88pm80x.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31
32#define PM805_CHIP_ID (0x00)
33
34static const struct i2c_device_id pm80x_id_table[] = {
35 {"88PM805", CHIP_PM805},
36};
37MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
38
39/* Interrupt Number in 88PM805 */
40enum {
41 PM805_IRQ_LDO_OFF, /*0 */
42 PM805_IRQ_SRC_DPLL_LOCK, /*1 */
43 PM805_IRQ_CLIP_FAULT,
44 PM805_IRQ_MIC_CONFLICT,
45 PM805_IRQ_HP2_SHRT,
46 PM805_IRQ_HP1_SHRT, /*5 */
47 PM805_IRQ_FINE_PLL_FAULT,
48 PM805_IRQ_RAW_PLL_FAULT,
49 PM805_IRQ_VOLP_BTN_DET,
50 PM805_IRQ_VOLM_BTN_DET,
51 PM805_IRQ_SHRT_BTN_DET, /*10 */
52 PM805_IRQ_MIC_DET, /*11 */
53
54 PM805_MAX_IRQ,
55};
56
57static struct resource codec_resources[] = {
58 {
59 /* Headset microphone insertion or removal */
60 .name = "micin",
61 .start = PM805_IRQ_MIC_DET,
62 .end = PM805_IRQ_MIC_DET,
63 .flags = IORESOURCE_IRQ,
64 },
65 {
66 /* Audio short HP1 */
67 .name = "audio-short1",
68 .start = PM805_IRQ_HP1_SHRT,
69 .end = PM805_IRQ_HP1_SHRT,
70 .flags = IORESOURCE_IRQ,
71 },
72 {
73 /* Audio short HP2 */
74 .name = "audio-short2",
75 .start = PM805_IRQ_HP2_SHRT,
76 .end = PM805_IRQ_HP2_SHRT,
77 .flags = IORESOURCE_IRQ,
78 },
79};
80
81static struct mfd_cell codec_devs[] = {
82 {
83 .name = "88pm80x-codec",
84 .num_resources = ARRAY_SIZE(codec_resources),
85 .resources = &codec_resources[0],
86 .id = -1,
87 },
88};
89
90static struct regmap_irq pm805_irqs[] = {
91 /* INT0 */
92 [PM805_IRQ_LDO_OFF] = {
93 .mask = PM805_INT1_HP1_SHRT,
94 },
95 [PM805_IRQ_SRC_DPLL_LOCK] = {
96 .mask = PM805_INT1_HP2_SHRT,
97 },
98 [PM805_IRQ_CLIP_FAULT] = {
99 .mask = PM805_INT1_MIC_CONFLICT,
100 },
101 [PM805_IRQ_MIC_CONFLICT] = {
102 .mask = PM805_INT1_CLIP_FAULT,
103 },
104 [PM805_IRQ_HP2_SHRT] = {
105 .mask = PM805_INT1_LDO_OFF,
106 },
107 [PM805_IRQ_HP1_SHRT] = {
108 .mask = PM805_INT1_SRC_DPLL_LOCK,
109 },
110 /* INT1 */
111 [PM805_IRQ_FINE_PLL_FAULT] = {
112 .reg_offset = 1,
113 .mask = PM805_INT2_MIC_DET,
114 },
115 [PM805_IRQ_RAW_PLL_FAULT] = {
116 .reg_offset = 1,
117 .mask = PM805_INT2_SHRT_BTN_DET,
118 },
119 [PM805_IRQ_VOLP_BTN_DET] = {
120 .reg_offset = 1,
121 .mask = PM805_INT2_VOLM_BTN_DET,
122 },
123 [PM805_IRQ_VOLM_BTN_DET] = {
124 .reg_offset = 1,
125 .mask = PM805_INT2_VOLP_BTN_DET,
126 },
127 [PM805_IRQ_SHRT_BTN_DET] = {
128 .reg_offset = 1,
129 .mask = PM805_INT2_RAW_PLL_FAULT,
130 },
131 [PM805_IRQ_MIC_DET] = {
132 .reg_offset = 1,
133 .mask = PM805_INT2_FINE_PLL_FAULT,
134 },
135};
136
137static int __devinit device_irq_init_805(struct pm80x_chip *chip)
138{
139 struct regmap *map = chip->regmap;
140 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
141 int data, mask, ret = -EINVAL;
142
143 if (!map || !chip->irq) {
144 dev_err(chip->dev, "incorrect parameters\n");
145 return -EINVAL;
146 }
147
148 /*
149 * irq_mode defines the way of clearing interrupt. it's read-clear by
150 * default.
151 */
152 mask =
153 PM805_STATUS0_INT_CLEAR | PM805_STATUS0_INV_INT |
154 PM800_STATUS0_INT_MASK;
155
156 data = PM805_STATUS0_INT_CLEAR;
157 ret = regmap_update_bits(map, PM805_INT_STATUS0, mask, data);
158 /*
159 * PM805_INT_STATUS is under 32K clock domain, so need to
160 * add proper delay before the next I2C register access.
161 */
162 msleep(1);
163
164 if (ret < 0)
165 goto out;
166
167 ret =
168 regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1,
169 chip->regmap_irq_chip, &chip->irq_data);
170
171out:
172 return ret;
173}
174
175static void device_irq_exit_805(struct pm80x_chip *chip)
176{
177 regmap_del_irq_chip(chip->irq, chip->irq_data);
178}
179
180static struct regmap_irq_chip pm805_irq_chip = {
181 .name = "88pm805",
182 .irqs = pm805_irqs,
183 .num_irqs = ARRAY_SIZE(pm805_irqs),
184
185 .num_regs = 2,
186 .status_base = PM805_INT_STATUS1,
187 .mask_base = PM805_INT_MASK1,
188 .ack_base = PM805_INT_STATUS1,
189};
190
191static int __devinit device_805_init(struct pm80x_chip *chip)
192{
193 int ret = 0;
194 struct regmap *map = chip->regmap;
195
196 if (!map) {
197 dev_err(chip->dev, "regmap is invalid\n");
198 return -EINVAL;
199 }
200
201 regmap_read(map, PM805_CHIP_ID, &ret);
202 if (ret < 0) {
203 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
204 goto out_irq_init;
205 }
206 chip->version = ret;
207
208 chip->regmap_irq_chip = &pm805_irq_chip;
209
210 ret = device_irq_init_805(chip);
211 if (ret < 0) {
212 dev_err(chip->dev, "Failed to init pm805 irq!\n");
213 goto out_irq_init;
214 }
215
216 ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
217 ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
218 if (ret < 0) {
219 dev_err(chip->dev, "Failed to add codec subdev\n");
220 goto out_codec;
221 } else
222 dev_info(chip->dev, "[%s]:Added mfd codec_devs\n", __func__);
223
224 return 0;
225
226out_codec:
227 device_irq_exit_805(chip);
228out_irq_init:
229 return ret;
230}
231
232static int __devinit pm805_probe(struct i2c_client *client,
233 const struct i2c_device_id *id)
234{
235 int ret = 0;
236 struct pm80x_chip *chip;
237 struct pm80x_platform_data *pdata = client->dev.platform_data;
238
239 ret = pm80x_init(client, id);
240 if (ret) {
241 dev_err(&client->dev, "pm805_init fail!\n");
242 goto out_init;
243 }
244
245 chip = i2c_get_clientdata(client);
246
247 ret = device_805_init(chip);
248 if (ret) {
249 dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
250 goto err_805_init;
251 }
252
253 if (pdata->plat_config)
254 pdata->plat_config(chip, pdata);
255
256err_805_init:
257 pm80x_deinit(client);
258out_init:
259 return ret;
260}
261
262static int __devexit pm805_remove(struct i2c_client *client)
263{
264 struct pm80x_chip *chip = i2c_get_clientdata(client);
265
266 mfd_remove_devices(chip->dev);
267 device_irq_exit_805(chip);
268
269 pm80x_deinit(client);
270
271 return 0;
272}
273
274static struct i2c_driver pm805_driver = {
275 .driver = {
276 .name = "88PM80X",
277 .owner = THIS_MODULE,
278 .pm = &pm80x_pm_ops,
279 },
280 .probe = pm805_probe,
281 .remove = __devexit_p(pm805_remove),
282 .id_table = pm80x_id_table,
283};
284
285static int __init pm805_i2c_init(void)
286{
287 return i2c_add_driver(&pm805_driver);
288}
289subsys_initcall(pm805_i2c_init);
290
291static void __exit pm805_i2c_exit(void)
292{
293 i2c_del_driver(&pm805_driver);
294}
295module_exit(pm805_i2c_exit);
296
297MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM805");
298MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");
299MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
new file mode 100644
index 000000000000..90aa18a37f79
--- /dev/null
+++ b/drivers/mfd/88pm80x.c
@@ -0,0 +1,116 @@
1/*
2 * I2C driver for Marvell 88PM80x
3 *
4 * Copyright (C) 2012 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * Joseph(Yossi) Hanin <yhanin@marvell.com>
7 * Qiao Zhou <zhouqiao@marvell.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/i2c.h>
16#include <linux/mfd/88pm80x.h>
17#include <linux/slab.h>
18#include <linux/uaccess.h>
19#include <linux/err.h>
20
21
22const struct regmap_config pm80x_regmap_config = {
23 .reg_bits = 8,
24 .val_bits = 8,
25};
26
27int __devinit pm80x_init(struct i2c_client *client,
28 const struct i2c_device_id *id)
29{
30 struct pm80x_chip *chip;
31 struct regmap *map;
32 int ret = 0;
33
34 chip =
35 devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
36 if (!chip)
37 return -ENOMEM;
38
39 map = devm_regmap_init_i2c(client, &pm80x_regmap_config);
40 if (IS_ERR(map)) {
41 ret = PTR_ERR(map);
42 dev_err(&client->dev, "Failed to allocate register map: %d\n",
43 ret);
44 goto err_regmap_init;
45 }
46
47 chip->id = id->driver_data;
48 if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) {
49 ret = -EINVAL;
50 goto err_chip_id;
51 }
52
53 chip->client = client;
54 chip->regmap = map;
55
56 chip->irq = client->irq;
57
58 chip->dev = &client->dev;
59 dev_set_drvdata(chip->dev, chip);
60 i2c_set_clientdata(chip->client, chip);
61
62 device_init_wakeup(&client->dev, 1);
63
64 return 0;
65
66err_chip_id:
67 regmap_exit(map);
68err_regmap_init:
69 devm_kfree(&client->dev, chip);
70 return ret;
71}
72EXPORT_SYMBOL_GPL(pm80x_init);
73
74int __devexit pm80x_deinit(struct i2c_client *client)
75{
76 struct pm80x_chip *chip = i2c_get_clientdata(client);
77
78 regmap_exit(chip->regmap);
79 devm_kfree(&client->dev, chip);
80
81 return 0;
82}
83EXPORT_SYMBOL_GPL(pm80x_deinit);
84
85#ifdef CONFIG_PM_SLEEP
86static int pm80x_suspend(struct device *dev)
87{
88 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
89 struct pm80x_chip *chip = i2c_get_clientdata(client);
90
91 if (chip && chip->wu_flag)
92 if (device_may_wakeup(chip->dev))
93 enable_irq_wake(chip->irq);
94
95 return 0;
96}
97
98static int pm80x_resume(struct device *dev)
99{
100 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
101 struct pm80x_chip *chip = i2c_get_clientdata(client);
102
103 if (chip && chip->wu_flag)
104 if (device_may_wakeup(chip->dev))
105 disable_irq_wake(chip->irq);
106
107 return 0;
108}
109#endif
110
111SIMPLE_DEV_PM_OPS(pm80x_pm_ops, pm80x_suspend, pm80x_resume);
112EXPORT_SYMBOL_GPL(pm80x_pm_ops);
113
114MODULE_DESCRIPTION("I2C Driver for Marvell 88PM80x");
115MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");
116MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 5c043693f52c..9c3ab2ab7dc7 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -21,6 +21,30 @@ config MFD_88PM860X
21 select individual components like voltage regulators, RTC and 21 select individual components like voltage regulators, RTC and
22 battery-charger under the corresponding menus. 22 battery-charger under the corresponding menus.
23 23
24config MFD_88PM800
25 tristate "Support Marvell 88PM800"
26 depends on I2C=y && GENERIC_HARDIRQS
27 select REGMAP_I2C
28 select REGMAP_IRQ
29 select MFD_CORE
30 help
31 This supports for Marvell 88PM800 Power Management IC.
32 This includes the I2C driver and the core APIs _only_, you have to
33 select individual components like voltage regulators, RTC and
34 battery-charger under the corresponding menus.
35
36config MFD_88PM805
37 tristate "Support Marvell 88PM805"
38 depends on I2C=y && GENERIC_HARDIRQS
39 select REGMAP_I2C
40 select REGMAP_IRQ
41 select MFD_CORE
42 help
43 This supports for Marvell 88PM805 Power Management IC. This includes
44 the I2C driver and the core APIs _only_, you have to select individual
45 components like codec device, headset/Mic device under the
46 corresponding menus.
47
24config MFD_SM501 48config MFD_SM501
25 tristate "Support for Silicon Motion SM501" 49 tristate "Support for Silicon Motion SM501"
26 ---help--- 50 ---help---
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f28885bb103c..09674a99eb60 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -4,6 +4,8 @@
4 4
588pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o 588pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o
6obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o 6obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
7obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o
8obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
7obj-$(CONFIG_MFD_SM501) += sm501.o 9obj-$(CONFIG_MFD_SM501) += sm501.o
8obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 10obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
9 11
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
new file mode 100644
index 000000000000..6c126e9714a3
--- /dev/null
+++ b/include/linux/mfd/88pm80x.h
@@ -0,0 +1,368 @@
1/*
2 * Marvell 88PM80x Interface
3 *
4 * Copyright (C) 2012 Marvell International Ltd.
5 * Qiao Zhou <zhouqiao@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __LINUX_MFD_88PM80X_H
13#define __LINUX_MFD_88PM80X_H
14
15#include <linux/platform_device.h>
16#include <linux/interrupt.h>
17#include <linux/regmap.h>
18#include <linux/atomic.h>
19
20#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */
21enum {
22 CHIP_INVALID = 0,
23 CHIP_PM800,
24 CHIP_PM805,
25 CHIP_MAX,
26};
27
28enum {
29 PM800_ID_BUCK1 = 0,
30 PM800_ID_BUCK2,
31 PM800_ID_BUCK3,
32 PM800_ID_BUCK4,
33 PM800_ID_BUCK5,
34
35 PM800_ID_LDO1,
36 PM800_ID_LDO2,
37 PM800_ID_LDO3,
38 PM800_ID_LDO4,
39 PM800_ID_LDO5,
40 PM800_ID_LDO6,
41 PM800_ID_LDO7,
42 PM800_ID_LDO8,
43 PM800_ID_LDO9,
44 PM800_ID_LDO10,
45 PM800_ID_LDO11,
46 PM800_ID_LDO12,
47 PM800_ID_LDO13,
48 PM800_ID_LDO14,
49 PM800_ID_LDO15,
50 PM800_ID_LDO16,
51 PM800_ID_LDO17,
52 PM800_ID_LDO18,
53 PM800_ID_LDO19,
54
55 PM800_ID_RG_MAX,
56};
57#define PM800_MAX_REGULATOR PM800_ID_RG_MAX /* 5 Bucks, 19 LDOs */
58#define PM800_NUM_BUCK (5) /*5 Bucks */
59#define PM800_NUM_LDO (19) /*19 Bucks */
60
61/* page 0 basic: slave adder 0x60 */
62
63#define PM800_STATUS_1 (0x01)
64#define PM800_ONKEY_STS1 (1 << 0)
65#define PM800_EXTON_STS1 (1 << 1)
66#define PM800_CHG_STS1 (1 << 2)
67#define PM800_BAT_STS1 (1 << 3)
68#define PM800_VBUS_STS1 (1 << 4)
69#define PM800_LDO_PGOOD_STS1 (1 << 5)
70#define PM800_BUCK_PGOOD_STS1 (1 << 6)
71
72#define PM800_STATUS_2 (0x02)
73#define PM800_RTC_ALARM_STS2 (1 << 0)
74
75/* Wakeup Registers */
76#define PM800_WAKEUP1 (0x0D)
77
78#define PM800_WAKEUP2 (0x0E)
79#define PM800_WAKEUP2_INV_INT (1 << 0)
80#define PM800_WAKEUP2_INT_CLEAR (1 << 1)
81#define PM800_WAKEUP2_INT_MASK (1 << 2)
82
83#define PM800_POWER_UP_LOG (0x10)
84
85/* Referance and low power registers */
86#define PM800_LOW_POWER1 (0x20)
87#define PM800_LOW_POWER2 (0x21)
88#define PM800_LOW_POWER_CONFIG3 (0x22)
89#define PM800_LOW_POWER_CONFIG4 (0x23)
90
91/* GPIO register */
92#define PM800_GPIO_0_1_CNTRL (0x30)
93#define PM800_GPIO0_VAL (1 << 0)
94#define PM800_GPIO0_GPIO_MODE(x) (x << 1)
95#define PM800_GPIO1_VAL (1 << 4)
96#define PM800_GPIO1_GPIO_MODE(x) (x << 5)
97
98#define PM800_GPIO_2_3_CNTRL (0x31)
99#define PM800_GPIO2_VAL (1 << 0)
100#define PM800_GPIO2_GPIO_MODE(x) (x << 1)
101#define PM800_GPIO3_VAL (1 << 4)
102#define PM800_GPIO3_GPIO_MODE(x) (x << 5)
103#define PM800_GPIO3_MODE_MASK 0x1F
104#define PM800_GPIO3_HEADSET_MODE PM800_GPIO3_GPIO_MODE(6)
105
106#define PM800_GPIO_4_CNTRL (0x32)
107#define PM800_GPIO4_VAL (1 << 0)
108#define PM800_GPIO4_GPIO_MODE(x) (x << 1)
109
110#define PM800_HEADSET_CNTRL (0x38)
111#define PM800_HEADSET_DET_EN (1 << 7)
112#define PM800_HSDET_SLP (1 << 1)
113/* PWM register */
114#define PM800_PWM1 (0x40)
115#define PM800_PWM2 (0x41)
116#define PM800_PWM3 (0x42)
117#define PM800_PWM4 (0x43)
118
119/* RTC Registers */
120#define PM800_RTC_CONTROL (0xD0)
121#define PM800_RTC_MISC1 (0xE1)
122#define PM800_RTC_MISC2 (0xE2)
123#define PM800_RTC_MISC3 (0xE3)
124#define PM800_RTC_MISC4 (0xE4)
125#define PM800_RTC_MISC5 (0xE7)
126/* bit definitions of RTC Register 1 (0xD0) */
127#define PM800_ALARM1_EN (1 << 0)
128#define PM800_ALARM_WAKEUP (1 << 4)
129#define PM800_ALARM (1 << 5)
130#define PM800_RTC1_USE_XO (1 << 7)
131
132/* Regulator Control Registers: BUCK1,BUCK5,LDO1 have DVC */
133
134/* buck registers */
135#define PM800_SLEEP_BUCK1 (0x30)
136
137/* BUCK Sleep Mode Register 1: BUCK[1..4] */
138#define PM800_BUCK_SLP1 (0x5A)
139#define PM800_BUCK1_SLP1_SHIFT 0
140#define PM800_BUCK1_SLP1_MASK (0x3 << PM800_BUCK1_SLP1_SHIFT)
141
142/* page 2 GPADC: slave adder 0x02 */
143#define PM800_GPADC_MEAS_EN1 (0x01)
144#define PM800_MEAS_EN1_VBAT (1 << 2)
145#define PM800_GPADC_MEAS_EN2 (0x02)
146#define PM800_MEAS_EN2_RFTMP (1 << 0)
147#define PM800_MEAS_GP0_EN (1 << 2)
148#define PM800_MEAS_GP1_EN (1 << 3)
149#define PM800_MEAS_GP2_EN (1 << 4)
150#define PM800_MEAS_GP3_EN (1 << 5)
151#define PM800_MEAS_GP4_EN (1 << 6)
152
153#define PM800_GPADC_MISC_CONFIG1 (0x05)
154#define PM800_GPADC_MISC_CONFIG2 (0x06)
155#define PM800_GPADC_MISC_GPFSM_EN (1 << 0)
156#define PM800_GPADC_SLOW_MODE(x) (x << 3)
157
158#define PM800_GPADC_MISC_CONFIG3 (0x09)
159#define PM800_GPADC_MISC_CONFIG4 (0x0A)
160
161#define PM800_GPADC_PREBIAS1 (0x0F)
162#define PM800_GPADC0_GP_PREBIAS_TIME(x) (x << 0)
163#define PM800_GPADC_PREBIAS2 (0x10)
164
165#define PM800_GP_BIAS_ENA1 (0x14)
166#define PM800_GPADC_GP_BIAS_EN0 (1 << 0)
167#define PM800_GPADC_GP_BIAS_EN1 (1 << 1)
168#define PM800_GPADC_GP_BIAS_EN2 (1 << 2)
169#define PM800_GPADC_GP_BIAS_EN3 (1 << 3)
170
171#define PM800_GP_BIAS_OUT1 (0x15)
172#define PM800_BIAS_OUT_GP0 (1 << 0)
173#define PM800_BIAS_OUT_GP1 (1 << 1)
174#define PM800_BIAS_OUT_GP2 (1 << 2)
175#define PM800_BIAS_OUT_GP3 (1 << 3)
176
177#define PM800_GPADC0_LOW_TH 0x20
178#define PM800_GPADC1_LOW_TH 0x21
179#define PM800_GPADC2_LOW_TH 0x22
180#define PM800_GPADC3_LOW_TH 0x23
181#define PM800_GPADC4_LOW_TH 0x24
182
183#define PM800_GPADC0_UPP_TH 0x30
184#define PM800_GPADC1_UPP_TH 0x31
185#define PM800_GPADC2_UPP_TH 0x32
186#define PM800_GPADC3_UPP_TH 0x33
187#define PM800_GPADC4_UPP_TH 0x34
188
189#define PM800_VBBAT_MEAS1 0x40
190#define PM800_VBBAT_MEAS2 0x41
191#define PM800_VBAT_MEAS1 0x42
192#define PM800_VBAT_MEAS2 0x43
193#define PM800_VSYS_MEAS1 0x44
194#define PM800_VSYS_MEAS2 0x45
195#define PM800_VCHG_MEAS1 0x46
196#define PM800_VCHG_MEAS2 0x47
197#define PM800_TINT_MEAS1 0x50
198#define PM800_TINT_MEAS2 0x51
199#define PM800_PMOD_MEAS1 0x52
200#define PM800_PMOD_MEAS2 0x53
201
202#define PM800_GPADC0_MEAS1 0x54
203#define PM800_GPADC0_MEAS2 0x55
204#define PM800_GPADC1_MEAS1 0x56
205#define PM800_GPADC1_MEAS2 0x57
206#define PM800_GPADC2_MEAS1 0x58
207#define PM800_GPADC2_MEAS2 0x59
208#define PM800_GPADC3_MEAS1 0x5A
209#define PM800_GPADC3_MEAS2 0x5B
210#define PM800_GPADC4_MEAS1 0x5C
211#define PM800_GPADC4_MEAS2 0x5D
212
213#define PM800_GPADC4_AVG1 0xA8
214#define PM800_GPADC4_AVG2 0xA9
215
216/* 88PM805 Registers */
217#define PM805_MAIN_POWERUP (0x01)
218#define PM805_INT_STATUS0 (0x02) /* for ena/dis all interrupts */
219
220#define PM805_STATUS0_INT_CLEAR (1 << 0)
221#define PM805_STATUS0_INV_INT (1 << 1)
222#define PM800_STATUS0_INT_MASK (1 << 2)
223
224#define PM805_INT_STATUS1 (0x03)
225
226#define PM805_INT1_HP1_SHRT (1 << 0)
227#define PM805_INT1_HP2_SHRT (1 << 1)
228#define PM805_INT1_MIC_CONFLICT (1 << 2)
229#define PM805_INT1_CLIP_FAULT (1 << 3)
230#define PM805_INT1_LDO_OFF (1 << 4)
231#define PM805_INT1_SRC_DPLL_LOCK (1 << 5)
232
233#define PM805_INT_STATUS2 (0x04)
234
235#define PM805_INT2_MIC_DET (1 << 0)
236#define PM805_INT2_SHRT_BTN_DET (1 << 1)
237#define PM805_INT2_VOLM_BTN_DET (1 << 2)
238#define PM805_INT2_VOLP_BTN_DET (1 << 3)
239#define PM805_INT2_RAW_PLL_FAULT (1 << 4)
240#define PM805_INT2_FINE_PLL_FAULT (1 << 5)
241
242#define PM805_INT_MASK1 (0x05)
243#define PM805_INT_MASK2 (0x06)
244#define PM805_SHRT_BTN_DET (1 << 1)
245
246/* number of status and int reg in a row */
247#define PM805_INT_REG_NUM (2)
248
249#define PM805_MIC_DET1 (0x07)
250#define PM805_MIC_DET_EN_MIC_DET (1 << 0)
251#define PM805_MIC_DET2 (0x08)
252#define PM805_MIC_DET_STATUS1 (0x09)
253
254#define PM805_MIC_DET_STATUS3 (0x0A)
255#define PM805_AUTO_SEQ_STATUS1 (0x0B)
256#define PM805_AUTO_SEQ_STATUS2 (0x0C)
257
258#define PM805_ADC_SETTING1 (0x10)
259#define PM805_ADC_SETTING2 (0x11)
260#define PM805_ADC_SETTING3 (0x11)
261#define PM805_ADC_GAIN1 (0x12)
262#define PM805_ADC_GAIN2 (0x13)
263#define PM805_DMIC_SETTING (0x15)
264#define PM805_DWS_SETTING (0x16)
265#define PM805_MIC_CONFLICT_STS (0x17)
266
267#define PM805_PDM_SETTING1 (0x20)
268#define PM805_PDM_SETTING2 (0x21)
269#define PM805_PDM_SETTING3 (0x22)
270#define PM805_PDM_CONTROL1 (0x23)
271#define PM805_PDM_CONTROL2 (0x24)
272#define PM805_PDM_CONTROL3 (0x25)
273
274#define PM805_HEADPHONE_SETTING (0x26)
275#define PM805_HEADPHONE_GAIN_A2A (0x27)
276#define PM805_HEADPHONE_SHORT_STATE (0x28)
277#define PM805_EARPHONE_SETTING (0x29)
278#define PM805_AUTO_SEQ_SETTING (0x2A)
279
280struct pm80x_rtc_pdata {
281 int vrtc;
282 int rtc_wakeup;
283};
284
285struct pm80x_subchip {
286 struct i2c_client *power_page; /* chip client for power page */
287 struct i2c_client *gpadc_page; /* chip client for gpadc page */
288 struct regmap *regmap_power;
289 struct regmap *regmap_gpadc;
290 unsigned short power_page_addr; /* power page I2C address */
291 unsigned short gpadc_page_addr; /* gpadc page I2C address */
292};
293
294struct pm80x_chip {
295 struct pm80x_subchip *subchip;
296 struct device *dev;
297 struct i2c_client *client;
298 struct regmap *regmap;
299 struct regmap_irq_chip *regmap_irq_chip;
300 struct regmap_irq_chip_data *irq_data;
301 unsigned char version;
302 int id;
303 int irq;
304 int irq_mode;
305 unsigned long wu_flag;
306 spinlock_t lock;
307};
308
309struct pm80x_platform_data {
310 struct pm80x_rtc_pdata *rtc;
311 unsigned short power_page_addr; /* power page I2C address */
312 unsigned short gpadc_page_addr; /* gpadc page I2C address */
313 int irq_mode; /* Clear interrupt by read/write(0/1) */
314 int batt_det; /* enable/disable */
315 int (*plat_config)(struct pm80x_chip *chip,
316 struct pm80x_platform_data *pdata);
317};
318
319extern const struct dev_pm_ops pm80x_pm_ops;
320extern const struct regmap_config pm80x_regmap_config;
321
322static inline int pm80x_request_irq(struct pm80x_chip *pm80x, int irq,
323 irq_handler_t handler, unsigned long flags,
324 const char *name, void *data)
325{
326 if (!pm80x->irq_data)
327 return -EINVAL;
328 return request_threaded_irq(regmap_irq_get_virq(pm80x->irq_data, irq),
329 NULL, handler, flags, name, data);
330}
331
332static inline void pm80x_free_irq(struct pm80x_chip *pm80x, int irq, void *data)
333{
334 if (!pm80x->irq_data)
335 return;
336 free_irq(regmap_irq_get_virq(pm80x->irq_data, irq), data);
337}
338
339#ifdef CONFIG_PM
340static inline int pm80x_dev_suspend(struct device *dev)
341{
342 struct platform_device *pdev = to_platform_device(dev);
343 struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
344 int irq = platform_get_irq(pdev, 0);
345
346 if (device_may_wakeup(dev))
347 set_bit((1 << irq), &chip->wu_flag);
348
349 return 0;
350}
351
352static inline int pm80x_dev_resume(struct device *dev)
353{
354 struct platform_device *pdev = to_platform_device(dev);
355 struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
356 int irq = platform_get_irq(pdev, 0);
357
358 if (device_may_wakeup(dev))
359 clear_bit((1 << irq), &chip->wu_flag);
360
361 return 0;
362}
363#endif
364
365extern int pm80x_init(struct i2c_client *client,
366 const struct i2c_device_id *id) __devinit;
367extern int pm80x_deinit(struct i2c_client *client) __devexit;
368#endif /* __LINUX_MFD_88PM80X_H */