aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-11-30 18:43:58 -0500
committerSamuel Ortiz <samuel@sortiz.org>2009-01-04 06:17:39 -0500
commitdad759ff8ba79927766e3f0159bfc5fb6de0f982 (patch)
tree06849276db93d8893d763175b8d3acb4b2b5e2f8 /drivers/mfd
parent67460a7c26271fd7a32e5d51b2c806a84ce78a62 (diff)
mfd: twl4030: create some regulator devices
Initial code to create twl4030 voltage regulator devices, using the new regulator framework. Note that this now starts to care what name is used to declare the TWL chip: - TWL4030 is the "old" chip; newer ones have a bigger variety of VAUX2 voltages. - TWL5030 is the core "new" chip; TPS65950 is its catalog version. - The TPS65930 and TPS65920 are cost-reduced catalog versions of TWL5030 parts ... fewer regulators, no battery charger, etc. Board-specific regulator configuration should be provided, listing which regulators are used and their constraints (e.g. 1.8V only). Code that could ("should"?) leverage the regulator stuff includes TWL4030 USB transceiver support and MMC glue, LCD support for the 3430SDP and Labrador boards, and S-Video output. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Samuel Ortiz <sameo@openedhand.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/twl4030-core.c174
1 files changed, 164 insertions, 10 deletions
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index f5486cce86f4..8ab9ee8543a6 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -33,6 +33,8 @@
33#include <linux/clk.h> 33#include <linux/clk.h>
34#include <linux/err.h> 34#include <linux/err.h>
35 35
36#include <linux/regulator/machine.h>
37
36#include <linux/i2c.h> 38#include <linux/i2c.h>
37#include <linux/i2c/twl4030.h> 39#include <linux/i2c/twl4030.h>
38 40
@@ -71,6 +73,13 @@
71#define twl_has_gpio() false 73#define twl_has_gpio() false
72#endif 74#endif
73 75
76#if defined(CONFIG_REGULATOR_TWL4030) \
77 || defined(CONFIG_REGULATOR_TWL4030_MODULE)
78#define twl_has_regulator() true
79#else
80#define twl_has_regulator() false
81#endif
82
74#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) 83#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
75#define twl_has_madc() true 84#define twl_has_madc() true
76#else 85#else
@@ -149,6 +158,10 @@
149#define HIGH_PERF_SQ (1 << 3) 158#define HIGH_PERF_SQ (1 << 3)
150 159
151 160
161/* chip-specific feature flags, for i2c_device_id.driver_data */
162#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
163#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
164
152/*----------------------------------------------------------------------*/ 165/*----------------------------------------------------------------------*/
153 166
154/* is driver active, bound to a chip? */ 167/* is driver active, bound to a chip? */
@@ -352,7 +365,8 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8);
352 365
353/*----------------------------------------------------------------------*/ 366/*----------------------------------------------------------------------*/
354 367
355static struct device *add_child(unsigned chip, const char *name, 368static struct device *
369add_numbered_child(unsigned chip, const char *name, int num,
356 void *pdata, unsigned pdata_len, 370 void *pdata, unsigned pdata_len,
357 bool can_wakeup, int irq0, int irq1) 371 bool can_wakeup, int irq0, int irq1)
358{ 372{
@@ -360,7 +374,7 @@ static struct device *add_child(unsigned chip, const char *name,
360 struct twl4030_client *twl = &twl4030_modules[chip]; 374 struct twl4030_client *twl = &twl4030_modules[chip];
361 int status; 375 int status;
362 376
363 pdev = platform_device_alloc(name, -1); 377 pdev = platform_device_alloc(name, num);
364 if (!pdev) { 378 if (!pdev) {
365 dev_dbg(&twl->client->dev, "can't alloc dev\n"); 379 dev_dbg(&twl->client->dev, "can't alloc dev\n");
366 status = -ENOMEM; 380 status = -ENOMEM;
@@ -402,17 +416,52 @@ err:
402 return &pdev->dev; 416 return &pdev->dev;
403} 417}
404 418
419static inline struct device *add_child(unsigned chip, const char *name,
420 void *pdata, unsigned pdata_len,
421 bool can_wakeup, int irq0, int irq1)
422{
423 return add_numbered_child(chip, name, -1, pdata, pdata_len,
424 can_wakeup, irq0, irq1);
425}
426
427static struct device *
428add_regulator_linked(int num, struct regulator_init_data *pdata,
429 struct regulator_consumer_supply *consumers,
430 unsigned num_consumers)
431{
432 /* regulator framework demands init_data ... */
433 if (!pdata)
434 return NULL;
435
436 if (consumers && !pdata->consumer_supplies) {
437 pdata->consumer_supplies = consumers;
438 pdata->num_consumer_supplies = num_consumers;
439 }
440
441 /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
442 return add_numbered_child(3, "twl4030_reg", num,
443 pdata, sizeof(*pdata), false, 0, 0);
444}
445
446static struct device *
447add_regulator(int num, struct regulator_init_data *pdata)
448{
449 return add_regulator_linked(num, pdata, NULL, 0);
450}
451
405/* 452/*
406 * NOTE: We know the first 8 IRQs after pdata->base_irq are 453 * NOTE: We know the first 8 IRQs after pdata->base_irq are
407 * for the PIH, and the next are for the PWR_INT SIH, since 454 * for the PIH, and the next are for the PWR_INT SIH, since
408 * that's how twl_init_irq() sets things up. 455 * that's how twl_init_irq() sets things up.
409 */ 456 */
410 457
411static int add_children(struct twl4030_platform_data *pdata) 458static int
459add_children(struct twl4030_platform_data *pdata, unsigned long features)
412{ 460{
413 struct device *child; 461 struct device *child;
462 struct device *usb_transceiver = NULL;
414 463
415 if (twl_has_bci() && pdata->bci) { 464 if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) {
416 child = add_child(3, "twl4030_bci", 465 child = add_child(3, "twl4030_bci",
417 pdata->bci, sizeof(*pdata->bci), 466 pdata->bci, sizeof(*pdata->bci),
418 false, 467 false,
@@ -469,6 +518,111 @@ static int add_children(struct twl4030_platform_data *pdata)
469 pdata->irq_base + 8 + 2, pdata->irq_base + 4); 518 pdata->irq_base + 8 + 2, pdata->irq_base + 4);
470 if (IS_ERR(child)) 519 if (IS_ERR(child))
471 return PTR_ERR(child); 520 return PTR_ERR(child);
521
522 /* we need to connect regulators to this transceiver */
523 usb_transceiver = child;
524 }
525
526 if (twl_has_regulator()) {
527 /*
528 child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
529 if (IS_ERR(child))
530 return PTR_ERR(child);
531 */
532
533 child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
534 if (IS_ERR(child))
535 return PTR_ERR(child);
536
537 child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
538 if (IS_ERR(child))
539 return PTR_ERR(child);
540
541 child = add_regulator((features & TWL4030_VAUX2)
542 ? TWL4030_REG_VAUX2_4030
543 : TWL4030_REG_VAUX2,
544 pdata->vaux2);
545 if (IS_ERR(child))
546 return PTR_ERR(child);
547 }
548
549 if (twl_has_regulator() && usb_transceiver) {
550 static struct regulator_consumer_supply usb1v5 = {
551 .supply = "usb1v5",
552 };
553 static struct regulator_consumer_supply usb1v8 = {
554 .supply = "usb1v8",
555 };
556 static struct regulator_consumer_supply usb3v1 = {
557 .supply = "usb3v1",
558 };
559 static struct regulator_consumer_supply usbcp = {
560 .supply = "usbcp",
561 };
562
563 /* this is a template that gets copied */
564 struct regulator_init_data usb_fixed = {
565 .constraints.valid_modes_mask =
566 REGULATOR_MODE_NORMAL
567 | REGULATOR_MODE_STANDBY,
568 .constraints.valid_ops_mask =
569 REGULATOR_CHANGE_MODE
570 | REGULATOR_CHANGE_STATUS,
571 };
572
573 usb1v5.dev = usb_transceiver;
574 usb1v8.dev = usb_transceiver;
575 usb3v1.dev = usb_transceiver;
576 usbcp.dev = usb_transceiver;
577
578 child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed,
579 &usb1v5, 1);
580 if (IS_ERR(child))
581 return PTR_ERR(child);
582
583 child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed,
584 &usb1v8, 1);
585 if (IS_ERR(child))
586 return PTR_ERR(child);
587
588 child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed,
589 &usb3v1, 1);
590 if (IS_ERR(child))
591 return PTR_ERR(child);
592
593 child = add_regulator_linked(TWL4030_REG_VUSBCP, &usb_fixed,
594 &usbcp, 1);
595 if (IS_ERR(child))
596 return PTR_ERR(child);
597 }
598
599 /* maybe add LDOs that are omitted on cost-reduced parts */
600 if (twl_has_regulator() && !(features & TPS_SUBSET)) {
601 /*
602 child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
603 if (IS_ERR(child))
604 return PTR_ERR(child);
605 */
606
607 child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
608 if (IS_ERR(child))
609 return PTR_ERR(child);
610
611 child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
612 if (IS_ERR(child))
613 return PTR_ERR(child);
614
615 child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
616 if (IS_ERR(child))
617 return PTR_ERR(child);
618
619 child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
620 if (IS_ERR(child))
621 return PTR_ERR(child);
622
623 child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
624 if (IS_ERR(child))
625 return PTR_ERR(child);
472 } 626 }
473 627
474 return 0; 628 return 0;
@@ -632,7 +786,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
632 goto fail; 786 goto fail;
633 } 787 }
634 788
635 status = add_children(pdata); 789 status = add_children(pdata, id->driver_data);
636fail: 790fail:
637 if (status < 0) 791 if (status < 0)
638 twl4030_remove(client); 792 twl4030_remove(client);
@@ -640,11 +794,11 @@ fail:
640} 794}
641 795
642static const struct i2c_device_id twl4030_ids[] = { 796static const struct i2c_device_id twl4030_ids[] = {
643 { "twl4030", 0 }, /* "Triton 2" */ 797 { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */
644 { "tps65950", 0 }, /* catalog version of twl4030 */ 798 { "twl5030", 0 }, /* T2 updated */
645 { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */ 799 { "tps65950", 0 }, /* catalog version of twl5030 */
646 { "tps65920", 0 }, /* fewer LDOs; no codec or charger */ 800 { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
647 { "twl5030", 0 }, /* T2 updated */ 801 { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
648 { /* end of list */ }, 802 { /* end of list */ },
649}; 803};
650MODULE_DEVICE_TABLE(i2c, twl4030_ids); 804MODULE_DEVICE_TABLE(i2c, twl4030_ids);