From eb244486c4a709fcd2306f2f7d3851b57898543e Mon Sep 17 00:00:00 2001 From: Michel JAOUEN Date: Fri, 27 Jan 2012 17:47:21 +0100 Subject: 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 Signed-off-by: Alex MACRO Signed-off-by: Michel JAOUEN Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46634 --- drivers/regulator/ab8500-debug.c | 301 ++++++++++++++++--- drivers/regulator/ab8500.c | 624 ++++++++++++++++++++++++++++++++++++++- 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 #include #include +#include #include #include #include /* 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 #include #include /* for sysclkreq pins */ +#include /** * 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 = ®ulator_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 = ®ulator_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 = ®ulator_info[i]; dev_vdbg(rdev_get_dev(info->regulator), "%s-remove\n", info->desc.name); -- cgit v1.2.3