linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/10] rtc: pcf2127: add variant-specific configuration structure
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 02/10] rtc: pcf2127: adapt for time/date registers at any offset Hugo Villeneuve
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Create variant-specific configuration structures to simplify the
implementation of new variants into this driver. It will also avoid
to have too many tests for a specific variant, or a list of variants
for new devices, inside the code itself.

Add configuration options for the support of the NVMEM, bit CD0 in
register WD_CTL as well as the maximum number of registers for each
variant, instead of hardcoding the variant (PCF2127) inside the
i2c_device_id and spi_device_id structures.

Also specify a different maximum number of registers (max_register)
for the PCF2129.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 96 +++++++++++++++++++++++++++++++--------
 1 file changed, 78 insertions(+), 18 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 81a5b1f2e68c..d2b335a64887 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/of_device.h>
 #include <linux/regmap.h>
 #include <linux/watchdog.h>
 
@@ -101,10 +102,17 @@
 		PCF2127_BIT_CTRL2_WDTF | \
 		PCF2127_BIT_CTRL2_TSF2)
 
+struct pcf21xx_config {
+	int max_register;
+	unsigned int has_nvmem:1;
+	unsigned int has_bit_wd_ctl_cd0:1;
+};
+
 struct pcf2127 {
 	struct rtc_device *rtc;
 	struct watchdog_device wdd;
 	struct regmap *regmap;
+	const struct pcf21xx_config *cfg;
 	time64_t ts;
 	bool ts_valid;
 	bool irq_enabled;
@@ -630,8 +638,27 @@ static const struct attribute_group pcf2127_attr_group = {
 	.attrs	= pcf2127_attrs,
 };
 
+enum pcf21xx_type {
+	PCF2127,
+	PCF2129,
+	PCF21XX_LAST_ID
+};
+
+static struct pcf21xx_config pcf21xx_cfg[] = {
+	[PCF2127] = {
+		.max_register = 0x1d,
+		.has_nvmem = 1,
+		.has_bit_wd_ctl_cd0 = 1,
+	},
+	[PCF2129] = {
+		.max_register = 0x19,
+		.has_nvmem = 0,
+		.has_bit_wd_ctl_cd0 = 0,
+	},
+};
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
-			 int alarm_irq, const char *name, bool is_pcf2127)
+			 int alarm_irq, const char *name, const struct pcf21xx_config *config)
 {
 	struct pcf2127 *pcf2127;
 	int ret = 0;
@@ -644,6 +671,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 		return -ENOMEM;
 
 	pcf2127->regmap = regmap;
+	pcf2127->cfg = config;
 
 	dev_set_drvdata(dev, pcf2127);
 
@@ -675,7 +703,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 		set_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features);
 	}
 
