summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel JAOUEN <michel.jaouen@stericsson.com>2012-01-27 17:47:21 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 10:59:30 +0200
commiteb244486c4a709fcd2306f2f7d3851b57898543e (patch)
treec816c208833611b5af1de21531bac88516d072c6
parent2c82676cdc339dc5d70b94771c700db4fd3aad36 (diff)
drivers: regulator ab9540
ST-Ericsson ID: 409625 ST-Ericsson FOSS-OUT ID: trivial ST-Ericsson Linux next: NA Change-Id: I8d6135e8d4920a801a2836435479cce575c27a5e Signed-off-by: Maxime Coquelin <maxime.coquelin@st-ericsson.com> Signed-off-by: Alex MACRO <alex.macro@stericsson.com> Signed-off-by: Michel JAOUEN <michel.jaouen@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46634
-rw-r--r--drivers/regulator/ab8500-debug.c301
-rw-r--r--drivers/regulator/ab8500.c624
2 files changed, 874 insertions, 51 deletions
diff --git a/drivers/regulator/ab8500-debug.c b/drivers/regulator/ab8500-debug.c
index 0375c616027..010dfd2f7e3 100644
--- a/drivers/regulator/ab8500-debug.c
+++ b/drivers/regulator/ab8500-debug.c
@@ -15,6 +15,7 @@
#include <linux/kobject.h>
#include <linux/slab.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/ab8500-debug.h>
#include <linux/io.h>
#include <mach/db8500-regs.h> /* U8500_BACKUPRAM1_BASE */
@@ -75,6 +76,7 @@ enum ab8500_register_id {
AB8500_REGU_SW_HP_REQ_VALID2,
AB8500_REGU_SYSCLK_REQ1_VALID,
AB8500_REGU_SYSCLK_REQ2_VALID,
+ AB9540_REGU_VAUX4_REQ_VALID,
AB8500_REGU_MISC1,
AB8500_REGU_OTG_SUPPLY_CTRL,
AB8500_REGU_VUSB_CTRL,
@@ -97,6 +99,9 @@ enum ab8500_register_id {
AB8500_REGU_VAPE_SEL1,
AB8500_REGU_VAPE_SEL2,
AB8500_REGU_VAPE_SEL3,
+ AB9540_REGU_VAUX4_REQ_CTRL,
+ AB9540_REGU_VAUX4_REGU,
+ AB9540_REGU_VAUX4_SEL,
AB8500_REGU_VBB_SEL1,
AB8500_REGU_VBB_SEL2,
AB8500_REGU_VSMPS1_SEL1,
@@ -117,6 +122,7 @@ enum ab8500_register_id {
AB8500_REGU_VMOD_SEL2,
AB8500_REGU_CTRL_DISCH,
AB8500_REGU_CTRL_DISCH2,
+ AB9540_REGU_CTRL_DISCH3,
AB8500_OTHER_SYSCLK_CTRL, /* Other */
AB8500_OTHER_VSIM_SYSCLK_CTRL, /* Other */
AB8500_OTHER_SYSULPCLK_CTRL1, /* Other */
@@ -127,6 +133,7 @@ struct ab8500_register {
const char *name;
u8 bank;
u8 addr;
+ u8 unavailable; /* Used to flag when AB doesn't support a register */
};
static struct ab8500_register
@@ -201,6 +208,12 @@ static struct ab8500_register
.bank = 0x03,
.addr = 0x10,
},
+ [AB9540_REGU_VAUX4_REQ_VALID] = {
+ .name = "ReguVaux4ReqValid",
+ .bank = 0x03,
+ .addr = 0x11,
+ .unavailable = true, /* ab9540 register */
+ },
[AB8500_REGU_MISC1] = {
.name = "ReguMisc1",
.bank = 0x03,
@@ -311,6 +324,24 @@ static struct ab8500_register
.bank = 0x04,
.addr = 0x10,
},
+ [AB9540_REGU_VAUX4_REQ_CTRL] = {
+ .name = "Vaux4ReqCtrl",
+ .bank = 0x04,
+ .addr = 0x2d,
+ .unavailable = true, /* ab9540 register */
+ },
+ [AB9540_REGU_VAUX4_REGU] = {
+ .name = "Vaux4Regu",
+ .bank = 0x04,
+ .addr = 0x2e,
+ .unavailable = true, /* ab9540 register */
+ },
+ [AB9540_REGU_VAUX4_SEL] = {
+ .name = "Vaux4Sel",
+ .bank = 0x04,
+ .addr = 0x2f,
+ .unavailable = true, /* ab9540 register */
+ },
[AB8500_REGU_VBB_SEL1] = {
.name = "VBBSel1",
.bank = 0x04,
@@ -411,6 +442,12 @@ static struct ab8500_register
.bank = 0x04,
.addr = 0x44,
},
+ [AB9540_REGU_CTRL_DISCH3] = {
+ .name = "ReguCtrlDisch3",
+ .bank = 0x04,
+ .addr = 0x48,
+ .unavailable = true, /* ab9540 register */
+ },
/* Outside regulator banks */
[AB8500_OTHER_SYSCLK_CTRL] = {
.name = "SysClkCtrl",
@@ -429,6 +466,67 @@ static struct ab8500_register
},
};
+struct ab9540_register_update {
+ /* Identity of register to be updated */
+ u8 bank;
+ u8 addr;
+ /* New value for unavailable flag */
+ u8 unavailable;
+};
+
+static const struct ab9540_register_update ab9540_update[] = {
+ /* AB8500 register which is unavailable to AB9540 */
+ /* AB8500_REGU_VREF_DDR */
+ {
+ .bank = 0x04,
+ .addr = 0x07,
+ .unavailable = true,
+ },
+
+ /* Registers which were not available to AB8500 but are on the
+ * AB9540. */
+ /* AB9540_REGU_VAUX4_REQ_VALID */
+ {
+ .bank = 0x03,
+ .addr = 0x11,
+ },
+ /* AB9540_REGU_VAUX4_REQ_CTRL */
+ {
+ .bank = 0x04,
+ .addr = 0x2d,
+ },
+ /* AB9540_REGU_VAUX4_REGU */
+ {
+ .bank = 0x04,
+ .addr = 0x2e,
+ },
+ /* AB9540_REGU_VAUX4_SEL */
+ {
+ .bank = 0x04,
+ .addr = 0x2f,
+ },
+ /* AB9540_REGU_CTRL_DISCH3 */
+ {
+ .bank = 0x04,
+ .addr = 0x48,
+ },
+};
+
+static void ab9540_registers_update(void)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < NUM_AB8500_REGISTER; i++)
+ for (j = 0; j < ARRAY_SIZE(ab9540_update); j++)
+ if (ab8500_register[i].bank == ab9540_update[j].bank &&
+ ab8500_register[i].addr == ab9540_update[j].addr) {
+ ab8500_register[i].unavailable =
+ ab9540_update[j].unavailable;
+ break;
+ }
+}
+
static u8 ab8500_register_state[NUM_REGULATOR_STATE][NUM_AB8500_REGISTER];
static bool ab8500_register_state_saved[NUM_REGULATOR_STATE];
static bool ab8500_register_state_save = true;
@@ -452,6 +550,9 @@ static int ab8500_regulator_record_state(int state)
ab8500_register_state_saved[state] = true;
for (i = 1; i < NUM_AB8500_REGISTER; i++) {
+ if (ab8500_register[i].unavailable)
+ continue;
+
ret = abx500_get_register_interruptible(dev,
ab8500_register[i].bank,
ab8500_register[i].addr,
@@ -519,6 +620,9 @@ static int ab8500_regulator_dump_print(struct seq_file *s, void *p)
/* dump registers */
for (reg_id = 1; reg_id < NUM_AB8500_REGISTER; reg_id++) {
+ if (ab8500_register[reg_id].unavailable)
+ continue;
+
err = seq_printf(s, "%22s 0x%02x%02x:",
ab8500_register[reg_id].name,
ab8500_register[reg_id].bank,
@@ -579,6 +683,7 @@ enum ab8500_regulator_id {
AB8500_VAUX1,
AB8500_VAUX2,
AB8500_VAUX3,
+ AB9540_VAUX4,
AB8500_VINTCORE,
AB8500_VTVOUT,
AB8500_VAUDIO,
@@ -623,6 +728,7 @@ struct regulator_volt_range {
* @vsel_mask
* @vsel_range
* @vsel_range_len
+ * @unavailable {true/false depending on whether AB supports the regulator}
*/
struct ab8500_regulator {
const char *name;
@@ -641,6 +747,7 @@ struct ab8500_regulator {
u8 vsel_mask[3];
struct regulator_volt_range const *vsel_range[3];
int vsel_range_len[3];
+ u8 unavailable;
};
static const char *update_val_name[] = {
@@ -660,25 +767,50 @@ static const char *hw_mode_val_name[] = {
};
/* voltage selection */
-static const struct regulator_volt_range varm_vape_vmod_vsel[] = {
+/* AB8500 device - Varm_vsel in 12.5mV steps */
+#define AB8500_VARM_VSEL_MASK 0x3f
+static const struct regulator_volt_range ab8500_varm_vsel[] = {
{ {0x00, 700000}, {0x01, 12500}, {0x35, 1362500} },
{ {0x36, 1362500}, {0x01, 0}, {0x3f, 1362500} },
};
-static const struct regulator_volt_range vbbp_vsel[] = {
+/* AB9540 device - Varm_vsel in 6.25mV steps */
+#define AB9540_VARM_VSEL_MASK 0x7f
+static const struct regulator_volt_range ab9540_varm_vsel[] = {
+ { {0x00, 600000}, {0x01, 6250}, {0x7f, 1393750} },
+};
+
+static const struct regulator_volt_range vape_vmod_vsel[] = {
+ { {0x00, 700000}, {0x01, 12500}, {0x35, 1362500} },
+ { {0x36, 1362500}, {0x01, 0}, {0x3f, 1362500} },
+};
+
+/* AB8500 device - Vbbp_vsel and Vbbn_sel in 100mV steps */
+static const struct regulator_volt_range ab8500_vbbp_vsel[] = {
{ {0x00, 0}, {0x10, 100000}, {0x40, 400000} },
{ {0x50, 400000}, {0x10, 0}, {0x70, 400000} },
{ {0x80, -400000}, {0x10, 0}, {0xb0, -400000} },
{ {0xc0, -400000}, {0x10, 100000}, {0xf0, -100000} },
};
-static const struct regulator_volt_range vbbn_vsel[] = {
+static const struct regulator_volt_range ab8500_vbbn_vsel[] = {
{ {0x00, 0}, {0x01, -100000}, {0x04, -400000} },
{ {0x05, -400000}, {0x01, 0}, {0x07, -400000} },
{ {0x08, 0}, {0x01, 100000}, {0x0c, 400000} },
{ {0x0d, 400000}, {0x01, 0}, {0x0f, 400000} },
};
+/* AB9540 device - Vbbp_vsel and Vbbn_sel in 50mV steps */
+static const struct regulator_volt_range ab9540_vbbp_vsel[] = {
+ { {0x00, 0}, {0x10, -50000}, {0x70, -350000} },
+ { {0x80, 50000}, {0x10, 50000}, {0xf0, 400000} },
+};
+
+static const struct regulator_volt_range ab9540_vbbn_vsel[] = {
+ { {0x00, 0}, {0x01, -50000}, {0x07, -350000} },
+ { {0x08, 50000}, {0x01, 50000}, {0x0f, 400000} },
+};
+
static const struct regulator_volt_range vsmps1_vsel[] = {
{ {0x00, 1100000}, {0x01, 0}, {0x1f, 1100000} },
{ {0x20, 1100000}, {0x01, 12500}, {0x30, 1300000} },
@@ -695,7 +827,8 @@ static const struct regulator_volt_range vsmps3_vsel[] = {
{ {0x36, 1363500}, {0x01, 0}, {0x7f, 1363500} },
};
-static const struct regulator_volt_range vaux1_vaux2_vsel[] = {
+/* for Vaux1, Vaux2 and Vaux4 */
+static const struct regulator_volt_range vauxn_vsel[] = {
{ {0x00, 1100000}, {0x01, 100000}, {0x04, 1500000} },
{ {0x05, 1800000}, {0x01, 50000}, {0x07, 1900000} },
{ {0x08, 2500000}, {0x01, 0}, {0x08, 2500000} },
@@ -740,17 +873,17 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_sel_mask = 0x0c,
.vsel_sel_val = {0x00, 0x04, 0x08, 0x0c},
.vsel_regid[0] = AB8500_REGU_VARM_SEL1,
- .vsel_mask[0] = 0x3f,
- .vsel_range[0] = varm_vape_vmod_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_mask[0] = AB8500_VARM_VSEL_MASK,
+ .vsel_range[0] = ab8500_varm_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(ab8500_varm_vsel),
.vsel_regid[1] = AB8500_REGU_VARM_SEL2,
- .vsel_mask[1] = 0x3f,
- .vsel_range[1] = varm_vape_vmod_vsel,
- .vsel_range_len[1] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_mask[1] = AB8500_VARM_VSEL_MASK,
+ .vsel_range[1] = ab8500_varm_vsel,
+ .vsel_range_len[1] = ARRAY_SIZE(ab8500_varm_vsel),
.vsel_regid[2] = AB8500_REGU_VARM_SEL3,
- .vsel_mask[2] = 0x3f,
- .vsel_range[2] = varm_vape_vmod_vsel,
- .vsel_range_len[2] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_mask[2] = AB8500_VARM_VSEL_MASK,
+ .vsel_range[2] = ab8500_varm_vsel,
+ .vsel_range_len[2] = ARRAY_SIZE(ab8500_varm_vsel),
},
[AB8500_VBBP] = {
.name = "Vbbp",
@@ -764,12 +897,12 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_sel_val = {0x00, 0x10, 0x00, 0x00},
.vsel_regid[0] = AB8500_REGU_VBB_SEL1,
.vsel_mask[0] = 0xf0,
- .vsel_range[0] = vbbp_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(vbbp_vsel),
+ .vsel_range[0] = ab8500_vbbp_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(ab8500_vbbp_vsel),
.vsel_regid[1] = AB8500_REGU_VBB_SEL2,
.vsel_mask[1] = 0xf0,
- .vsel_range[1] = vbbp_vsel,
- .vsel_range_len[1] = ARRAY_SIZE(vbbp_vsel),
+ .vsel_range[1] = ab8500_vbbp_vsel,
+ .vsel_range_len[1] = ARRAY_SIZE(ab8500_vbbp_vsel),
},
[AB8500_VBBN] = {
.name = "Vbbn",
@@ -783,12 +916,12 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_sel_val = {0x00, 0x20, 0x00, 0x00},
.vsel_regid[0] = AB8500_REGU_VBB_SEL1,
.vsel_mask[0] = 0x0f,
- .vsel_range[0] = vbbn_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(vbbn_vsel),
+ .vsel_range[0] = ab8500_vbbn_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(ab8500_vbbn_vsel),
.vsel_regid[1] = AB8500_REGU_VBB_SEL2,
.vsel_mask[1] = 0x0f,
- .vsel_range[1] = vbbn_vsel,
- .vsel_range_len[1] = ARRAY_SIZE(vbbn_vsel),
+ .vsel_range[1] = ab8500_vbbn_vsel,
+ .vsel_range_len[1] = ARRAY_SIZE(ab8500_vbbn_vsel),
},
[AB8500_VAPE] = {
.name = "Vape",
@@ -807,16 +940,16 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_sel_val = {0x00, 0x04, 0x20, 0x24},
.vsel_regid[0] = AB8500_REGU_VAPE_SEL1,
.vsel_mask[0] = 0x3f,
- .vsel_range[0] = varm_vape_vmod_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_range[0] = vape_vmod_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(vape_vmod_vsel),
.vsel_regid[1] = AB8500_REGU_VAPE_SEL2,
.vsel_mask[1] = 0x3f,
- .vsel_range[1] = varm_vape_vmod_vsel,
- .vsel_range_len[1] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_range[1] = vape_vmod_vsel,
+ .vsel_range_len[1] = ARRAY_SIZE(vape_vmod_vsel),
.vsel_regid[2] = AB8500_REGU_VAPE_SEL3,
.vsel_mask[2] = 0x3f,
- .vsel_range[2] = varm_vape_vmod_vsel,
- .vsel_range_len[2] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_range[2] = vape_vmod_vsel,
+ .vsel_range_len[2] = ARRAY_SIZE(vape_vmod_vsel),
},
[AB8500_VSMPS1] = {
.name = "Vsmps1",
@@ -958,12 +1091,12 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_sel_val = {0x00, 0x04, 0x00, 0x00},
.vsel_regid[0] = AB8500_REGU_VMOD_SEL1,
.vsel_mask[0] = 0x3f,
- .vsel_range[0] = varm_vape_vmod_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_range[0] = vape_vmod_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(vape_vmod_vsel),
.vsel_regid[1] = AB8500_REGU_VMOD_SEL2,
.vsel_mask[1] = 0x3f,
- .vsel_range[1] = varm_vape_vmod_vsel,
- .vsel_range_len[1] = ARRAY_SIZE(varm_vape_vmod_vsel),
+ .vsel_range[1] = vape_vmod_vsel,
+ .vsel_range_len[1] = ARRAY_SIZE(vape_vmod_vsel),
},
[AB8500_VEXTSUPPLY1] = {
.name = "Vextsupply1",
@@ -1061,8 +1194,8 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.hw_valid_mask[3] = 0x80,
.vsel_regid[0] = AB8500_REGU_VAUX1_SEL,
.vsel_mask[0] = 0x0f,
- .vsel_range[0] = vaux1_vaux2_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(vaux1_vaux2_vsel),
+ .vsel_range[0] = vauxn_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(vauxn_vsel),
},
[AB8500_VAUX2] = {
.name = "Vaux2",
@@ -1082,8 +1215,8 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.hw_valid_mask[3] = 0x01,
.vsel_regid[0] = AB8500_REGU_VAUX2_SEL,
.vsel_mask[0] = 0x0f,
- .vsel_range[0] = vaux1_vaux2_vsel,
- .vsel_range_len[0] = ARRAY_SIZE(vaux1_vaux2_vsel),
+ .vsel_range[0] = vauxn_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(vauxn_vsel),
},
[AB8500_VAUX3] = {
.name = "Vaux3",
@@ -1106,6 +1239,28 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
.vsel_range[0] = vaux3_vsel,
.vsel_range_len[0] = ARRAY_SIZE(vaux3_vsel),
},
+ [AB9540_VAUX4] = {
+ .name = "Vaux4",
+ .update_regid = AB9540_REGU_VAUX4_REGU,
+ .update_mask = 0x03,
+ .update_val = {0x00, 0x01, 0x02, 0x03},
+ .hw_mode_regid = AB9540_REGU_VAUX4_REQ_CTRL,
+ .hw_mode_mask = 0x03,
+ .hw_mode_val = {0x00, 0x01, 0x02, 0x03},
+ .hw_valid_regid[0] = AB9540_REGU_VAUX4_REQ_VALID,
+ .hw_valid_mask[0] = 0x08,
+ .hw_valid_regid[1] = AB9540_REGU_VAUX4_REQ_VALID,
+ .hw_valid_mask[1] = 0x04,
+ .hw_valid_regid[2] = AB9540_REGU_VAUX4_REQ_VALID,
+ .hw_valid_mask[2] = 0x02,
+ .hw_valid_regid[3] = AB9540_REGU_VAUX4_REQ_VALID,
+ .hw_valid_mask[3] = 0x01,
+ .vsel_regid[0] = AB9540_REGU_VAUX4_SEL,
+ .vsel_mask[0] = 0x0f,
+ .vsel_range[0] = vauxn_vsel,
+ .vsel_range_len[0] = ARRAY_SIZE(vauxn_vsel),
+ .unavailable = true, /* AB9540 regulator */
+ },
[AB8500_VINTCORE] = {
.name = "VintCore12",
.update_regid = AB8500_REGU_MISC1,
@@ -1166,6 +1321,41 @@ static struct ab8500_regulator ab8500_regulator[AB8500_NUM_REGULATORS] = {
},
};
+static void ab9540_regulators_update(void)
+{
+ /* Update unavailable regulators */
+ ab8500_regulator[AB8500_VREFDDR].unavailable = true;
+ ab8500_regulator[AB9540_VAUX4].unavailable = false;
+
+ /* Update regulator characteristics for AB9540 */
+ ab8500_regulator[AB8500_VARM].vsel_mask[0] = AB9540_VARM_VSEL_MASK;
+ ab8500_regulator[AB8500_VARM].vsel_range[0] = ab9540_varm_vsel;
+ ab8500_regulator[AB8500_VARM].vsel_range_len[0] =
+ ARRAY_SIZE(ab9540_varm_vsel);
+ ab8500_regulator[AB8500_VARM].vsel_mask[1] = AB9540_VARM_VSEL_MASK;
+ ab8500_regulator[AB8500_VARM].vsel_range[1] = ab9540_varm_vsel;
+ ab8500_regulator[AB8500_VARM].vsel_range_len[1] =
+ ARRAY_SIZE(ab9540_varm_vsel);
+ ab8500_regulator[AB8500_VARM].vsel_mask[2] = AB9540_VARM_VSEL_MASK;
+ ab8500_regulator[AB8500_VARM].vsel_range[2] = ab9540_varm_vsel;
+ ab8500_regulator[AB8500_VARM].vsel_range_len[2] =
+ ARRAY_SIZE(ab9540_varm_vsel);
+
+ ab8500_regulator[AB8500_VBBP].vsel_range[0] = ab9540_vbbp_vsel;
+ ab8500_regulator[AB8500_VBBP].vsel_range_len[0] =
+ ARRAY_SIZE(ab9540_vbbp_vsel);
+ ab8500_regulator[AB8500_VBBP].vsel_range[1] = ab9540_vbbp_vsel;
+ ab8500_regulator[AB8500_VBBP].vsel_range_len[1] =
+ ARRAY_SIZE(ab9540_vbbp_vsel);
+
+ ab8500_regulator[AB8500_VBBN].vsel_range[0] = ab9540_vbbn_vsel;
+ ab8500_regulator[AB8500_VBBN].vsel_range_len[0] =
+ ARRAY_SIZE(ab9540_vbbn_vsel);
+ ab8500_regulator[AB8500_VBBN].vsel_range[1] = ab9540_vbbn_vsel;
+ ab8500_regulator[AB8500_VBBN].vsel_range_len[1] =
+ ARRAY_SIZE(ab9540_vbbn_vsel);
+}
+
static int status_state = AB8500_REGULATOR_STATE_CURRENT;
static int _get_voltage(struct regulator_volt_range const *volt_range,
@@ -1271,6 +1461,10 @@ static int ab8500_regulator_status_print(struct seq_file *s, void *p)
/* dump registers */
for (id = 0; id < AB8500_NUM_REGULATORS; id++) {
+ if (ab8500_register[id].unavailable ||
+ ab8500_regulator[id].unavailable)
+ continue;
+
/* print name */
err = seq_printf(s, "|%11s|",
ab8500_regulator[id].name);
@@ -1445,6 +1639,7 @@ struct ab8500_force_reg {
u8 val;
bool restore;
u8 restore_val;
+ u8 unavailable;
};
static struct ab8500_force_reg ab8500_force_reg[] = {
@@ -1512,6 +1707,28 @@ static struct ab8500_force_reg ab8500_force_reg[] = {
},
};
+static void ab9540_force_reg_update(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ab8500_force_reg); i++) {
+ if (ab8500_force_reg[i].bank == 0x02 &&
+ ab8500_force_reg[i].addr == 0x0C) {
+ /*
+ * SysClkCtrl
+ * OTP: 0x00, HSI: 0x06, suspend: 0x00/0x07 (value/mask)
+ * [ 2] USBClkEna = disable SysClk path to USB block
+ */
+ ab8500_force_reg[i].mask = 0x04;
+ ab8500_force_reg[i].val = 0x00;
+ } else if (ab8500_force_reg[i].bank == 0x06 &&
+ ab8500_force_reg[i].addr == 0x80) {
+ /* TVoutCtrl not supported by AB9540 */
+ ab8500_force_reg[i].unavailable = true;
+ }
+ }
+}
+
void ab8500_regulator_debug_force(void)
{
int ret, i;
@@ -1531,6 +1748,9 @@ void ab8500_regulator_debug_force(void)
*/
for (i = 0; i < ARRAY_SIZE(ab8500_force_reg); i++) {
+ if (ab8500_force_reg[i].unavailable)
+ continue;
+
dev_vdbg(&pdev->dev, "Save and set %s: "
"0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",
ab8500_force_reg[i].name,
@@ -1586,6 +1806,9 @@ void ab8500_regulator_debug_restore(void)
if (ret < 0)
dev_err(&pdev->dev, "Failed to record resume state.\n");
for (i = ARRAY_SIZE(ab8500_force_reg) - 1; i >= 0; i--) {
+ if (ab8500_force_reg[i].unavailable)
+ continue;
+
/* restore register value */
if (ab8500_force_reg[i].restore) {
ret = abx500_mask_and_set_register_interruptible(
@@ -1685,6 +1908,7 @@ int __devinit ab8500_regulator_debug_init(struct platform_device *plf)
{
void __iomem *boot_info_backupram;
int ret;
+ struct ab8500 *ab8500;
/* setup dev pointers */
dev = &plf->dev;
@@ -1695,6 +1919,13 @@ int __devinit ab8500_regulator_debug_init(struct platform_device *plf)
if (ret < 0)
dev_err(&plf->dev, "Failed to record init state.\n");
+ ab8500 = dev_get_drvdata(plf->dev.parent);
+ /* Update data structures for AB9540 */
+ if (is_ab9540(ab8500)) {
+ ab9540_registers_update();
+ ab9540_regulators_update();
+ ab9540_force_reg_update();
+ }
/* make suspend-force default if board profile is v5x-power */
boot_info_backupram = ioremap(BOOT_INFO_BACKUPRAM1, 0x4);
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index 76d23ec65aa..92558ec86f0 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -22,6 +22,7 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
#include <linux/mfd/abx500/ab8500-gpio.h> /* for sysclkreq pins */
+#include <mach/id.h>
/**
* struct ab8500_regulator_info - ab8500 regulator information
@@ -553,6 +554,7 @@ static struct regulator_ops ab8500_sysclkreq_ops = {
.list_voltage = ab8500_list_voltage,
};
+/* AB8500 regulator information */
static struct ab8500_regulator_info
ab8500_regulator_info[AB8500_NUM_REGULATORS] = {
/*
@@ -794,6 +796,291 @@ static struct ab8500_regulator_info
},
};
+/* AB9540 regulator information */
+static struct ab8500_regulator_info
+ ab9540_regulator_info[AB9540_NUM_REGULATORS] = {
+ /*
+ * Variable Voltage Regulators
+ * name, min mV, max mV,
+ * update bank, reg, mask, enable val
+ * volt bank, reg, mask, table, table length
+ */
+ [AB9540_LDO_AUX1] = {
+ .desc = {
+ .name = "LDO-AUX1",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_AUX1,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .load_lp_uA = 5000,
+ .update_bank = 0x04,
+ .update_reg = 0x09,
+ .update_mask = 0x03,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x1f,
+ .voltage_mask = 0x0f,
+ .voltages = ldo_vauxn_voltages,
+ .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ [AB9540_LDO_AUX2] = {
+ .desc = {
+ .name = "LDO-AUX2",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_AUX2,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .load_lp_uA = 5000,
+ .update_bank = 0x04,
+ .update_reg = 0x09,
+ .update_mask = 0x0c,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x20,
+ .voltage_mask = 0x0f,
+ .voltages = ldo_vauxn_voltages,
+ .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ [AB9540_LDO_AUX3] = {
+ .desc = {
+ .name = "LDO-AUX3",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_AUX3,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
+ },
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .load_lp_uA = 5000,
+ .update_bank = 0x04,
+ .update_reg = 0x0a,
+ .update_mask = 0x03,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x21,
+ .voltage_mask = 0x07,
+ .voltages = ldo_vaux3_voltages,
+ .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages),
+ },
+ [AB9540_LDO_AUX4] = {
+ .desc = {
+ .name = "LDO-AUX4",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_LDO_AUX4,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .load_lp_uA = 5000,
+ /* values for Vaux4Regu register */
+ .update_bank = 0x04,
+ .update_reg = 0x2e,
+ .update_mask = 0x03,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ /* values for Vaux4SEL register */
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x2f,
+ .voltage_mask = 0x0f,
+ .voltages = ldo_vauxn_voltages,
+ .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
+ },
+ [AB9540_LDO_INTCORE] = {
+ .desc = {
+ .name = "LDO-INTCORE",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_INTCORE,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages),
+ },
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .load_lp_uA = 5000,
+ .update_bank = 0x03,
+ .update_reg = 0x80,
+ .update_mask = 0x44,
+ .update_val = 0x44,
+ .update_val_idle = 0x44,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x03,
+ .voltage_reg = 0x80,
+ .voltage_mask = 0x38,
+ .voltages = ldo_vintcore_voltages,
+ .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages),
+ },
+
+ /*
+ * Fixed Voltage Regulators
+ * name, fixed mV,
+ * update bank, reg, mask, enable val
+ */
+ [AB9540_LDO_TVOUT] = {
+ .desc = {
+ .name = "LDO-TVOUT",
+ .ops = &ab8500_regulator_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_TVOUT,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .delay = 10000,
+ .fixed_uV = 2000000,
+ .load_lp_uA = 1000,
+ .update_bank = 0x03,
+ .update_reg = 0x80,
+ .update_mask = 0x82,
+ .update_val = 0x02,
+ .update_val_idle = 0x82,
+ .update_val_normal = 0x02,
+ },
+ [AB9540_LDO_USB] = {
+ .desc = {
+ .name = "LDO-USB",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_LDO_USB,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 3300000,
+ .update_bank = 0x03,
+ .update_reg = 0x82,
+ .update_mask = 0x03,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ },
+ [AB9540_LDO_AUDIO] = {
+ .desc = {
+ .name = "LDO-AUDIO",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_AUDIO,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 2000000,
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x02,
+ .update_val = 0x02,
+ },
+ [AB9540_LDO_ANAMIC1] = {
+ .desc = {
+ .name = "LDO-ANAMIC1",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANAMIC1,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 2050000,
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x08,
+ .update_val = 0x08,
+ },
+ [AB9540_LDO_ANAMIC2] = {
+ .desc = {
+ .name = "LDO-ANAMIC2",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANAMIC2,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 2050000,
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x10,
+ .update_val = 0x10,
+ },
+ [AB9540_LDO_DMIC] = {
+ .desc = {
+ .name = "LDO-DMIC",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_DMIC,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 1800000,
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x04,
+ .update_val = 0x04,
+ },
+
+ /*
+ * Regulators with fixed voltage and normal/idle modes
+ */
+ [AB9540_LDO_ANA] = {
+ .desc = {
+ .name = "LDO-ANA",
+ .ops = &ab8500_regulator_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANA,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 1200000,
+ .load_lp_uA = 1000,
+ .update_bank = 0x04,
+ .update_reg = 0x06,
+ .update_mask = 0x0c,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ },
+
+ /*
+ * SysClkReq regulators
+ */
+ [AB9540_SYSCLKREQ_2] = {
+ .desc = {
+ .name = "SYSCLKREQ-2",
+ .ops = &ab8500_sysclkreq_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_SYSCLKREQ_2,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 1, /* bogus value */
+ .gpio_pin = AB8500_PIN_GPIO1,
+ },
+ [AB9540_SYSCLKREQ_4] = {
+ .desc = {
+ .name = "SYSCLKREQ-4",
+ .ops = &ab8500_sysclkreq_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_SYSCLKREQ_4,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ },
+ .fixed_uV = 1, /* bogus value */
+ .gpio_pin = AB8500_PIN_GPIO3,
+ },
+};
+
struct ab8500_reg_init {
u8 bank;
u8 addr;
@@ -807,6 +1094,7 @@ struct ab8500_reg_init {
.mask = _mask, \
}
+/* AB8500 register init */
static struct ab8500_reg_init ab8500_reg_init[] = {
/*
* 0x30, VanaRequestCtrl
@@ -990,12 +1278,292 @@ int __attribute__((weak)) ab8500_regulator_debug_exit(
return 0;
}
+/* AB9540 register init */
+static struct ab8500_reg_init ab9540_reg_init[] = {
+ /*
+ * 0x03, VarmRequestCtrl
+ * 0x0c, VapeRequestCtrl
+ * 0x30, Vsmps1RequestCtrl
+ * 0xc0, Vsmps2RequestCtrl
+ */
+ REG_INIT(AB9540_REGUREQUESTCTRL1, 0x03, 0x03, 0xff),
+ /*
+ * 0x03, Vsmps3RequestCtrl
+ * 0x0c, VpllRequestCtrl
+ * 0x30, VanaRequestCtrl
+ * 0xc0, VextSupply1RequestCtrl
+ */
+ REG_INIT(AB9540_REGUREQUESTCTRL2, 0x03, 0x04, 0xff),
+ /*
+ * 0x03, VextSupply2RequestCtrl
+ * 0x0c, VextSupply3RequestCtrl
+ * 0x30, Vaux1RequestCtrl
+ * 0xc0, Vaux2RequestCtrl
+ */
+ REG_INIT(AB9540_REGUREQUESTCTRL3, 0x03, 0x05, 0xff),
+ /*
+ * 0x03, Vaux3RequestCtrl
+ * 0x04, SwHPReq
+ */
+ REG_INIT(AB9540_REGUREQUESTCTRL4, 0x03, 0x06, 0x07),
+ /*
+ * 0x01, Vsmps1SysClkReq1HPValid
+ * 0x02, Vsmps2SysClkReq1HPValid
+ * 0x04, Vsmps3SysClkReq1HPValid
+ * 0x08, VanaSysClkReq1HPValid
+ * 0x10, VpllSysClkReq1HPValid
+ * 0x20, Vaux1SysClkReq1HPValid
+ * 0x40, Vaux2SysClkReq1HPValid
+ * 0x80, Vaux3SysClkReq1HPValid
+ */
+ REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff),
+ /*
+ * 0x01, VapeSysClkReq1HPValid
+ * 0x02, VarmSysClkReq1HPValid
+ * 0x04, VbbSysClkReq1HPValid
+ * 0x08, VmodSysClkReq1HPValid
+ * 0x10, VextSupply1SysClkReq1HPValid
+ * 0x20, VextSupply2SysClkReq1HPValid
+ * 0x40, VextSupply3SysClkReq1HPValid
+ */
+ REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x7f),
+ /*
+ * 0x01, Vsmps1HwHPReq1Valid
+ * 0x02, Vsmps2HwHPReq1Valid
+ * 0x04, Vsmps3HwHPReq1Valid
+ * 0x08, VanaHwHPReq1Valid
+ * 0x10, VpllHwHPReq1Valid
+ * 0x20, Vaux1HwHPReq1Valid
+ * 0x40, Vaux2HwHPReq1Valid
+ * 0x80, Vaux3HwHPReq1Valid
+ */
+ REG_INIT(AB9540_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff),
+ /*
+ * 0x01, VextSupply1HwHPReq1Valid
+ * 0x02, VextSupply2HwHPReq1Valid
+ * 0x04, VextSupply3HwHPReq1Valid
+ * 0x08, VmodHwHPReq1Valid
+ */
+ REG_INIT(AB9540_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x0f),
+ /*
+ * 0x01, Vsmps1HwHPReq2Valid
+ * 0x02, Vsmps2HwHPReq2Valid
+ * 0x03, Vsmps3HwHPReq2Valid
+ * 0x08, VanaHwHPReq2Valid
+ * 0x10, VpllHwHPReq2Valid
+ * 0x20, Vaux1HwHPReq2Valid
+ * 0x40, Vaux2HwHPReq2Valid
+ * 0x80, Vaux3HwHPReq2Valid
+ */
+ REG_INIT(AB9540_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff),
+ /*
+ * 0x01, VextSupply1HwHPReq2Valid
+ * 0x02, VextSupply2HwHPReq2Valid
+ * 0x04, VextSupply3HwHPReq2Valid
+ * 0x08, VmodHwHPReq2Valid
+ */
+ REG_INIT(AB9540_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x0f),
+ /*
+ * 0x01, VapeSwHPReqValid
+ * 0x02, VarmSwHPReqValid
+ * 0x04, Vsmps1SwHPReqValid
+ * 0x08, Vsmps2SwHPReqValid
+ * 0x10, Vsmps3SwHPReqValid
+ * 0x20, VanaSwHPReqValid
+ * 0x40, VpllSwHPReqValid
+ * 0x80, Vaux1SwHPReqValid
+ */
+ REG_INIT(AB9540_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff),
+ /*
+ * 0x01, Vaux2SwHPReqValid
+ * 0x02, Vaux3SwHPReqValid
+ * 0x04, VextSupply1SwHPReqValid
+ * 0x08, VextSupply2SwHPReqValid
+ * 0x10, VextSupply3SwHPReqValid
+ * 0x20, VmodSwHPReqValid
+ */
+ REG_INIT(AB9540_REGUSWHPREQVALID2, 0x03, 0x0e, 0x3f),
+ /*
+ * 0x02, SysClkReq2Valid1
+ * ...
+ * 0x80, SysClkReq8Valid1
+ */
+ REG_INIT(AB9540_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xfe),
+ /*
+ * 0x02, SysClkReq2Valid2
+ * ...
+ * 0x80, SysClkReq8Valid2
+ */
+ REG_INIT(AB9540_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xfe),
+ /*
+ * 0x01, Vaux4SwHPReqValid
+ * 0x02, Vaux4HwHPReq2Valid
+ * 0x04, Vaux4HwHPReq1Valid
+ * 0x08, Vaux4SysClkReq1HPValid
+ */
+ REG_INIT(AB9540_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f),
+ /*
+ * 0x02, VTVoutEna
+ * 0x04, Vintcore12Ena
+ * 0x38, Vintcore12Sel
+ * 0x40, Vintcore12LP
+ * 0x80, VTVoutLP
+ */
+ REG_INIT(AB9540_REGUMISC1, 0x03, 0x80, 0xfe),
+ /*
+ * 0x02, VaudioEna
+ * 0x04, VdmicEna
+ * 0x08, Vamic1Ena
+ * 0x10, Vamic2Ena
+ */
+ REG_INIT(AB9540_VAUDIOSUPPLY, 0x03, 0x83, 0x1e),
+ /*
+ * 0x01, Vamic1_dzout
+ * 0x02, Vamic2_dzout
+ */
+ REG_INIT(AB9540_REGUCTRL1VAMIC, 0x03, 0x84, 0x03),
+ /*
+ * 0x03, Vsmps1Regu
+ * 0x0c, Vsmps1SelCtrl
+ * 0x10, Vsmps1AutoMode
+ * 0x20, Vsmps1PWMMode
+ */
+ REG_INIT(AB9540_VSMPS1REGU, 0x04, 0x03, 0x3f),
+ /*
+ * 0x03, Vsmps2Regu
+ * 0x0c, Vsmps2SelCtrl
+ * 0x10, Vsmps2AutoMode
+ * 0x20, Vsmps2PWMMode
+ */
+ REG_INIT(AB9540_VSMPS2REGU, 0x04, 0x04, 0x3f),
+ /*
+ * 0x03, Vsmps3Regu
+ * 0x0c, Vsmps3SelCtrl
+ * NOTE! PRCMU register
+ */
+ REG_INIT(AB9540_VSMPS3REGU, 0x04, 0x05, 0x0f),
+ /*
+ * 0x03, VpllRegu
+ * 0x0c, VanaRegu
+ */
+ REG_INIT(AB9540_VPLLVANAREGU, 0x04, 0x06, 0x0f),
+ /*
+ * 0x03, VextSupply1Regu
+ * 0x0c, VextSupply2Regu
+ * 0x30, VextSupply3Regu
+ * 0x40, ExtSupply2Bypass
+ * 0x80, ExtSupply3Bypass
+ */
+ REG_INIT(AB9540_EXTSUPPLYREGU, 0x04, 0x08, 0xff),
+ /*
+ * 0x03, Vaux1Regu
+ * 0x0c, Vaux2Regu
+ */
+ REG_INIT(AB9540_VAUX12REGU, 0x04, 0x09, 0x0f),
+ /*
+ * 0x0c, Vrf1Regu
+ * 0x03, Vaux3Regu
+ */
+ REG_INIT(AB9540_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f),
+ /*
+ * 0x3f, Vsmps1Sel1
+ */
+ REG_INIT(AB9540_VSMPS1SEL1, 0x04, 0x13, 0x3f),
+ /*
+ * 0x3f, Vsmps1Sel2
+ */
+ REG_INIT(AB9540_VSMPS1SEL2, 0x04, 0x14, 0x3f),
+ /*
+ * 0x3f, Vsmps1Sel3
+ */
+ REG_INIT(AB9540_VSMPS1SEL3, 0x04, 0x15, 0x3f),
+ /*
+ * 0x3f, Vsmps2Sel1
+ */
+ REG_INIT(AB9540_VSMPS2SEL1, 0x04, 0x17, 0x3f),
+ /*
+ * 0x3f, Vsmps2Sel2
+ */
+ REG_INIT(AB9540_VSMPS2SEL2, 0x04, 0x18, 0x3f),
+ /*
+ * 0x3f, Vsmps2Sel3
+ */
+ REG_INIT(AB9540_VSMPS2SEL3, 0x04, 0x19, 0x3f),
+ /*
+ * 0x7f, Vsmps3Sel1
+ * NOTE! PRCMU register
+ */
+ REG_INIT(AB9540_VSMPS3SEL1, 0x04, 0x1b, 0x7f),
+ /*
+ * 0x7f, Vsmps3Sel2
+ * NOTE! PRCMU register
+ */
+ REG_INIT(AB9540_VSMPS3SEL2, 0x04, 0x1c, 0x7f),
+ /*
+ * 0x0f, Vaux1Sel
+ */
+ REG_INIT(AB9540_VAUX1SEL, 0x04, 0x1f, 0x0f),
+ /*
+ * 0x0f, Vaux2Sel
+ */
+ REG_INIT(AB9540_VAUX2SEL, 0x04, 0x20, 0x0f),
+ /*
+ * 0x07, Vaux3Sel
+ * 0x30, Vrf1Sel
+ */
+ REG_INIT(AB9540_VRF1VAUX3SEL, 0x04, 0x21, 0x37),
+ /*
+ * 0x01, VextSupply12LP
+ */
+ REG_INIT(AB9540_REGUCTRL2SPARE, 0x04, 0x22, 0x01),
+ /*
+ * 0x03, Vaux4RequestCtrl
+ */
+ REG_INIT(AB9540_VAUX4REQCTRL, 0x04, 0x2d, 0x03),
+ /*
+ * 0x03, Vaux4Regu
+ */
+ REG_INIT(AB9540_VAUX4REGU, 0x04, 0x2e, 0x03),
+ /*
+ * 0x08, Vaux4Sel
+ */
+ REG_INIT(AB9540_VAUX4SEL, 0x04, 0x2f, 0x0f),
+ /*
+ * 0x01, VpllDisch
+ * 0x02, Vrf1Disch
+ * 0x04, Vaux1Disch
+ * 0x08, Vaux2Disch
+ * 0x10, Vaux3Disch
+ * 0x20, Vintcore12Disch
+ * 0x40, VTVoutDisch
+ * 0x80, VaudioDisch
+ */
+ REG_INIT(AB9540_REGUCTRLDISCH, 0x04, 0x43, 0xff),
+ /*
+ * 0x01, VsimDisch
+ * 0x02, VanaDisch
+ * 0x04, VdmicPullDownEna
+ * 0x08, VpllPullDownEna
+ * 0x10, VdmicDisch
+ */
+ REG_INIT(AB9540_REGUCTRLDISCH2, 0x04, 0x44, 0x1f),
+ /*
+ * 0x01, Vaux4Disch
+ */
+ REG_INIT(AB9540_REGUCTRLDISCH3, 0x04, 0x48, 0x01),
+};
+
static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *ppdata;
struct ab8500_regulator_platform_data *pdata;
int i, err;
+ struct ab8500_regulator_info *regulator_info;
+ int regulator_info_size;
+ struct ab8500_reg_init *reg_init;
+ int reg_init_size;
+ /* cache values needed repeatedly inside for-loops */
if (!ab8500) {
dev_err(&pdev->dev, "null mfd parent\n");
@@ -1014,8 +1582,20 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
return -EINVAL;
}
+ if (is_ab9540(ab8500)) {
+ regulator_info = ab9540_regulator_info;
+ regulator_info_size = ARRAY_SIZE(ab9540_regulator_info);
+ reg_init = ab9540_reg_init;
+ reg_init_size = AB9540_NUM_REGULATOR_REGISTERS;
+ } else {
+ regulator_info = ab8500_regulator_info;
+ regulator_info_size = ARRAY_SIZE(ab8500_regulator_info);
+ reg_init = ab8500_reg_init;
+ reg_init_size = AB8500_NUM_REGULATOR_REGISTERS;
+ }
+
/* make sure the platform data has the correct size */
- if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
+ if (pdata->num_regulator != regulator_info_size) {
dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
return -EINVAL;
}
@@ -1035,26 +1615,26 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
value = pdata->reg_init[i].value;
/* check for configuration errors */
- BUG_ON(id >= AB8500_NUM_REGULATOR_REGISTERS);
+ BUG_ON(id >= reg_init_size);
BUG_ON(value & ~mask);
- BUG_ON(mask & ~ab8500_reg_init[id].mask);
+ BUG_ON(mask & ~reg_init[id].mask);
/* initialize register */
err = abx500_mask_and_set_register_interruptible(&pdev->dev,
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr,
+ reg_init[id].bank,
+ reg_init[id].addr,
mask, value);
if (err < 0) {
dev_err(&pdev->dev,
"Failed to initialize 0x%02x, 0x%02x.\n",
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr);
+ reg_init[id].bank,
+ reg_init[id].addr);
return err;
}
dev_vdbg(&pdev->dev,
" init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr,
+ reg_init[id].bank,
+ reg_init[id].addr,
mask, value);
}
@@ -1065,7 +1645,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
* This only affects power consumption and it depends on the
* HREF OTP configurations.
*/
- if (abx500_get_chip_id(&pdev->dev) < 0x30) {
+ if (is_ab8500_2p0_or_earlier(ab8500)) {
err = abx500_mask_and_set_register_interruptible(&pdev->dev,
AB8500_REGU_CTRL2, 0x08, 0x30, 0x30);
if (err < 0) {
@@ -1082,15 +1662,15 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
return err;
/* register all regulators */
- for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+ for (i = 0; i < regulator_info_size; i++) {
struct ab8500_regulator_info *info = NULL;
/* assign per-regulator data */
- info = &ab8500_regulator_info[i];
+ info = &regulator_info[i];
info->dev = &pdev->dev;
/* fix for hardware before ab8500v2.0 */
- if (abx500_get_chip_id(info->dev) < 0x20) {
+ if (is_ab8500_1p1_or_earlier(ab8500)) {
if (info->desc.id == AB8500_LDO_AUX3) {
info->desc.n_voltages =
ARRAY_SIZE(ldo_vauxn_voltages);
@@ -1110,7 +1690,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
info->desc.name);
/* when we fail, un-register all earlier regulators */
while (--i >= 0) {
- info = &ab8500_regulator_info[i];
+ info = &regulator_info[i];
regulator_unregister(info->regulator);
}
return err;
@@ -1126,10 +1706,22 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
{
int i, err;
+ struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+ struct ab8500_regulator_info *regulator_info;
+ int regulator_info_size;
+
+
+ if (is_ab9540(ab8500)) {
+ regulator_info = ab9540_regulator_info;
+ regulator_info_size = ARRAY_SIZE(ab9540_regulator_info);
+ } else {
+ regulator_info = ab8500_regulator_info;
+ regulator_info_size = ARRAY_SIZE(ab8500_regulator_info);
+ }
- for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+ for (i = 0; i < regulator_info_size; i++) {
struct ab8500_regulator_info *info = NULL;
- info = &ab8500_regulator_info[i];
+ info = &regulator_info[i];
dev_vdbg(rdev_get_dev(info->regulator),
"%s-remove\n", info->desc.name);