linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] rtc: add new ioctl interface and BSM support
@ 2021-10-15 19:21 Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 1/7] rtc: add alarm related features Alexandre Belloni
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo; +Cc: linux-rtc, linux-kernel, Alexandre Belloni

This adds a new ioctl interface allowing to get and set extended
parameters on RTCs. While its main goal is to support backup switch
mode, it also intends to fix a long time issue. Until now, it was not
possible to know what features were supported by an RTC before actually
trying to make use of it and see that succeed or fail. In order to make
tests more reliable and allow userspace to take the correct decision,
the features are now exposed.

Alexandre Belloni (7):
  rtc: add alarm related features
  rtc: add parameter ioctl
  rtc: expose correction feature
  rtc: add correction parameter
  rtc: add BSM parameter
  rtc: rv3028: add BSM support
  rtc: rv3032: allow setting BSM

 drivers/rtc/class.c      |  3 ++
 drivers/rtc/dev.c        | 65 +++++++++++++++++++++++++++++++++
 drivers/rtc/rtc-rv3028.c | 73 +++++++++++++++++++++++++++++++++++++
 drivers/rtc/rtc-rv3032.c | 78 ++++++++++++++++++++++++++++++++++++++++
 include/linux/rtc.h      |  2 ++
 include/uapi/linux/rtc.h | 33 +++++++++++++++--
 6 files changed, 252 insertions(+), 2 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/7] rtc: add alarm related features
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 2/7] rtc: add parameter ioctl Alexandre Belloni
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

Correct and add alarm related features to be declared by drivers.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 include/uapi/linux/rtc.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index f950bff75e97..60ea711b1843 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -113,8 +113,10 @@ struct rtc_pll_info {
 /* feature list */
 #define RTC_FEATURE_ALARM		0
 #define RTC_FEATURE_ALARM_RES_MINUTE	1
-#define RTC_FEATURE_NEED_WEEK_DAY	2
-#define RTC_FEATURE_CNT			3
+#define RTC_FEATURE_ALARM_RES_2S	2
+#define RTC_FEATURE_UPDATE_INTERRUPT	3
+#define RTC_FEATURE_NEED_WEEK_DAY	4
+#define RTC_FEATURE_CNT			5
 
 #define RTC_MAX_FREQ	8192
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/7] rtc: add parameter ioctl
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 1/7] rtc: add alarm related features Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 3/7] rtc: expose correction feature Alexandre Belloni
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