-	if (is_pcf2127) {
+	if (pcf2127->cfg->has_nvmem) {
 		struct nvmem_config nvmem_cfg = {
 			.priv = pcf2127,
 			.reg_read = pcf2127_nvmem_read,
@@ -721,7 +749,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 				 PCF2127_BIT_WD_CTL_TF1 |
 				 PCF2127_BIT_WD_CTL_TF0,
 				 PCF2127_BIT_WD_CTL_CD1 |
-				 (is_pcf2127 ? PCF2127_BIT_WD_CTL_CD0 : 0) |
+				 (pcf2127->cfg->has_bit_wd_ctl_cd0 ? PCF2127_BIT_WD_CTL_CD0 : 0) |
 				 PCF2127_BIT_WD_CTL_TF1);
 	if (ret) {
 		dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
@@ -786,9 +814,9 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
 #ifdef CONFIG_OF
 static const struct of_device_id pcf2127_of_match[] = {
-	{ .compatible = "nxp,pcf2127" },
-	{ .compatible = "nxp,pcf2129" },
-	{ .compatible = "nxp,pca2129" },
+	{ .compatible = "nxp,pcf2127", .data = &pcf21xx_cfg[PCF2127] },
+	{ .compatible = "nxp,pcf2129", .data = &pcf21xx_cfg[PCF2129] },
+	{ .compatible = "nxp,pca2129", .data = &pcf21xx_cfg[PCF2129] },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf2127_of_match);
@@ -872,19 +900,36 @@ static const struct regmap_bus pcf2127_i2c_regmap = {
 
 static struct i2c_driver pcf2127_i2c_driver;
 
+static const struct i2c_device_id pcf2127_i2c_id[];
+
 static int pcf2127_i2c_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct regmap *regmap;
-	static const struct regmap_config config = {
+	static struct regmap_config config = {
 		.reg_bits = 8,
 		.val_bits = 8,
-		.max_register = 0x1d,
 	};
+	const struct pcf21xx_config *variant;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
 
+	if (client->dev.of_node) {
+		variant = of_device_get_match_data(&client->dev);
+		if (!variant)
+			return -ENODEV;
+	} else {
+		enum pcf21xx_type type =
+			i2c_match_id(pcf2127_i2c_id, client)->driver_data;
+
+		if (type >= PCF21XX_LAST_ID)
+			return -ENODEV;
+		variant = &pcf21xx_cfg[type];
+	}
+
+	config.max_register = variant->max_register,
+
 	regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap,
 					&client->dev, &config);
 	if (IS_ERR(regmap)) {
@@ -894,13 +939,13 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
 	}
 
 	return pcf2127_probe(&client->dev, regmap, client->irq,
-			     pcf2127_i2c_driver.driver.name, id->driver_data);
+			     pcf2127_i2c_driver.driver.name, variant);
 }
 
 static const struct i2c_device_id pcf2127_i2c_id[] = {
-	{ "pcf2127", 1 },
-	{ "pcf2129", 0 },
-	{ "pca2129", 0 },
+	{ "pcf2127", PCF2127 },
+	{ "pcf2129", PCF2129 },
+	{ "pca2129", PCF2129 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
@@ -940,17 +985,32 @@ static void pcf2127_i2c_unregister_driver(void)
 #if IS_ENABLED(CONFIG_SPI_MASTER)
 
 static struct spi_driver pcf2127_spi_driver;
+static const struct spi_device_id pcf2127_spi_id[];
 
 static int pcf2127_spi_probe(struct spi_device *spi)
 {
-	static const struct regmap_config config = {
+	static struct regmap_config config = {
 		.reg_bits = 8,
 		.val_bits = 8,
 		.read_flag_mask = 0xa0,
 		.write_flag_mask = 0x20,
-		.max_register = 0x1d,
 	};
 	struct regmap *regmap;
+	const struct pcf21xx_config *variant;
+
+	if (spi->dev.of_node) {
+		variant = of_device_get_match_data(&spi->dev);
+		if (!variant)
+			return -ENODEV;
+	} else {
+		enum pcf21xx_type type = spi_get_device_id(spi)->driver_data;
+
+		if (type >= PCF21XX_LAST_ID)
+			return -ENODEV;
+		variant = &pcf21xx_cfg[type];
+	}
+
+	config.max_register = variant->max_register,
 
 	regmap = devm_regmap_init_spi(spi, &config);
 	if (IS_ERR(regmap)) {
@@ -961,13 +1021,13 @@ static int pcf2127_spi_probe(struct spi_device *spi)
 
 	return pcf2127_probe(&spi->dev, regmap, spi->irq,
 			     pcf2127_spi_driver.driver.name,
-			     spi_get_device_id(spi)->driver_data);
+			     variant);
 }
 
 static const struct spi_device_id pcf2127_spi_id[] = {
-	{ "pcf2127", 1 },
-	{ "pcf2129", 0 },
-	{ "pca2129", 0 },
+	{ "pcf2127", PCF2127 },
+	{ "pcf2129", PCF2129 },
+	{ "pca2129", PCF2129 },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
-- 
2.30.2


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

* [PATCH 02/10] rtc: pcf2127: adapt for time/date registers at any offset
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
  2022-01-25 20:00 ` [PATCH 01/10] rtc: pcf2127: add variant-specific configuration structure Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 03/10] rtc: pcf2127: adapt for alarm " Hugo Villeneuve
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This will simplify the implementation of new variants into this driver.

Some variants (PCF2131) have a 100th seconds register. This register is
currently not supported in this driver.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 68 ++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 29 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index d2b335a64887..144b4da8d7f1 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -44,14 +44,17 @@
 #define PCF2127_BIT_CTRL3_BF			BIT(3)
 #define PCF2127_BIT_CTRL3_BTSE			BIT(4)
 /* Time and date registers */
-#define PCF2127_REG_SC			0x03
+#define PCF2127_REG_TIME_DATE_BASE	0x03
+/* Time and date registers offsets (starting from base register) */
+#define PCF2127_OFFSET_TD_SC		0
+#define PCF2127_OFFSET_TD_MN		1
+#define PCF2127_OFFSET_TD_HR		2
+#define PCF2127_OFFSET_TD_DM		3
+#define PCF2127_OFFSET_TD_DW		4
+#define PCF2127_OFFSET_TD_MO		5
+#define PCF2127_OFFSET_TD_YR		6
+/* Time and date registers bits */
 #define PCF2127_BIT_SC_OSF			BIT(7)
-#define PCF2127_REG_MN			0x04
-#define PCF2127_REG_HR			0x05
-#define PCF2127_REG_DM			0x06
-#define PCF2127_REG_DW			0x07
-#define PCF2127_REG_MO			0x08
-#define PCF2127_REG_YR			0x09
 /* Alarm registers */
 #define PCF2127_REG_ALARM_SC		0x0A
 #define PCF2127_REG_ALARM_MN		0x0B
@@ -106,6 +109,7 @@ struct pcf21xx_config {
 	int max_register;
 	unsigned int has_nvmem:1;
 	unsigned int has_bit_wd_ctl_cd0:1;
+	u8 regs_td_base; /* Time/data base registers. */
 };
 
 struct pcf2127 {
@@ -125,27 +129,31 @@ struct pcf2127 {
 static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
-	unsigned char buf[10];
+	unsigned char buf[7];
+	unsigned int ctrl3;
 	int ret;
 
 	/*
 	 * Avoid reading CTRL2 register as it causes WD_VAL register
 	 * value to reset to 0 which means watchdog is stopped.
 	 */
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL3,
-			       (buf + PCF2127_REG_CTRL3),
-			       ARRAY_SIZE(buf) - PCF2127_REG_CTRL3);
-	if (ret) {
-		dev_err(dev, "%s: read error\n", __func__);
+	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &ctrl3);
+	if (ret)
 		return ret;
-	}
 
-	if (buf[PCF2127_REG_CTRL3] & PCF2127_BIT_CTRL3_BLF)
+	if (ctrl3 & PCF2127_BIT_CTRL3_BLF)
 		dev_info(dev,
 			"low voltage detected, check/replace RTC battery.\n");
 
+	ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->regs_td_base,
+			       buf, sizeof(buf));
+	if (ret) {
+		dev_err(dev, "%s: read error\n", __func__);
+		return ret;
+	}
+
 	/* Clock integrity is not guaranteed when OSF flag is set. */
-	if (buf[PCF2127_REG_SC] & PCF2127_BIT_SC_OSF) {
+	if (buf[PCF2127_OFFSET_TD_SC] & PCF2127_BIT_SC_OSF) {
 		/*
 		 * no need clear the flag here,
 		 * it will be cleared once the new date is saved
@@ -158,18 +166,18 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	dev_dbg(dev,
 		"%s: raw data is cr3=%02x, sec=%02x, min=%02x, hr=%02x, "
 		"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
-		__func__, buf[PCF2127_REG_CTRL3], buf[PCF2127_REG_SC],
-		buf[PCF2127_REG_MN], buf[PCF2127_REG_HR],
-		buf[PCF2127_REG_DM], buf[PCF2127_REG_DW],
-		buf[PCF2127_REG_MO], buf[PCF2127_REG_YR]);
-
-	tm->tm_sec = bcd2bin(buf[PCF2127_REG_SC] & 0x7F);
-	tm->tm_min = bcd2bin(buf[PCF2127_REG_MN] & 0x7F);
-	tm->tm_hour = bcd2bin(buf[PCF2127_REG_HR] & 0x3F); /* rtc hr 0-23 */
-	tm->tm_mday = bcd2bin(buf[PCF2127_REG_DM] & 0x3F);
-	tm->tm_wday = buf[PCF2127_REG_DW] & 0x07;
-	tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-	tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]);
+		__func__, ctrl3, buf[PCF2127_OFFSET_TD_SC],
+		buf[PCF2127_OFFSET_TD_MN], buf[PCF2127_OFFSET_TD_HR],
+		buf[PCF2127_OFFSET_TD_DM], buf[PCF2127_OFFSET_TD_DW],
+		buf[PCF2127_OFFSET_TD_MO], buf[PCF2127_OFFSET_TD_YR]);
+
+	tm->tm_sec = bcd2bin(buf[PCF2127_OFFSET_TD_SC] & 0x7F);
+	tm->tm_min = bcd2bin(buf[PCF2127_OFFSET_TD_MN] & 0x7F);
+	tm->tm_hour = bcd2bin(buf[PCF2127_OFFSET_TD_HR] & 0x3F); /* rtc hr 0-23 */
+	tm->tm_mday = bcd2bin(buf[PCF2127_OFFSET_TD_DM] & 0x3F);
+	tm->tm_wday = buf[PCF2127_OFFSET_TD_DW] & 0x07;
+	tm->tm_mon = bcd2bin(buf[PCF2127_OFFSET_TD_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+	tm->tm_year = bcd2bin(buf[PCF2127_OFFSET_TD_YR]);
 	tm->tm_year += 100;
 
 	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -207,7 +215,7 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	buf[i++] = bin2bcd(tm->tm_year - 100);
 
 	/* write register's data */
-	err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
+	err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i);
 	if (err) {
 		dev_err(dev,
 			"%s: err=%d", __func__, err);
@@ -649,11 +657,13 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.max_register = 0x1d,
 		.has_nvmem = 1,
 		.has_bit_wd_ctl_cd0 = 1,
+		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 	},
 	[PCF2129] = {
 		.max_register = 0x19,
 		.has_nvmem = 0,
 		.has_bit_wd_ctl_cd0 = 0,
+		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 	},
 };
 
-- 
2.30.2


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

* [PATCH 03/10] rtc: pcf2127: adapt for alarm registers at any offset
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
  2022-01-25 20:00 ` [PATCH 01/10] rtc: pcf2127: add variant-specific configuration structure Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 02/10] rtc: pcf2127: adapt for time/date registers at any offset Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 04/10] rtc: pcf2127: adapt for WD " Hugo Villeneuve
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This will simplify the implementation of new variants into this driver.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 42 ++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 144b4da8d7f1..7a13a34eb21b 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -56,11 +56,14 @@
 /* Time and date registers bits */
 #define PCF2127_BIT_SC_OSF			BIT(7)
 /* Alarm registers */
-#define PCF2127_REG_ALARM_SC		0x0A
-#define PCF2127_REG_ALARM_MN		0x0B
-#define PCF2127_REG_ALARM_HR		0x0C
-#define PCF2127_REG_ALARM_DM		0x0D
-#define PCF2127_REG_ALARM_DW		0x0E
+#define PCF2127_REG_ALARM_BASE		0x0A
+/* Alarm registers offsets (starting from base register) */
+#define PCF2127_OFFSET_ALARM_SC		0
+#define PCF2127_OFFSET_ALARM_MN		1
+#define PCF2127_OFFSET_ALARM_HR		2
+#define PCF2127_OFFSET_ALARM_DM		3
+#define PCF2127_OFFSET_ALARM_DW		4
+/* Alarm bits */
 #define PCF2127_BIT_ALARM_AE			BIT(7)
 /* CLKOUT control register */
 #define PCF2127_REG_CLKOUT		0x0f
@@ -110,6 +113,7 @@ struct pcf21xx_config {
 	unsigned int has_nvmem:1;
 	unsigned int has_bit_wd_ctl_cd0:1;
 	u8 regs_td_base; /* Time/data base registers. */
+	u8 regs_alarm_base; /* Alarm function base registers. */
 };
 
 struct pcf2127 {
@@ -401,18 +405,18 @@ static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf,
-			       sizeof(buf));
+	ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->regs_alarm_base,
+			       buf, sizeof(buf));
 	if (ret)
 		return ret;
 
 	alrm->enabled = ctrl2 & PCF2127_BIT_CTRL2_AIE;
 	alrm->pending = ctrl2 & PCF2127_BIT_CTRL2_AF;
 
-	alrm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
-	alrm->time.tm_min = bcd2bin(buf[1] & 0x7F);
-	alrm->time.tm_hour = bcd2bin(buf[2] & 0x3F);
-	alrm->time.tm_mday = bcd2bin(buf[3] & 0x3F);
+	alrm->time.tm_sec = bcd2bin(buf[PCF2127_OFFSET_ALARM_SC] & 0x7F);
+	alrm->time.tm_min = bcd2bin(buf[PCF2127_OFFSET_ALARM_MN] & 0x7F);
+	alrm->time.tm_hour = bcd2bin(buf[PCF2127_OFFSET_ALARM_HR] & 0x3F);
+	alrm->time.tm_mday = bcd2bin(buf[PCF2127_OFFSET_ALARM_DM] & 0x3F);
 
 	return 0;
 }
@@ -446,14 +450,14 @@ static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (ret)
 		return ret;
 
-	buf[0] = bin2bcd(alrm->time.tm_sec);
-	buf[1] = bin2bcd(alrm->time.tm_min);
-	buf[2] = bin2bcd(alrm->time.tm_hour);
-	buf[3] = bin2bcd(alrm->time.tm_mday);
-	buf[4] = PCF2127_BIT_ALARM_AE; /* Do not match on week day */
+	buf[PCF2127_OFFSET_ALARM_SC] = bin2bcd(alrm->time.tm_sec);
+	buf[PCF2127_OFFSET_ALARM_MN] = bin2bcd(alrm->time.tm_min);
+	buf[PCF2127_OFFSET_ALARM_HR] = bin2bcd(alrm->time.tm_hour);
+	buf[PCF2127_OFFSET_ALARM_DM] = bin2bcd(alrm->time.tm_mday);
+	buf[PCF2127_OFFSET_ALARM_DW] = PCF2127_BIT_ALARM_AE; /* Do not match on week day */
 
-	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf,
-				sizeof(buf));
+	ret = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_alarm_base,
+				buf, sizeof(buf));
 	if (ret)
 		return ret;
 
@@ -658,12 +662,14 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.has_nvmem = 1,
 		.has_bit_wd_ctl_cd0 = 1,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
+		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 	},
 	[PCF2129] = {
 		.max_register = 0x19,
 		.has_nvmem = 0,
 		.has_bit_wd_ctl_cd0 = 0,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
+		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 	},
 };
 
-- 
2.30.2


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

* [PATCH 04/10] rtc: pcf2127: adapt for WD registers at any offset
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (2 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 03/10] rtc: pcf2127: adapt for alarm " Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 05/10] rtc: pcf2127: adapt for CLKOUT register " Hugo Villeneuve
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This will simplify the implementation of new variants into this driver.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 7a13a34eb21b..82e4af999c29 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -114,6 +114,8 @@ struct pcf21xx_config {
 	unsigned int has_bit_wd_ctl_cd0:1;
 	u8 regs_td_base; /* Time/data base registers. */
 	u8 regs_alarm_base; /* Alarm function base registers. */
+	u8 reg_wd_ctl; /* Watchdog control register. */
+	u8 reg_wd_val; /* Watchdog value register. */
 };
 
 struct pcf2127 {
@@ -297,7 +299,7 @@ static int pcf2127_wdt_ping(struct watchdog_device *wdd)
 {
 	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
 
-	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, wdd->timeout);
+	return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wdd->timeout);
 }
 
 /*
@@ -331,7 +333,7 @@ static int pcf2127_wdt_stop(struct watchdog_device *wdd)
 {
 	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
 
-	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL,
+	return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val,
 			    PCF2127_WD_VAL_STOP);
 }
 
@@ -380,7 +382,7 @@ static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
 	watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
 
 	/* Test if watchdog timer is started by bootloader */
