Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm831x_power.c
Go to the documentation of this file.
1 /*
2  * PMU driver for Wolfson Microelectronics wm831x PMICs
3  *
4  * Copyright 2009 Wolfson Microelectronics PLC.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/module.h>
12 #include <linux/err.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/slab.h>
16 
17 #include <linux/mfd/wm831x/core.h>
19 #include <linux/mfd/wm831x/pmu.h>
20 #include <linux/mfd/wm831x/pdata.h>
21 
22 struct wm831x_power {
23  struct wm831x *wm831x;
25  struct power_supply usb;
27  char wall_name[20];
28  char usb_name[20];
29  char battery_name[20];
31 };
32 
33 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
35 {
36  int ret;
37 
39  if (ret < 0)
40  return ret;
41 
42  if (ret & supply)
43  val->intval = 1;
44  else
45  val->intval = 0;
46 
47  return 0;
48 }
49 
50 static int wm831x_power_read_voltage(struct wm831x *wm831x,
51  enum wm831x_auxadc src,
53 {
54  int ret;
55 
56  ret = wm831x_auxadc_read_uv(wm831x, src);
57  if (ret >= 0)
58  val->intval = ret;
59 
60  return ret;
61 }
62 
63 /*********************************************************************
64  * WALL Power
65  *********************************************************************/
66 static int wm831x_wall_get_prop(struct power_supply *psy,
67  enum power_supply_property psp,
68  union power_supply_propval *val)
69 {
70  struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
71  struct wm831x *wm831x = wm831x_power->wm831x;
72  int ret = 0;
73 
74  switch (psp) {
76  ret = wm831x_power_check_online(wm831x, WM831X_PWR_WALL, val);
77  break;
79  ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_WALL, val);
80  break;
81  default:
82  ret = -EINVAL;
83  break;
84  }
85 
86  return ret;
87 }
88 
89 static enum power_supply_property wm831x_wall_props[] = {
92 };
93 
94 /*********************************************************************
95  * USB Power
96  *********************************************************************/
97 static int wm831x_usb_get_prop(struct power_supply *psy,
98  enum power_supply_property psp,
99  union power_supply_propval *val)
100 {
101  struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
102  struct wm831x *wm831x = wm831x_power->wm831x;
103  int ret = 0;
104 
105  switch (psp) {
107  ret = wm831x_power_check_online(wm831x, WM831X_PWR_USB, val);
108  break;
110  ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_USB, val);
111  break;
112  default:
113  ret = -EINVAL;
114  break;
115  }
116 
117  return ret;
118 }
119 
120 static enum power_supply_property wm831x_usb_props[] = {
123 };
124 
125 /*********************************************************************
126  * Battery properties
127  *********************************************************************/
128 
129 struct chg_map {
130  int val;
131  int reg_val;
132 };
133 
134 static struct chg_map trickle_ilims[] = {
135  { 50, 0 << WM831X_CHG_TRKL_ILIM_SHIFT },
136  { 100, 1 << WM831X_CHG_TRKL_ILIM_SHIFT },
137  { 150, 2 << WM831X_CHG_TRKL_ILIM_SHIFT },
138  { 200, 3 << WM831X_CHG_TRKL_ILIM_SHIFT },
139 };
140 
141 static struct chg_map vsels[] = {
142  { 4050, 0 << WM831X_CHG_VSEL_SHIFT },
143  { 4100, 1 << WM831X_CHG_VSEL_SHIFT },
144  { 4150, 2 << WM831X_CHG_VSEL_SHIFT },
145  { 4200, 3 << WM831X_CHG_VSEL_SHIFT },
146 };
147 
148 static struct chg_map fast_ilims[] = {
149  { 0, 0 << WM831X_CHG_FAST_ILIM_SHIFT },
150  { 50, 1 << WM831X_CHG_FAST_ILIM_SHIFT },
151  { 100, 2 << WM831X_CHG_FAST_ILIM_SHIFT },
152  { 150, 3 << WM831X_CHG_FAST_ILIM_SHIFT },
153  { 200, 4 << WM831X_CHG_FAST_ILIM_SHIFT },
154  { 250, 5 << WM831X_CHG_FAST_ILIM_SHIFT },
155  { 300, 6 << WM831X_CHG_FAST_ILIM_SHIFT },
156  { 350, 7 << WM831X_CHG_FAST_ILIM_SHIFT },
157  { 400, 8 << WM831X_CHG_FAST_ILIM_SHIFT },
158  { 450, 9 << WM831X_CHG_FAST_ILIM_SHIFT },
159  { 500, 10 << WM831X_CHG_FAST_ILIM_SHIFT },
160  { 600, 11 << WM831X_CHG_FAST_ILIM_SHIFT },
161  { 700, 12 << WM831X_CHG_FAST_ILIM_SHIFT },
162  { 800, 13 << WM831X_CHG_FAST_ILIM_SHIFT },
163  { 900, 14 << WM831X_CHG_FAST_ILIM_SHIFT },
164  { 1000, 15 << WM831X_CHG_FAST_ILIM_SHIFT },
165 };
166 
167 static struct chg_map eoc_iterms[] = {
168  { 20, 0 << WM831X_CHG_ITERM_SHIFT },
169  { 30, 1 << WM831X_CHG_ITERM_SHIFT },
170  { 40, 2 << WM831X_CHG_ITERM_SHIFT },
171  { 50, 3 << WM831X_CHG_ITERM_SHIFT },
172  { 60, 4 << WM831X_CHG_ITERM_SHIFT },
173  { 70, 5 << WM831X_CHG_ITERM_SHIFT },
174  { 80, 6 << WM831X_CHG_ITERM_SHIFT },
175  { 90, 7 << WM831X_CHG_ITERM_SHIFT },
176 };
177 
178 static struct chg_map chg_times[] = {
179  { 60, 0 << WM831X_CHG_TIME_SHIFT },
180  { 90, 1 << WM831X_CHG_TIME_SHIFT },
181  { 120, 2 << WM831X_CHG_TIME_SHIFT },
182  { 150, 3 << WM831X_CHG_TIME_SHIFT },
183  { 180, 4 << WM831X_CHG_TIME_SHIFT },
184  { 210, 5 << WM831X_CHG_TIME_SHIFT },
185  { 240, 6 << WM831X_CHG_TIME_SHIFT },
186  { 270, 7 << WM831X_CHG_TIME_SHIFT },
187  { 300, 8 << WM831X_CHG_TIME_SHIFT },
188  { 330, 9 << WM831X_CHG_TIME_SHIFT },
189  { 360, 10 << WM831X_CHG_TIME_SHIFT },
190  { 390, 11 << WM831X_CHG_TIME_SHIFT },
191  { 420, 12 << WM831X_CHG_TIME_SHIFT },
192  { 450, 13 << WM831X_CHG_TIME_SHIFT },
193  { 480, 14 << WM831X_CHG_TIME_SHIFT },
194  { 510, 15 << WM831X_CHG_TIME_SHIFT },
195 };
196 
197 static void wm831x_battey_apply_config(struct wm831x *wm831x,
198  struct chg_map *map, int count, int val,
199  int *reg, const char *name,
200  const char *units)
201 {
202  int i;
203 
204  for (i = 0; i < count; i++)
205  if (val == map[i].val)
206  break;
207  if (i == count) {
208  dev_err(wm831x->dev, "Invalid %s %d%s\n",
209  name, val, units);
210  } else {
211  *reg |= map[i].reg_val;
212  dev_dbg(wm831x->dev, "Set %s of %d%s\n", name, val, units);
213  }
214 }
215 
216 static void wm831x_config_battery(struct wm831x *wm831x)
217 {
218  struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
219  struct wm831x_battery_pdata *pdata;
220  int ret, reg1, reg2;
221 
222  if (!wm831x_pdata || !wm831x_pdata->battery) {
223  dev_warn(wm831x->dev,
224  "No battery charger configuration\n");
225  return;
226  }
227 
228  pdata = wm831x_pdata->battery;
229 
230  reg1 = 0;
231  reg2 = 0;
232 
233  if (!pdata->enable) {
234  dev_info(wm831x->dev, "Battery charger disabled\n");
235  return;
236  }
237 
238  reg1 |= WM831X_CHG_ENA;
239  if (pdata->off_mask)
240  reg2 |= WM831X_CHG_OFF_MSK;
241  if (pdata->fast_enable)
242  reg1 |= WM831X_CHG_FAST;
243 
244  wm831x_battey_apply_config(wm831x, trickle_ilims,
245  ARRAY_SIZE(trickle_ilims),
246  pdata->trickle_ilim, &reg2,
247  "trickle charge current limit", "mA");
248 
249  wm831x_battey_apply_config(wm831x, vsels, ARRAY_SIZE(vsels),
250  pdata->vsel, &reg2,
251  "target voltage", "mV");
252 
253  wm831x_battey_apply_config(wm831x, fast_ilims, ARRAY_SIZE(fast_ilims),
254  pdata->fast_ilim, &reg2,
255  "fast charge current limit", "mA");
256 
257  wm831x_battey_apply_config(wm831x, eoc_iterms, ARRAY_SIZE(eoc_iterms),
258  pdata->eoc_iterm, &reg1,
259  "end of charge current threshold", "mA");
260 
261  wm831x_battey_apply_config(wm831x, chg_times, ARRAY_SIZE(chg_times),
262  pdata->timeout, &reg2,
263  "charger timeout", "min");
264 
265  ret = wm831x_reg_unlock(wm831x);
266  if (ret != 0) {
267  dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
268  return;
269  }
270 
275  reg1);
276  if (ret != 0)
277  dev_err(wm831x->dev, "Failed to set charger control 1: %d\n",
278  ret);
279 
286  reg2);
287  if (ret != 0)
288  dev_err(wm831x->dev, "Failed to set charger control 2: %d\n",
289  ret);
290 
291  wm831x_reg_lock(wm831x);
292 }
293 
294 static int wm831x_bat_check_status(struct wm831x *wm831x, int *status)
295 {
296  int ret;
297 
298  ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
299  if (ret < 0)
300  return ret;
301 
302  if (ret & WM831X_PWR_SRC_BATT) {
304  return 0;
305  }
306 
307  ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
308  if (ret < 0)
309  return ret;
310 
311  switch (ret & WM831X_CHG_STATE_MASK) {
314  break;
318  break;
319 
320  default:
321  *status = POWER_SUPPLY_STATUS_UNKNOWN;
322  break;
323  }
324 
325  return 0;
326 }
327 
328 static int wm831x_bat_check_type(struct wm831x *wm831x, int *type)
329 {
330  int ret;
331 
332  ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
333  if (ret < 0)
334  return ret;
335 
336  switch (ret & WM831X_CHG_STATE_MASK) {
340  break;
344  break;
345  default:
347  break;
348  }
349 
350  return 0;
351 }
352 
353 static int wm831x_bat_check_health(struct wm831x *wm831x, int *health)
354 {
355  int ret;
356 
357  ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
358  if (ret < 0)
359  return ret;
360 
361  if (ret & WM831X_BATT_HOT_STS) {
363  return 0;
364  }
365 
366  if (ret & WM831X_BATT_COLD_STS) {
367  *health = POWER_SUPPLY_HEALTH_COLD;
368  return 0;
369  }
370 
371  if (ret & WM831X_BATT_OV_STS) {
373  return 0;
374  }
375 
376  switch (ret & WM831X_CHG_STATE_MASK) {
380  break;
383  break;
384  default:
385  *health = POWER_SUPPLY_HEALTH_GOOD;
386  break;
387  }
388 
389  return 0;
390 }
391 
392 static int wm831x_bat_get_prop(struct power_supply *psy,
393  enum power_supply_property psp,
394  union power_supply_propval *val)
395 {
396  struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
397  struct wm831x *wm831x = wm831x_power->wm831x;
398  int ret = 0;
399 
400  switch (psp) {
402  ret = wm831x_bat_check_status(wm831x, &val->intval);
403  break;
405  ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT,
406  val);
407  break;
409  ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
410  break;
412  ret = wm831x_bat_check_health(wm831x, &val->intval);
413  break;
415  ret = wm831x_bat_check_type(wm831x, &val->intval);
416  break;
417  default:
418  ret = -EINVAL;
419  break;
420  }
421 
422  return ret;
423 }
424 
425 static enum power_supply_property wm831x_bat_props[] = {
431 };
432 
433 static const char *wm831x_bat_irqs[] = {
434  "BATT HOT",
435  "BATT COLD",
436  "BATT FAIL",
437  "OV",
438  "END",
439  "TO",
440  "MODE",
441  "START",
442 };
443 
444 static irqreturn_t wm831x_bat_irq(int irq, void *data)
445 {
446  struct wm831x_power *wm831x_power = data;
447  struct wm831x *wm831x = wm831x_power->wm831x;
448 
449  dev_dbg(wm831x->dev, "Battery status changed: %d\n", irq);
450 
451  /* The battery charger is autonomous so we don't need to do
452  * anything except kick user space */
453  if (wm831x_power->have_battery)
454  power_supply_changed(&wm831x_power->battery);
455 
456  return IRQ_HANDLED;
457 }
458 
459 
460 /*********************************************************************
461  * Initialisation
462  *********************************************************************/
463 
464 static irqreturn_t wm831x_syslo_irq(int irq, void *data)
465 {
466  struct wm831x_power *wm831x_power = data;
467  struct wm831x *wm831x = wm831x_power->wm831x;
468 
469  /* Not much we can actually *do* but tell people for
470  * posterity, we're probably about to run out of power. */
471  dev_crit(wm831x->dev, "SYSVDD under voltage\n");
472 
473  return IRQ_HANDLED;
474 }
475 
476 static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
477 {
478  struct wm831x_power *wm831x_power = data;
479  struct wm831x *wm831x = wm831x_power->wm831x;
480 
481  dev_dbg(wm831x->dev, "Power source changed\n");
482 
483  /* Just notify for everything - little harm in overnotifying. */
484  if (wm831x_power->have_battery)
485  power_supply_changed(&wm831x_power->battery);
486  power_supply_changed(&wm831x_power->usb);
487  power_supply_changed(&wm831x_power->wall);
488 
489  return IRQ_HANDLED;
490 }
491 
492 static __devinit int wm831x_power_probe(struct platform_device *pdev)
493 {
494  struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
495  struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
496  struct wm831x_power *power;
497  struct power_supply *usb;
498  struct power_supply *battery;
499  struct power_supply *wall;
500  int ret, irq, i;
501 
502  power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL);
503  if (power == NULL)
504  return -ENOMEM;
505 
506  power->wm831x = wm831x;
507  platform_set_drvdata(pdev, power);
508 
509  usb = &power->usb;
510  battery = &power->battery;
511  wall = &power->wall;
512 
513  if (wm831x_pdata && wm831x_pdata->wm831x_num) {
514  snprintf(power->wall_name, sizeof(power->wall_name),
515  "wm831x-wall.%d", wm831x_pdata->wm831x_num);
516  snprintf(power->battery_name, sizeof(power->wall_name),
517  "wm831x-battery.%d", wm831x_pdata->wm831x_num);
518  snprintf(power->usb_name, sizeof(power->wall_name),
519  "wm831x-usb.%d", wm831x_pdata->wm831x_num);
520  } else {
521  snprintf(power->wall_name, sizeof(power->wall_name),
522  "wm831x-wall");
523  snprintf(power->battery_name, sizeof(power->wall_name),
524  "wm831x-battery");
525  snprintf(power->usb_name, sizeof(power->wall_name),
526  "wm831x-usb");
527  }
528 
529  /* We ignore configuration failures since we can still read back
530  * the status without enabling the charger.
531  */
532  wm831x_config_battery(wm831x);
533 
534  wall->name = power->wall_name;
536  wall->properties = wm831x_wall_props;
537  wall->num_properties = ARRAY_SIZE(wm831x_wall_props);
538  wall->get_property = wm831x_wall_get_prop;
539  ret = power_supply_register(&pdev->dev, wall);
540  if (ret)
541  goto err_kmalloc;
542 
543  usb->name = power->usb_name,
545  usb->properties = wm831x_usb_props;
546  usb->num_properties = ARRAY_SIZE(wm831x_usb_props);
547  usb->get_property = wm831x_usb_get_prop;
548  ret = power_supply_register(&pdev->dev, usb);
549  if (ret)
550  goto err_wall;
551 
553  if (ret < 0)
554  goto err_wall;
555  power->have_battery = ret & WM831X_CHG_ENA;
556 
557  if (power->have_battery) {
558  battery->name = power->battery_name;
559  battery->properties = wm831x_bat_props;
560  battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
561  battery->get_property = wm831x_bat_get_prop;
562  battery->use_for_apm = 1;
563  ret = power_supply_register(&pdev->dev, battery);
564  if (ret)
565  goto err_usb;
566  }
567 
568  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
569  ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
570  IRQF_TRIGGER_RISING, "System power low",
571  power);
572  if (ret != 0) {
573  dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
574  irq, ret);
575  goto err_battery;
576  }
577 
578  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
579  ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
580  IRQF_TRIGGER_RISING, "Power source",
581  power);
582  if (ret != 0) {
583  dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n",
584  irq, ret);
585  goto err_syslo;
586  }
587 
588  for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
589  irq = wm831x_irq(wm831x,
591  wm831x_bat_irqs[i]));
592  ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
594  wm831x_bat_irqs[i],
595  power);
596  if (ret != 0) {
597  dev_err(&pdev->dev,
598  "Failed to request %s IRQ %d: %d\n",
599  wm831x_bat_irqs[i], irq, ret);
600  goto err_bat_irq;
601  }
602  }
603 
604  return ret;
605 
606 err_bat_irq:
607  for (; i >= 0; i--) {
608  irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
609  free_irq(irq, power);
610  }
611  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
612  free_irq(irq, power);
613 err_syslo:
614  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
615  free_irq(irq, power);
616 err_battery:
617  if (power->have_battery)
618  power_supply_unregister(battery);
619 err_usb:
621 err_wall:
623 err_kmalloc:
624  kfree(power);
625  return ret;
626 }
627 
628 static __devexit int wm831x_power_remove(struct platform_device *pdev)
629 {
630  struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
631  struct wm831x *wm831x = wm831x_power->wm831x;
632  int irq, i;
633 
634  for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
635  irq = wm831x_irq(wm831x,
637  wm831x_bat_irqs[i]));
638  free_irq(irq, wm831x_power);
639  }
640 
641  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
642  free_irq(irq, wm831x_power);
643 
644  irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
645  free_irq(irq, wm831x_power);
646 
647  if (wm831x_power->have_battery)
648  power_supply_unregister(&wm831x_power->battery);
649  power_supply_unregister(&wm831x_power->wall);
650  power_supply_unregister(&wm831x_power->usb);
651  kfree(wm831x_power);
652  return 0;
653 }
654 
655 static struct platform_driver wm831x_power_driver = {
656  .probe = wm831x_power_probe,
657  .remove = __devexit_p(wm831x_power_remove),
658  .driver = {
659  .name = "wm831x-power",
660  },
661 };
662 
663 module_platform_driver(wm831x_power_driver);
664 
665 MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
666 MODULE_AUTHOR("Mark Brown <[email protected]>");
667 MODULE_LICENSE("GPL");
668 MODULE_ALIAS("platform:wm831x-power");