Skip to content

Commit 9727452

Browse files
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>
1 parent 58589c6 commit 9727452

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

drivers/rtc/rtc-pcf2127.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/i2c.h>
2121
#include <linux/spi/spi.h>
2222
#include <linux/bcd.h>
23+
#include <linux/bitfield.h>
2324
#include <linux/rtc.h>
2425
#include <linux/slab.h>
2526
#include <linux/module.h>
@@ -48,6 +49,7 @@
4849
#define PCF2127_BIT_CTRL3_BLF BIT(2)
4950
#define PCF2127_BIT_CTRL3_BF BIT(3)
5051
#define PCF2127_BIT_CTRL3_BTSE BIT(4)
52+
#define PCF2127_CTRL3_PM GENMASK(7, 5)
5153
/* Time and date registers */
5254
#define PCF2127_REG_TIME_BASE 0x03
5355
#define PCF2127_BIT_SC_OSF BIT(7)
@@ -331,6 +333,84 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
331333
return 0;
332334
}
333335

336+
static int pcf2127_param_get(struct device *dev, struct rtc_param *param)
337+
{
338+
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
339+
u32 value;
340+
int ret;
341+
342+
switch (param->param) {
343+
case RTC_PARAM_BACKUP_SWITCH_MODE:
344+
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value);
345+
if (ret < 0)
346+
return ret;
347+
348+
value = FIELD_GET(PCF2127_CTRL3_PM, value);
349+
350+
if (value < 0x3)
351+
param->uvalue = RTC_BSM_LEVEL;
352+
else if (value < 0x6)
353+
param->uvalue = RTC_BSM_DIRECT;
354+
else
355+
param->uvalue = RTC_BSM_DISABLED;
356+
357+
break;
358+
359+
default:
360+
return -EINVAL;
361+
}
362+
363+
return 0;
364+
}
365+
366+
static int pcf2127_param_set(struct device *dev, struct rtc_param *param)
367+
{
368+
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
369+
u8 mode = 0;
370+
u32 value;
371+
int ret;
372+
373+
switch (param->param) {
374+
case RTC_PARAM_BACKUP_SWITCH_MODE:
375+
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value);
376+
if (ret < 0)
377+
return ret;
378+
379+
value = FIELD_GET(PCF2127_CTRL3_PM, value);
380+
381+
if (value > 5)
382+
value -= 5;
383+
else if (value > 2)
384+
value -= 3;
385+
386+
switch (param->uvalue) {
387+
case RTC_BSM_LEVEL:
388+
break;
389+
case RTC_BSM_DIRECT:
390+
mode = 3;
391+
break;
392+
case RTC_BSM_DISABLED:
393+
if (value == 0)
394+
value = 1;
395+
mode = 5;
396+
break;
397+
default:
398+
return -EINVAL;
399+
}
400+
401+
return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
402+
PCF2127_CTRL3_PM,
403+
FIELD_PREP(PCF2127_CTRL3_PM, mode + value));
404+
405+
break;
406+
407+
default:
408+
return -EINVAL;
409+
}
410+
411+
return 0;
412+
}
413+
334414
static int pcf2127_rtc_ioctl(struct device *dev,
335415
unsigned int cmd, unsigned long arg)
336416
{
@@ -741,6 +821,8 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
741821
.read_alarm = pcf2127_rtc_read_alarm,
742822
.set_alarm = pcf2127_rtc_set_alarm,
743823
.alarm_irq_enable = pcf2127_rtc_alarm_irq_enable,
824+
.param_get = pcf2127_param_get,
825+
.param_set = pcf2127_param_set,
744826
};
745827

746828
/* sysfs interface */

0 commit comments

Comments
 (0)