-	ret = regmap_read(pcf2127->regmap, PCF2127_REG_WD_VAL, &wdd_timeout);
+	ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_wd_val, &wdd_timeout);
 	if (ret)
 		return ret;
 
@@ -663,6 +665,8 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.has_bit_wd_ctl_cd0 = 1,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
+		.reg_wd_ctl = PCF2127_REG_WD_CTL,
+		.reg_wd_val = PCF2127_REG_WD_VAL,
 	},
 	[PCF2129] = {
 		.max_register = 0x19,
@@ -670,6 +674,8 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.has_bit_wd_ctl_cd0 = 0,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
+		.reg_wd_ctl = PCF2127_REG_WD_CTL,
+		.reg_wd_val = PCF2127_REG_WD_VAL,
 	},
 };
 
@@ -759,7 +765,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	 * as T. Bits labeled as T must always be written with
 	 * logic 0.
 	 */
-	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,
+	ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->reg_wd_ctl,
 				 PCF2127_BIT_WD_CTL_CD1 |
 				 PCF2127_BIT_WD_CTL_CD0 |
 				 PCF2127_BIT_WD_CTL_TF1 |
-- 
2.30.2


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

* [PATCH 05/10] rtc: pcf2127: adapt for CLKOUT register at any offset
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (3 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 04/10] rtc: pcf2127: adapt for WD " Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 06/10] rtc: pcf2127: add support for multiple TS functions Hugo Villeneuve
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This will simplify the implementation of new variants into this driver.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 82e4af999c29..13a7f95f52c5 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -116,6 +116,7 @@ struct pcf21xx_config {
 	u8 regs_alarm_base; /* Alarm function base registers. */
 	u8 reg_wd_ctl; /* Watchdog control register. */
 	u8 reg_wd_val; /* Watchdog value register. */
+	u8 reg_clkout; /* Clkout register. */
 };
 
 struct pcf2127 {
@@ -667,6 +668,7 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
 		.reg_wd_val = PCF2127_REG_WD_VAL,
+		.reg_clkout = PCF2127_REG_CLKOUT,
 	},
 	[PCF2129] = {
 		.max_register = 0x19,
@@ -676,6 +678,7 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
 		.reg_wd_val = PCF2127_REG_WD_VAL,
+		.reg_clkout = PCF2127_REG_CLKOUT,
 	},
 };
 
@@ -743,12 +746,12 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	regmap_clear_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
 				PCF2127_BIT_CTRL1_POR_OVRD);
 
-	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CLKOUT, &val);
+	ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_clkout, &val);
 	if (ret < 0)
 		return ret;
 
 	if (!(val & PCF2127_BIT_CLKOUT_OTPR)) {
-		ret = regmap_set_bits(pcf2127->regmap, PCF2127_REG_CLKOUT,
+		ret = regmap_set_bits(pcf2127->regmap, pcf2127->cfg->reg_clkout,
 				      PCF2127_BIT_CLKOUT_OTPR);
 		if (ret < 0)
 			return ret;
-- 
2.30.2


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

* [PATCH 06/10] rtc: pcf2127: add support for multiple TS functions
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (4 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 05/10] rtc: pcf2127: adapt for CLKOUT register " Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 07/10] rtc: pcf2127: add support for PCF2131 RTC Hugo Villeneuve
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This will simplify the implementation of new variants into this driver.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 304 +++++++++++++++++++++++++++-----------
 1 file changed, 216 insertions(+), 88 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 13a7f95f52c5..e806d65e4504 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -75,16 +75,19 @@
 #define PCF2127_BIT_WD_CTL_CD0			BIT(6)
 #define PCF2127_BIT_WD_CTL_CD1			BIT(7)
 #define PCF2127_REG_WD_VAL		0x11
-/* Tamper timestamp registers */
-#define PCF2127_REG_TS_CTRL		0x12
+/* Tamper timestamp1 registers */
+#define PCF2127_REG_TS1_BASE		0x12
+/* Tamper timestamp registers common offsets (starting from base register) */
+#define PCF2127_OFFSET_TS_CTL		0
+#define PCF2127_OFFSET_TS_SC		1
+#define PCF2127_OFFSET_TS_MN		2
+#define PCF2127_OFFSET_TS_HR		3
+#define PCF2127_OFFSET_TS_DM		4
+#define PCF2127_OFFSET_TS_MO		5
+#define PCF2127_OFFSET_TS_YR		6
+/* Tamper timestamp registers common bits */
 #define PCF2127_BIT_TS_CTRL_TSOFF		BIT(6)
 #define PCF2127_BIT_TS_CTRL_TSM			BIT(7)
-#define PCF2127_REG_TS_SC		0x13
-#define PCF2127_REG_TS_MN		0x14
-#define PCF2127_REG_TS_HR		0x15
-#define PCF2127_REG_TS_DM		0x16
-#define PCF2127_REG_TS_MO		0x17
-#define PCF2127_REG_TS_YR		0x18
 /*
  * RAM registers
  * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
@@ -108,6 +111,20 @@
 		PCF2127_BIT_CTRL2_WDTF | \
 		PCF2127_BIT_CTRL2_TSF2)
 
+struct pcf21xx_ts_config {
+	u8 regs_base; /* Base register to read timestamp values. */
+	/* TS input pin driven to GND detection (supported by all variants): */
+	u8 low_reg; /* Interrupt control register. */
+	u8 low_bit; /* Interrupt flag in low_reg control register. */
+	/* TS input pin driven to intermediate level between GND and supply
+	 * detection (optional feature depending on variant):
+	 */
+	u8 inter_reg; /* Interrupt control register. */
+	u8 inter_bit; /* Interrupt flag in inter_reg control register. */
+	u8 ie_reg; /* Interrupt enable control register. */
+	u8 ie_bit; /* Interrupt enable bit. */
+};
+
 struct pcf21xx_config {
 	int max_register;
 	unsigned int has_nvmem:1;
@@ -117,6 +134,9 @@ struct pcf21xx_config {
 	u8 reg_wd_ctl; /* Watchdog control register. */
 	u8 reg_wd_val; /* Watchdog value register. */
 	u8 reg_clkout; /* Clkout register. */
+	unsigned int ts_count;
+	struct pcf21xx_ts_config ts[4];
+	struct attribute_group attribute_group;
 };
 
 struct pcf2127 {
@@ -124,9 +144,9 @@ struct pcf2127 {
 	struct watchdog_device wdd;
 	struct regmap *regmap;
 	const struct pcf21xx_config *cfg;
-	time64_t ts;
-	bool ts_valid;
 	bool irq_enabled;
+	time64_t ts[4]; /* Timestamp values. */
+	bool ts_valid[4];  /* Timestamp valid indication. */
 };
 
 /*
@@ -468,38 +488,39 @@ static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 }
 
 /*
- * This function reads ctrl2 register, caller is responsible for calling
- * pcf2127_wdt_active_ping()
+ * This function reads one timestamp function data, caller is responsible for
+ * calling pcf2127_wdt_active_ping()
  */
-static int pcf2127_rtc_ts_read(struct device *dev, time64_t *ts)
+static int pcf2127_rtc_ts_read(struct device *dev, time64_t *ts,
+			       int ts_id)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
 	struct rtc_time tm;
 	int ret;
-	unsigned char data[25];
+	unsigned char data[7]; /* To store result of reading 7 consecutive
+				* timestamp registers.
+				*/
 
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data,
-			       sizeof(data));
+	ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->ts[ts_id].regs_base,
+			       data, sizeof(data));
 	if (ret) {
-		dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
+		dev_err(dev, "%s: bulk read error ret=%d\n", __func__, ret);
 		return ret;
 	}
 
 	dev_dbg(dev,
-		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
-		__func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2],
-		data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC],
-		data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR],
-		data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO],
-		data[PCF2127_REG_TS_YR]);
-
-	tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F);
-	tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F);
-	tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F);
-	tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F);
+		"%s: raw data is ts_sc=%02x, ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
+		__func__, data[PCF2127_OFFSET_TS_SC], data[PCF2127_OFFSET_TS_MN],
+		data[PCF2127_OFFSET_TS_HR], data[PCF2127_OFFSET_TS_DM],
+		data[PCF2127_OFFSET_TS_MO], data[PCF2127_OFFSET_TS_YR]);
+
+	tm.tm_sec = bcd2bin(data[PCF2127_OFFSET_TS_SC] & 0x7F);
+	tm.tm_min = bcd2bin(data[PCF2127_OFFSET_TS_MN] & 0x7F);
+	tm.tm_hour = bcd2bin(data[PCF2127_OFFSET_TS_HR] & 0x3F);
+	tm.tm_mday = bcd2bin(data[PCF2127_OFFSET_TS_DM] & 0x3F);
 	/* TS_MO register (month) value range: 1-12 */
-	tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1;
-	tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]);
+	tm.tm_mon = bcd2bin(data[PCF2127_OFFSET_TS_MO] & 0x1F) - 1;
+	tm.tm_year = bcd2bin(data[PCF2127_OFFSET_TS_YR]);
 	if (tm.tm_year < 70)
 		tm.tm_year += 100; /* assume we are in 1970...2069 */
 
@@ -513,18 +534,21 @@ static int pcf2127_rtc_ts_read(struct device *dev, time64_t *ts)
 	return 0;
 };
 
-static void pcf2127_rtc_ts_snapshot(struct device *dev)
+static void pcf2127_rtc_ts_snapshot(struct device *dev, int ts_id)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
 	int ret;
 
+	if (ts_id >= pcf2127->cfg->ts_count)
+		return;
+
 	/* Let userspace read the first timestamp */
-	if (pcf2127->ts_valid)
+	if (pcf2127->ts_valid[ts_id])
 		return;
 
-	ret = pcf2127_rtc_ts_read(dev, &pcf2127->ts);
+	ret = pcf2127_rtc_ts_read(dev, &pcf2127->ts[ts_id], ts_id);
 	if (!ret)
