diff options
-rw-r--r-- | drivers/mfd/ricoh583.c | 150 | ||||
-rw-r--r-- | drivers/regulator/ricoh583-regulator.c | 123 | ||||
-rw-r--r-- | include/linux/mfd/ricoh583.h | 34 | ||||
-rw-r--r-- | include/linux/regulator/ricoh583-regulator.h | 6 |
4 files changed, 204 insertions, 109 deletions
diff --git a/drivers/mfd/ricoh583.c b/drivers/mfd/ricoh583.c index fa11254806b1..52aafe65ee57 100644 --- a/drivers/mfd/ricoh583.c +++ b/drivers/mfd/ricoh583.c @@ -35,6 +35,8 @@ #include <linux/mfd/core.h> #include <linux/mfd/ricoh583.h> +#define RICOH_ONOFFSEL_REG 0x10 + /* Interrupt enable register */ #define RICOH583_INT_EN_SYS1 0x19 #define RICOH583_INT_EN_SYS2 0x1D @@ -97,6 +99,11 @@ struct ricoh583_irq_data { int grp_index; }; +struct deepsleep_control_data { + u8 reg_add; + u8 ds_pos_bit; +}; + #define RICOH583_IRQ(_int_type, _master_bit, _grp_index, _int_bit, _mask_ind) \ { \ .int_type = _int_type, \ @@ -153,8 +160,37 @@ static const struct ricoh583_irq_data ricoh583_irqs[] = { [RICOH583_NR_IRQS] = RICOH583_IRQ(GPIO_INT, 4, 8, 8, 7), }; +#define DEEPSLEEP_INIT(_id, _reg, _pos) \ + [RICOH583_DS_##_id] = {.reg_add = _reg, .ds_pos_bit = _pos} + +static struct deepsleep_control_data deepsleep_data[] = { + DEEPSLEEP_INIT(DC1, 0x21, 4), + DEEPSLEEP_INIT(DC2, 0x22, 0), + DEEPSLEEP_INIT(DC3, 0x22, 4), + DEEPSLEEP_INIT(LDO0, 0x23, 0), + DEEPSLEEP_INIT(LDO1, 0x23, 4), + DEEPSLEEP_INIT(LDO2, 0x24, 0), + DEEPSLEEP_INIT(LDO3, 0x24, 4), + DEEPSLEEP_INIT(LDO4, 0x25, 0), + DEEPSLEEP_INIT(LDO5, 0x25, 4), + DEEPSLEEP_INIT(LDO6, 0x26, 0), + DEEPSLEEP_INIT(LDO7, 0x26, 4), + DEEPSLEEP_INIT(LDO8, 0x27, 0), + DEEPSLEEP_INIT(LDO9, 0x27, 4), + DEEPSLEEP_INIT(PSO0, 0x28, 0), + DEEPSLEEP_INIT(PSO1, 0x28, 4), + DEEPSLEEP_INIT(PSO2, 0x29, 0), + DEEPSLEEP_INIT(PSO3, 0x29, 4), + DEEPSLEEP_INIT(PSO4, 0x2A, 0), + DEEPSLEEP_INIT(PSO5, 0x2A, 4), + DEEPSLEEP_INIT(PSO6, 0x2B, 0), + DEEPSLEEP_INIT(PSO7, 0x2B, 4), +}; + #define MAX_INTERRUPT_MASKS 8 #define MAX_MAIN_INTERRUPT 5 +#define EXT_PWR_REQ \ + (RICOH583_EXT_PWRREQ1_CONTROL | RICOH583_EXT_PWRREQ2_CONTROL) struct ricoh583 { struct device *dev; @@ -363,6 +399,112 @@ out: } EXPORT_SYMBOL_GPL(ricoh583_update); +static int __ricoh583_set_ext_pwrreq1_control(struct device *dev, + enum ricoh583_deepsleep_control_id id, + enum ricoh583_ext_pwrreq_control ext_pwr, int slots) +{ + int ret; + uint8_t sleepseq_val; + u8 en_bit; + u8 slot_bit; + + if (!(ext_pwr & RICOH583_EXT_PWRREQ1_CONTROL)) + return 0; + + if (id == RICOH583_DS_DC0) { + dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id); + return -EINVAL; + } + + en_bit = deepsleep_data[id].ds_pos_bit; + slot_bit = en_bit + 1; + ret = ricoh583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val); + if (ret < 0) { + dev_err(dev, "Error in reading reg 0x%x\n", + deepsleep_data[id].reg_add); + return ret; + } + + sleepseq_val &= ~(0xF << en_bit); + sleepseq_val |= (1 << en_bit); + sleepseq_val |= ((slots & 0x7) << slot_bit); + ret = ricoh583_set_bits(dev, RICOH_ONOFFSEL_REG, (1 << 1)); + if (ret < 0) { + dev_err(dev, "Error in updating the 0x%02x register\n", + RICOH_ONOFFSEL_REG); + return ret; + } + + ret = ricoh583_write(dev, deepsleep_data[id].reg_add, sleepseq_val); + if (ret < 0) + dev_err(dev, "Error in writing reg 0x%x\n", + deepsleep_data[id].reg_add); + return ret; +} + +static int __ricoh583_set_ext_pwrreq2_control(struct device *dev, + enum ricoh583_deepsleep_control_id id, + enum ricoh583_ext_pwrreq_control ext_pwr) +{ + int ret; + + if (!(ext_pwr & RICOH583_EXT_PWRREQ2_CONTROL)) + return 0; + + if (id != RICOH583_DS_DC0) { + dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id); + return -EINVAL; + } + + ret = ricoh583_set_bits(dev, RICOH_ONOFFSEL_REG, (1 << 2)); + if (ret < 0) + dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n"); + return ret; +} + +int ricoh583_ext_power_req_config(struct device *dev, + enum ricoh583_deepsleep_control_id id, + enum ricoh583_ext_pwrreq_control ext_pwr_req, + int deepsleep_slot_nr) +{ + if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ) + return -EINVAL; + + if (ext_pwr_req & RICOH583_EXT_PWRREQ1_CONTROL) + return __ricoh583_set_ext_pwrreq1_control(dev, id, + ext_pwr_req, deepsleep_slot_nr); + + if (ext_pwr_req & RICOH583_EXT_PWRREQ2_CONTROL) + return __ricoh583_set_ext_pwrreq2_control(dev, + id, ext_pwr_req); + return 0; +} +EXPORT_SYMBOL_GPL(ricoh583_ext_power_req_config); + +static int __devinit ricoh583_ext_power_init(struct ricoh583 *ricoh583, + struct ricoh583_platform_data *pdata) +{ + int ret; + int i; + + /* Clear ONOFFSEL register */ + mutex_lock(&ricoh583->io_lock); + ret = __ricoh583_write(ricoh583->client, RICOH_ONOFFSEL_REG, 0x0); + if (ret < 0) + dev_err(ricoh583->dev, "Error in writing reg %d error: " + "%d\n", RICOH_ONOFFSEL_REG, ret); + + /* Clear sleepseq register */ + for (i = 0x21; i < 0x2B; ++i) { + ret = __ricoh583_write(ricoh583->client, i, 0x0); + if (ret < 0) + dev_err(ricoh583->dev, "Error in writing reg 0x%02x " + "error: %d\n", i, ret); + } + mutex_unlock(&ricoh583->io_lock); + return 0; +} + static struct i2c_client *ricoh583_i2c_client; int ricoh583_power_off(void) { @@ -943,13 +1085,9 @@ static int ricoh583_i2c_probe(struct i2c_client *i2c, mutex_init(&ricoh583->io_lock); - /* Clear ONOFFSEL register */ - ret = __ricoh583_write(ricoh583->client, 0x10, 0x0); - if (ret < 0) { - dev_err(ricoh583->dev, "Error in writing reg 0x10 error: " - "%d\n", ret); + ret = ricoh583_ext_power_init(ricoh583, pdata); + if (ret < 0) goto err_irq_init; - } if (i2c->irq) { ret = ricoh583_irq_init(ricoh583, i2c->irq, pdata->irq_base); diff --git a/drivers/regulator/ricoh583-regulator.c b/drivers/regulator/ricoh583-regulator.c index 33f13252cfa7..2f3ef87ecda7 100644 --- a/drivers/regulator/ricoh583-regulator.c +++ b/drivers/regulator/ricoh583-regulator.c @@ -36,10 +36,9 @@ #include <linux/mfd/ricoh583.h> #include <linux/regulator/ricoh583-regulator.h> - -#define RICOH_ONOFFSEL_REG 0x10 struct ricoh583_regulator { int id; + int deepsleep_id; /* Regulator register address.*/ u8 reg_en_reg; u8 en_bit; @@ -49,8 +48,6 @@ struct ricoh583_regulator { u8 vout_mask; u8 vout_reg_cache; u8 deepsleep_reg; - u8 sleepseq_reg; - u8 sleepseq_shift; /* chip constraints on regulator behavior */ int min_uV; @@ -150,73 +147,6 @@ static int __ricoh583_set_ds_voltage(struct device *parent, return ret; } -static int __ricoh583_set_ext_pwrreq1_control(struct device *parent, - struct ricoh583_regulator *ri, unsigned long flags, int slots) -{ - int ret; - uint8_t sleepseq_val; - u8 en_bit; - u8 slot_bit; - - if (ri->id == RICOH583_ID_DC0) { - if (flags & EXT_PWRREQ1_CONTROL) { - dev_err(ri->dev, "PWRREQ1 is invalid control for " - "rail %d\n", ri->id); - return -EINVAL; - } - return 0; - } - - en_bit = ri->sleepseq_shift; - slot_bit = en_bit + 1; - ret = ricoh583_read(parent, ri->sleepseq_reg, &sleepseq_val); - if (ret < 0) { - dev_err(ri->dev, "Error in reading reg 0x%x\n", - ri->sleepseq_reg); - return ret; - } - - if (flags & EXT_PWRREQ1_CONTROL) { - sleepseq_val |= (1 << en_bit); - sleepseq_val &= ~(0x7 << slot_bit); - sleepseq_val |= ((slots & 0x7) << slot_bit); - ret = ricoh583_set_bits(parent, RICOH_ONOFFSEL_REG, (1 << 1)); - if (ret < 0) { - dev_err(ri->dev, "Error in updating the ONOFFSEL 0x10 register\n"); - return ret; - } - } else { - sleepseq_val &= ~(0xF << en_bit); - } - ret = ricoh583_write(parent, ri->sleepseq_reg, sleepseq_val); - if (ret < 0) - dev_err(ri->dev, "Error in writing reg 0x%x\n", - ri->sleepseq_reg); - return ret; -} - -static int __ricoh583_set_ext_pwrreq2_control(struct device *parent, - struct ricoh583_regulator *ri, unsigned long flags) -{ - int ret; - - if (ri->id != RICOH583_ID_DC0) { - if (flags & EXT_PWRREQ2_CONTROL) { - dev_err(ri->dev, "PWRREQ2 is invalid control for " - "rail %d\n", ri->id); - return -EINVAL; - } - return 0; - } - if (flags & EXT_PWRREQ2_CONTROL) - ret = ricoh583_set_bits(parent, RICOH_ONOFFSEL_REG, (1 << 2)); - else - ret = ricoh583_clr_bits(parent, RICOH_ONOFFSEL_REG, (1 << 2)); - if (ret < 0) - dev_err(ri->dev, "Error in updating the ONOFFSEL 0x10 register\n"); - return ret; -} - static int __ricoh583_set_voltage(struct device *parent, struct ricoh583_regulator *ri, int min_uV, int max_uV) { @@ -271,8 +201,8 @@ static struct regulator_ops ricoh583_ops = { }; #define RICOH583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ - _vout_mask, _ds_reg, _slpseq_reg, _slpseq_shift, _min_mv, \ - _max_mv, _step_uV, _nsteps, _ops, _delay) \ + _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \ + _ops, _delay) \ { \ .reg_en_reg = _en_reg, \ .en_bit = _en_bit, \ @@ -281,14 +211,13 @@ static struct regulator_ops ricoh583_ops = { .vout_reg = _vout_reg, \ .vout_mask = _vout_mask, \ .deepsleep_reg = _ds_reg, \ - .sleepseq_reg = _slpseq_reg, \ - .sleepseq_shift = _slpseq_shift, \ .min_uV = _min_mv * 1000, \ .max_uV = _max_mv * 1000, \ .step_uV = _step_uV, \ .nsteps = _nsteps, \ .delay = _delay, \ .id = RICOH583_ID_##_id, \ + .deepsleep_id = RICOH583_DS_##_id, \ .desc = { \ .name = ricoh583_rails(_id), \ .id = RICOH583_ID_##_id, \ @@ -300,33 +229,33 @@ static struct regulator_ops ricoh583_ops = { } static struct ricoh583_regulator ricoh583_regulator[] = { - RICOH583_REG(DC0, 0x30, 0, 0x30, 1, 0x31, 0x7F, 0x60, 0x21, 0, + RICOH583_REG(DC0, 0x30, 0, 0x30, 1, 0x31, 0x7F, 0x60, 700, 1500, 12500, 0x41, ricoh583_ops, 500), - RICOH583_REG(DC1, 0x34, 0, 0x34, 1, 0x35, 0x7F, 0x61, 0x21, 4, + RICOH583_REG(DC1, 0x34, 0, 0x34, 1, 0x35, 0x7F, 0x61, 700, 1500, 12500, 0x41, ricoh583_ops, 500), - RICOH583_REG(DC2, 0x38, 0, 0x38, 1, 0x39, 0x7F, 0x62, 0x22, 0, + RICOH583_REG(DC2, 0x38, 0, 0x38, 1, 0x39, 0x7F, 0x62, 900, 2400, 12500, 0x79, ricoh583_ops, 500), - RICOH583_REG(DC3, 0x3C, 0, 0x3C, 1, 0x3D, 0x7F, 0x63, 0x22, 4, + RICOH583_REG(DC3, 0x3C, 0, 0x3C, 1, 0x3D, 0x7F, 0x63, 900, 2400, 12500, 0x79, ricoh583_ops, 500), - RICOH583_REG(LDO0, 0x51, 0, 0x53, 0, 0x54, 0x7F, 0x64, 0x23, 0, + RICOH583_REG(LDO0, 0x51, 0, 0x53, 0, 0x54, 0x7F, 0x64, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO1, 0x51, 1, 0x53, 1, 0x55, 0x7F, 0x65, 0x23, 4, + RICOH583_REG(LDO1, 0x51, 1, 0x53, 1, 0x55, 0x7F, 0x65, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO2, 0x51, 2, 0x53, 2, 0x56, 0x7F, 0x66, 0x24, 0, + RICOH583_REG(LDO2, 0x51, 2, 0x53, 2, 0x56, 0x7F, 0x66, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO3, 0x51, 3, 0x53, 3, 0x57, 0x7F, 0x67, 0x24, 4, + RICOH583_REG(LDO3, 0x51, 3, 0x53, 3, 0x57, 0x7F, 0x67, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO4, 0x51, 4, 0x53, 4, 0x58, 0x3F, 0x68, 0x25, 0, + RICOH583_REG(LDO4, 0x51, 4, 0x53, 4, 0x58, 0x3F, 0x68, 750, 1500, 12500, 0x3D, ricoh583_ops, 500), - RICOH583_REG(LDO5, 0x51, 5, 0x53, 5, 0x59, 0x7F, 0x69, 0x25, 4, + RICOH583_REG(LDO5, 0x51, 5, 0x53, 5, 0x59, 0x7F, 0x69, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO6, 0x51, 6, 0x53, 6, 0x5A, 0x7F, 0x6A, 0x26, 0, + RICOH583_REG(LDO6, 0x51, 6, 0x53, 6, 0x5A, 0x7F, 0x6A, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO7, 0x51, 7, 0x53, 7, 0x5B, 0x7F, 0x6B, 0x26, 4, + RICOH583_REG(LDO7, 0x51, 7, 0x53, 7, 0x5B, 0x7F, 0x6B, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO8, 0x50, 0, 0x52, 0, 0x5C, 0x7F, 0x6C, 0x27, 0, + RICOH583_REG(LDO8, 0x50, 0, 0x52, 0, 0x5C, 0x7F, 0x6C, 900, 3400, 25000, 0x65, ricoh583_ops, 500), - RICOH583_REG(LDO9, 0x50, 1, 0x52, 1, 0x5D, 0x7F, 0x6D, 0x27, 4, + RICOH583_REG(LDO9, 0x50, 1, 0x52, 1, 0x5D, 0x7F, 0x6D, 900, 3400, 25000, 0x65, ricoh583_ops, 500), }; static inline struct ricoh583_regulator *find_regulator_info(int id) @@ -348,15 +277,13 @@ static int ricoh583_regulator_preinit(struct device *parent, { int ret = 0; - ret = __ricoh583_set_ext_pwrreq1_control(parent, ri, - ricoh583_pdata->flags, ricoh583_pdata->deepsleep_slots); - if (ret < 0) - return ret; - - ret = __ricoh583_set_ext_pwrreq2_control(parent, ri, - ricoh583_pdata->flags); - if (ret < 0) - return ret; + if (ri->deepsleep_id != RICOH583_DS_NONE) { + ret = ricoh583_ext_power_req_config(parent, ri->deepsleep_id, + ricoh583_pdata->ext_pwr_req, + ricoh583_pdata->deepsleep_slots); + if (ret < 0) + return ret; + } if (!ricoh583_pdata->init_apply) return 0; diff --git a/include/linux/mfd/ricoh583.h b/include/linux/mfd/ricoh583.h index e420bc9a57cd..db1099e4cf57 100644 --- a/include/linux/mfd/ricoh583.h +++ b/include/linux/mfd/ricoh583.h @@ -85,6 +85,36 @@ enum { RICOH583_NR_GPIO, }; +enum ricoh583_deepsleep_control_id { + RICOH583_DS_NONE, + RICOH583_DS_DC0, + RICOH583_DS_DC1, + RICOH583_DS_DC2, + RICOH583_DS_DC3, + RICOH583_DS_LDO0, + RICOH583_DS_LDO1, + RICOH583_DS_LDO2, + RICOH583_DS_LDO3, + RICOH583_DS_LDO4, + RICOH583_DS_LDO5, + RICOH583_DS_LDO6, + RICOH583_DS_LDO7, + RICOH583_DS_LDO8, + RICOH583_DS_LDO9, + RICOH583_DS_PSO0, + RICOH583_DS_PSO1, + RICOH583_DS_PSO2, + RICOH583_DS_PSO3, + RICOH583_DS_PSO4, + RICOH583_DS_PSO5, + RICOH583_DS_PSO6, + RICOH583_DS_PSO7, +}; +enum ricoh583_ext_pwrreq_control { + RICOH583_EXT_PWRREQ1_CONTROL = 0x1, + RICOH583_EXT_PWRREQ2_CONTROL = 0x2, +}; + struct ricoh583_subdev_info { int id; const char *name; @@ -122,6 +152,10 @@ extern int ricoh583_set_bits(struct device *dev, u8 reg, uint8_t bit_mask); extern int ricoh583_clr_bits(struct device *dev, u8 reg, uint8_t bit_mask); extern int ricoh583_update(struct device *dev, u8 reg, uint8_t val, uint8_t mask); +extern int ricoh583_ext_power_req_config(struct device *dev, + enum ricoh583_deepsleep_control_id control_id, + enum ricoh583_ext_pwrreq_control ext_pwr_req, + int deepsleep_slot_nr); extern int ricoh583_power_off(void); #endif diff --git a/include/linux/regulator/ricoh583-regulator.h b/include/linux/regulator/ricoh583-regulator.h index 71990b86a2b6..39fdb9e56e05 100644 --- a/include/linux/regulator/ricoh583-regulator.h +++ b/include/linux/regulator/ricoh583-regulator.h @@ -49,11 +49,6 @@ enum regulator_id { RICOH583_ID_LDO9, }; -enum ext_control { - EXT_PWRREQ1_CONTROL = 0x1, - EXT_PWRREQ2_CONTROL = 0x2, -}; - struct ricoh583_regulator_platform_data { struct regulator_init_data regulator; int init_uV; @@ -61,6 +56,7 @@ struct ricoh583_regulator_platform_data { unsigned init_apply:1; int deepsleep_uV; int deepsleep_slots; + unsigned long ext_pwr_req; unsigned long flags; }; |