Add an ioctl allowing to get and set extra parameters for an RTC. For now,
only handle getting available features.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/dev.c        | 40 ++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/rtc.h | 18 ++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index 5b8ebe86124a..143c097eff0f 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -208,6 +208,7 @@ static long rtc_dev_ioctl(struct file *file,
 	const struct rtc_class_ops *ops = rtc->ops;
 	struct rtc_time tm;
 	struct rtc_wkalrm alarm;
+	struct rtc_param param;
 	void __user *uarg = (void __user *)arg;
 
 	err = mutex_lock_interruptible(&rtc->ops_lock);
@@ -221,6 +222,7 @@ static long rtc_dev_ioctl(struct file *file,
 	switch (cmd) {
 	case RTC_EPOCH_SET:
 	case RTC_SET_TIME:
+	case RTC_PARAM_SET:
 		if (!capable(CAP_SYS_TIME))
 			err = -EACCES;
 		break;
@@ -382,6 +384,44 @@ static long rtc_dev_ioctl(struct file *file,
 			err = -EFAULT;
 		return err;
 
+	case RTC_PARAM_GET:
+		if (copy_from_user(&param, uarg, sizeof(param))) {
+			mutex_unlock(&rtc->ops_lock);
+			return -EFAULT;
+		}
+
+		switch(param.param) {
+			long offset;
+		case RTC_PARAM_FEATURES:
+			if (param.index != 0)
+				err = -EINVAL;
+			param.uvalue = rtc->features[0];
+			break;
+
+		default:
+			err = -EINVAL;
+		}
+
+		if (!err)
+			if (copy_to_user(uarg, &param, sizeof(param)))
+				err = -EFAULT;
+
+		break;
+
+	case RTC_PARAM_SET:
+		if (copy_from_user(&param, uarg, sizeof(param))) {
+			mutex_unlock(&rtc->ops_lock);
+			return -EFAULT;
+		}
+
+		switch(param.param) {
+		case RTC_PARAM_FEATURES:
+		default:
+			err = -EINVAL;
+		}
+
+		break;
+
 	default:
 		/* Finally try the driver's ioctl interface */
 		if (ops->ioctl) {
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index 60ea711b1843..e4128be7963b 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -14,6 +14,7 @@
 
 #include <linux/const.h>
 #include <linux/ioctl.h>
+#include <linux/types.h>
 
 /*
  * The struct used to pass data via the following ioctl. Similar to the
@@ -66,6 +67,17 @@ struct rtc_pll_info {
 	long pll_clock;     /* base PLL frequency */
 };
 
+struct rtc_param {
+	__u64 param;
+	union {
+		__u64 uvalue;
+		__s64 svalue;
+		__u64 ptr;
+	};
+	__u32 index;
+	__u32 __pad;
+};
+
 /*
  * ioctl calls that are permitted to the /dev/rtc interface, if
  * any of the RTC drivers are enabled.
@@ -95,6 +107,9 @@ struct rtc_pll_info {
 #define RTC_PLL_GET	_IOR('p', 0x11, struct rtc_pll_info)  /* Get PLL correction */
 #define RTC_PLL_SET	_IOW('p', 0x12, struct rtc_pll_info)  /* Set PLL correction */
 
+#define RTC_PARAM_GET	_IOW('p', 0x13, struct rtc_param)  /* Get parameter */
+#define RTC_PARAM_SET	_IOW('p', 0x14, struct rtc_param)  /* Set parameter */
+
 #define RTC_VL_DATA_INVALID	_BITUL(0) /* Voltage too low, RTC data is invalid */
 #define RTC_VL_BACKUP_LOW	_BITUL(1) /* Backup voltage is low */
 #define RTC_VL_BACKUP_EMPTY	_BITUL(2) /* Backup empty or not present */
@@ -118,6 +133,9 @@ struct rtc_pll_info {
 #define RTC_FEATURE_NEED_WEEK_DAY	4
 #define RTC_FEATURE_CNT			5
 
+/* parameter list */
+#define RTC_PARAM_FEATURES		0
+
 #define RTC_MAX_FREQ	8192
 
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/7] rtc: expose correction feature
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 1/7] rtc: add alarm related features Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 2/7] rtc: add parameter ioctl Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 4/7] rtc: add correction parameter Alexandre Belloni
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

Add a new feature for RTCs able to correct the oscillator imprecision. This
is also called offset or trimming. Such drivers have a .set_offset callback,
use that to set the feature bit from the core.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/class.c      | 3 +++
 include/uapi/linux/rtc.h | 3 ++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index dbccd71589b9..2e0cbc190a8a 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -389,6 +389,9 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
 	if (!rtc->ops->set_alarm)
 		clear_bit(RTC_FEATURE_ALARM, rtc->features);
 
+	if (rtc->ops->set_offset)
+		set_bit(RTC_FEATURE_CORRECTION, rtc->features);
+
 	rtc->owner = owner;
 	rtc_device_get_offset(rtc);
 
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index e4128be7963b..ded2aaab7ec7 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -131,7 +131,8 @@ struct rtc_param {
 #define RTC_FEATURE_ALARM_RES_2S	2
 #define RTC_FEATURE_UPDATE_INTERRUPT	3
 #define RTC_FEATURE_NEED_WEEK_DAY	4
-#define RTC_FEATURE_CNT			5
+#define RTC_FEATURE_CORRECTION		5
+#define RTC_FEATURE_CNT			6
 
 /* parameter list */
 #define RTC_PARAM_FEATURES		0
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/7] rtc: add correction parameter
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
                   ` (2 preceding siblings ...)
  2021-10-15 19:21 ` [PATCH 3/7] rtc: expose correction feature Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 5/7] rtc: add BSM parameter Alexandre Belloni
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

Add a new parameter allowing the get and set the correction using ioctls
instead of just sysfs.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/dev.c        | 19 +++++++++++++++++++
 include/uapi/linux/rtc.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index 143c097eff0f..abee1fc4705e 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -398,6 +398,16 @@ static long rtc_dev_ioctl(struct file *file,
 			param.uvalue = rtc->features[0];
 			break;
 
+		case RTC_PARAM_CORRECTION:
+			mutex_unlock(&rtc->ops_lock);
+			if (param.index != 0)
+				return -EINVAL;
+			err = rtc_read_offset(rtc, &offset);
+			mutex_lock(&rtc->ops_lock);
+			if (err == 0)
+				param.svalue = offset;
+			break;
+
 		default:
 			err = -EINVAL;
 		}
@@ -416,6 +426,15 @@ static long rtc_dev_ioctl(struct file *file,
 
 		switch(param.param) {
 		case RTC_PARAM_FEATURES:
+			err = -EINVAL;
+			break;
+
+		case RTC_PARAM_CORRECTION:
+			mutex_unlock(&rtc->ops_lock);
+			if (param.index != 0)
+				return -EINVAL;
+			return rtc_set_offset(rtc, param.svalue);
+
 		default:
 			err = -EINVAL;
 		}
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index ded2aaab7ec7..04da6c3082b3 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -136,6 +136,7 @@ struct rtc_param {
 
 /* parameter list */
 #define RTC_PARAM_FEATURES		0
+#define RTC_PARAM_CORRECTION		1
 
 #define RTC_MAX_FREQ	8192
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/7] rtc: add BSM parameter
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
                   ` (3 preceding siblings ...)
  2021-10-15 19:21 ` [PATCH 4/7] rtc: add correction parameter Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 6/7] rtc: rv3028: add BSM support Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 7/7] rtc: rv3032: allow setting BSM Alexandre Belloni
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

