mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
rtc: pcf2127: add BSM support
The pcf2127 encodes BSM, BLD and power fail detection in the same set of bits so it is necessary to do some calculation when changing BSM to keep the rest of the configuration as-is. However, when BSM is disabled, there is no configuration with BLD enabled so this will be lost when coming back to a mode with BSM enabled. Link: https://lore.kernel.org/r/20250127162728.86234-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
parent
58589c6a6e
commit
97274527e8
@ -20,6 +20,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
@ -48,6 +49,7 @@
|
||||
#define PCF2127_BIT_CTRL3_BLF BIT(2)
|
||||
#define PCF2127_BIT_CTRL3_BF BIT(3)
|
||||
#define PCF2127_BIT_CTRL3_BTSE BIT(4)
|
||||
#define PCF2127_CTRL3_PM GENMASK(7, 5)
|
||||
/* Time and date registers */
|
||||
#define PCF2127_REG_TIME_BASE 0x03
|
||||
#define PCF2127_BIT_SC_OSF BIT(7)
|
||||
@ -331,6 +333,84 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf2127_param_get(struct device *dev, struct rtc_param *param)
|
||||
{
|
||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
switch (param->param) {
|
||||
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
value = FIELD_GET(PCF2127_CTRL3_PM, value);
|
||||
|
||||
if (value < 0x3)
|
||||
param->uvalue = RTC_BSM_LEVEL;
|
||||
else if (value < 0x6)
|
||||
param->uvalue = RTC_BSM_DIRECT;
|
||||
else
|
||||
param->uvalue = RTC_BSM_DISABLED;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf2127_param_set(struct device *dev, struct rtc_param *param)
|
||||
{
|
||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||
u8 mode = 0;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
switch (param->param) {
|
||||
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
value = FIELD_GET(PCF2127_CTRL3_PM, value);
|
||||
|
||||
if (value > 5)
|
||||
value -= 5;
|
||||
else if (value > 2)
|
||||
value -= 3;
|
||||
|
||||
switch (param->uvalue) {
|
||||
case RTC_BSM_LEVEL:
|
||||
break;
|
||||
case RTC_BSM_DIRECT:
|
||||
mode = 3;
|
||||
break;
|
||||
case RTC_BSM_DISABLED:
|
||||
if (value == 0)
|
||||
value = 1;
|
||||
mode = 5;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
|
||||
PCF2127_CTRL3_PM,
|
||||
FIELD_PREP(PCF2127_CTRL3_PM, mode + value));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf2127_rtc_ioctl(struct device *dev,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
@ -741,6 +821,8 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
|
||||
.read_alarm = pcf2127_rtc_read_alarm,
|
||||
.set_alarm = pcf2127_rtc_set_alarm,
|
||||
.alarm_irq_enable = pcf2127_rtc_alarm_irq_enable,
|
||||
.param_get = pcf2127_param_get,
|
||||
.param_set = pcf2127_param_set,
|
||||
};
|
||||
|
||||
/* sysfs interface */
|
||||
|
Loading…
x
Reference in New Issue
Block a user