summaryrefslogtreecommitdiff
path: root/drivers/regulator/ab8500-debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/ab8500-debug.c')
-rw-r--r--drivers/regulator/ab8500-debug.c301
1 files changed, 266 insertions, 35 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);