BSM or Backup Switch Mode is a common feature on RTCs, allowing to select
how the RTC will decide when to switch from its primary power supply to the
backup power supply. It is necessary to be able to set it from userspace as
there are uses cases where it has to be done dynamically.

Supported values are:
  RTC_BSM_DISABLED: disabled
  RTC_BSM_DIRECT: switching will happen as soon as Vbackup > Vdd
  RTC_BSM_LEVEL: switching will happen around a threshold, usually with an
  hysteresis
  RTC_BSM_STANDBY: switching will not happen until Vdd > Vbackup, this is
  useful to ensure the RTC doesn't draw any power until the device is first
  powered on.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/dev.c        | 10 ++++++++--
 include/linux/rtc.h      |  2 ++
 include/uapi/linux/rtc.h |  9 ++++++++-
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index abee1fc4705e..e104972a28fd 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -409,7 +409,10 @@ static long rtc_dev_ioctl(struct file *file,
 			break;
 
 		default:
-			err = -EINVAL;
+			if (rtc->ops->param_get)
+				err = rtc->ops->param_get(rtc->dev.parent, &param);
+			else
+				err = -EINVAL;
 		}
 
 		if (!err)
@@ -436,7 +439,10 @@ static long rtc_dev_ioctl(struct file *file,
 			return rtc_set_offset(rtc, param.svalue);
 
 		default:
-			err = -EINVAL;
+			if (rtc->ops->param_set)
+				err = rtc->ops->param_set(rtc->dev.parent, &param);
+			else
+				err = -EINVAL;
 		}
 
 		break;
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 354e0843ab17..47fd1c2d3a57 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -66,6 +66,8 @@ struct rtc_class_ops {
 	int (*alarm_irq_enable)(struct device *, unsigned int enabled);
 	int (*read_offset)(struct device *, long *offset);
 	int (*set_offset)(struct device *, long offset);
+	int (*param_get)(struct device *, struct rtc_param *param);
+	int (*param_set)(struct device *, struct rtc_param *param);
 };
 
 struct rtc_device;
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index 04da6c3082b3..dbbab0dbc8c8 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -132,11 +132,18 @@ struct rtc_param {
 #define RTC_FEATURE_UPDATE_INTERRUPT	3
 #define RTC_FEATURE_NEED_WEEK_DAY	4
 #define RTC_FEATURE_CORRECTION		5
-#define RTC_FEATURE_CNT			6
+#define RTC_FEATURE_BACKUP_SWITCH_MODE	6
+#define RTC_FEATURE_CNT			7
 
 /* parameter list */
 #define RTC_PARAM_FEATURES		0
 #define RTC_PARAM_CORRECTION		1
+#define RTC_PARAM_BACKUP_SWITCH_MODE	2
+
+#define RTC_BSM_DISABLED	0
+#define RTC_BSM_DIRECT		1
+#define RTC_BSM_LEVEL		2
+#define RTC_BSM_STANDBY		3
 
 #define RTC_MAX_FREQ	8192
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/7] rtc: rv3028: add BSM support
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
                   ` (4 preceding siblings ...)
  2021-10-15 19:21 ` [PATCH 5/7] rtc: add BSM parameter Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  2021-10-15 19:21 ` [PATCH 7/7] rtc: rv3032: allow setting BSM Alexandre Belloni
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

Backup Switch Mode controls how the RTC decides when to switch to the
backup power supply. As it is disabled by default, provide a way to enable
and configure it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/rtc-rv3028.c | 73 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index 12c807306893..45c82e59d68f 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -10,6 +10,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/bcd.h>
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -80,6 +81,10 @@
 
 #define RV3028_BACKUP_TCE		BIT(5)
 #define RV3028_BACKUP_TCR_MASK		GENMASK(1,0)
+#define RV3028_BACKUP_BSM		GENMASK(3,2)
+
+#define RV3028_BACKUP_BSM_DSM		0x1
+#define RV3028_BACKUP_BSM_LSM		0x3
 
 #define OFFSET_STEP_PPT			953674
 
@@ -512,6 +517,72 @@ static int rv3028_set_offset(struct device *dev, long offset)
 
 }
 
+static int rv3028_param_get(struct device *dev, struct rtc_param *param)
+{
+	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
+	int ret;
+
+	switch(param->param) {
+		u32 value;
+
+	case RTC_PARAM_BACKUP_SWITCH_MODE:
+		ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
+		if (ret < 0)
+			return ret;
+
+		value = FIELD_GET(RV3028_BACKUP_BSM, value);
+
+		switch(value) {
+		case RV3028_BACKUP_BSM_DSM:
+			param->uvalue = RTC_BSM_DIRECT;
+			break;
+		case RV3028_BACKUP_BSM_LSM:
+			param->uvalue = RTC_BSM_LEVEL;
+			break;
+		default:
+			param->uvalue = RTC_BSM_DISABLED;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rv3028_param_set(struct device *dev, struct rtc_param *param)
+{
+	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
+
+	switch(param->param) {
+		u8 mode;
+	case RTC_PARAM_BACKUP_SWITCH_MODE:
+		switch (param->uvalue) {
+		case RTC_BSM_DISABLED:
+			mode = 0;
+			break;
+		case RTC_BSM_DIRECT:
+			mode = RV3028_BACKUP_BSM_DSM;
+			break;
+		case RTC_BSM_LEVEL:
+			mode = RV3028_BACKUP_BSM_LSM;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_BSM,
+				  FIELD_PREP(RV3028_BACKUP_BSM, mode));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
@@ -776,6 +847,8 @@ static const struct rtc_class_ops rv3028_rtc_ops = {
 	.read_offset = rv3028_read_offset,
 	.set_offset = rv3028_set_offset,
 	.ioctl = rv3028_ioctl,
+	.param_get = rv3028_param_get,
+	.param_set = rv3028_param_set,
 };
 
 static const struct regmap_config regmap_config = {
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 7/7] rtc: rv3032: allow setting BSM
  2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
                   ` (5 preceding siblings ...)
  2021-10-15 19:21 ` [PATCH 6/7] rtc: rv3028: add BSM support Alexandre Belloni
@ 2021-10-15 19:21 ` Alexandre Belloni
  6 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2021-10-15 19:21 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel

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>
---
 drivers/rtc/rtc-rv3032.c | 78 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c