-		pcf2127->ts_valid = true;
+		pcf2127->ts_valid[ts_id] = true;
 }
 
 static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
@@ -545,7 +569,7 @@ static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
 		return IRQ_NONE;
 
 	if (ctrl1 & PCF2127_BIT_CTRL1_TSF1 || ctrl2 & PCF2127_BIT_CTRL2_TSF2)
-		pcf2127_rtc_ts_snapshot(dev);
+		pcf2127_rtc_ts_snapshot(dev, 0);
 
 	if (ctrl1 & PCF2127_CTRL1_IRQ_MASK)
 		regmap_write(pcf2127->regmap, PCF2127_REG_CTRL1,
@@ -574,28 +598,40 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
 
 /* sysfs interface */
 
-static ssize_t timestamp0_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
+static ssize_t timestamp_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count, int ts_id)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
 	int ret;
 
+	if (ts_id >= pcf2127->cfg->ts_count)
+		return 0;
+
 	if (pcf2127->irq_enabled) {
-		pcf2127->ts_valid = false;
+		pcf2127->ts_valid[ts_id] = false;
 	} else {
-		ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
-			PCF2127_BIT_CTRL1_TSF1, 0);
+		/* Always clear LOW interrupt bit. */
+		ret = regmap_update_bits(pcf2127->regmap,
+					 pcf2127->cfg->ts[ts_id].low_reg,
+					 pcf2127->cfg->ts[ts_id].low_bit,
+					 0);
+
 		if (ret) {
-			dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret);
+			dev_err(dev, "%s: update TS low ret=%d\n", __func__, ret);
 			return ret;
 		}
 
-		ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
-			PCF2127_BIT_CTRL2_TSF2, 0);
-		if (ret) {
-			dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret);
-			return ret;
+		if (pcf2127->cfg->ts[ts_id].inter_bit) {
+			/* Clear INTERMEDIATE interrupt bit if supported. */
+			ret = regmap_update_bits(pcf2127->regmap,
+						 pcf2127->cfg->ts[ts_id].inter_reg,
+						 pcf2127->cfg->ts[ts_id].inter_bit,
+						 0);
+			if (ret) {
+				dev_err(dev, "%s: update TS intermediate ret=%d\n", __func__, ret);
+				return ret;
+			}
 		}
 
 		ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
@@ -604,34 +640,63 @@ static ssize_t timestamp0_store(struct device *dev,
 	}
 
 	return count;
+}
+
+static ssize_t timestamp0_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	return timestamp_store(dev, attr, buf, count, 0);
 };
 
-static ssize_t timestamp0_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
+static ssize_t timestamp_show(struct device *dev,
+			      struct device_attribute *attr, char *buf,
+			      int ts_id)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
-	unsigned int ctrl1, ctrl2;
 	int ret;
 	time64_t ts;
 
+	if (ts_id >= pcf2127->cfg->ts_count)
+		return 0;
+
 	if (pcf2127->irq_enabled) {
-		if (!pcf2127->ts_valid)
+		if (!pcf2127->ts_valid[ts_id])
 			return 0;
-		ts = pcf2127->ts;
+		ts = pcf2127->ts[ts_id];
 	} else {
-		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1);
-		if (ret)
-			return 0;
+		u8 valid_low = 0;
+		u8 valid_inter = 0;
+		unsigned int ctrl;
 
-		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
+		/* Check if TS input pin is driven to GND, supported by all
+		 * variants.
+		 */
+		ret = regmap_read(pcf2127->regmap,
+				  pcf2127->cfg->ts[ts_id].low_reg,
+				  &ctrl);
 		if (ret)
 			return 0;
 
-		if (!(ctrl1 & PCF2127_BIT_CTRL1_TSF1) &&
-		    !(ctrl2 & PCF2127_BIT_CTRL2_TSF2))
+		valid_low = ctrl & pcf2127->cfg->ts[ts_id].low_bit;
+
+		if (pcf2127->cfg->ts[ts_id].inter_bit) {
+			/* Check if TS input pin is driven to intermediate level
+			 * between GND and supply, if supported by variant.
+			 */
+			ret = regmap_read(pcf2127->regmap,
+					  pcf2127->cfg->ts[ts_id].inter_reg,
+					  &ctrl);
+			if (ret)
+				return 0;
+
+			valid_inter = ctrl & pcf2127->cfg->ts[ts_id].inter_bit;
+		}
+
+		if (!valid_low && !valid_inter)
 			return 0;
 
-		ret = pcf2127_rtc_ts_read(dev->parent, &ts);
+		ret = pcf2127_rtc_ts_read(dev->parent, &ts, ts_id);
 		if (ret)
 			return 0;
 
@@ -640,6 +705,12 @@ static ssize_t timestamp0_show(struct device *dev,
 			return ret;
 	}
 	return sprintf(buf, "%llu\n", (unsigned long long)ts);
+}
+
+static ssize_t timestamp0_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return timestamp_show(dev, attr, buf, 0);
 };
 
 static DEVICE_ATTR_RW(timestamp0);
@@ -649,10 +720,6 @@ static struct attribute *pcf2127_attrs[] = {
 	NULL
 };
 
-static const struct attribute_group pcf2127_attr_group = {
-	.attrs	= pcf2127_attrs,
-};
-
 enum pcf21xx_type {
 	PCF2127,
 	PCF2129,
@@ -669,6 +736,19 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
 		.reg_wd_val = PCF2127_REG_WD_VAL,
 		.reg_clkout = PCF2127_REG_CLKOUT,
+		.ts_count = 1,
+		.ts[0] = {
+			.regs_base = PCF2127_REG_TS1_BASE,
+			.low_reg   = PCF2127_REG_CTRL1,
+			.low_bit   = PCF2127_BIT_CTRL1_TSF1,
+			.inter_reg = PCF2127_REG_CTRL2,
+			.inter_bit = PCF2127_BIT_CTRL2_TSF2,
+			.ie_reg    = PCF2127_REG_CTRL2,
+			.ie_bit    = PCF2127_BIT_CTRL2_TSIE,
+		},
+		.attribute_group = {
+			.attrs	= pcf2127_attrs,
+		},
 	},
 	[PCF2129] = {
 		.max_register = 0x19,
@@ -679,15 +759,82 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
 		.reg_wd_val = PCF2127_REG_WD_VAL,
 		.reg_clkout = PCF2127_REG_CLKOUT,
+		.ts_count = 1,
+		.ts[0] = {
+			.regs_base = PCF2127_REG_TS1_BASE,
+			.low_reg   = PCF2127_REG_CTRL1,
+			.low_bit   = PCF2127_BIT_CTRL1_TSF1,
+			.inter_reg = PCF2127_REG_CTRL2,
+			.inter_bit = PCF2127_BIT_CTRL2_TSF2,
+			.ie_reg    = PCF2127_REG_CTRL2,
+			.ie_bit    = PCF2127_BIT_CTRL2_TSIE,
+		},
+		.attribute_group = {
+			.attrs	= pcf2127_attrs,
+		},
 	},
 };
 
+/*
+ * Enable timestamp function and corresponding interrupt(s).
+ */
+static int pcf2127_enable_ts(struct device *dev, int ts_id)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	int ret;
+
+	if (ts_id >= pcf2127->cfg->ts_count) {
+		dev_err(dev, "%s: invalid tamper detection ID (%d)\n",
+			__func__, ts_id);
+		return -EINVAL;
+	}
+
+	/* Enable timestamp function. */
+	ret = regmap_update_bits(pcf2127->regmap,
+				 pcf2127->cfg->ts[ts_id].regs_base,
+				 PCF2127_BIT_TS_CTRL_TSOFF |
+				 PCF2127_BIT_TS_CTRL_TSM,
+				 PCF2127_BIT_TS_CTRL_TSM);
+	if (ret) {
+		dev_err(dev, "%s: tamper detection config (ts%d_ctrl) failed\n",
+			__func__, ts_id);
+		return ret;
+	}
+
+	/* TS input pin driven to GND detection is supported by all variants.
+	 * Make sure that low_bit and low_reg are defined.
+	 */
+	if ((pcf2127->cfg->ts[ts_id].low_bit == 0) ||
+	    (pcf2127->cfg->ts[ts_id].low_reg == 0)) {
+		dev_err(dev, "%s: tamper detection LOW configuration invalid\n",
+			__func__);
+		return ret;
+	}
+
+	/*
+	 * Enable interrupt generation when TSF timestamp flag is set.
+	 * Interrupt signals are open-drain outputs and can be left floating if
+	 * unused.
+	 */
+	ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->ts[ts_id].ie_reg,
+				 pcf2127->cfg->ts[ts_id].ie_bit,
+				 pcf2127->cfg->ts[ts_id].ie_bit);
+	if (ret) {
+		dev_err(dev, "%s: tamper detection TSIE%d config failed\n",
+			__func__, ts_id);
+		return ret;
+	}
+
+	return ret;
+}
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 			 int alarm_irq, const char *name, const struct pcf21xx_config *config)
 {
 	struct pcf2127 *pcf2127;
 	int ret = 0;
 	unsigned int val;
+	int i;
 
 	dev_dbg(dev, "%s\n", __func__);
 
@@ -800,34 +947,15 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	}
 
 	/*
-	 * Enable timestamp function and store timestamp of first trigger
-	 * event until TSF1 and TSF2 interrupt flags are cleared.
+	 * Enable timestamp functions 1 to 4.
 	 */
