mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
rtc: rv3032: allow setting BSM
Backup Switch Mode is currently set properly when the trickle charger is enabled. However, in the case of a non-rechargeable battery, it is necessary to be able to enable it, only allow that when the trickle charger is disabled. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Link: https://lore.kernel.org/r/20211018151933.76865-8-alexandre.belloni@bootlin.com
This commit is contained in:
parent
018d959ba7
commit
6084eac38e
@ -106,6 +106,7 @@
|
|||||||
struct rv3032_data {
|
struct rv3032_data {
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
|
bool trickle_charger_set;
|
||||||
#ifdef CONFIG_COMMON_CLK
|
#ifdef CONFIG_COMMON_CLK
|
||||||
struct clk_hw clkout_hw;
|
struct clk_hw clkout_hw;
|
||||||
#endif
|
#endif
|
||||||
@ -402,6 +403,75 @@ static int rv3032_set_offset(struct device *dev, long offset)
|
|||||||
FIELD_PREP(RV3032_OFFSET_MSK, offset));
|
FIELD_PREP(RV3032_OFFSET_MSK, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rv3032_param_get(struct device *dev, struct rtc_param *param)
|
||||||
|
{
|
||||||
|
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch(param->param) {
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||||
|
ret = regmap_read(rv3032->regmap, RV3032_PMU, &value);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
value = FIELD_GET(RV3032_PMU_BSM, value);
|
||||||
|
|
||||||
|
switch(value) {
|
||||||
|
case RV3032_PMU_BSM_DSM:
|
||||||
|
param->uvalue = RTC_BSM_DIRECT;
|
||||||
|
break;
|
||||||
|
case RV3032_PMU_BSM_LSM:
|
||||||
|
param->uvalue = RTC_BSM_LEVEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
param->uvalue = RTC_BSM_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rv3032_param_set(struct device *dev, struct rtc_param *param)
|
||||||
|
{
|
||||||
|
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
switch(param->param) {
|
||||||
|
u8 mode;
|
||||||
|
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||||
|
if (rv3032->trickle_charger_set)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (param->uvalue) {
|
||||||
|
case RTC_BSM_DISABLED:
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
case RTC_BSM_DIRECT:
|
||||||
|
mode = RV3032_PMU_BSM_DSM;
|
||||||
|
break;
|
||||||
|
case RTC_BSM_LEVEL:
|
||||||
|
mode = RV3032_PMU_BSM_LSM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv3032_update_cfg(rv3032, RV3032_PMU, RV3032_PMU_BSM,
|
||||||
|
FIELD_PREP(RV3032_PMU_BSM, mode));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
|
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
|
||||||
@ -541,6 +611,8 @@ static int rv3032_trickle_charger_setup(struct device *dev, struct rv3032_data *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv3032->trickle_charger_set = true;
|
||||||
|
|
||||||
return rv3032_update_cfg(rv3032, RV3032_PMU,
|
return rv3032_update_cfg(rv3032, RV3032_PMU,
|
||||||
RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM,
|
RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM,
|
||||||
val | FIELD_PREP(RV3032_PMU_TCR, i));
|
val | FIELD_PREP(RV3032_PMU_TCR, i));
|
||||||
@ -813,6 +885,8 @@ static const struct rtc_class_ops rv3032_rtc_ops = {
|
|||||||
.read_alarm = rv3032_get_alarm,
|
.read_alarm = rv3032_get_alarm,
|
||||||
.set_alarm = rv3032_set_alarm,
|
.set_alarm = rv3032_set_alarm,
|
||||||
.alarm_irq_enable = rv3032_alarm_irq_enable,
|
.alarm_irq_enable = rv3032_alarm_irq_enable,
|
||||||
|
.param_get = rv3032_param_get,
|
||||||
|
.param_set = rv3032_param_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regmap_config regmap_config = {
|
static const struct regmap_config regmap_config = {
|
||||||
@ -883,6 +957,8 @@ static int rv3032_probe(struct i2c_client *client)
|
|||||||
|
|
||||||
rv3032_trickle_charger_setup(&client->dev, rv3032);
|
rv3032_trickle_charger_setup(&client->dev, rv3032);
|
||||||
|
|
||||||
|
set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3032->rtc->features);
|
||||||
|
|
||||||
rv3032->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
rv3032->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
rv3032->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
rv3032->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
rv3032->rtc->ops = &rv3032_rtc_ops;
|
rv3032->rtc->ops = &rv3032_rtc_ops;
|
||||||
|
Loading…
Reference in New Issue
Block a user