index 1b62ed2f1459..ba189f2f36c4 100644
--- a/drivers/rtc/rtc-rv3032.c
+++ b/drivers/rtc/rtc-rv3032.c
@@ -106,6 +106,7 @@
 struct rv3032_data {
 	struct regmap *regmap;
 	struct rtc_device *rtc;
+	bool trickle_charger_set;
 #ifdef CONFIG_COMMON_CLK
 	struct clk_hw clkout_hw;
 #endif
@@ -402,6 +403,77 @@ static int rv3032_set_offset(struct device *dev, long 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 = 0x1;
+			break;
+		case RTC_BSM_LEVEL:
+			mode = 0x3;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		rv3032_update_cfg(rv3032, RV3032_PMU, RV3032_PMU_BSM,
+				  FIELD_PREP(RV3032_PMU_BSM, mode));
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	struct rv3032_data *rv3032 = dev_get_drvdata(dev);
@@ -541,6 +613,8 @@ static int rv3032_trickle_charger_setup(struct device *dev, struct rv3032_data *
 		return 0;
 	}
 
+	rv3032->trickle_charger_set = true;
+
 	return rv3032_update_cfg(rv3032, RV3032_PMU,
 				 RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM,
 				 val | FIELD_PREP(RV3032_PMU_TCR, i));
@@ -813,6 +887,8 @@ static const struct rtc_class_ops rv3032_rtc_ops = {
 	.read_alarm = rv3032_get_alarm,
 	.set_alarm = rv3032_set_alarm,
 	.alarm_irq_enable = rv3032_alarm_irq_enable,
+	.param_get = rv3032_param_get,
+	.param_set = rv3032_param_set,
 };
 
 static const struct regmap_config regmap_config = {
@@ -883,6 +959,8 @@ static int rv3032_probe(struct i2c_client *client)
 
 	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_max = RTC_TIMESTAMP_END_2099;
 	rv3032->rtc->ops = &rv3032_rtc_ops;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-10-15 19:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-15 19:21 [PATCH 0/7] rtc: add new ioctl interface and BSM support Alexandre Belloni
2021-10-15 19:21 ` [PATCH 1/7] rtc: add alarm related features Alexandre Belloni
2021-10-15 19:21 ` [PATCH 2/7] rtc: add parameter ioctl Alexandre Belloni
2021-10-15 19:21 ` [PATCH 3/7] rtc: expose correction feature Alexandre Belloni
2021-10-15 19:21 ` [PATCH 4/7] rtc: add correction parameter Alexandre Belloni
2021-10-15 19:21 ` [PATCH 5/7] rtc: add BSM parameter Alexandre Belloni
2021-10-15 19:21 ` [PATCH 6/7] rtc: rv3028: add BSM support Alexandre Belloni
2021-10-15 19:21 ` [PATCH 7/7] rtc: rv3032: allow setting BSM Alexandre Belloni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).