-	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL,
-				 PCF2127_BIT_TS_CTRL_TSOFF |
-				 PCF2127_BIT_TS_CTRL_TSM,
-				 PCF2127_BIT_TS_CTRL_TSM);
-	if (ret) {
-		dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n",
-			__func__);
-		return ret;
-	}
-
-	/*
-	 * Enable interrupt generation when TSF1 or TSF2 timestamp flags
-	 * are set. Interrupt signal is an open-drain output and can be
-	 * left floating if unused.
-	 */
-	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
-				 PCF2127_BIT_CTRL2_TSIE,
-				 PCF2127_BIT_CTRL2_TSIE);
-	if (ret) {
-		dev_err(dev, "%s: tamper detection config (ctrl2) failed\n",
-			__func__);
-		return ret;
+	for (i = 0; i < pcf2127->cfg->ts_count; i++) {
+		ret = pcf2127_enable_ts(dev, i);
+		if (ret)
+			return ret;
 	}
 
-	ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group);
+	ret = rtc_add_group(pcf2127->rtc, &pcf2127->cfg->attribute_group);
 	if (ret) {
 		dev_err(dev, "%s: tamper sysfs registering failed\n",
 			__func__);
-- 
2.30.2


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

* [PATCH 07/10] rtc: pcf2127: add support for PCF2131 RTC
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (5 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 06/10] rtc: pcf2127: add support for multiple TS functions Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 08/10] rtc: pcf2127: add support for PCF2131 alarm interrupt on outputs INT_A/B Hugo Villeneuve
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

This RTC is very similar in functionality to the PCF2127/29.

Basically it:
  -supports two new control registers at offsets 4 and 5
  -supports a new reset register (not implemented in this driver)
  -supports 4 tamper detection functions instead of 1
  -has no nvmem (like the PCF2129)
  -has two output interrupt pins

Because of that, most of the register addresses are very different,
although they still follow the same layout. For example, the tamper
registers have a different base address, but the offsets are all the same.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/Kconfig       |   4 +-
 drivers/rtc/rtc-pcf2127.c | 234 ++++++++++++++++++++++++++++++++++----
 2 files changed, 215 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d85a3c31347c..9b083ca6b4c4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -899,9 +899,9 @@ config RTC_DRV_PCF2127
 	select REGMAP_SPI if SPI_MASTER
 	select WATCHDOG_CORE if WATCHDOG
 	help
-	  If you say yes here you get support for the NXP PCF2127/29 RTC
+	  If you say yes here you get support for the NXP PCF2127/29/31 RTC
 	  chips with integrated quartz crystal for industrial applications.
-	  Both chips also have watchdog timer and tamper switch detection
+	  These chips also have watchdog timer and tamper switch detection
 	  features.
 
 	  PCF2127 has an additional feature of 512 bytes battery backed
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index e806d65e4504..fdce31e169a6 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -1,16 +1,27 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * An I2C and SPI driver for the NXP PCF2127/29 RTC
+ * An I2C and SPI driver for the NXP PCF2127/29/31 RTC
  * Copyright 2013 Til-Technologies
+ * Copyright 2021 DimOnOff
  *
  * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
  *
  * Watchdog and tamper functions
  * Author: Bruno Thomsen <bruno.thomsen@gmail.com>
  *
+ * PCF2131 support
+ * Author: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+ *
  * based on the other drivers in this same directory.
  *
- * Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf
+ * Datasheets: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf
+ *             https://www.nxp.com/docs/en/data-sheet/PCF2131DS.pdf
+ */
+
+/*
+ * The following features are not yet implemented for the PCF2131:
+ *   - support for reset register
+ *   - support for 1/100th seconds
  */
 
 #include <linux/i2c.h>
@@ -43,8 +54,29 @@
 #define PCF2127_BIT_CTRL3_BLF			BIT(2)
 #define PCF2127_BIT_CTRL3_BF			BIT(3)
 #define PCF2127_BIT_CTRL3_BTSE			BIT(4)
+/* Control register 4 */
+#define PCF2131_REG_CTRL4		0x03
+#define PCF2131_BIT_CTRL4_TSF4			BIT(4)
+#define PCF2131_BIT_CTRL4_TSF3			BIT(5)
+#define PCF2131_BIT_CTRL4_TSF2			BIT(6)
+#define PCF2131_BIT_CTRL4_TSF1			BIT(7)
+/* Control register 5 */
+#define PCF2131_REG_CTRL5		0x04
+#define PCF2131_BIT_CTRL5_TSIE4			BIT(4)
+#define PCF2131_BIT_CTRL5_TSIE3			BIT(5)
+#define PCF2131_BIT_CTRL5_TSIE2			BIT(6)
+#define PCF2131_BIT_CTRL5_TSIE1			BIT(7)
+/* Software reset register */
+#define PCF2131_REG_SR_RESET		0x05
+#define PCF2131_SR_RESET_READ_PATTERN	0b00100100 /* Fixed pattern. */
 /* Time and date registers */
 #define PCF2127_REG_TIME_DATE_BASE	0x03
+#define PCF2131_REG_TIME_DATE_BASE	0x07 /* Register 0x06 is 100th seconds,
+					      * but we do not support it. By
+					      * using offset 0x07, we can be
+					      * compatible with existing
+					      * time/date functions.
+					      */
 /* Time and date registers offsets (starting from base register) */
 #define PCF2127_OFFSET_TD_SC		0
 #define PCF2127_OFFSET_TD_MN		1
@@ -57,6 +89,7 @@
 #define PCF2127_BIT_SC_OSF			BIT(7)
 /* Alarm registers */
 #define PCF2127_REG_ALARM_BASE		0x0A
+#define PCF2131_REG_ALARM_BASE		0x0E
 /* Alarm registers offsets (starting from base register) */
 #define PCF2127_OFFSET_ALARM_SC		0
 #define PCF2127_OFFSET_ALARM_MN		1
@@ -67,16 +100,26 @@
 #define PCF2127_BIT_ALARM_AE			BIT(7)
 /* CLKOUT control register */
 #define PCF2127_REG_CLKOUT		0x0f
+#define PCF2131_REG_CLKOUT		0x13
 #define PCF2127_BIT_CLKOUT_OTPR			BIT(5)
 /* Watchdog registers */
 #define PCF2127_REG_WD_CTL		0x10
+#define PCF2131_REG_WD_CTL		0x35
 #define PCF2127_BIT_WD_CTL_TF0			BIT(0)
 #define PCF2127_BIT_WD_CTL_TF1			BIT(1)
 #define PCF2127_BIT_WD_CTL_CD0			BIT(6)
 #define PCF2127_BIT_WD_CTL_CD1			BIT(7)
 #define PCF2127_REG_WD_VAL		0x11
+#define PCF2131_REG_WD_VAL		0x36
 /* Tamper timestamp1 registers */
 #define PCF2127_REG_TS1_BASE		0x12
+#define PCF2131_REG_TS1_BASE		0x14
+/* Tamper timestamp2 registers */
+#define PCF2131_REG_TS2_BASE		0x1B
+/* Tamper timestamp3 registers */
+#define PCF2131_REG_TS3_BASE		0x22
+/* Tamper timestamp4 registers */
+#define PCF2131_REG_TS4_BASE		0x29
 /* Tamper timestamp registers common offsets (starting from base register) */
 #define PCF2127_OFFSET_TS_CTL		0
 #define PCF2127_OFFSET_TS_SC		1
@@ -92,11 +135,22 @@
  * RAM registers
  * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
  * battery backed and can survive a power outage.
- * PCF2129 doesn't have this feature.
+ * PCF2129/31 doesn't have this feature.
  */
 #define PCF2127_REG_RAM_ADDR_MSB	0x1A
 #define PCF2127_REG_RAM_WRT_CMD		0x1C
 #define PCF2127_REG_RAM_RD_CMD		0x1D
+/* Interrupt mask registers */
+#define PCF2131_REG_INT_A_MASK1		0x31
+#define PCF2131_REG_INT_A_MASK2		0x32
+#define PCF2131_REG_INT_B_MASK1		0x33
+#define PCF2131_REG_INT_B_MASK2		0x34
+#define PCF2131_BIT_INT_BLIE		BIT(0)
+#define PCF2131_BIT_INT_BIE		BIT(1)
+#define PCF2131_BIT_INT_AIE		BIT(2)
+#define PCF2131_BIT_INT_WD_CD		BIT(3)
+#define PCF2131_BIT_INT_SI		BIT(4)
+#define PCF2131_BIT_INT_MI		BIT(5)
 
 /* Watchdog timer value constants */
 #define PCF2127_WD_VAL_STOP		0
@@ -110,6 +164,14 @@
 		PCF2127_BIT_CTRL2_AF | \
 		PCF2127_BIT_CTRL2_WDTF | \
 		PCF2127_BIT_CTRL2_TSF2)
+#define PCF2131_CTRL2_IRQ_MASK ( \
+		PCF2127_BIT_CTRL2_AF | \
+		PCF2127_BIT_CTRL2_WDTF)
+#define PCF2131_CTRL4_IRQ_MASK ( \
+		PCF2131_BIT_CTRL4_TSF4 | \
+		PCF2131_BIT_CTRL4_TSF3 | \
+		PCF2131_BIT_CTRL4_TSF2 | \
+		PCF2131_BIT_CTRL4_TSF1)
 
 struct pcf21xx_ts_config {
 	u8 regs_base; /* Base register to read timestamp values. */
@@ -370,7 +432,7 @@ static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd,
 }
 
 static const struct watchdog_info pcf2127_wdt_info = {
-	.identity = "NXP PCF2127/PCF2129 Watchdog",
+	.identity = "NXP PCF2127/29/31 Watchdog",
 	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
 };
 
@@ -554,30 +616,64 @@ static void pcf2127_rtc_ts_snapshot(struct device *dev, int ts_id)
 static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
 {
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
-	unsigned int ctrl1, ctrl2;
+	unsigned int ctrl2;
 	int ret = 0;
 
-	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1);
-	if (ret)
-		return IRQ_NONE;
-
 	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
 	if (ret)
 		return IRQ_NONE;
 
