regulator: fan53555: fix up the dcdc is disabled when reboot

Before reboot if the DCDC is disabled,
the DCDC is still disabled after restart.
We have an method to workaround:
Use vsel pin to switch the voltage between value in FAN53555_VSEL0
and FAN53555_VSEL1. If VSEL pin is inactive, the voltage of DCDC
are controlled by FAN53555_VSEL0, when we pull vsel pin to active,
they would be controlled by FAN53555_VSEL1.
In this case, we can set FAN53555_VSEL1 to disable dcdc,
So we can make vsel pin to active to disable dcdc,
VSEL pin is inactive to enable DCDC.

Change-Id: I14c823ed11dc3369044ad2ed0b53a6027acbccd0
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
Elaine Zhang
2016-08-16 18:44:04 +08:00
committed by Tao Huang
parent 30c764755f
commit 14d85ea556
2 changed files with 76 additions and 4 deletions
+75 -4
View File
@@ -20,6 +20,8 @@
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/regulator/fan53555.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
/* Voltage setting */
#define FAN53555_VSEL0 0x00
@@ -106,6 +108,8 @@ struct fan53555_device_info {
unsigned int mode_mask;
/* Sleep voltage cache */
unsigned int sleep_vol_cache;
struct gpio_desc *vsel_gpio;
unsigned int sleep_vsel_id;
};
static unsigned int fan53555_map_mode(unsigned int mode)
@@ -151,6 +155,54 @@ static int fan53555_set_suspend_disable(struct regulator_dev *rdev)
VSEL_BUCK_EN, 0);
}
static int fan53555_set_enable(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
if (di->vsel_gpio) {
gpiod_set_raw_value(di->vsel_gpio, !di->sleep_vsel_id);
return 0;
}
return regmap_update_bits(rdev->regmap, di->vol_reg,
VSEL_BUCK_EN, VSEL_BUCK_EN);
}
static int fan53555_set_disable(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
if (di->vsel_gpio) {
gpiod_set_raw_value(di->vsel_gpio, di->sleep_vsel_id);
return 0;
}
return regmap_update_bits(rdev->regmap, di->vol_reg,
VSEL_BUCK_EN, 0);
}
static int fan53555_is_enabled(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
unsigned int val;
int ret = 0;
if (di->vsel_gpio) {
if (di->sleep_vsel_id)
return !gpiod_get_raw_value(di->vsel_gpio);
else
return gpiod_get_raw_value(di->vsel_gpio);
}
ret = regmap_read(rdev->regmap, di->vol_reg, &val);
if (ret < 0)
return ret;
if (val & VSEL_BUCK_EN)
return 1;
else
return 0;
}
static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
@@ -223,9 +275,9 @@ static const struct regulator_ops fan53555_regulator_ops = {
.map_voltage = regulator_map_voltage_linear,
.list_voltage = regulator_list_voltage_linear,
.set_suspend_voltage = fan53555_set_suspend_voltage,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = fan53555_set_enable,
.disable = fan53555_set_disable,
.is_enabled = fan53555_is_enabled,
.set_mode = fan53555_set_mode,
.get_mode = fan53555_get_mode,
.set_ramp_delay = fan53555_set_ramp,
@@ -410,6 +462,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
rdesc->vsel_reg = di->vol_reg;
rdesc->vsel_mask = di->vsel_count - 1;
rdesc->owner = THIS_MODULE;
rdesc->enable_time = 400;
rdev = devm_regulator_register(di->dev, &di->desc, config);
return PTR_ERR_OR_ZERO(rdev);
@@ -425,7 +478,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
const struct regulator_desc *desc)
{
struct fan53555_platform_data *pdata;
int ret;
int ret, flag;
u32 tmp;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -433,12 +486,27 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
return NULL;
pdata->regulator = of_get_regulator_init_data(dev, np, desc);
pdata->regulator->constraints.initial_state = PM_SUSPEND_MEM;
ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
&tmp);
if (!ret)
pdata->sleep_vsel_id = tmp;
if (pdata->sleep_vsel_id)
flag = GPIOD_OUT_LOW;
else
flag = GPIOD_OUT_HIGH;
pdata->vsel_gpio =
devm_gpiod_get_index_optional(dev, "vsel", 0,
flag);
if (IS_ERR(pdata->vsel_gpio)) {
ret = PTR_ERR(pdata->vsel_gpio);
dev_err(dev, "failed to get vesl gpio (%d)\n", ret);
pdata->vsel_gpio = NULL;
}
return pdata;
}
@@ -487,6 +555,9 @@ static int fan53555_regulator_probe(struct i2c_client *client,
return -ENODEV;
}
di->vsel_gpio = pdata->vsel_gpio;
di->sleep_vsel_id = pdata->sleep_vsel_id;
di->regulator = pdata->regulator;
if (client->dev.of_node) {
di->vendor =
+1
View File
@@ -52,6 +52,7 @@ struct fan53555_platform_data {
unsigned int slew_rate;
/* Sleep VSEL ID */
unsigned int sleep_vsel_id;
struct gpio_desc *vsel_gpio;
};
#endif /* __FAN53555_H__ */