blob: ce6a016a66470dbe4c37e499f7c0f72a6ccdce2b [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
17#include <linux/slab.h>
18#include <linux/spinlock.h>
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +053019#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020#include <linux/platform_device.h>
21#include <linux/mfd/pm8xxx/core.h>
22#include <linux/mfd/pm8xxx/misc.h>
23
24/* PON CTRL 1 register */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +053025#define REG_PM8XXX_PON_CTRL_1 0x01C
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026
27#define PON_CTRL_1_PULL_UP_MASK 0xE0
28#define PON_CTRL_1_USB_PWR_EN 0x10
29
30#define PON_CTRL_1_WD_EN_MASK 0x08
31#define PON_CTRL_1_WD_EN_RESET 0x08
32#define PON_CTRL_1_WD_EN_PWR_OFF 0x00
33
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +053034/* Regulator master enable addresses */
35#define REG_PM8058_VREG_EN_MSM 0x018
36#define REG_PM8058_VREG_EN_GRP_5_4 0x1C8
37
38/* Regulator control registers for shutdown/reset */
39#define REG_PM8058_S0_CTRL 0x004
40#define REG_PM8058_S1_CTRL 0x005
41#define REG_PM8058_S3_CTRL 0x111
42#define REG_PM8058_L21_CTRL 0x120
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#define REG_PM8058_L22_CTRL 0x121
44
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +053045#define PM8058_REGULATOR_ENABLE_MASK 0x80
46#define PM8058_REGULATOR_ENABLE 0x80
47#define PM8058_REGULATOR_DISABLE 0x00
48#define PM8058_REGULATOR_PULL_DOWN_MASK 0x40
49#define PM8058_REGULATOR_PULL_DOWN_EN 0x40
50
51/* Buck CTRL register */
52#define PM8058_SMPS_LEGACY_VREF_SEL 0x20
53#define PM8058_SMPS_LEGACY_VPROG_MASK 0x1F
54#define PM8058_SMPS_ADVANCED_BAND_MASK 0xC0
55#define PM8058_SMPS_ADVANCED_BAND_SHIFT 6
56#define PM8058_SMPS_ADVANCED_VPROG_MASK 0x3F
57
58/* Buck TEST2 registers for shutdown/reset */
59#define REG_PM8058_S0_TEST2 0x084
60#define REG_PM8058_S1_TEST2 0x085
61#define REG_PM8058_S3_TEST2 0x11A
62
63#define PM8058_REGULATOR_BANK_WRITE 0x80
64#define PM8058_REGULATOR_BANK_MASK 0x70
65#define PM8058_REGULATOR_BANK_SHIFT 4
66#define PM8058_REGULATOR_BANK_SEL(n) ((n) << PM8058_REGULATOR_BANK_SHIFT)
67
68/* Buck TEST2 register bank 1 */
69#define PM8058_SMPS_LEGACY_VLOW_SEL 0x01
70
71/* Buck TEST2 register bank 7 */
72#define PM8058_SMPS_ADVANCED_MODE_MASK 0x02
73#define PM8058_SMPS_ADVANCED_MODE 0x02
74#define PM8058_SMPS_LEGACY_MODE 0x00
75
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076/* SLEEP CTRL register */
77#define REG_PM8058_SLEEP_CTRL 0x02B
78#define REG_PM8921_SLEEP_CTRL 0x10A
Jay Chokshi86580f22011-10-17 12:27:52 -070079#define REG_PM8018_SLEEP_CTRL 0x10A
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080
81#define SLEEP_CTRL_SMPL_EN_MASK 0x04
82#define SLEEP_CTRL_SMPL_EN_RESET 0x04
83#define SLEEP_CTRL_SMPL_EN_PWR_OFF 0x00
84
Anirudh Ghayalbfbaf822011-11-01 14:28:34 +053085#define SLEEP_CTRL_SMPL_SEL_MASK 0x03
86#define SLEEP_CTRL_SMPL_SEL_MIN 0
87#define SLEEP_CTRL_SMPL_SEL_MAX 3
88
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070089/* FTS regulator PMR registers */
90#define REG_PM8901_REGULATOR_S1_PMR 0xA7
91#define REG_PM8901_REGULATOR_S2_PMR 0xA8
92#define REG_PM8901_REGULATOR_S3_PMR 0xA9
93#define REG_PM8901_REGULATOR_S4_PMR 0xAA
94
95#define PM8901_REGULATOR_PMR_STATE_MASK 0x60
96#define PM8901_REGULATOR_PMR_STATE_OFF 0x20
97
Anirudh Ghayal7b382292011-11-01 14:08:34 +053098/* COINCELL CHG registers */
99#define REG_PM8058_COIN_CHG 0x02F
100#define REG_PM8921_COIN_CHG 0x09C
101#define REG_PM8018_COIN_CHG 0x09C
102
103#define COINCELL_RESISTOR_SHIFT 0x2
104
Anirudh Ghayal5213eb82011-10-24 14:44:58 +0530105/* GPIO UART MUX CTRL registers */
106#define REG_PM8XXX_GPIO_MUX_CTRL 0x1CC
107
108#define UART_PATH_SEL_MASK 0x60
109#define UART_PATH_SEL_SHIFT 0x5
110
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700111struct pm8xxx_misc_chip {
112 struct list_head link;
113 struct pm8xxx_misc_platform_data pdata;
114 struct device *dev;
115 enum pm8xxx_version version;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530116 u64 osc_halt_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117};
118
119static LIST_HEAD(pm8xxx_misc_chips);
120static DEFINE_SPINLOCK(pm8xxx_misc_chips_lock);
121
122static int pm8xxx_misc_masked_write(struct pm8xxx_misc_chip *chip, u16 addr,
123 u8 mask, u8 val)
124{
125 int rc;
126 u8 reg;
127
128 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
129 if (rc) {
130 pr_err("pm8xxx_readb(0x%03X) failed, rc=%d\n", addr, rc);
131 return rc;
132 }
133 reg &= ~mask;
134 reg |= val & mask;
135 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
136 if (rc)
137 pr_err("pm8xxx_writeb(0x%03X)=0x%02X failed, rc=%d\n", addr,
138 reg, rc);
139 return rc;
140}
141
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +0530142/*
143 * Set an SMPS regulator to be disabled in its CTRL register, but enabled
144 * in the master enable register. Also set it's pull down enable bit.
145 * Take care to make sure that the output voltage doesn't change if switching
146 * from advanced mode to legacy mode.
147 */
148static int
149__pm8058_disable_smps_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
150 u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr,
151 u8 master_enable_bit)
152{
153 int rc = 0;
154 u8 vref_sel, vlow_sel, band, vprog, bank, reg;
155
156 bank = PM8058_REGULATOR_BANK_SEL(7);
157 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
158 if (rc) {
159 pr_err("%s: pm8xxx_writeb(0x%03X) failed: rc=%d\n", __func__,
160 test2_addr, rc);
161 goto done;
162 }
163
164 rc = pm8xxx_readb(chip->dev->parent, test2_addr, &reg);
165 if (rc) {
166 pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
167 __func__, test2_addr, rc);
168 goto done;
169 }
170
171 /* Check if in advanced mode. */
172 if ((reg & PM8058_SMPS_ADVANCED_MODE_MASK) ==
173 PM8058_SMPS_ADVANCED_MODE) {
174 /* Determine current output voltage. */
175 rc = pm8xxx_readb(chip->dev->parent, ctrl_addr, &reg);
176 if (rc) {
177 pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
178 __func__, ctrl_addr, rc);
179 goto done;
180 }
181
182 band = (reg & PM8058_SMPS_ADVANCED_BAND_MASK)
183 >> PM8058_SMPS_ADVANCED_BAND_SHIFT;
184 switch (band) {
185 case 3:
186 vref_sel = 0;
187 vlow_sel = 0;
188 break;
189 case 2:
190 vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
191 vlow_sel = 0;
192 break;
193 case 1:
194 vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
195 vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL;
196 break;
197 default:
198 pr_err("%s: regulator already disabled\n", __func__);
199 return -EPERM;
200 }
201 vprog = (reg & PM8058_SMPS_ADVANCED_VPROG_MASK);
202 /* Round up if fine step is in use. */
203 vprog = (vprog + 1) >> 1;
204 if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK)
205 vprog = PM8058_SMPS_LEGACY_VPROG_MASK;
206
207 /* Set VLOW_SEL bit. */
208 bank = PM8058_REGULATOR_BANK_SEL(1);
209 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
210 if (rc) {
211 pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
212 __func__, test2_addr, rc);
213 goto done;
214 }
215
216 rc = pm8xxx_misc_masked_write(chip, test2_addr,
217 PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK
218 | PM8058_SMPS_LEGACY_VLOW_SEL,
219 PM8058_REGULATOR_BANK_WRITE |
220 PM8058_REGULATOR_BANK_SEL(1) | vlow_sel);
221 if (rc)
222 goto done;
223
224 /* Switch to legacy mode */
225 bank = PM8058_REGULATOR_BANK_SEL(7);
226 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
227 if (rc) {
228 pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
229 __func__, test2_addr, rc);
230 goto done;
231 }
232 rc = pm8xxx_misc_masked_write(chip, test2_addr,
233 PM8058_REGULATOR_BANK_WRITE |
234 PM8058_REGULATOR_BANK_MASK |
235 PM8058_SMPS_ADVANCED_MODE_MASK,
236 PM8058_REGULATOR_BANK_WRITE |
237 PM8058_REGULATOR_BANK_SEL(7) |
238 PM8058_SMPS_LEGACY_MODE);
239 if (rc)
240 goto done;
241
242 /* Enable locally, enable pull down, keep voltage the same. */
243 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
244 PM8058_REGULATOR_ENABLE_MASK |
245 PM8058_REGULATOR_PULL_DOWN_MASK |
246 PM8058_SMPS_LEGACY_VREF_SEL |
247 PM8058_SMPS_LEGACY_VPROG_MASK,
248 PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN
249 | vref_sel | vprog);
250 if (rc)
251 goto done;
252 }
253
254 /* Enable in master control register. */
255 rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
256 master_enable_bit, master_enable_bit);
257 if (rc)
258 goto done;
259
260 /* Disable locally and enable pull down. */
261 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
262 PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
263 PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
264
265done:
266 return rc;
267}
268
269static int
270__pm8058_disable_ldo_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
271 u16 ctrl_addr, u16 master_enable_addr, u8 master_enable_bit)
272{
273 int rc;
274
275 /* Enable LDO in master control register. */
276 rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
277 master_enable_bit, master_enable_bit);
278 if (rc)
279 goto done;
280
281 /* Disable LDO in CTRL register and set pull down */
282 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
283 PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
284 PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
285
286done:
287 return rc;
288}
289
Jay Chokshi86580f22011-10-17 12:27:52 -0700290static int __pm8018_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
291{
292 int rc;
293
294 /* Enable SMPL if resetting is desired. */
295 rc = pm8xxx_misc_masked_write(chip, REG_PM8018_SLEEP_CTRL,
296 SLEEP_CTRL_SMPL_EN_MASK,
297 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
298 if (rc) {
299 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
300 return rc;
301 }
302
303 /*
304 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
305 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
306 * USB charging is enabled.
307 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530308 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Jay Chokshi86580f22011-10-17 12:27:52 -0700309 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
310 | PON_CTRL_1_WD_EN_MASK,
311 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
312 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
313 if (rc)
314 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
315
316 return rc;
317}
318
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319static int __pm8058_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
320{
321 int rc;
322
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +0530323 /* When shutting down, enable active pulldowns on important rails. */
324 if (!reset) {
325 /* Disable SMPS's 0,1,3 locally and set pulldown enable bits. */
326 __pm8058_disable_smps_locally_set_pull_down(chip,
327 REG_PM8058_S0_CTRL, REG_PM8058_S0_TEST2,
328 REG_PM8058_VREG_EN_MSM, BIT(7));
329 __pm8058_disable_smps_locally_set_pull_down(chip,
330 REG_PM8058_S1_CTRL, REG_PM8058_S1_TEST2,
331 REG_PM8058_VREG_EN_MSM, BIT(6));
332 __pm8058_disable_smps_locally_set_pull_down(chip,
333 REG_PM8058_S3_CTRL, REG_PM8058_S3_TEST2,
334 REG_PM8058_VREG_EN_GRP_5_4, BIT(7) | BIT(4));
335 /* Disable LDO 21 locally and set pulldown enable bit. */
336 __pm8058_disable_ldo_locally_set_pull_down(chip,
337 REG_PM8058_L21_CTRL, REG_PM8058_VREG_EN_GRP_5_4,
338 BIT(1));
339 }
340
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341 /*
342 * Fix-up: Set regulator LDO22 to 1.225 V in high power mode. Leave its
343 * pull-down state intact. This ensures a safe shutdown.
344 */
345 rc = pm8xxx_misc_masked_write(chip, REG_PM8058_L22_CTRL, 0xBF, 0x93);
346 if (rc) {
347 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
348 goto read_write_err;
349 }
350
351 /* Enable SMPL if resetting is desired. */
352 rc = pm8xxx_misc_masked_write(chip, REG_PM8058_SLEEP_CTRL,
353 SLEEP_CTRL_SMPL_EN_MASK,
354 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
355 if (rc) {
356 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
357 goto read_write_err;
358 }
359
360 /*
361 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
362 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
363 * USB charging is enabled.
364 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530365 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
367 | PON_CTRL_1_WD_EN_MASK,
368 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
369 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
370 if (rc) {
371 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
372 goto read_write_err;
373 }
374
375read_write_err:
376 return rc;
377}
378
379static int __pm8901_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
380{
381 int rc = 0, i;
382 u8 pmr_addr[4] = {
383 REG_PM8901_REGULATOR_S2_PMR,
384 REG_PM8901_REGULATOR_S3_PMR,
385 REG_PM8901_REGULATOR_S4_PMR,
386 REG_PM8901_REGULATOR_S1_PMR,
387 };
388
389 /* Fix-up: Turn off regulators S1, S2, S3, S4 when shutting down. */
390 if (!reset) {
391 for (i = 0; i < 4; i++) {
392 rc = pm8xxx_misc_masked_write(chip, pmr_addr[i],
393 PM8901_REGULATOR_PMR_STATE_MASK,
394 PM8901_REGULATOR_PMR_STATE_OFF);
395 if (rc) {
396 pr_err("pm8xxx_misc_masked_write failed, "
397 "rc=%d\n", rc);
398 goto read_write_err;
399 }
400 }
401 }
402
403read_write_err:
404 return rc;
405}
406
407static int __pm8921_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
408{
409 int rc;
410
411 /* Enable SMPL if resetting is desired. */
412 rc = pm8xxx_misc_masked_write(chip, REG_PM8921_SLEEP_CTRL,
413 SLEEP_CTRL_SMPL_EN_MASK,
414 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
415 if (rc) {
416 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
417 goto read_write_err;
418 }
419
420 /*
421 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
422 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
423 * USB charging is enabled.
424 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530425 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
427 | PON_CTRL_1_WD_EN_MASK,
428 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
429 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
430 if (rc) {
431 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
432 goto read_write_err;
433 }
434
435read_write_err:
436 return rc;
437}
438
439/**
440 * pm8xxx_reset_pwr_off - switch all PM8XXX PMIC chips attached to the system to
441 * either reset or shutdown when they are turned off
442 * @reset: 0 = shudown the PMICs, 1 = shutdown and then restart the PMICs
443 *
444 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
445 */
446int pm8xxx_reset_pwr_off(int reset)
447{
448 struct pm8xxx_misc_chip *chip;
449 unsigned long flags;
450 int rc = 0;
451
452 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
453
454 /* Loop over all attached PMICs and call specific functions for them. */
455 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
456 switch (chip->version) {
Jay Chokshi86580f22011-10-17 12:27:52 -0700457 case PM8XXX_VERSION_8018:
458 rc = __pm8018_reset_pwr_off(chip, reset);
459 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 case PM8XXX_VERSION_8058:
461 rc = __pm8058_reset_pwr_off(chip, reset);
462 break;
463 case PM8XXX_VERSION_8901:
464 rc = __pm8901_reset_pwr_off(chip, reset);
465 break;
466 case PM8XXX_VERSION_8921:
467 rc = __pm8921_reset_pwr_off(chip, reset);
468 break;
469 default:
470 /* PMIC doesn't have reset_pwr_off; do nothing. */
471 break;
472 }
473 if (rc) {
474 pr_err("reset_pwr_off failed, rc=%d\n", rc);
475 break;
476 }
477 }
478
479 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
480
481 return rc;
482}
483EXPORT_SYMBOL_GPL(pm8xxx_reset_pwr_off);
484
Anirudh Ghayal7b382292011-11-01 14:08:34 +0530485/**
Anirudh Ghayalbfbaf822011-11-01 14:28:34 +0530486 * pm8xxx_smpl_control - enables/disables SMPL detection
487 * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
488 *
489 * This function enables or disables the Sudden Momentary Power Loss detection
490 * module. If SMPL detection is enabled, then when a sufficiently long power
491 * loss event occurs, the PMIC will automatically reset itself. If SMPL
492 * detection is disabled, then the PMIC will shutdown when power loss occurs.
493 *
494 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
495 */
496int pm8xxx_smpl_control(int enable)
497{
498 struct pm8xxx_misc_chip *chip;
499 unsigned long flags;
500 int rc = 0;
501
502 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
503
504 /* Loop over all attached PMICs and call specific functions for them. */
505 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
506 switch (chip->version) {
507 case PM8XXX_VERSION_8018:
508 rc = pm8xxx_misc_masked_write(chip,
509 REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
510 (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
511 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
512 break;
513 case PM8XXX_VERSION_8058:
514 rc = pm8xxx_misc_masked_write(chip,
515 REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
516 (enable ? SLEEP_CTRL_SMPL_EN_RESET
517 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
518 break;
519 case PM8XXX_VERSION_8921:
520 rc = pm8xxx_misc_masked_write(chip,
521 REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
522 (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
523 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
524 break;
525 default:
526 /* PMIC doesn't have reset_pwr_off; do nothing. */
527 break;
528 }
529 if (rc) {
530 pr_err("setting smpl control failed, rc=%d\n", rc);
531 break;
532 }
533 }
534
535 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
536
537 return rc;
538}
539EXPORT_SYMBOL(pm8xxx_smpl_control);
540
541
542/**
543 * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
544 * @delay: enum value corresponding to delay time
545 *
546 * This function sets the time delay of the SMPL detection module. If power
547 * is reapplied within this interval, then the PMIC reset automatically. The
548 * SMPL detection module must be enabled for this delay time to take effect.
549 *
550 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
551 */
552int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
553{
554 struct pm8xxx_misc_chip *chip;
555 unsigned long flags;
556 int rc = 0;
557
558 if (delay < SLEEP_CTRL_SMPL_SEL_MIN
559 || delay > SLEEP_CTRL_SMPL_SEL_MAX) {
560 pr_err("%s: invalid delay specified: %d\n", __func__, delay);
561 return -EINVAL;
562 }
563
564 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
565
566 /* Loop over all attached PMICs and call specific functions for them. */
567 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
568 switch (chip->version) {
569 case PM8XXX_VERSION_8018:
570 rc = pm8xxx_misc_masked_write(chip,
571 REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
572 delay);
573 break;
574 case PM8XXX_VERSION_8058:
575 rc = pm8xxx_misc_masked_write(chip,
576 REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
577 delay);
578 break;
579 case PM8XXX_VERSION_8921:
580 rc = pm8xxx_misc_masked_write(chip,
581 REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
582 delay);
583 break;
584 default:
585 /* PMIC doesn't have reset_pwr_off; do nothing. */
586 break;
587 }
588 if (rc) {
589 pr_err("setting smpl delay failed, rc=%d\n", rc);
590 break;
591 }
592 }
593
594 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
595
596 return rc;
597}
598EXPORT_SYMBOL(pm8xxx_smpl_set_delay);
599
600/**
Anirudh Ghayal7b382292011-11-01 14:08:34 +0530601 * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
602 * configures its voltage and resistor settings.
603 * @chg_config: Holds both voltage and resistor values, and a
604 * switch to change the state of charger.
605 * If state is to disable the charger then
606 * both voltage and resistor are disregarded.
607 *
608 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
609 */
610int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
611{
612 struct pm8xxx_misc_chip *chip;
613 unsigned long flags;
614 u8 reg = 0, voltage, resistor;
615 int rc = 0;
616
617 if (chg_config == NULL) {
618 pr_err("chg_config is NULL\n");
619 return -EINVAL;
620 }
621
622 voltage = chg_config->voltage;
623 resistor = chg_config->resistor;
624
625 if (resistor < PM8XXX_COINCELL_RESISTOR_2100_OHMS ||
626 resistor > PM8XXX_COINCELL_RESISTOR_800_OHMS) {
627 pr_err("Invalid resistor value provided\n");
628 return -EINVAL;
629 }
630
631 if (voltage < PM8XXX_COINCELL_VOLTAGE_3p2V ||
632 (voltage > PM8XXX_COINCELL_VOLTAGE_3p0V &&
633 voltage != PM8XXX_COINCELL_VOLTAGE_2p5V)) {
634 pr_err("Invalid voltage value provided\n");
635 return -EINVAL;
636 }
637
638 if (chg_config->state == PM8XXX_COINCELL_CHG_DISABLE) {
639 reg = 0;
640 } else {
641 reg |= voltage;
642 reg |= (resistor << COINCELL_RESISTOR_SHIFT);
643 }
644
645 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
646
647 /* Loop over all attached PMICs and call specific functions for them. */
648 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
649 switch (chip->version) {
650 case PM8XXX_VERSION_8018:
651 rc = pm8xxx_writeb(chip->dev->parent,
652 REG_PM8018_COIN_CHG, reg);
653 break;
654 case PM8XXX_VERSION_8058:
655 rc = pm8xxx_writeb(chip->dev->parent,
656 REG_PM8058_COIN_CHG, reg);
657 break;
658 case PM8XXX_VERSION_8921:
659 rc = pm8xxx_writeb(chip->dev->parent,
660 REG_PM8921_COIN_CHG, reg);
661 break;
662 default:
663 /* PMIC doesn't have reset_pwr_off; do nothing. */
664 break;
665 }
666 if (rc) {
667 pr_err("coincell chg. config failed, rc=%d\n", rc);
668 break;
669 }
670 }
671
672 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
673
674 return rc;
675}
676EXPORT_SYMBOL(pm8xxx_coincell_chg_config);
677
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530678/**
679 * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
680 * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
681 *
682 * This function enables or disables the PMIC watchdog reset detection feature.
683 * If watchdog reset detection is enabled, then the PMIC will reset itself
684 * when PS_HOLD goes low. If it is not enabled, then the PMIC will shutdown
685 * when PS_HOLD goes low.
686 *
687 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
688 */
689int pm8xxx_watchdog_reset_control(int enable)
690{
691 struct pm8xxx_misc_chip *chip;
692 unsigned long flags;
693 int rc = 0;
694
695 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
696
697 /* Loop over all attached PMICs and call specific functions for them. */
698 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
699 switch (chip->version) {
700 case PM8XXX_VERSION_8018:
701 case PM8XXX_VERSION_8058:
702 case PM8XXX_VERSION_8921:
703 rc = pm8xxx_misc_masked_write(chip,
704 REG_PM8XXX_PON_CTRL_1, PON_CTRL_1_WD_EN_MASK,
705 (enable ? PON_CTRL_1_WD_EN_RESET
706 : PON_CTRL_1_WD_EN_PWR_OFF));
707 break;
708 default:
709 /* WD reset control not supported */
710 break;
711 }
712 if (rc) {
713 pr_err("setting WD reset control failed, rc=%d\n", rc);
714 break;
715 }
716 }
717
718 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
719
720 return rc;
721}
722EXPORT_SYMBOL(pm8xxx_watchdog_reset_control);
723
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530724/* Handle the OSC_HALT interrupt: 32 kHz XTAL oscillator has stopped. */
725static irqreturn_t pm8xxx_osc_halt_isr(int irq, void *data)
726{
727 struct pm8xxx_misc_chip *chip = data;
728 u64 count = 0;
729
730 if (chip) {
731 chip->osc_halt_count++;
732 count = chip->osc_halt_count;
733 }
734
735 pr_crit("%s: OSC_HALT interrupt has triggered, 32 kHz XTAL oscillator"
736 " has halted (%llu)!\n", __func__, count);
737
738 return IRQ_HANDLED;
739}
740
Anirudh Ghayal5213eb82011-10-24 14:44:58 +0530741/**
742 * pm8xxx_uart_gpio_mux_ctrl - Mux configuration to select the UART
743 *
744 * @uart_path_sel: Input argument to select either UART1/2/3
745 *
746 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
747 */
748int pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel)
749{
750 struct pm8xxx_misc_chip *chip;
751 unsigned long flags;
752 int rc = 0;
753
754 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
755
756 /* Loop over all attached PMICs and call specific functions for them. */
757 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
758 switch (chip->version) {
759 case PM8XXX_VERSION_8018:
760 case PM8XXX_VERSION_8058:
761 case PM8XXX_VERSION_8921:
762 rc = pm8xxx_misc_masked_write(chip,
763 REG_PM8XXX_GPIO_MUX_CTRL, UART_PATH_SEL_MASK,
764 uart_path_sel << UART_PATH_SEL_SHIFT);
765 break;
766 default:
767 /* Functionality not supported */
768 break;
769 }
770 if (rc) {
771 pr_err("uart_gpio_mux_ctrl failed, rc=%d\n", rc);
772 break;
773 }
774 }
775
776 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
777
778 return rc;
779}
780EXPORT_SYMBOL(pm8xxx_uart_gpio_mux_ctrl);
781
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
783{
784 const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
785 struct pm8xxx_misc_chip *chip;
786 struct pm8xxx_misc_chip *sibling;
787 struct list_head *prev;
788 unsigned long flags;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530789 int rc = 0, irq;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790
791 if (!pdata) {
792 pr_err("missing platform data\n");
793 return -EINVAL;
794 }
795
796 chip = kzalloc(sizeof(struct pm8xxx_misc_chip), GFP_KERNEL);
797 if (!chip) {
798 pr_err("Cannot allocate %d bytes\n",
799 sizeof(struct pm8xxx_misc_chip));
800 return -ENOMEM;
801 }
802
803 chip->dev = &pdev->dev;
804 chip->version = pm8xxx_get_version(chip->dev->parent);
805 memcpy(&(chip->pdata), pdata, sizeof(struct pm8xxx_misc_platform_data));
806
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530807 irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
808 if (irq > 0) {
809 rc = request_any_context_irq(irq, pm8xxx_osc_halt_isr,
810 IRQF_TRIGGER_RISING | IRQF_DISABLED,
811 "pm8xxx_osc_halt_irq", chip);
812 if (rc < 0) {
813 pr_err("%s: request_any_context_irq(%d) FAIL: %d\n",
814 __func__, irq, rc);
815 goto fail_irq;
816 }
817 }
818
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819 /* Insert PMICs in priority order (lowest value first). */
820 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
821 prev = &pm8xxx_misc_chips;
822 list_for_each_entry(sibling, &pm8xxx_misc_chips, link) {
823 if (chip->pdata.priority < sibling->pdata.priority)
824 break;
825 else
826 prev = &sibling->link;
827 }
828 list_add(&chip->link, prev);
829 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
830
831 platform_set_drvdata(pdev, chip);
832
833 return rc;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530834
835fail_irq:
836 platform_set_drvdata(pdev, NULL);
837 kfree(chip);
838 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839}
840
841static int __devexit pm8xxx_misc_remove(struct platform_device *pdev)
842{
843 struct pm8xxx_misc_chip *chip = platform_get_drvdata(pdev);
844 unsigned long flags;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530845 int irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
846 if (irq > 0)
847 free_irq(irq, chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700848
849 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
850 list_del(&chip->link);
851 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
852
853 platform_set_drvdata(pdev, NULL);
854 kfree(chip);
855
856 return 0;
857}
858
859static struct platform_driver pm8xxx_misc_driver = {
860 .probe = pm8xxx_misc_probe,
861 .remove = __devexit_p(pm8xxx_misc_remove),
862 .driver = {
863 .name = PM8XXX_MISC_DEV_NAME,
864 .owner = THIS_MODULE,
865 },
866};
867
868static int __init pm8xxx_misc_init(void)
869{
870 return platform_driver_register(&pm8xxx_misc_driver);
871}
872postcore_initcall(pm8xxx_misc_init);
873
874static void __exit pm8xxx_misc_exit(void)
875{
876 platform_driver_unregister(&pm8xxx_misc_driver);
877}
878module_exit(pm8xxx_misc_exit);
879
880MODULE_LICENSE("GPL v2");
881MODULE_DESCRIPTION("PMIC 8XXX misc driver");
882MODULE_VERSION("1.0");
883MODULE_ALIAS("platform:" PM8XXX_MISC_DEV_NAME);