-	if (!(ctrl1 & PCF2127_CTRL1_IRQ_MASK || ctrl2 & PCF2127_CTRL2_IRQ_MASK))
-		return IRQ_NONE;
+	if (pcf2127->cfg->ts_count == 1) {
+		/* PCF2127/29 */
+		unsigned int ctrl1;
 
-	if (ctrl1 & PCF2127_BIT_CTRL1_TSF1 || ctrl2 & PCF2127_BIT_CTRL2_TSF2)
-		pcf2127_rtc_ts_snapshot(dev, 0);
+		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1);
+		if (ret)
+			return IRQ_NONE;
+
+		if (!(ctrl1 & PCF2127_CTRL1_IRQ_MASK || ctrl2 & PCF2127_CTRL2_IRQ_MASK))
+			return IRQ_NONE;
+
+		if (ctrl1 & PCF2127_BIT_CTRL1_TSF1 || ctrl2 & PCF2127_BIT_CTRL2_TSF2)
+			pcf2127_rtc_ts_snapshot(dev, 0);
+
+		if (ctrl1 & PCF2127_CTRL1_IRQ_MASK)
+			regmap_write(pcf2127->regmap, PCF2127_REG_CTRL1,
+				     ctrl1 & ~PCF2127_CTRL1_IRQ_MASK);
+
+		if (ctrl2 & PCF2127_CTRL2_IRQ_MASK)
+			regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
+				     ctrl2 & ~PCF2127_CTRL2_IRQ_MASK);
+	} else {
+		/* PCF2131. */
+		unsigned int ctrl4;
+
+		ret = regmap_read(pcf2127->regmap, PCF2131_REG_CTRL4, &ctrl4);
+		if (ret)
+			return IRQ_NONE;
 
-	if (ctrl1 & PCF2127_CTRL1_IRQ_MASK)
-		regmap_write(pcf2127->regmap, PCF2127_REG_CTRL1,
-			ctrl1 & ~PCF2127_CTRL1_IRQ_MASK);
+		if (!(ctrl4 & PCF2131_CTRL4_IRQ_MASK || ctrl2 & PCF2131_CTRL2_IRQ_MASK))
+			return IRQ_NONE;
 
-	if (ctrl2 & PCF2127_CTRL2_IRQ_MASK)
-		regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
-			ctrl2 & ~PCF2127_CTRL2_IRQ_MASK);
+		if (ctrl4 & PCF2131_CTRL4_IRQ_MASK) {
+			int i;
+			int tsf_bit = PCF2131_BIT_CTRL4_TSF1; /* Start at bit 7. */
+
+			for (i = 0; i < pcf2127->cfg->ts_count; i++) {
+				if (ctrl4 & tsf_bit)
+					pcf2127_rtc_ts_snapshot(dev, i);
+
+				tsf_bit = tsf_bit >> 1;
+			}
+
+			regmap_write(pcf2127->regmap, PCF2131_REG_CTRL4,
+				     ctrl4 & ~PCF2131_CTRL4_IRQ_MASK);
+		}
+
+		if (ctrl2 & PCF2131_CTRL2_IRQ_MASK)
+			regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
+				     ctrl2 & ~PCF2131_CTRL2_IRQ_MASK);
+	}
 
 	if (ctrl2 & PCF2127_BIT_CTRL2_AF)
 		rtc_update_irq(pcf2127->rtc, 1, RTC_IRQF | RTC_AF);
@@ -649,6 +745,27 @@ static ssize_t timestamp0_store(struct device *dev,
 	return timestamp_store(dev, attr, buf, count, 0);
 };
 
+static ssize_t timestamp1_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	return timestamp_store(dev, attr, buf, count, 1);
+};
+
+static ssize_t timestamp2_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	return timestamp_store(dev, attr, buf, count, 2);
+};
+
+static ssize_t timestamp3_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	return timestamp_store(dev, attr, buf, count, 3);
+};
+
 static ssize_t timestamp_show(struct device *dev,
 			      struct device_attribute *attr, char *buf,
 			      int ts_id)
@@ -713,16 +830,46 @@ static ssize_t timestamp0_show(struct device *dev,
 	return timestamp_show(dev, attr, buf, 0);
 };
 
+static ssize_t timestamp1_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return timestamp_show(dev, attr, buf, 1);
+};
+
+static ssize_t timestamp2_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return timestamp_show(dev, attr, buf, 2);
+};
+
+static ssize_t timestamp3_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return timestamp_show(dev, attr, buf, 3);
+};
+
 static DEVICE_ATTR_RW(timestamp0);
+static DEVICE_ATTR_RW(timestamp1);
+static DEVICE_ATTR_RW(timestamp2);
+static DEVICE_ATTR_RW(timestamp3);
 
 static struct attribute *pcf2127_attrs[] = {
 	&dev_attr_timestamp0.attr,
 	NULL
 };
 
+static struct attribute *pcf2131_attrs[] = {
+	&dev_attr_timestamp0.attr,
+	&dev_attr_timestamp1.attr,
+	&dev_attr_timestamp2.attr,
+	&dev_attr_timestamp3.attr,
+	NULL
+};
+
 enum pcf21xx_type {
 	PCF2127,
 	PCF2129,
+	PCF2131,
 	PCF21XX_LAST_ID
 };
 
@@ -773,6 +920,48 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 			.attrs	= pcf2127_attrs,
 		},
 	},
+	[PCF2131] = {
+		.max_register = 0x36,
+		.has_nvmem = 0,
+		.has_bit_wd_ctl_cd0 = 0,
+		.regs_td_base = PCF2131_REG_TIME_DATE_BASE,
+		.regs_alarm_base = PCF2131_REG_ALARM_BASE,
+		.reg_wd_ctl = PCF2131_REG_WD_CTL,
+		.reg_wd_val = PCF2131_REG_WD_VAL,
+		.reg_clkout = PCF2131_REG_CLKOUT,
+		.ts_count = 4,
+		.ts[0] = {
+			.regs_base = PCF2131_REG_TS1_BASE,
+			.low_reg   = PCF2131_REG_CTRL4,
+			.low_bit   = PCF2131_BIT_CTRL4_TSF1,
+			.ie_reg    = PCF2131_REG_CTRL5,
+			.ie_bit    = PCF2131_BIT_CTRL5_TSIE1,
+		},
+		.ts[1] = {
+			.regs_base = PCF2131_REG_TS2_BASE,
+			.low_reg   = PCF2131_REG_CTRL4,
+			.low_bit   = PCF2131_BIT_CTRL4_TSF2,
+			.ie_reg    = PCF2131_REG_CTRL5,
+			.ie_bit    = PCF2131_BIT_CTRL5_TSIE2,
+		},
+		.ts[2] = {
+			.regs_base = PCF2131_REG_TS3_BASE,
+			.low_reg   = PCF2131_REG_CTRL4,
+			.low_bit   = PCF2131_BIT_CTRL4_TSF3,
+			.ie_reg    = PCF2131_REG_CTRL5,
+			.ie_bit    = PCF2131_BIT_CTRL5_TSIE3,
+		},
+		.ts[3] = {
+			.regs_base = PCF2131_REG_TS4_BASE,
+			.low_reg   = PCF2131_REG_CTRL4,
+			.low_bit   = PCF2131_BIT_CTRL4_TSF4,
+			.ie_reg    = PCF2131_REG_CTRL5,
+			.ie_bit    = PCF2131_BIT_CTRL5_TSIE4,
+		},
+		.attribute_group = {
+			.attrs	= pcf2131_attrs,
+		},
+	},
 };
 
 /*
@@ -910,7 +1099,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	 * Watchdog timer enabled and reset pin /RST activated when timed out.
 	 * Select 1Hz clock source for watchdog timer.
 	 * Note: Countdown timer disabled and not available.
-	 * For pca2129, pcf2129, only bit[7] is for Symbol WD_CD
+	 * For pca2129, pcf2129 and pcf2131, only bit[7] is for Symbol WD_CD
 	 * of register watchdg_tim_ctl. The bit[6] is labeled
 	 * as T. Bits labeled as T must always be written with
 	 * logic 0.
@@ -970,6 +1159,7 @@ static const struct of_device_id pcf2127_of_match[] = {
 	{ .compatible = "nxp,pcf2127", .data = &pcf21xx_cfg[PCF2127] },
 	{ .compatible = "nxp,pcf2129", .data = &pcf21xx_cfg[PCF2129] },
 	{ .compatible = "nxp,pca2129", .data = &pcf21xx_cfg[PCF2129] },
+	{ .compatible = "nxp,pcf2131", .data = &pcf21xx_cfg[PCF2131] },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf2127_of_match);
@@ -1099,6 +1289,7 @@ static const struct i2c_device_id pcf2127_i2c_id[] = {
 	{ "pcf2127", PCF2127 },
 	{ "pcf2129", PCF2129 },
 	{ "pca2129", PCF2129 },
+	{ "pcf2131", PCF2131 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
@@ -1181,6 +1372,7 @@ static const struct spi_device_id pcf2127_spi_id[] = {
 	{ "pcf2127", PCF2127 },
 	{ "pcf2129", PCF2129 },
 	{ "pca2129", PCF2129 },
+	{ "pcf2131", PCF2131 },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
@@ -1245,5 +1437,5 @@ static void __exit pcf2127_exit(void)
 module_exit(pcf2127_exit)
 
 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
-MODULE_DESCRIPTION("NXP PCF2127/29 RTC driver");
+MODULE_DESCRIPTION("NXP PCF2127/29/31 RTC driver");
 MODULE_LICENSE("GPL v2");
-- 
2.30.2


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

* [PATCH 08/10] rtc: pcf2127: add support for PCF2131 alarm interrupt on outputs INT_A/B
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (6 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 07/10] rtc: pcf2127: add support for PCF2131 RTC Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131 Hugo Villeneuve
  2022-01-25 20:00 ` [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support Hugo Villeneuve
  9 siblings, 0 replies; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni
  Cc: hugo, Hugo Villeneuve, linux-rtc, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

The PCF2127 and PCF2129 have one output interrupt pin. The PCF2131 has
two, named INT_A and INT_B. The alarm interrupt can be routed to
either one or both of them.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 drivers/rtc/rtc-pcf2127.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index fdce31e169a6..a75deab47284 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -191,6 +191,7 @@ struct pcf21xx_config {
 	int max_register;
 	unsigned int has_nvmem:1;
 	unsigned int has_bit_wd_ctl_cd0:1;
+	unsigned int has_int_a_b:1; /* PCF2131 supports two interrupt outputs. */
 	u8 regs_td_base; /* Time/data base registers. */
 	u8 regs_alarm_base; /* Alarm function base registers. */
 	u8 reg_wd_ctl; /* Watchdog control register. */
