summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2011-11-08 11:36:02 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:03 -0800
commit06d83985d3959fae1c27898c55ccb541025c7d3a (patch)
treea5ab2c1609f746e63a53a2102e5d105e510130c3 /drivers/mfd
parent53300ac9ea9da75f06dd955800f3bdf6280d8a94 (diff)
mfd: tps80031: Move external pwr req to core driver
Moving the configuration function for configuring the rail control through the PREQ line to core from regulator driver. Fixing the correct voltage configuration for the LDO2 based on TRACK mode. Reviewed-on: http://git-master/r/63503 (cherry picked from commit 9190130f6cf1ba0bae3231321841ebe4ad94a54e) Change-Id: I7dd511da7f809a44b1e66706054c0a4c57c36323 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/64055 Rebase-Id: R433728b4c83ccaf6f3ae2734412a90d9c89b6a2c
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/tps80031.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index 3630f7b0b66d..094adaa19a49 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -87,7 +87,18 @@
#define STATE_ON 0x01
#define STATE_MASK 0x03
+#define TRANS_SLEEP_OFF 0x00
+#define TRANS_SLEEP_ON 0x04
+#define TRANS_SLEEP_MASK 0x0C
+
#define TPS_NUM_SLAVES 4
+#define EXT_PWR_REQ (PWR_REQ_INPUT_PREQ1 | PWR_REQ_INPUT_PREQ2 | \
+ PWR_REQ_INPUT_PREQ3)
+#define TPS80031_PREQ1_RES_ASS_A 0xD7
+#define TPS80031_PREQ2_RES_ASS_A 0xDA
+#define TPS80031_PREQ3_RES_ASS_A 0xDD
+#define TPS80031_PHOENIX_MSK_TRANSITION 0x20
+
static u8 pmc_ext_control_base[] = {
REGEN1_BASE_ADD,
@@ -403,6 +414,69 @@ out:
}
EXPORT_SYMBOL_GPL(tps80031_force_update);
+int tps80031_ext_power_req_config(struct device *dev,
+ enum tps80031_ext_control ext_pwr_ctrl, int preq_bit,
+ int state_reg_add, int trans_reg_add)
+{
+ u8 res_ass_reg = 0;
+ int preq_mask_bit = 0;
+ int ret;
+
+ if (!(ext_pwr_ctrl & EXT_PWR_REQ))
+ return 0;
+
+ if (ext_pwr_ctrl & PWR_REQ_INPUT_PREQ1) {
+ res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (preq_bit >> 3);
+ preq_mask_bit = 5;
+ } else if (ext_pwr_ctrl & PWR_REQ_INPUT_PREQ2) {
+ res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (preq_bit >> 3);
+ preq_mask_bit = 6;
+ } else if (ext_pwr_ctrl & PWR_REQ_INPUT_PREQ3) {
+ res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3);
+ preq_mask_bit = 7;
+ }
+
+ /* Configure REQ_ASS registers */
+ ret = tps80031_set_bits(dev, SLAVE_ID1, res_ass_reg,
+ BIT(preq_bit & 0x7));
+ if (ret < 0) {
+ dev_err(dev, "%s() Not able to set bit %d of "
+ "reg %d error %d\n",
+ __func__, preq_bit, res_ass_reg, ret);
+ return ret;
+ }
+
+ /* Unmask the PREQ */
+ ret = tps80031_clr_bits(dev, SLAVE_ID1,
+ TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit));
+ if (ret < 0) {
+ dev_err(dev, "%s() Not able to clear bit %d of "
+ "reg %d error %d\n",
+ __func__, preq_mask_bit,
+ TPS80031_PHOENIX_MSK_TRANSITION, ret);
+ return ret;
+ }
+
+ /* Switch regulator control to resource now */
+ if (ext_pwr_ctrl & (PWR_REQ_INPUT_PREQ2 | PWR_REQ_INPUT_PREQ3)) {
+ ret = tps80031_update(dev, SLAVE_ID1, state_reg_add, 0x0,
+ STATE_MASK);
+ if (ret < 0)
+ dev_err(dev, "%s() Error in writing the STATE "
+ "register %d error %d\n", __func__,
+ state_reg_add, ret);
+ } else {
+ ret = tps80031_update(dev, SLAVE_ID1, trans_reg_add,
+ TRANS_SLEEP_OFF, TRANS_SLEEP_MASK);
+ if (ret < 0)
+ dev_err(dev, "%s() Error in writing the TRANS "
+ "register %d error %d\n", __func__,
+ trans_reg_add, ret);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config);
+
unsigned long tps80031_get_chip_info(struct device *dev)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
@@ -421,6 +495,29 @@ int tps80031_power_off(void)
return __tps80031_write(tps->client, TPS80031_PHOENIX_DEV_ON, DEVOFF);
}
+static void tps80031_init_ext_control(struct tps80031 *tps80031,
+ struct tps80031_platform_data *pdata) {
+ int ret;
+ int i;
+
+ /* Clear all external control for this rail */
+ for (i = 0; i < 9; ++i) {
+ tps80031_write(tps80031->dev, SLAVE_ID1,
+ TPS80031_PREQ1_RES_ASS_A + i, 0);
+ if (ret < 0)
+ dev_err(tps80031->dev, "%s() Error in clearing "
+ "register %02x\n", __func__,
+ TPS80031_PREQ1_RES_ASS_A + i);
+ }
+
+ /* Mask the PREQ */
+ ret = tps80031_set_bits(tps80031->dev, SLAVE_ID1,
+ TPS80031_PHOENIX_MSK_TRANSITION, 0x7 << 5);
+ if (ret < 0)
+ dev_err(tps80031->dev, "%s() Not able to mask register "
+ "0x%02x\n", __func__, TPS80031_PHOENIX_MSK_TRANSITION);
+}
+
static int tps80031_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct tps80031 *tps80031 = container_of(gc, struct tps80031, gpio);
@@ -491,16 +588,36 @@ static void tps80031_gpio_disable(struct gpio_chip *gc, unsigned offset)
STATE_OFF, STATE_MASK);
}
+
static void tps80031_gpio_init(struct tps80031 *tps80031,
struct tps80031_platform_data *pdata)
{
int ret;
int gpio_base = pdata->gpio_base;
struct tps80031_client *tps = &tps80031->tps_clients[SLAVE_ID1];
+ struct tps80031_gpio_init_data *gpio_init_data = pdata->gpio_init_data;
+ int data_size = pdata->gpio_init_data_size;
+ static int preq_bit_pos[TPS80031_GPIO_NR] = {16, 17, 18};
+ int base_add;
+ int i;
if (gpio_base <= 0)
return;
+ /* Configure the external request mode */
+ for (i = 0; i < data_size; ++i) {
+ if (!(gpio_init_data[i].ext_control & EXT_PWR_REQ))
+ continue;
+ base_add = pmc_ext_control_base[gpio_init_data[i].gpio_nr];
+ ret = tps80031_ext_power_req_config(tps80031->dev,
+ gpio_init_data[i].ext_control,
+ preq_bit_pos[gpio_init_data[i].gpio_nr],
+ base_add + EXT_CONTROL_CFG_STATE,
+ base_add + EXT_CONTROL_CFG_TRANS);
+ if (!ret)
+ dev_warn(tps80031->dev, "GPIO sleep control fails\n");
+ }
+
tps80031->gpio.owner = THIS_MODULE;
tps80031->gpio.label = tps->client->name;
tps80031->gpio.dev = tps80031->dev;
@@ -890,6 +1007,7 @@ static int dbg_tps_show(struct seq_file *s, void *unused)
print_regs("INT Regs", s, SLAVE_ID2, 0xD0, 0xD8);
print_regs("PREQ Regs", s, SLAVE_ID1, 0xD7, 0xDF);
print_regs("MASK_PH Regs", s, SLAVE_ID1, 0x20, 0x21);
+ print_regs("PMC MISC Regs", s, SLAVE_ID1, 0xE0, 0xEF);
print_regs("CONT_STATE", s, SLAVE_ID2, 0xE0, 0xE4);
print_regs("VERNUM Regs", s, SLAVE_ID1, 0x87, 0x87);
print_regs("CHARGE Regs", s, SLAVE_ID2, 0xDA, 0xF5);
@@ -1014,6 +1132,7 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
goto fail;
}
}
+ tps80031_init_ext_control(tps80031, pdata);
ret = tps80031_add_subdevs(tps80031, pdata);
if (ret) {