From d454cee86edac49aca7bdc1d2357e69adfe829ee Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 24 Nov 2011 19:23:46 +0530 Subject: mfd: tps80031: Support sleep configuration through platform data Supporting the sleep configuration through platform data. Rearranging clock initialization to take external power control. Reviewed-on: http://git-master/r/67076 (cherry picked from commit 9da9d369bdbe988b98eec9b63085dfdb26de8237) Change-Id: I40c5a8608522dbc322e148b5d569e8f5a00faa21 Signed-off-by: Laxman Dewangan Reviewed-on: http://git-master/r/67331 --- drivers/mfd/tps80031.c | 106 +++++++++++++++++++++++++-------- drivers/regulator/tps80031-regulator.c | 33 ++++++++-- 2 files changed, 107 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c index 1cffa45f1e96..6fe80dc51931 100644 --- a/drivers/mfd/tps80031.c +++ b/drivers/mfd/tps80031.c @@ -106,6 +106,11 @@ static u8 pmc_ext_control_base[] = { SYSEN_BASE_ADD, }; +static u8 pmc_clk32k_control_base[] = { + CLK32KAO_BASE_ADD, + CLK32KG_BASE_ADD, + CLK32KAUDIO_BASE_ADD, +}; struct tps80031_irq_data { u8 mask_reg; u8 mask_mask; @@ -416,23 +421,23 @@ 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, + unsigned long ext_ctrl_flag, 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)) + if (!(ext_ctrl_flag & EXT_PWR_REQ)) return 0; - if (ext_pwr_ctrl & PWR_REQ_INPUT_PREQ1) { + if (ext_ctrl_flag & 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) { + } else if (ext_ctrl_flag & 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) { + } else if (ext_ctrl_flag & PWR_REQ_INPUT_PREQ3) { res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3); preq_mask_bit = 7; } @@ -459,7 +464,7 @@ int tps80031_ext_power_req_config(struct device *dev, } /* Switch regulator control to resource now */ - if (ext_pwr_ctrl & (PWR_REQ_INPUT_PREQ2 | PWR_REQ_INPUT_PREQ3)) { + if (ext_ctrl_flag & (PWR_REQ_INPUT_PREQ2 | PWR_REQ_INPUT_PREQ3)) { ret = tps80031_update(dev, SLAVE_ID1, state_reg_add, 0x0, STATE_MASK); if (ret < 0) @@ -596,7 +601,6 @@ 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) { @@ -614,16 +618,35 @@ static void tps80031_gpio_init(struct tps80031 *tps80031, /* 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"); + struct tps80031_gpio_init_data *gpio_pd = &gpio_init_data[i]; + base_add = pmc_ext_control_base[gpio_pd->gpio_nr]; + + if (gpio_pd->ext_ctrl_flag & EXT_PWR_REQ) { + ret = tps80031_ext_power_req_config(tps80031->dev, + gpio_pd->ext_ctrl_flag, + preq_bit_pos[gpio_pd->gpio_nr], + base_add + EXT_CONTROL_CFG_STATE, + base_add + EXT_CONTROL_CFG_TRANS); + if (ret < 0) + dev_warn(tps80031->dev, "Ext pwrreq GPIO " + "sleep control fails\n"); + } + + if (gpio_pd->ext_ctrl_flag & PWR_OFF_ON_SLEEP) { + ret = tps80031_update(tps80031->dev, SLAVE_ID1, + base_add + EXT_CONTROL_CFG_TRANS, 0x0, 0xC); + if (ret < 0) + dev_warn(tps80031->dev, "GPIO OFF on sleep " + "control fails\n"); + } + + if (gpio_pd->ext_ctrl_flag & PWR_ON_ON_SLEEP) { + ret = tps80031_update(tps80031->dev, SLAVE_ID1, + base_add + EXT_CONTROL_CFG_TRANS, 0x4, 0xC); + if (ret < 0) + dev_warn(tps80031->dev, "GPIO ON on sleep " + "control fails\n"); + } } tps80031->gpio.owner = THIS_MODULE; @@ -917,20 +940,51 @@ static void tps80031_clk32k_enable(struct tps80031 *tps80031, int base_add) static void tps80031_clk32k_init(struct tps80031 *tps80031, struct tps80031_platform_data *pdata) { - struct tps80031_32kclock_plat_data *clk32k_pdata; + int ret; + struct tps80031_clk32k_init_data *clk32_idata = pdata->clk32k_init_data; + int data_size = pdata->clk32k_init_data_size; + static int clk32k_preq_bit_pos[TPS80031_CLOCK32K_NR] = {-1, 20, 19}; + int base_add; + int i; - if (!(pdata && pdata->clk32k_pdata)) + if (!clk32_idata || !data_size) return; - clk32k_pdata = pdata->clk32k_pdata; - if (clk32k_pdata->en_clk32kao) - tps80031_clk32k_enable(tps80031, CLK32KAO_BASE_ADD); + /* Configure the external request mode */ + for (i = 0; i < data_size; ++i) { + struct tps80031_clk32k_init_data *clk32_pd = &clk32_idata[i]; + base_add = pmc_clk32k_control_base[clk32_pd->clk32k_nr]; + if (clk32_pd->enable) + tps80031_clk32k_enable(tps80031, base_add); + + if ((clk32_pd->ext_ctrl_flag & EXT_PWR_REQ) && + (clk32k_preq_bit_pos[clk32_pd->clk32k_nr] != -1)) { + ret = tps80031_ext_power_req_config(tps80031->dev, + clk32_pd->ext_ctrl_flag, + clk32k_preq_bit_pos[clk32_pd->clk32k_nr], + base_add + EXT_CONTROL_CFG_STATE, + base_add + EXT_CONTROL_CFG_TRANS); + if (ret < 0) + dev_warn(tps80031->dev, "Clk32 ext control " + "fails\n"); + } - if (clk32k_pdata->en_clk32kg) - tps80031_clk32k_enable(tps80031, CLK32KG_BASE_ADD); + if (clk32_pd->ext_ctrl_flag & PWR_OFF_ON_SLEEP) { + ret = tps80031_update(tps80031->dev, SLAVE_ID1, + base_add + EXT_CONTROL_CFG_TRANS, 0x0, 0xC); + if (ret < 0) + dev_warn(tps80031->dev, "clk OFF on sleep " + "control fails\n"); + } - if (clk32k_pdata->en_clk32kaudio) - tps80031_clk32k_enable(tps80031, CLK32KAUDIO_BASE_ADD); + if (clk32_pd->ext_ctrl_flag & PWR_ON_ON_SLEEP) { + ret = tps80031_update(tps80031->dev, SLAVE_ID1, + base_add + EXT_CONTROL_CFG_TRANS, 0x4, 0xC); + if (ret < 0) + dev_warn(tps80031->dev, "clk ON sleep " + "control fails\n"); + } + } } static int __devinit tps80031_add_subdevs(struct tps80031 *tps80031, diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c index 9ea5cb9725a6..deca7adebb14 100644 --- a/drivers/regulator/tps80031-regulator.c +++ b/drivers/regulator/tps80031-regulator.c @@ -106,7 +106,7 @@ struct tps80031_regulator { u8 flags; unsigned int platform_flags; - enum tps80031_ext_control ext_pwr_ctrl; + unsigned int ext_ctrl_flag; /* used by regulator core */ struct regulator_desc desc; @@ -160,7 +160,7 @@ static int tps80031_reg_is_enabled(struct regulator_dev *rdev) { struct tps80031_regulator *ri = rdev_get_drvdata(rdev); - if (ri->ext_pwr_ctrl & EXT_PWR_REQ) + if (ri->ext_ctrl_flag & EXT_PWR_REQ) return true; return ((ri->state_reg_cache & STATE_MASK) == STATE_ON); } @@ -172,7 +172,7 @@ static int tps80031_reg_enable(struct regulator_dev *rdev) int ret; uint8_t reg_val; - if (ri->ext_pwr_ctrl & EXT_PWR_REQ) + if (ri->ext_ctrl_flag & EXT_PWR_REQ) return 0; reg_val = (ri->state_reg_cache & ~STATE_MASK) | @@ -194,7 +194,7 @@ static int tps80031_reg_disable(struct regulator_dev *rdev) int ret; uint8_t reg_val; - if (ri->ext_pwr_ctrl & EXT_PWR_REQ) + if (ri->ext_ctrl_flag & EXT_PWR_REQ) return 0; reg_val = (ri->state_reg_cache & ~STATE_MASK) | @@ -793,10 +793,12 @@ static int tps80031_power_req_config(struct device *parent, struct tps80031_regulator_platform_data *tps80031_pdata) { int ret; + uint8_t reg_val; + if (ri->preq_bit < 0) return 0; - ret = tps80031_ext_power_req_config(parent, ri->ext_pwr_ctrl, + ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag, ri->preq_bit, ri->state_reg, ri->trans_reg); if (!ret) ret = tps80031_read(parent, SLAVE_ID1, ri->trans_reg, @@ -805,6 +807,25 @@ static int tps80031_power_req_config(struct device *parent, if (!ret && ri->state_reg) ret = tps80031_read(parent, SLAVE_ID1, ri->state_reg, &ri->state_reg_cache); + if (ret < 0) { + dev_err(ri->dev, "%s() fails\n", __func__); + return ret; + } + + if (tps80031_pdata->ext_ctrl_flag & + (PWR_OFF_ON_SLEEP | PWR_ON_ON_SLEEP)) { + reg_val = (ri->trans_reg_cache & ~0xC); + if (tps80031_pdata->ext_ctrl_flag & PWR_ON_ON_SLEEP) + reg_val |= 0x4; + + ret = tps80031_write(parent, SLAVE_ID1, ri->trans_reg, + reg_val); + if (ret < 0) + dev_err(ri->dev, "Not able to write reg 0x%02x\n", + ri->trans_reg); + else + ri->trans_reg_cache = reg_val; + } return ret; } @@ -997,7 +1018,7 @@ static int __devinit tps80031_regulator_probe(struct platform_device *pdev) check_smps_mode_mult(pdev->dev.parent, ri); ri->platform_flags = tps_pdata->flags; - ri->ext_pwr_ctrl = tps_pdata->ext_pwr_ctrl; + ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag; err = tps80031_cache_regulator_register(pdev->dev.parent, ri); if (err) { -- cgit v1.2.3