summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/ricoh583.c150
-rw-r--r--drivers/regulator/ricoh583-regulator.c123
-rw-r--r--include/linux/mfd/ricoh583.h34
-rw-r--r--include/linux/regulator/ricoh583-regulator.h6
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;
};