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:
@@ -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 =
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
Reference in New Issue
Block a user