diff options
-rw-r--r-- | drivers/mfd/ricoh583.c | 16 | ||||
-rw-r--r-- | drivers/regulator/ricoh583-regulator.c | 149 | ||||
-rw-r--r-- | include/linux/regulator/ricoh583-regulator.h | 7 |
3 files changed, 136 insertions, 36 deletions
diff --git a/drivers/mfd/ricoh583.c b/drivers/mfd/ricoh583.c index 794f6bf48dea..fa11254806b1 100644 --- a/drivers/mfd/ricoh583.c +++ b/drivers/mfd/ricoh583.c @@ -499,10 +499,12 @@ static void __devinit ricoh583_gpio_init(struct ricoh583 *ricoh583, dev_err(ricoh583->dev, "Gpio %d init " "dir configuration failed: %d\n", i, ret); - ret = ricoh583_clr_bits(ricoh583->dev, RICOH583_GPIO_PGSEL, 1 << i); + ret = ricoh583_clr_bits(ricoh583->dev, RICOH583_GPIO_PGSEL, + 1 << i); if (ret < 0) - dev_err(ricoh583->dev, "%s(): The error in writing register " - "0x%02x\n", __func__, RICOH583_GPIO_PGSEL); + dev_err(ricoh583->dev, "%s(): The error in writing " + "register 0x%02x\n", __func__, + RICOH583_GPIO_PGSEL); } ricoh583->gpio.owner = THIS_MODULE; @@ -941,6 +943,14 @@ 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); + goto err_irq_init; + } + if (i2c->irq) { ret = ricoh583_irq_init(ricoh583, i2c->irq, pdata->irq_base); if (ret) { diff --git a/drivers/regulator/ricoh583-regulator.c b/drivers/regulator/ricoh583-regulator.c index 4ea861969b89..33f13252cfa7 100644 --- a/drivers/regulator/ricoh583-regulator.c +++ b/drivers/regulator/ricoh583-regulator.c @@ -36,6 +36,8 @@ #include <linux/mfd/ricoh583.h> #include <linux/regulator/ricoh583-regulator.h> + +#define RICOH_ONOFFSEL_REG 0x10 struct ricoh583_regulator { int id; /* Regulator register address.*/ @@ -47,6 +49,8 @@ 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; @@ -64,6 +68,7 @@ struct ricoh583_regulator { struct device *dev; }; + static inline struct device *to_ricoh583_dev(struct regulator_dev *rdev) { return rdev_get_dev(rdev)->parent->parent; @@ -145,6 +150,73 @@ 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) { @@ -159,7 +231,8 @@ static int __ricoh583_set_voltage(struct device *parent, if (vsel > ri->nsteps) return -EDOM; - vout_val = (ri->vout_reg_cache & ~ri->vout_mask) | (vsel & ri->vout_mask); + vout_val = (ri->vout_reg_cache & ~ri->vout_mask) | + (vsel & ri->vout_mask); ret = ricoh583_write(parent, ri->vout_reg, vout_val); if (ret < 0) dev_err(ri->dev, "Error in writing the Voltage register\n"); @@ -187,7 +260,6 @@ static int ricoh583_get_voltage(struct regulator_dev *rdev) return ri->min_uV + vsel * ri->step_uV; } - static struct regulator_ops ricoh583_ops = { .list_voltage = ricoh583_list_voltage, .set_voltage = ricoh583_set_voltage, @@ -198,10 +270,9 @@ static struct regulator_ops ricoh583_ops = { .enable_time = ricoh583_regulator_enable_time, }; - #define RICOH583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ - _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \ - _ops, _delay) \ + _vout_mask, _ds_reg, _slpseq_reg, _slpseq_shift, _min_mv, \ + _max_mv, _step_uV, _nsteps, _ops, _delay) \ { \ .reg_en_reg = _en_reg, \ .en_bit = _en_bit, \ @@ -210,6 +281,8 @@ 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, \ @@ -227,34 +300,34 @@ static struct regulator_ops ricoh583_ops = { } static struct ricoh583_regulator ricoh583_regulator[] = { - 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, 700, 1500, - 12500, 0x41, ricoh583_ops, 500), - 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, 900, 2400, - 12500, 0x79, ricoh583_ops, 500), - 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, 900, 3400, - 25000, 0x65, ricoh583_ops, 500), - 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, 900, 3400, - 25000, 0x65, ricoh583_ops, 500), - 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, 900, 3400, - 25000, 0x65, ricoh583_ops, 500), - 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, 900, 3400, - 25000, 0x65, ricoh583_ops, 500), - 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, 900, 3400, - 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(DC0, 0x30, 0, 0x30, 1, 0x31, 0x7F, 0x60, 0x21, 0, + 700, 1500, 12500, 0x41, ricoh583_ops, 500), + RICOH583_REG(DC1, 0x34, 0, 0x34, 1, 0x35, 0x7F, 0x61, 0x21, 4, + 700, 1500, 12500, 0x41, ricoh583_ops, 500), + RICOH583_REG(DC2, 0x38, 0, 0x38, 1, 0x39, 0x7F, 0x62, 0x22, 0, + 900, 2400, 12500, 0x79, ricoh583_ops, 500), + RICOH583_REG(DC3, 0x3C, 0, 0x3C, 1, 0x3D, 0x7F, 0x63, 0x22, 4, + 900, 2400, 12500, 0x79, ricoh583_ops, 500), + RICOH583_REG(LDO0, 0x51, 0, 0x53, 0, 0x54, 0x7F, 0x64, 0x23, 0, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO1, 0x51, 1, 0x53, 1, 0x55, 0x7F, 0x65, 0x23, 4, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO2, 0x51, 2, 0x53, 2, 0x56, 0x7F, 0x66, 0x24, 0, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO3, 0x51, 3, 0x53, 3, 0x57, 0x7F, 0x67, 0x24, 4, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO4, 0x51, 4, 0x53, 4, 0x58, 0x3F, 0x68, 0x25, 0, + 750, 1500, 12500, 0x3D, ricoh583_ops, 500), + RICOH583_REG(LDO5, 0x51, 5, 0x53, 5, 0x59, 0x7F, 0x69, 0x25, 4, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO6, 0x51, 6, 0x53, 6, 0x5A, 0x7F, 0x6A, 0x26, 0, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO7, 0x51, 7, 0x53, 7, 0x5B, 0x7F, 0x6B, 0x26, 4, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO8, 0x50, 0, 0x52, 0, 0x5C, 0x7F, 0x6C, 0x27, 0, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), + RICOH583_REG(LDO9, 0x50, 1, 0x52, 1, 0x5D, 0x7F, 0x6D, 0x27, 4, + 900, 3400, 25000, 0x65, ricoh583_ops, 500), }; static inline struct ricoh583_regulator *find_regulator_info(int id) { @@ -275,6 +348,16 @@ 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 (!ricoh583_pdata->init_apply) return 0; diff --git a/include/linux/regulator/ricoh583-regulator.h b/include/linux/regulator/ricoh583-regulator.h index d932f7094459..71990b86a2b6 100644 --- a/include/linux/regulator/ricoh583-regulator.h +++ b/include/linux/regulator/ricoh583-regulator.h @@ -49,12 +49,19 @@ 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; unsigned init_enable:1; unsigned init_apply:1; int deepsleep_uV; + int deepsleep_slots; + unsigned long flags; }; #endif |