Linux RTC
 help / color / mirror / Atom feed
* [PATCH] rtc: rv3028: configure backup switch mode from device tree
@ 2026-08-22  9:29 Dhaval Shiroya
  2026-08-22  9:39 ` sashiko-bot
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Dhaval Shiroya @ 2026-08-22  9:29 UTC (permalink / raw)
  To: alexandre.belloni; +Cc: Dhaval Shiroya, linux-rtc, linux-kernel

Enable and set the backup switch mode directly from the device tree at
probe, instead of requiring a userspace RTC_PARAM_BACKUP_SWITCH_MODE
ioctl on every unit.

Signed-off-by: Dhaval Shiroya <dhaval.shiroya@siliconsignals.io>

diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index d96f6bb68850..5dde1aed76dd 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -80,6 +80,7 @@
 #define RV3028_EEBUSY_TIMEOUT		100000
 
 #define RV3028_BACKUP_TCE		BIT(5)
+#define RV3028_BACKUP_FEDE		BIT(4)
 #define RV3028_BACKUP_TCR_MASK		GENMASK(1,0)
 #define RV3028_BACKUP_BSM		GENMASK(3,2)
 
@@ -519,70 +520,6 @@ 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;
-	u32 value;
-
-	switch(param->param) {
-	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);
-	u8 mode;
-
-	switch(param->param) {
-	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;
-		}
-
-		return rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_BSM,
-					 FIELD_PREP(RV3028_BACKUP_BSM, mode));
-
-	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);
@@ -852,8 +789,6 @@ 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 = {
@@ -920,6 +855,65 @@ static u8 rv3028_set_trickle_charger(struct rv3028_data *rv3028,
 	return ret;
 }
 
+/*
+ * Configure backup switchover mode from device tree.
+ *   0 = disabled
+ *   1 = DSM (Direct Switching Mode)  - switch when VDD < VBACKUP
+ *   3 = LSM (Level Switching Mode)   - switch when VDD < 2.0V
+ */
+static int rv3028_set_bsm_from_dt(struct rv3028_data *rv3028,
+				  struct i2c_client *client)
+{
+	u32 val_old, bsm_dt, bsm_bits;
+	int ret;
+
+	if (device_property_read_u32(&client->dev, "backup-switch-mode",
+				     &bsm_dt))
+		return 0;
+
+	/* Validate and convert DT value to register bits */
+	switch (bsm_dt) {
+	case 0:
+		bsm_bits = 0;
+		break;
+	case 1:
+		bsm_bits = FIELD_PREP(RV3028_BACKUP_BSM, RV3028_BACKUP_BSM_DSM);
+		break;
+	case 3:
+		bsm_bits = FIELD_PREP(RV3028_BACKUP_BSM, RV3028_BACKUP_BSM_LSM);
+		break;
+	default:
+		dev_warn(&client->dev,
+			 "invalid backup-switch-mode %u (use 0, 1, or 3)\n",
+			 bsm_dt);
+		return 0;
+	}
+
+	/* Read current BACKUP register */
+	ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &val_old);
+	if (ret < 0)
+		return ret;
+
+	/* Check if BSM and FEDE already match desired values */
+	if ((val_old & (RV3028_BACKUP_BSM | RV3028_BACKUP_FEDE)) ==
+	    (bsm_bits | RV3028_BACKUP_FEDE)) {
+		dev_dbg(&client->dev,
+			"backup switch mode already set to %u\n", bsm_dt);
+		return 0;
+	}
+
+	dev_info(&client->dev,
+		 "setting backup switch mode to %u (reg 0x37: 0x%02x -> 0x%02x)\n",
+		 bsm_dt, val_old,
+		 (val_old & ~(RV3028_BACKUP_BSM | RV3028_BACKUP_FEDE)) |
+		 bsm_bits | RV3028_BACKUP_FEDE);
+
+	/* Set BSM and always enable FEDE as recommended by datasheet */
+	return rv3028_update_cfg(rv3028, RV3028_BACKUP,
+				 RV3028_BACKUP_BSM | RV3028_BACKUP_FEDE,
+				 bsm_bits | RV3028_BACKUP_FEDE);
+}
+
 static int rv3028_probe(struct i2c_client *client)
 {
 	struct rv3028_data *rv3028;
@@ -1005,11 +999,14 @@ static int rv3028_probe(struct i2c_client *client)
 	if (ret)
 		return ret;
 
-	ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
+	/* Configure backup switchover mode from device tree */
+	ret = rv3028_set_bsm_from_dt(rv3028, client);
 	if (ret)
 		return ret;
 
-	set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3028->rtc->features);
+	ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
+	if (ret)
+		return ret;
 
 	rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 	rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
-- 
2.34.1


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

end of thread, other threads:[~2026-08-25  1:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-22  9:29 [PATCH] rtc: rv3028: configure backup switch mode from device tree Dhaval Shiroya
2026-08-22  9:39 ` sashiko-bot
2026-08-22 13:09 ` Alexandre Belloni
2026-08-24 23:05 ` kernel test robot
2026-08-25  1:34 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox