Skip to content

Commit

Permalink
mfd: Add phoenix lite (twl6025) support to twl6030
Browse files Browse the repository at this point in the history
Phoenix Lite is based on the twl6030 family of PMICs. It has mostly the
same feature set of twl6030 but with small changes. The codec block has
also been removed. It also has a new charger block and new features in
its ADC block. VUSB handling also differs.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Graeme Gregory authored and Samuel Ortiz committed May 26, 2011
1 parent 586e1a1 commit 521d8ec
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 37 deletions.
190 changes: 153 additions & 37 deletions drivers/mfd/twl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
#define TWL6030_BASEADD_GASGAUGE 0x00C0
#define TWL6030_BASEADD_PIH 0x00D0
#define TWL6030_BASEADD_CHARGER 0x00E0
#define TWL6025_BASEADD_CHARGER 0x00DA

/* subchip/slave 2 0x4A - DFT */
#define TWL6030_BASEADD_DIEID 0x00C0
Expand Down Expand Up @@ -331,6 +332,7 @@ static struct twl_mapping twl6030_map[] = {

{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
};

/*----------------------------------------------------------------------*/
Expand Down Expand Up @@ -604,7 +606,7 @@ static inline struct device *add_child(unsigned chip, const char *name,
static struct device *
add_regulator_linked(int num, struct regulator_init_data *pdata,
struct regulator_consumer_supply *consumers,
unsigned num_consumers)
unsigned num_consumers, unsigned long features)
{
unsigned sub_chip_id;
/* regulator framework demands init_data ... */
Expand All @@ -616,16 +618,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
pdata->num_consumer_supplies = num_consumers;
}

pdata->driver_data = (void *)features;

/* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
return add_numbered_child(sub_chip_id, "twl_reg", num,
pdata, sizeof(*pdata), false, 0, 0);
}

static struct device *
add_regulator(int num, struct regulator_init_data *pdata)
add_regulator(int num, struct regulator_init_data *pdata,
unsigned long features)
{
return add_regulator_linked(num, pdata, NULL, 0);
return add_regulator_linked(num, pdata, NULL, 0, features);
}

/*
Expand Down Expand Up @@ -705,17 +710,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
};

child = add_regulator_linked(TWL4030_REG_VUSB1V5,
&usb_fixed, &usb1v5, 1);
&usb_fixed, &usb1v5, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator_linked(TWL4030_REG_VUSB1V8,
&usb_fixed, &usb1v8, 1);
&usb_fixed, &usb1v8, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator_linked(TWL4030_REG_VUSB3V1,
&usb_fixed, &usb3v1, 1);
&usb_fixed, &usb3v1, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

Expand All @@ -740,9 +748,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
}
if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {

static struct regulator_consumer_supply usb3v3 = {
.supply = "vusb",
};
static struct regulator_consumer_supply usb3v3;
int regulator;

if (twl_has_regulator()) {
/* this is a template that gets copied */
Expand All @@ -755,12 +762,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
| REGULATOR_CHANGE_STATUS,
};

child = add_regulator_linked(TWL6030_REG_VUSB,
&usb_fixed, &usb3v3, 1);
if (features & TWL6025_SUBCLASS) {
usb3v3.supply = "ldousb";
regulator = TWL6025_REG_LDOUSB;
} else {
usb3v3.supply = "vusb";
regulator = TWL6030_REG_VUSB;
}
child = add_regulator_linked(regulator, &usb_fixed,
&usb3v3, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}

pdata->usb->features = features;

child = add_child(0, "twl6030_usb",
pdata->usb, sizeof(*pdata->usb),
true,
Expand All @@ -773,7 +790,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* we need to connect regulators to this transceiver */
if (twl_has_regulator() && child)
usb3v3.dev = child;
} else if (twl_has_regulator() && twl_class_is_6030()) {
if (features & TWL6025_SUBCLASS)
child = add_regulator(TWL6025_REG_LDOUSB,
pdata->ldousb, features);
else
child = add_regulator(TWL6030_REG_VUSB,
pdata->vusb, features);

if (IS_ERR(child))
return PTR_ERR(child);
}

if (twl_has_watchdog() && twl_class_is_4030()) {
Expand Down Expand Up @@ -810,119 +836,208 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)

/* twl4030 regulators */
if (twl_has_regulator() && twl_class_is_4030()) {
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VIO, pdata->vio);
child = add_regulator(TWL4030_REG_VIO, pdata->vio,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1);
child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2);
child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator((features & TWL4030_VAUX2)
? TWL4030_REG_VAUX2_4030
: TWL4030_REG_VAUX2,
pdata->vaux2);
pdata->vaux2, features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1);
child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2);
child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig);
child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}

/* maybe add LDOs that are omitted on cost-reduced parts */
if (twl_has_regulator() && !(features & TPS_SUBSET)
&& twl_class_is_4030()) {
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}

/* twl6030 regulators */
if (twl_has_regulator() && twl_class_is_6030() &&
!(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}

/* 6030 and 6025 share this regulator */
if (twl_has_regulator() && twl_class_is_6030()) {
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc);
child = add_regulator(TWL6030_REG_VANA, pdata->vana,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}

/* twl6025 regulators */
if (twl_has_regulator() && twl_class_is_6030() &&
(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VPP, pdata->vpp);
child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim);
child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VANA, pdata->vana);
child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio);
child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VDAC, pdata->vdac);
child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2);
child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg);
child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
features);
if (IS_ERR(child))
return PTR_ERR(child);

child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
features);
if (IS_ERR(child))
return PTR_ERR(child);

}

if (twl_has_bci() && pdata->bci &&
Expand Down Expand Up @@ -1170,6 +1285,7 @@ static const struct i2c_device_id twl_ids[] = {
{ "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
{ "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
{ "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */
{ "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(i2c, twl_ids);
Expand Down
Loading

0 comments on commit 521d8ec

Please sign in to comment.