@@ -511,6 +512,39 @@ static int pcf2127_rtc_alarm_irq_enable(struct device *dev, u32 enable)
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
 	int ret;
 
+	if (pcf2127->cfg->has_int_a_b) {
+		/*
+		 * The PCF2131 supports two interrupt outputs, INT_A and INT_B.
+		 * The alarm interrupt can be routed to either one or both of
+		 * them. Make sure that at least one output pin is requested.
+		 */
+		if (enable &&
+		    !device_property_read_bool(dev, "alarm-output-a") &&
+		    !device_property_read_bool(dev, "alarm-output-b")) {
+			dev_warn(dev, "no alarm interrupt output pin selected, alarm function will not work\n");
+			return -EINVAL;
+		}
+
+		if (device_property_read_bool(dev, "alarm-output-a")) {
+			ret = regmap_update_bits(pcf2127->regmap,
+						 PCF2131_REG_INT_A_MASK1,
+						 PCF2131_BIT_INT_AIE,
+						 enable ? PCF2131_BIT_INT_AIE : 0);
+			if (ret)
+				return ret;
+		}
+
+		if (device_property_read_bool(dev, "alarm-output-b")) {
+			ret = regmap_update_bits(pcf2127->regmap,
+						 PCF2131_REG_INT_B_MASK1,
+						 PCF2131_BIT_INT_AIE,
+						 enable ? PCF2131_BIT_INT_AIE : 0);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Enable alarm interrupt. */
 	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
 				 PCF2127_BIT_CTRL2_AIE,
 				 enable ? PCF2127_BIT_CTRL2_AIE : 0);
@@ -878,6 +912,7 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.max_register = 0x1d,
 		.has_nvmem = 1,
 		.has_bit_wd_ctl_cd0 = 1,
+		.has_int_a_b = 0,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
@@ -901,6 +936,7 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.max_register = 0x19,
 		.has_nvmem = 0,
 		.has_bit_wd_ctl_cd0 = 0,
+		.has_int_a_b = 0,
 		.regs_td_base = PCF2127_REG_TIME_DATE_BASE,
 		.regs_alarm_base = PCF2127_REG_ALARM_BASE,
 		.reg_wd_ctl = PCF2127_REG_WD_CTL,
@@ -924,6 +960,7 @@ static struct pcf21xx_config pcf21xx_cfg[] = {
 		.max_register = 0x36,
 		.has_nvmem = 0,
 		.has_bit_wd_ctl_cd0 = 0,
+		.has_int_a_b = 1,
 		.regs_td_base = PCF2131_REG_TIME_DATE_BASE,
 		.regs_alarm_base = PCF2131_REG_ALARM_BASE,
 		.reg_wd_ctl = PCF2131_REG_WD_CTL,
-- 
2.30.2


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

* [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (7 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 08/10] rtc: pcf2127: add support for PCF2131 alarm interrupt on outputs INT_A/B Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-02-09  3:23   ` Rob Herring
  2022-01-25 20:00 ` [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support Hugo Villeneuve
  9 siblings, 1 reply; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring
  Cc: hugo, Hugo Villeneuve, linux-rtc, devicetree, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Add support for new NXP RTC PCF2131.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
index cde7b1675ead..57eb0a58afa3 100644
--- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
@@ -14,7 +14,9 @@ maintainers:
 
 properties:
   compatible:
-    const: nxp,pcf2127
+    enum:
+      - nxp,pcf2127
+      - nxp,pcf2131
 
   reg:
     maxItems: 1
@@ -48,4 +50,19 @@ examples:
         };
     };
 
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        rtc@53 {
+            compatible = "nxp,pcf2131";
+            reg = <0x53>;
+            pinctrl-0 = <&rtc_nint_pins>;
+            interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
+            reset-source;
+        };
+    };
+
 ...
-- 
2.30.2


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

* [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
       [not found] <20220125200009.900660-1-hugo@hugovil.com>
                   ` (8 preceding siblings ...)
  2022-01-25 20:00 ` [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131 Hugo Villeneuve
@ 2022-01-25 20:00 ` Hugo Villeneuve
  2022-02-09  3:20   ` Rob Herring
  9 siblings, 1 reply; 17+ messages in thread
From: Hugo Villeneuve @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Alessandro Zummo, Alexandre Belloni, Rob Herring
  Cc: hugo, Hugo Villeneuve, linux-rtc, devicetree, linux-kernel

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

The PCF2131 has two output interrupt pins, named INT_A and INT_B.

Add properties to identify onto which pin we want the alarm interrupt
to be routed. It can be either one, or both.

These properties are automatically set to false for variants other
than PCF2131 (ex: PCF2127).

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
index 57eb0a58afa3..83656dd2f97f 100644
--- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
@@ -24,6 +24,16 @@ properties:
   interrupts:
     maxItems: 1
 
+  alarm-output-a:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enable alarm interrupt on INT_A output pin.
+
+  alarm-output-b:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enable alarm interrupt on INT_B output pin.
+
   start-year: true
 
   reset-source: true
@@ -32,6 +42,18 @@ required:
   - compatible
   - reg
 
+if:
+  not:
+    properties:
+      compatible:
+        contains:
+          enum:
+            - nxp,pcf2131
+then:
+  properties:
+    alarm-output-a: false
+    alarm-output-b: false
+
 additionalProperties: false
 
 examples:
@@ -62,6 +84,7 @@ examples:
             pinctrl-0 = <&rtc_nint_pins>;
             interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
             reset-source;
+            alarm-output-b;
         };
     };
 
-- 
2.30.2


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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-01-25 20:00 ` [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support Hugo Villeneuve
@ 2022-02-09  3:20   ` Rob Herring
  2022-02-10 22:12     ` Hugo Villeneuve
  0 siblings, 1 reply; 17+ messages in thread
From: Rob Herring @ 2022-02-09  3:20 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Alessandro Zummo, Alexandre Belloni, Hugo Villeneuve, linux-rtc,
	devicetree, linux-kernel

On Tue, Jan 25, 2022 at 03:00:09PM -0500, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> The PCF2131 has two output interrupt pins, named INT_A and INT_B.
> 
> Add properties to identify onto which pin we want the alarm interrupt
> to be routed. It can be either one, or both.
> 
> These properties are automatically set to false for variants other
> than PCF2131 (ex: PCF2127).
> 
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> ---
>  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23 +++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> index 57eb0a58afa3..83656dd2f97f 100644
> --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> @@ -24,6 +24,16 @@ properties:
>    interrupts:
>      maxItems: 1
>  
> +  alarm-output-a:

nxp,alarm-output-a

> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      Enable alarm interrupt on INT_A output pin.
> +
> +  alarm-output-b:
> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      Enable alarm interrupt on INT_B output pin.
> +
>    start-year: true
>  
>    reset-source: true
> @@ -32,6 +42,18 @@ required:
>    - compatible
>    - reg
>  
> +if:
> +  not:
> +    properties:
> +      compatible:
> +        contains:
> +          enum:
> +            - nxp,pcf2131
> +then:
> +  properties:
> +    alarm-output-a: false
> +    alarm-output-b: false
> +
>  additionalProperties: false
>  
>  examples:
> @@ -62,6 +84,7 @@ examples:
>              pinctrl-0 = <&rtc_nint_pins>;
>              interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
>              reset-source;
> +            alarm-output-b;
>          };
>      };
>  
> -- 
> 2.30.2
> 
> 

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

* Re: [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131
  2022-01-25 20:00 ` [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131 Hugo Villeneuve
@ 2022-02-09  3:23   ` Rob Herring
  0 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2022-02-09  3:23 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Alessandro Zummo, Alexandre Belloni, Hugo Villeneuve, linux-rtc,
	devicetree, linux-kernel

On Tue, Jan 25, 2022 at 03:00:08PM -0500, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Add support for new NXP RTC PCF2131.
> 
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> ---
>  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-02-09  3:20   ` Rob Herring
@ 2022-02-10 22:12     ` Hugo Villeneuve
  2022-02-10 22:32       ` Alexandre Belloni
  0 siblings, 1 reply; 17+ messages in thread
From: Hugo Villeneuve @ 2022-02-10 22:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Alessandro Zummo, Alexandre Belloni, Hugo Villeneuve, linux-rtc,
	devicetree, linux-kernel

On Tue, 8 Feb 2022 21:20:28 -0600
Rob Herring <robh@kernel.org> wrote:

> On Tue, Jan 25, 2022 at 03:00:09PM -0500, Hugo Villeneuve wrote:
> > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > 
> > The PCF2131 has two output interrupt pins, named INT_A and INT_B.
> > 
> > Add properties to identify onto which pin we want the alarm interrupt
> > to be routed. It can be either one, or both.
> > 
> > These properties are automatically set to false for variants other
> > than PCF2131 (ex: PCF2127).
> > 
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > ---
> >  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23 +++++++++++++++++++
> >  1 file changed, 23 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > index 57eb0a58afa3..83656dd2f97f 100644
> > --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > @@ -24,6 +24,16 @@ properties:
> >    interrupts:
> >      maxItems: 1
> >  
> > +  alarm-output-a:
> 
> nxp,alarm-output-a

Ok, this will be fixed for V2.

Thank you, Hugo.

-- 
Hugo Villeneuve <hugo@hugovil.com>

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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-02-10 22:12     ` Hugo Villeneuve
@ 2022-02-10 22:32       ` Alexandre Belloni
  2022-02-10 22:55         ` Hugo Villeneuve
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Belloni @ 2022-02-10 22:32 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Rob Herring, Alessandro Zummo, Hugo Villeneuve, linux-rtc,
	devicetree, linux-kernel

On 10/02/2022 17:12:34-0500, Hugo Villeneuve wrote:
> On Tue, 8 Feb 2022 21:20:28 -0600
> Rob Herring <robh@kernel.org> wrote:
> 
> > On Tue, Jan 25, 2022 at 03:00:09PM -0500, Hugo Villeneuve wrote:
> > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > 
> > > The PCF2131 has two output interrupt pins, named INT_A and INT_B.
> > > 
> > > Add properties to identify onto which pin we want the alarm interrupt
> > > to be routed. It can be either one, or both.
> > > 
> > > These properties are automatically set to false for variants other
> > > than PCF2131 (ex: PCF2127).
> > > 
> > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > ---
> > >  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23 +++++++++++++++++++
> > >  1 file changed, 23 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > index 57eb0a58afa3..83656dd2f97f 100644
> > > --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > @@ -24,6 +24,16 @@ properties:
> > >    interrupts:
> > >      maxItems: 1
> > >  
> > > +  alarm-output-a:
> > 
> > nxp,alarm-output-a
> 
> Ok, this will be fixed for V2.
> 

Actually, this property has to be made more generic and thought out.
There are multiple RTCs that have multiple interrupt pins where one of
the pin can be used for different interrupt or clock output.

With your binding, there is no way to separate which interrupt is going
to which pin and so there is no way to get the alarm and BLF or the
watchdog on different pins and we certainly don't want to have a
property per interrupt type.

Also, the documentation is missing the fact that the driver makes having
one of the property mandatory.


-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-02-10 22:32       ` Alexandre Belloni
@ 2022-02-10 22:55         ` Hugo Villeneuve
  2022-02-11 20:16           ` Hugo Villeneuve
  0 siblings, 1 reply; 17+ messages in thread
From: Hugo Villeneuve @ 2022-02-10 22:55 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Rob Herring, Alessandro Zummo, Hugo Villeneuve, linux-rtc,
	devicetree, linux-kernel

On Thu, 10 Feb 2022 23:32:32 +0100
Alexandre Belloni <alexandre.belloni@bootlin.com> wrote:

> On 10/02/2022 17:12:34-0500, Hugo Villeneuve wrote:
> > On Tue, 8 Feb 2022 21:20:28 -0600
> > Rob Herring <robh@kernel.org> wrote:
> > 
> > > On Tue, Jan 25, 2022 at 03:00:09PM -0500, Hugo Villeneuve wrote:
> > > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > > 
> > > > The PCF2131 has two output interrupt pins, named INT_A and INT_B.
> > > > 
> > > > Add properties to identify onto which pin we want the alarm interrupt
> > > > to be routed. It can be either one, or both.
> > > > 
> > > > These properties are automatically set to false for variants other
> > > > than PCF2131 (ex: PCF2127).
> > > > 
> > > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > > ---
> > > >  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23 +++++++++++++++++++
> > > >  1 file changed, 23 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > index 57eb0a58afa3..83656dd2f97f 100644
> > > > --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > @@ -24,6 +24,16 @@ properties:
> > > >    interrupts:
> > > >      maxItems: 1
> > > >  
> > > > +  alarm-output-a:
> > > 
> > > nxp,alarm-output-a
> > 
> > Ok, this will be fixed for V2.
> > 
> 
> Actually, this property has to be made more generic and thought out.
> There are multiple RTCs that have multiple interrupt pins where one of
> the pin can be used for different interrupt or clock output.
> 
> With your binding, there is no way to separate which interrupt is going
> to which pin and so there is no way to get the alarm and BLF or the
> watchdog on different pins and we certainly don't want to have a
> property per interrupt type.

Hi,
can you please suggest how you would prefer it to be done?

> Also, the documentation is missing the fact that the driver makes having
> one of the property mandatory.

I will add it.

Thank you, Hugo.

-- 
Hugo Villeneuve <hugo@hugovil.com>

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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-02-10 22:55         ` Hugo Villeneuve
@ 2022-02-11 20:16           ` Hugo Villeneuve
  2022-02-11 21:02             ` Alexandre Belloni
  0 siblings, 1 reply; 17+ messages in thread
From: Hugo Villeneuve @ 2022-02-11 20:16 UTC (permalink / raw)
  To: hugo, alexandre.belloni
  Cc: robh, a.zummo, devicetree, linux-rtc, linux-kernel

On Thu, 2022-02-10 at 17:55 -0500, Hugo Villeneuve wrote:
> On Thu, 10 Feb 2022 23:32:32 +0100
> Alexandre Belloni <alexandre.belloni@bootlin.com> wrote:
> 
> > On 10/02/2022 17:12:34-0500, Hugo Villeneuve wrote:
> > > On Tue, 8 Feb 2022 21:20:28 -0600
> > > Rob Herring <robh@kernel.org> wrote:
> > > 
> > > > On Tue, Jan 25, 2022 at 03:00:09PM -0500, Hugo Villeneuve
> > > > wrote:
> > > > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > > > 
> > > > > The PCF2131 has two output interrupt pins, named INT_A and
> > > > > INT_B.
> > > > > 
> > > > > Add properties to identify onto which pin we want the alarm
> > > > > interrupt
> > > > > to be routed. It can be either one, or both.
> > > > > 
> > > > > These properties are automatically set to false for variants
> > > > > other
> > > > > than PCF2131 (ex: PCF2127).
> > > > > 
> > > > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > > > > ---
> > > > >  .../devicetree/bindings/rtc/nxp,pcf2127.yaml  | 23
> > > > > +++++++++++++++++++
> > > > >  1 file changed, 23 insertions(+)
> > > > > 
> > > > > diff --git
> > > > > a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > > b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > > index 57eb0a58afa3..83656dd2f97f 100644
> > > > > --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > > +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
> > > > > @@ -24,6 +24,16 @@ properties:
> > > > >    interrupts:
> > > > >      maxItems: 1
> > > > >  
> > > > > +  alarm-output-a:
> > > > 
> > > > nxp,alarm-output-a
> > > 
> > > Ok, this will be fixed for V2.
> > > 
> > 
> > Actually, this property has to be made more generic and thought
> > out.
> > There are multiple RTCs that have multiple interrupt pins where one
> > of
> > the pin can be used for different interrupt or clock output.

Hi,
the only example I could find of such a device is in rtc-pcf85363.c.
This device also has two interrupt pins, INT A/B, like the PCF2131.
However, in the pcf85363 driver, pin INT B is simply ignored, and all
interrupts are configured to go on INT A.

For the moment, I will simply modify my PCF2131 patches serie to mimic
the same behavior in V2. This simplifies things a lot, and support for
INT B pin could be added at a later stage (and also to pcf85363) if
anyone needs it (I don't).

Hugo.

> > With your binding, there is no way to separate which interrupt is
> > going
> > to which pin and so there is no way to get the alarm and BLF or the
> > watchdog on different pins and we certainly don't want to have a
> > property per interrupt type.
> 
> Hi,
> can you please suggest how you would prefer it to be done?
> 
> > Also, the documentation is missing the fact that the driver makes
> > having
> > one of the property mandatory.
> 
> I will add it.
> 
> Thank you, Hugo.
> 


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

* Re: [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support
  2022-02-11 20:16           ` Hugo Villeneuve
@ 2022-02-11 21:02             ` Alexandre Belloni
  0 siblings, 0 replies; 17+ messages in thread
From: Alexandre Belloni @ 2022-02-11 21:02 UTC (permalink / raw)
  To: Hugo Villeneuve; +Cc: hugo, robh, a.zummo, devicetree, linux-rtc, linux-kernel

On 11/02/2022 20:16:27+0000, Hugo Villeneuve wrote:
> > > Actually, this property has to be made more generic and thought
> > > out.
> > > There are multiple RTCs that have multiple interrupt pins where one
> > > of
> > > the pin can be used for different interrupt or clock output.
> 
> Hi,
> the only example I could find of such a device is in rtc-pcf85363.c.
> This device also has two interrupt pins, INT A/B, like the PCF2131.
> However, in the pcf85363 driver, pin INT B is simply ignored, and all
> interrupts are configured to go on INT A.
> 

Yes, this was the RTC for which we had that discussion last time but
there is also pcf8523 and other non NXP RTCs.

> For the moment, I will simply modify my PCF2131 patches serie to mimic
> the same behavior in V2. This simplifies things a lot, and support for
> INT B pin could be added at a later stage (and also to pcf85363) if
> anyone needs it (I don't).
> 
> Hugo.
> 
> > > With your binding, there is no way to separate which interrupt is
> > > going
> > > to which pin and so there is no way to get the alarm and BLF or the
> > > watchdog on different pins and we certainly don't want to have a
> > > property per interrupt type.
> > 
> > Hi,
> > can you please suggest how you would prefer it to be done?
> > 
> > > Also, the documentation is missing the fact that the driver makes
> > > having
> > > one of the property mandatory.
> > 
> > I will add it.
> > 
> > Thank you, Hugo.
> > 
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

end of thread, other threads:[~2022-02-11 21:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20220125200009.900660-1-hugo@hugovil.com>
2022-01-25 20:00 ` [PATCH 01/10] rtc: pcf2127: add variant-specific configuration structure Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 02/10] rtc: pcf2127: adapt for time/date registers at any offset Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 03/10] rtc: pcf2127: adapt for alarm " Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 04/10] rtc: pcf2127: adapt for WD " Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 05/10] rtc: pcf2127: adapt for CLKOUT register " Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 06/10] rtc: pcf2127: add support for multiple TS functions Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 07/10] rtc: pcf2127: add support for PCF2131 RTC Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 08/10] rtc: pcf2127: add support for PCF2131 alarm interrupt on outputs INT_A/B Hugo Villeneuve
2022-01-25 20:00 ` [PATCH 09/10] dt-bindings: rtc: pcf2127: add PCF2131 Hugo Villeneuve
2022-02-09  3:23   ` Rob Herring
2022-01-25 20:00 ` [PATCH 10/10] dt-bindings: rtc: pcf2127: add PCF2131 INT_A and INT_B support Hugo Villeneuve
2022-02-09  3:20   ` Rob Herring
2022-02-10 22:12     ` Hugo Villeneuve
2022-02-10 22:32       ` Alexandre Belloni
2022-02-10 22:55         ` Hugo Villeneuve
2022-02-11 20:16           ` Hugo Villeneuve
2022-02-11 21:02             ` 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).