blob: a73a6950491f150906bc2b5e1fce95313689cff1 [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 Ghayala4262a32011-11-10 00:02:18 +053034/* PON CNTL registers */
35#define REG_PM8058_PON_CNTL_4 0x098
36#define REG_PM8901_PON_CNTL_4 0x099
37#define REG_PM8018_PON_CNTL_4 0x01E
38#define REG_PM8921_PON_CNTL_4 0x01E
39#define REG_PM8058_PON_CNTL_5 0x07B
40#define REG_PM8901_PON_CNTL_5 0x09A
41#define REG_PM8018_PON_CNTL_5 0x01F
42#define REG_PM8921_PON_CNTL_5 0x01F
43
44#define PON_CTRL_4_RESET_EN_MASK 0x01
45#define PON_CTRL_4_SHUTDOWN_ON_RESET 0x0
46#define PON_CTRL_4_RESTART_ON_RESET 0x1
47#define PON_CTRL_5_HARD_RESET_EN_MASK 0x08
48#define PON_CTRL_5_HARD_RESET_EN 0x08
49#define PON_CTRL_5_HARD_RESET_DIS 0x00
50
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +053051/* Regulator master enable addresses */
52#define REG_PM8058_VREG_EN_MSM 0x018
53#define REG_PM8058_VREG_EN_GRP_5_4 0x1C8
54
55/* Regulator control registers for shutdown/reset */
56#define REG_PM8058_S0_CTRL 0x004
57#define REG_PM8058_S1_CTRL 0x005
58#define REG_PM8058_S3_CTRL 0x111
59#define REG_PM8058_L21_CTRL 0x120
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060#define REG_PM8058_L22_CTRL 0x121
61
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +053062#define PM8058_REGULATOR_ENABLE_MASK 0x80
63#define PM8058_REGULATOR_ENABLE 0x80
64#define PM8058_REGULATOR_DISABLE 0x00
65#define PM8058_REGULATOR_PULL_DOWN_MASK 0x40
66#define PM8058_REGULATOR_PULL_DOWN_EN 0x40
67
68/* Buck CTRL register */
69#define PM8058_SMPS_LEGACY_VREF_SEL 0x20
70#define PM8058_SMPS_LEGACY_VPROG_MASK 0x1F
71#define PM8058_SMPS_ADVANCED_BAND_MASK 0xC0
72#define PM8058_SMPS_ADVANCED_BAND_SHIFT 6
73#define PM8058_SMPS_ADVANCED_VPROG_MASK 0x3F
74
75/* Buck TEST2 registers for shutdown/reset */
76#define REG_PM8058_S0_TEST2 0x084
77#define REG_PM8058_S1_TEST2 0x085
78#define REG_PM8058_S3_TEST2 0x11A
79
80#define PM8058_REGULATOR_BANK_WRITE 0x80
81#define PM8058_REGULATOR_BANK_MASK 0x70
82#define PM8058_REGULATOR_BANK_SHIFT 4
83#define PM8058_REGULATOR_BANK_SEL(n) ((n) << PM8058_REGULATOR_BANK_SHIFT)
84
85/* Buck TEST2 register bank 1 */
86#define PM8058_SMPS_LEGACY_VLOW_SEL 0x01
87
88/* Buck TEST2 register bank 7 */
89#define PM8058_SMPS_ADVANCED_MODE_MASK 0x02
90#define PM8058_SMPS_ADVANCED_MODE 0x02
91#define PM8058_SMPS_LEGACY_MODE 0x00
92
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070093/* SLEEP CTRL register */
94#define REG_PM8058_SLEEP_CTRL 0x02B
95#define REG_PM8921_SLEEP_CTRL 0x10A
Jay Chokshi86580f22011-10-17 12:27:52 -070096#define REG_PM8018_SLEEP_CTRL 0x10A
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070097
98#define SLEEP_CTRL_SMPL_EN_MASK 0x04
99#define SLEEP_CTRL_SMPL_EN_RESET 0x04
100#define SLEEP_CTRL_SMPL_EN_PWR_OFF 0x00
101
Anirudh Ghayalbfbaf822011-11-01 14:28:34 +0530102#define SLEEP_CTRL_SMPL_SEL_MASK 0x03
103#define SLEEP_CTRL_SMPL_SEL_MIN 0
104#define SLEEP_CTRL_SMPL_SEL_MAX 3
105
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106/* FTS regulator PMR registers */
107#define REG_PM8901_REGULATOR_S1_PMR 0xA7
108#define REG_PM8901_REGULATOR_S2_PMR 0xA8
109#define REG_PM8901_REGULATOR_S3_PMR 0xA9
110#define REG_PM8901_REGULATOR_S4_PMR 0xAA
111
112#define PM8901_REGULATOR_PMR_STATE_MASK 0x60
113#define PM8901_REGULATOR_PMR_STATE_OFF 0x20
114
Anirudh Ghayal7b382292011-11-01 14:08:34 +0530115/* COINCELL CHG registers */
116#define REG_PM8058_COIN_CHG 0x02F
117#define REG_PM8921_COIN_CHG 0x09C
118#define REG_PM8018_COIN_CHG 0x09C
119
120#define COINCELL_RESISTOR_SHIFT 0x2
121
Anirudh Ghayal51e947f2011-11-01 14:49:45 +0530122/* GP TEST register */
123#define REG_PM8XXX_GP_TEST_1 0x07A
124
125/* Stay on configuration */
126#define PM8XXX_STAY_ON_CFG 0x92
127
Anirudh Ghayal5213eb82011-10-24 14:44:58 +0530128/* GPIO UART MUX CTRL registers */
129#define REG_PM8XXX_GPIO_MUX_CTRL 0x1CC
130
131#define UART_PATH_SEL_MASK 0x60
132#define UART_PATH_SEL_SHIFT 0x5
133
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134struct pm8xxx_misc_chip {
135 struct list_head link;
136 struct pm8xxx_misc_platform_data pdata;
137 struct device *dev;
138 enum pm8xxx_version version;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530139 u64 osc_halt_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700140};
141
142static LIST_HEAD(pm8xxx_misc_chips);
143static DEFINE_SPINLOCK(pm8xxx_misc_chips_lock);
144
145static int pm8xxx_misc_masked_write(struct pm8xxx_misc_chip *chip, u16 addr,
146 u8 mask, u8 val)
147{
148 int rc;
149 u8 reg;
150
151 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
152 if (rc) {
153 pr_err("pm8xxx_readb(0x%03X) failed, rc=%d\n", addr, rc);
154 return rc;
155 }
156 reg &= ~mask;
157 reg |= val & mask;
158 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
159 if (rc)
160 pr_err("pm8xxx_writeb(0x%03X)=0x%02X failed, rc=%d\n", addr,
161 reg, rc);
162 return rc;
163}
164
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +0530165/*
166 * Set an SMPS regulator to be disabled in its CTRL register, but enabled
167 * in the master enable register. Also set it's pull down enable bit.
168 * Take care to make sure that the output voltage doesn't change if switching
169 * from advanced mode to legacy mode.
170 */
171static int
172__pm8058_disable_smps_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
173 u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr,
174 u8 master_enable_bit)
175{
176 int rc = 0;
177 u8 vref_sel, vlow_sel, band, vprog, bank, reg;
178
179 bank = PM8058_REGULATOR_BANK_SEL(7);
180 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
181 if (rc) {
182 pr_err("%s: pm8xxx_writeb(0x%03X) failed: rc=%d\n", __func__,
183 test2_addr, rc);
184 goto done;
185 }
186
187 rc = pm8xxx_readb(chip->dev->parent, test2_addr, &reg);
188 if (rc) {
189 pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
190 __func__, test2_addr, rc);
191 goto done;
192 }
193
194 /* Check if in advanced mode. */
195 if ((reg & PM8058_SMPS_ADVANCED_MODE_MASK) ==
196 PM8058_SMPS_ADVANCED_MODE) {
197 /* Determine current output voltage. */
198 rc = pm8xxx_readb(chip->dev->parent, ctrl_addr, &reg);
199 if (rc) {
200 pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
201 __func__, ctrl_addr, rc);
202 goto done;
203 }
204
205 band = (reg & PM8058_SMPS_ADVANCED_BAND_MASK)
206 >> PM8058_SMPS_ADVANCED_BAND_SHIFT;
207 switch (band) {
208 case 3:
209 vref_sel = 0;
210 vlow_sel = 0;
211 break;
212 case 2:
213 vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
214 vlow_sel = 0;
215 break;
216 case 1:
217 vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
218 vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL;
219 break;
220 default:
221 pr_err("%s: regulator already disabled\n", __func__);
222 return -EPERM;
223 }
224 vprog = (reg & PM8058_SMPS_ADVANCED_VPROG_MASK);
225 /* Round up if fine step is in use. */
226 vprog = (vprog + 1) >> 1;
227 if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK)
228 vprog = PM8058_SMPS_LEGACY_VPROG_MASK;
229
230 /* Set VLOW_SEL bit. */
231 bank = PM8058_REGULATOR_BANK_SEL(1);
232 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
233 if (rc) {
234 pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
235 __func__, test2_addr, rc);
236 goto done;
237 }
238
239 rc = pm8xxx_misc_masked_write(chip, test2_addr,
240 PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK
241 | PM8058_SMPS_LEGACY_VLOW_SEL,
242 PM8058_REGULATOR_BANK_WRITE |
243 PM8058_REGULATOR_BANK_SEL(1) | vlow_sel);
244 if (rc)
245 goto done;
246
247 /* Switch to legacy mode */
248 bank = PM8058_REGULATOR_BANK_SEL(7);
249 rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
250 if (rc) {
251 pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
252 __func__, test2_addr, rc);
253 goto done;
254 }
255 rc = pm8xxx_misc_masked_write(chip, test2_addr,
256 PM8058_REGULATOR_BANK_WRITE |
257 PM8058_REGULATOR_BANK_MASK |
258 PM8058_SMPS_ADVANCED_MODE_MASK,
259 PM8058_REGULATOR_BANK_WRITE |
260 PM8058_REGULATOR_BANK_SEL(7) |
261 PM8058_SMPS_LEGACY_MODE);
262 if (rc)
263 goto done;
264
265 /* Enable locally, enable pull down, keep voltage the same. */
266 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
267 PM8058_REGULATOR_ENABLE_MASK |
268 PM8058_REGULATOR_PULL_DOWN_MASK |
269 PM8058_SMPS_LEGACY_VREF_SEL |
270 PM8058_SMPS_LEGACY_VPROG_MASK,
271 PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN
272 | vref_sel | vprog);
273 if (rc)
274 goto done;
275 }
276
277 /* Enable in master control register. */
278 rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
279 master_enable_bit, master_enable_bit);
280 if (rc)
281 goto done;
282
283 /* Disable locally and enable pull down. */
284 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
285 PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
286 PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
287
288done:
289 return rc;
290}
291
292static int
293__pm8058_disable_ldo_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
294 u16 ctrl_addr, u16 master_enable_addr, u8 master_enable_bit)
295{
296 int rc;
297
298 /* Enable LDO in master control register. */
299 rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
300 master_enable_bit, master_enable_bit);
301 if (rc)
302 goto done;
303
304 /* Disable LDO in CTRL register and set pull down */
305 rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
306 PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
307 PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
308
309done:
310 return rc;
311}
312
Jay Chokshi86580f22011-10-17 12:27:52 -0700313static int __pm8018_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
314{
315 int rc;
316
317 /* Enable SMPL if resetting is desired. */
318 rc = pm8xxx_misc_masked_write(chip, REG_PM8018_SLEEP_CTRL,
319 SLEEP_CTRL_SMPL_EN_MASK,
320 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
321 if (rc) {
322 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
323 return rc;
324 }
325
326 /*
327 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
328 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
329 * USB charging is enabled.
330 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530331 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Jay Chokshi86580f22011-10-17 12:27:52 -0700332 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
333 | PON_CTRL_1_WD_EN_MASK,
334 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
335 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
336 if (rc)
337 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
338
339 return rc;
340}
341
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342static int __pm8058_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
343{
344 int rc;
345
Anirudh Ghayal9e1bd642011-11-01 13:57:40 +0530346 /* When shutting down, enable active pulldowns on important rails. */
347 if (!reset) {
348 /* Disable SMPS's 0,1,3 locally and set pulldown enable bits. */
349 __pm8058_disable_smps_locally_set_pull_down(chip,
350 REG_PM8058_S0_CTRL, REG_PM8058_S0_TEST2,
351 REG_PM8058_VREG_EN_MSM, BIT(7));
352 __pm8058_disable_smps_locally_set_pull_down(chip,
353 REG_PM8058_S1_CTRL, REG_PM8058_S1_TEST2,
354 REG_PM8058_VREG_EN_MSM, BIT(6));
355 __pm8058_disable_smps_locally_set_pull_down(chip,
356 REG_PM8058_S3_CTRL, REG_PM8058_S3_TEST2,
357 REG_PM8058_VREG_EN_GRP_5_4, BIT(7) | BIT(4));
358 /* Disable LDO 21 locally and set pulldown enable bit. */
359 __pm8058_disable_ldo_locally_set_pull_down(chip,
360 REG_PM8058_L21_CTRL, REG_PM8058_VREG_EN_GRP_5_4,
361 BIT(1));
362 }
363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 /*
365 * Fix-up: Set regulator LDO22 to 1.225 V in high power mode. Leave its
366 * pull-down state intact. This ensures a safe shutdown.
367 */
368 rc = pm8xxx_misc_masked_write(chip, REG_PM8058_L22_CTRL, 0xBF, 0x93);
369 if (rc) {
370 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
371 goto read_write_err;
372 }
373
374 /* Enable SMPL if resetting is desired. */
375 rc = pm8xxx_misc_masked_write(chip, REG_PM8058_SLEEP_CTRL,
376 SLEEP_CTRL_SMPL_EN_MASK,
377 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
378 if (rc) {
379 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
380 goto read_write_err;
381 }
382
383 /*
384 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
385 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
386 * USB charging is enabled.
387 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530388 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700389 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
390 | PON_CTRL_1_WD_EN_MASK,
391 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
392 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
393 if (rc) {
394 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
395 goto read_write_err;
396 }
397
398read_write_err:
399 return rc;
400}
401
402static int __pm8901_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
403{
404 int rc = 0, i;
405 u8 pmr_addr[4] = {
406 REG_PM8901_REGULATOR_S2_PMR,
407 REG_PM8901_REGULATOR_S3_PMR,
408 REG_PM8901_REGULATOR_S4_PMR,
409 REG_PM8901_REGULATOR_S1_PMR,
410 };
411
412 /* Fix-up: Turn off regulators S1, S2, S3, S4 when shutting down. */
413 if (!reset) {
414 for (i = 0; i < 4; i++) {
415 rc = pm8xxx_misc_masked_write(chip, pmr_addr[i],
416 PM8901_REGULATOR_PMR_STATE_MASK,
417 PM8901_REGULATOR_PMR_STATE_OFF);
418 if (rc) {
419 pr_err("pm8xxx_misc_masked_write failed, "
420 "rc=%d\n", rc);
421 goto read_write_err;
422 }
423 }
424 }
425
426read_write_err:
427 return rc;
428}
429
430static int __pm8921_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
431{
432 int rc;
433
434 /* Enable SMPL if resetting is desired. */
435 rc = pm8xxx_misc_masked_write(chip, REG_PM8921_SLEEP_CTRL,
436 SLEEP_CTRL_SMPL_EN_MASK,
437 (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
438 if (rc) {
439 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
440 goto read_write_err;
441 }
442
443 /*
444 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
445 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
446 * USB charging is enabled.
447 */
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530448 rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
450 | PON_CTRL_1_WD_EN_MASK,
451 PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
452 | (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
453 if (rc) {
454 pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
455 goto read_write_err;
456 }
457
458read_write_err:
459 return rc;
460}
461
462/**
463 * pm8xxx_reset_pwr_off - switch all PM8XXX PMIC chips attached to the system to
464 * either reset or shutdown when they are turned off
465 * @reset: 0 = shudown the PMICs, 1 = shutdown and then restart the PMICs
466 *
467 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
468 */
469int pm8xxx_reset_pwr_off(int reset)
470{
471 struct pm8xxx_misc_chip *chip;
472 unsigned long flags;
473 int rc = 0;
474
475 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
476
477 /* Loop over all attached PMICs and call specific functions for them. */
478 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
479 switch (chip->version) {
Jay Chokshi86580f22011-10-17 12:27:52 -0700480 case PM8XXX_VERSION_8018:
481 rc = __pm8018_reset_pwr_off(chip, reset);
482 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700483 case PM8XXX_VERSION_8058:
484 rc = __pm8058_reset_pwr_off(chip, reset);
485 break;
486 case PM8XXX_VERSION_8901:
487 rc = __pm8901_reset_pwr_off(chip, reset);
488 break;
489 case PM8XXX_VERSION_8921:
490 rc = __pm8921_reset_pwr_off(chip, reset);
491 break;
492 default:
493 /* PMIC doesn't have reset_pwr_off; do nothing. */
494 break;
495 }
496 if (rc) {
497 pr_err("reset_pwr_off failed, rc=%d\n", rc);
498 break;
499 }
500 }
501
502 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
503
504 return rc;
505}
506EXPORT_SYMBOL_GPL(pm8xxx_reset_pwr_off);
507
Anirudh Ghayal7b382292011-11-01 14:08:34 +0530508/**
Anirudh Ghayalbfbaf822011-11-01 14:28:34 +0530509 * pm8xxx_smpl_control - enables/disables SMPL detection
510 * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
511 *
512 * This function enables or disables the Sudden Momentary Power Loss detection
513 * module. If SMPL detection is enabled, then when a sufficiently long power
514 * loss event occurs, the PMIC will automatically reset itself. If SMPL
515 * detection is disabled, then the PMIC will shutdown when power loss occurs.
516 *
517 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
518 */
519int pm8xxx_smpl_control(int enable)
520{
521 struct pm8xxx_misc_chip *chip;
522 unsigned long flags;
523 int rc = 0;
524
525 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
526
527 /* Loop over all attached PMICs and call specific functions for them. */
528 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
529 switch (chip->version) {
530 case PM8XXX_VERSION_8018:
531 rc = pm8xxx_misc_masked_write(chip,
532 REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
533 (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
534 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
535 break;
536 case PM8XXX_VERSION_8058:
537 rc = pm8xxx_misc_masked_write(chip,
538 REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
539 (enable ? SLEEP_CTRL_SMPL_EN_RESET
540 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
541 break;
542 case PM8XXX_VERSION_8921:
543 rc = pm8xxx_misc_masked_write(chip,
544 REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
545 (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
546 : SLEEP_CTRL_SMPL_EN_PWR_OFF));
547 break;
548 default:
549 /* PMIC doesn't have reset_pwr_off; do nothing. */
550 break;
551 }
552 if (rc) {
553 pr_err("setting smpl control failed, rc=%d\n", rc);
554 break;
555 }
556 }
557
558 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
559
560 return rc;
561}
562EXPORT_SYMBOL(pm8xxx_smpl_control);
563
564
565/**
566 * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
567 * @delay: enum value corresponding to delay time
568 *
569 * This function sets the time delay of the SMPL detection module. If power
570 * is reapplied within this interval, then the PMIC reset automatically. The
571 * SMPL detection module must be enabled for this delay time to take effect.
572 *
573 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
574 */
575int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
576{
577 struct pm8xxx_misc_chip *chip;
578 unsigned long flags;
579 int rc = 0;
580
581 if (delay < SLEEP_CTRL_SMPL_SEL_MIN
582 || delay > SLEEP_CTRL_SMPL_SEL_MAX) {
583 pr_err("%s: invalid delay specified: %d\n", __func__, delay);
584 return -EINVAL;
585 }
586
587 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
588
589 /* Loop over all attached PMICs and call specific functions for them. */
590 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
591 switch (chip->version) {
592 case PM8XXX_VERSION_8018:
593 rc = pm8xxx_misc_masked_write(chip,
594 REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
595 delay);
596 break;
597 case PM8XXX_VERSION_8058:
598 rc = pm8xxx_misc_masked_write(chip,
599 REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
600 delay);
601 break;
602 case PM8XXX_VERSION_8921:
603 rc = pm8xxx_misc_masked_write(chip,
604 REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
605 delay);
606 break;
607 default:
608 /* PMIC doesn't have reset_pwr_off; do nothing. */
609 break;
610 }
611 if (rc) {
612 pr_err("setting smpl delay failed, rc=%d\n", rc);
613 break;
614 }
615 }
616
617 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
618
619 return rc;
620}
621EXPORT_SYMBOL(pm8xxx_smpl_set_delay);
622
623/**
Anirudh Ghayal7b382292011-11-01 14:08:34 +0530624 * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
625 * configures its voltage and resistor settings.
626 * @chg_config: Holds both voltage and resistor values, and a
627 * switch to change the state of charger.
628 * If state is to disable the charger then
629 * both voltage and resistor are disregarded.
630 *
631 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
632 */
633int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
634{
635 struct pm8xxx_misc_chip *chip;
636 unsigned long flags;
637 u8 reg = 0, voltage, resistor;
638 int rc = 0;
639
640 if (chg_config == NULL) {
641 pr_err("chg_config is NULL\n");
642 return -EINVAL;
643 }
644
645 voltage = chg_config->voltage;
646 resistor = chg_config->resistor;
647
648 if (resistor < PM8XXX_COINCELL_RESISTOR_2100_OHMS ||
649 resistor > PM8XXX_COINCELL_RESISTOR_800_OHMS) {
650 pr_err("Invalid resistor value provided\n");
651 return -EINVAL;
652 }
653
654 if (voltage < PM8XXX_COINCELL_VOLTAGE_3p2V ||
655 (voltage > PM8XXX_COINCELL_VOLTAGE_3p0V &&
656 voltage != PM8XXX_COINCELL_VOLTAGE_2p5V)) {
657 pr_err("Invalid voltage value provided\n");
658 return -EINVAL;
659 }
660
661 if (chg_config->state == PM8XXX_COINCELL_CHG_DISABLE) {
662 reg = 0;
663 } else {
664 reg |= voltage;
665 reg |= (resistor << COINCELL_RESISTOR_SHIFT);
666 }
667
668 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
669
670 /* Loop over all attached PMICs and call specific functions for them. */
671 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
672 switch (chip->version) {
673 case PM8XXX_VERSION_8018:
674 rc = pm8xxx_writeb(chip->dev->parent,
675 REG_PM8018_COIN_CHG, reg);
676 break;
677 case PM8XXX_VERSION_8058:
678 rc = pm8xxx_writeb(chip->dev->parent,
679 REG_PM8058_COIN_CHG, reg);
680 break;
681 case PM8XXX_VERSION_8921:
682 rc = pm8xxx_writeb(chip->dev->parent,
683 REG_PM8921_COIN_CHG, reg);
684 break;
685 default:
686 /* PMIC doesn't have reset_pwr_off; do nothing. */
687 break;
688 }
689 if (rc) {
690 pr_err("coincell chg. config failed, rc=%d\n", rc);
691 break;
692 }
693 }
694
695 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
696
697 return rc;
698}
699EXPORT_SYMBOL(pm8xxx_coincell_chg_config);
700
Anirudh Ghayala23c1ca2011-11-01 14:36:24 +0530701/**
702 * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
703 * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
704 *
705 * This function enables or disables the PMIC watchdog reset detection feature.
706 * If watchdog reset detection is enabled, then the PMIC will reset itself
707 * when PS_HOLD goes low. If it is not enabled, then the PMIC will shutdown
708 * when PS_HOLD goes low.
709 *
710 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
711 */
712int pm8xxx_watchdog_reset_control(int enable)
713{
714 struct pm8xxx_misc_chip *chip;
715 unsigned long flags;
716 int rc = 0;
717
718 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
719
720 /* Loop over all attached PMICs and call specific functions for them. */
721 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
722 switch (chip->version) {
723 case PM8XXX_VERSION_8018:
724 case PM8XXX_VERSION_8058:
725 case PM8XXX_VERSION_8921:
726 rc = pm8xxx_misc_masked_write(chip,
727 REG_PM8XXX_PON_CTRL_1, PON_CTRL_1_WD_EN_MASK,
728 (enable ? PON_CTRL_1_WD_EN_RESET
729 : PON_CTRL_1_WD_EN_PWR_OFF));
730 break;
731 default:
732 /* WD reset control not supported */
733 break;
734 }
735 if (rc) {
736 pr_err("setting WD reset control failed, rc=%d\n", rc);
737 break;
738 }
739 }
740
741 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
742
743 return rc;
744}
745EXPORT_SYMBOL(pm8xxx_watchdog_reset_control);
746
Anirudh Ghayal51e947f2011-11-01 14:49:45 +0530747/**
748 * pm8xxx_stay_on - enables stay_on feature
749 *
750 * PMIC stay-on feature allows PMIC to ignore MSM PS_HOLD=low
751 * signal so that some special functions like debugging could be
752 * performed.
753 *
754 * This feature should not be used in any product release.
755 *
756 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
757 */
758int pm8xxx_stay_on(void)
759{
760 struct pm8xxx_misc_chip *chip;
761 unsigned long flags;
762 int rc = 0;
763
764 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
765
766 /* Loop over all attached PMICs and call specific functions for them. */
767 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
768 switch (chip->version) {
769 case PM8XXX_VERSION_8018:
770 case PM8XXX_VERSION_8058:
771 case PM8XXX_VERSION_8921:
772 rc = pm8xxx_writeb(chip->dev->parent,
773 REG_PM8XXX_GP_TEST_1, PM8XXX_STAY_ON_CFG);
774 break;
775 default:
776 /* stay on not supported */
777 break;
778 }
779 if (rc) {
780 pr_err("stay_on failed failed, rc=%d\n", rc);
781 break;
782 }
783 }
784
785 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
786
787 return rc;
788}
789EXPORT_SYMBOL(pm8xxx_stay_on);
790
Anirudh Ghayala4262a32011-11-10 00:02:18 +0530791static int
792__pm8xxx_hard_reset_config(struct pm8xxx_misc_chip *chip,
793 enum pm8xxx_pon_config config, u16 pon4_addr, u16 pon5_addr)
794{
795 int rc = 0;
796
797 switch (config) {
798 case PM8XXX_DISABLE_HARD_RESET:
799 rc = pm8xxx_misc_masked_write(chip, pon5_addr,
800 PON_CTRL_5_HARD_RESET_EN_MASK,
801 PON_CTRL_5_HARD_RESET_DIS);
802 break;
803 case PM8XXX_SHUTDOWN_ON_HARD_RESET:
804 rc = pm8xxx_misc_masked_write(chip, pon5_addr,
805 PON_CTRL_5_HARD_RESET_EN_MASK,
806 PON_CTRL_5_HARD_RESET_EN);
807 if (!rc) {
808 rc = pm8xxx_misc_masked_write(chip, pon4_addr,
809 PON_CTRL_4_RESET_EN_MASK,
810 PON_CTRL_4_SHUTDOWN_ON_RESET);
811 }
812 break;
813 case PM8XXX_RESTART_ON_HARD_RESET:
814 rc = pm8xxx_misc_masked_write(chip, pon5_addr,
815 PON_CTRL_5_HARD_RESET_EN_MASK,
816 PON_CTRL_5_HARD_RESET_EN);
817 if (!rc) {
818 rc = pm8xxx_misc_masked_write(chip, pon4_addr,
819 PON_CTRL_4_RESET_EN_MASK,
820 PON_CTRL_4_RESTART_ON_RESET);
821 }
822 break;
823 default:
824 rc = -EINVAL;
825 break;
826 }
827 return rc;
828}
829
830/**
831 * pm8xxx_hard_reset_config - Allows different reset configurations
832 *
833 * config = PM8XXX_DISABLE_HARD_RESET to disable hard reset
834 * = PM8XXX_SHUTDOWN_ON_HARD_RESET to turn off the system on hard reset
835 * = PM8XXX_RESTART_ON_HARD_RESET to restart the system on hard reset
836 *
837 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
838 */
839int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config)
840{
841 struct pm8xxx_misc_chip *chip;
842 unsigned long flags;
843 int rc = 0;
844
845 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
846
847 /* Loop over all attached PMICs and call specific functions for them. */
848 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
849 switch (chip->version) {
850 case PM8XXX_VERSION_8018:
851 __pm8xxx_hard_reset_config(chip, config,
852 REG_PM8018_PON_CNTL_4, REG_PM8018_PON_CNTL_5);
853 break;
854 case PM8XXX_VERSION_8058:
855 __pm8xxx_hard_reset_config(chip, config,
856 REG_PM8058_PON_CNTL_4, REG_PM8058_PON_CNTL_5);
857 break;
858 case PM8XXX_VERSION_8901:
859 __pm8xxx_hard_reset_config(chip, config,
860 REG_PM8901_PON_CNTL_4, REG_PM8901_PON_CNTL_5);
861 break;
862 case PM8XXX_VERSION_8921:
863 __pm8xxx_hard_reset_config(chip, config,
864 REG_PM8921_PON_CNTL_4, REG_PM8921_PON_CNTL_5);
865 break;
866 default:
867 /* hard reset config. no supported */
868 break;
869 }
870 if (rc) {
871 pr_err("hard reset config. failed, rc=%d\n", rc);
872 break;
873 }
874 }
875
876 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
877
878 return rc;
879}
880EXPORT_SYMBOL(pm8xxx_hard_reset_config);
881
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530882/* Handle the OSC_HALT interrupt: 32 kHz XTAL oscillator has stopped. */
883static irqreturn_t pm8xxx_osc_halt_isr(int irq, void *data)
884{
885 struct pm8xxx_misc_chip *chip = data;
886 u64 count = 0;
887
888 if (chip) {
889 chip->osc_halt_count++;
890 count = chip->osc_halt_count;
891 }
892
893 pr_crit("%s: OSC_HALT interrupt has triggered, 32 kHz XTAL oscillator"
894 " has halted (%llu)!\n", __func__, count);
895
896 return IRQ_HANDLED;
897}
898
Anirudh Ghayal5213eb82011-10-24 14:44:58 +0530899/**
900 * pm8xxx_uart_gpio_mux_ctrl - Mux configuration to select the UART
901 *
902 * @uart_path_sel: Input argument to select either UART1/2/3
903 *
904 * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
905 */
906int pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel)
907{
908 struct pm8xxx_misc_chip *chip;
909 unsigned long flags;
910 int rc = 0;
911
912 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
913
914 /* Loop over all attached PMICs and call specific functions for them. */
915 list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
916 switch (chip->version) {
917 case PM8XXX_VERSION_8018:
918 case PM8XXX_VERSION_8058:
919 case PM8XXX_VERSION_8921:
920 rc = pm8xxx_misc_masked_write(chip,
921 REG_PM8XXX_GPIO_MUX_CTRL, UART_PATH_SEL_MASK,
922 uart_path_sel << UART_PATH_SEL_SHIFT);
923 break;
924 default:
925 /* Functionality not supported */
926 break;
927 }
928 if (rc) {
929 pr_err("uart_gpio_mux_ctrl failed, rc=%d\n", rc);
930 break;
931 }
932 }
933
934 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
935
936 return rc;
937}
938EXPORT_SYMBOL(pm8xxx_uart_gpio_mux_ctrl);
939
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700940static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
941{
942 const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
943 struct pm8xxx_misc_chip *chip;
944 struct pm8xxx_misc_chip *sibling;
945 struct list_head *prev;
946 unsigned long flags;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530947 int rc = 0, irq;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700948
949 if (!pdata) {
950 pr_err("missing platform data\n");
951 return -EINVAL;
952 }
953
954 chip = kzalloc(sizeof(struct pm8xxx_misc_chip), GFP_KERNEL);
955 if (!chip) {
956 pr_err("Cannot allocate %d bytes\n",
957 sizeof(struct pm8xxx_misc_chip));
958 return -ENOMEM;
959 }
960
961 chip->dev = &pdev->dev;
962 chip->version = pm8xxx_get_version(chip->dev->parent);
963 memcpy(&(chip->pdata), pdata, sizeof(struct pm8xxx_misc_platform_data));
964
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530965 irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
966 if (irq > 0) {
967 rc = request_any_context_irq(irq, pm8xxx_osc_halt_isr,
968 IRQF_TRIGGER_RISING | IRQF_DISABLED,
969 "pm8xxx_osc_halt_irq", chip);
970 if (rc < 0) {
971 pr_err("%s: request_any_context_irq(%d) FAIL: %d\n",
972 __func__, irq, rc);
973 goto fail_irq;
974 }
975 }
976
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700977 /* Insert PMICs in priority order (lowest value first). */
978 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
979 prev = &pm8xxx_misc_chips;
980 list_for_each_entry(sibling, &pm8xxx_misc_chips, link) {
981 if (chip->pdata.priority < sibling->pdata.priority)
982 break;
983 else
984 prev = &sibling->link;
985 }
986 list_add(&chip->link, prev);
987 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
988
989 platform_set_drvdata(pdev, chip);
990
991 return rc;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +0530992
993fail_irq:
994 platform_set_drvdata(pdev, NULL);
995 kfree(chip);
996 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997}
998
999static int __devexit pm8xxx_misc_remove(struct platform_device *pdev)
1000{
1001 struct pm8xxx_misc_chip *chip = platform_get_drvdata(pdev);
1002 unsigned long flags;
Anirudh Ghayal8b8f1892011-11-11 10:48:41 +05301003 int irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
1004 if (irq > 0)
1005 free_irq(irq, chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006
1007 spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
1008 list_del(&chip->link);
1009 spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
1010
1011 platform_set_drvdata(pdev, NULL);
1012 kfree(chip);
1013
1014 return 0;
1015}
1016
1017static struct platform_driver pm8xxx_misc_driver = {
1018 .probe = pm8xxx_misc_probe,
1019 .remove = __devexit_p(pm8xxx_misc_remove),
1020 .driver = {
1021 .name = PM8XXX_MISC_DEV_NAME,
1022 .owner = THIS_MODULE,
1023 },
1024};
1025
1026static int __init pm8xxx_misc_init(void)
1027{
1028 return platform_driver_register(&pm8xxx_misc_driver);
1029}
1030postcore_initcall(pm8xxx_misc_init);
1031
1032static void __exit pm8xxx_misc_exit(void)
1033{
1034 platform_driver_unregister(&pm8xxx_misc_driver);
1035}
1036module_exit(pm8xxx_misc_exit);
1037
1038MODULE_LICENSE("GPL v2");
1039MODULE_DESCRIPTION("PMIC 8XXX misc driver");
1040MODULE_VERSION("1.0");
1041MODULE_ALIAS("platform:" PM8XXX_MISC_DEV_NAME);