|
@@ -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
|
|
@@ -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 },
|
|
|
};
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
@@ -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 ... */
|
|
@@ -616,6 +618,8 @@ 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,
|
|
@@ -623,9 +627,10 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -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);
|
|
|
|
|
@@ -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 */
|
|
@@ -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,
|
|
@@ -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()) {
|
|
@@ -810,46 +836,55 @@ 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);
|
|
|
}
|
|
@@ -857,72 +892,152 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|
|
/* 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 &&
|
|
@@ -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);
|