linux-rtc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] rtc: pcf2127: add alarm support
@ 2020-06-07 17:06 liambeguin
  2020-06-07 17:06 ` [PATCH 1/3] rtc: pcf2127: add pca2129 device id liambeguin
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: liambeguin @ 2020-06-07 17:06 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc

From: Liam Beguin <lvb@xiphos.com>

The board used to test this series has the interrupt line of the RTC
connected to a circuit controlling the power of the board.
An event on the interrupt line while the board is off will power it on.

This was tested on a PCA2129, with:

	$ date "2010-10-10 10:10"
	Sun Oct 10 10:10:00 UTC 2010
	$ /usr/sbin/rtcwake -u -d /dev/rtc0  -s10 --mode off
	[ ... ]
	$ # power on after 10 seconds

Liam Beguin (3):
  rtc: pcf2127: add pca2129 device id
  rtc: pcf2127: add alarm support
  rtc: pcf2127: reset alarm interrupt at power on

 drivers/rtc/rtc-pcf2127.c | 131 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 3 deletions(-)

-- 
2.27.0


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

* [PATCH 1/3] rtc: pcf2127: add pca2129 device id
  2020-06-07 17:06 [PATCH 0/3] rtc: pcf2127: add alarm support liambeguin
@ 2020-06-07 17:06 ` liambeguin
  2020-06-09 20:48   ` Bruno Thomsen
  2020-06-07 17:06 ` [PATCH 2/3] rtc: pcf2127: add alarm support liambeguin
  2020-06-07 17:06 ` [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on liambeguin
  2 siblings, 1 reply; 11+ messages in thread
From: liambeguin @ 2020-06-07 17:06 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc

From: Liam Beguin <lvb@xiphos.com>

From: Liam Beguin <lvb@xiphos.com>

The PCA2129 is the automotive grade version of the PCF2129.
add it to the list of compatibles.

Signed-off-by: Liam Beguin <lvb@xiphos.com>
---
 drivers/rtc/rtc-pcf2127.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 4e50d6768f13..396a1144a213 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -546,6 +546,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 static const struct of_device_id pcf2127_of_match[] = {
 	{ .compatible = "nxp,pcf2127" },
 	{ .compatible = "nxp,pcf2129" },
+	{ .compatible = "nxp,pca2129" },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf2127_of_match);
@@ -656,6 +657,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
 static const struct i2c_device_id pcf2127_i2c_id[] = {
 	{ "pcf2127", 1 },
 	{ "pcf2129", 0 },
+	{ "pca2129", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
@@ -720,6 +722,7 @@ static int pcf2127_spi_probe(struct spi_device *spi)
 static const struct spi_device_id pcf2127_spi_id[] = {
 	{ "pcf2127", 1 },
 	{ "pcf2129", 0 },
+	{ "pca2129", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
-- 
2.27.0


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

* [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-07 17:06 [PATCH 0/3] rtc: pcf2127: add alarm support liambeguin
  2020-06-07 17:06 ` [PATCH 1/3] rtc: pcf2127: add pca2129 device id liambeguin
@ 2020-06-07 17:06 ` liambeguin
  2020-06-09 20:42   ` Bruno Thomsen
  2020-06-09 21:05   ` Alexandre Belloni
  2020-06-07 17:06 ` [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on liambeguin
  2 siblings, 2 replies; 11+ messages in thread
From: liambeguin @ 2020-06-07 17:06 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc

From: Liam Beguin <lvb@xiphos.com>

From: Liam Beguin <lvb@xiphos.com>

Add alarm support for the pcf2127 RTC chip family.
Tested on pca2129.

Signed-off-by: Liam Beguin <lvb@xiphos.com>
---
 drivers/rtc/rtc-pcf2127.c | 120 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 117 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 396a1144a213..3eeb085a7c72 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -28,7 +28,9 @@
 #define PCF2127_BIT_CTRL1_TSF1			BIT(4)
 /* Control register 2 */
 #define PCF2127_REG_CTRL2		0x01
+#define PCF2127_BIT_CTRL2_AIE			BIT(1)
 #define PCF2127_BIT_CTRL2_TSIE			BIT(2)
+#define PCF2127_BIT_CTRL2_AF			BIT(4)
 #define PCF2127_BIT_CTRL2_TSF2			BIT(5)
 /* Control register 3 */
 #define PCF2127_REG_CTRL3		0x02
@@ -46,6 +48,12 @@
 #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
+#define PCF2127_REG_ALARM_HR		0x0C
+#define PCF2127_REG_ALARM_DM		0x0D
+#define PCF2127_REG_ALARM_DW		0x0E
 /* Watchdog registers */
 #define PCF2127_REG_WD_CTL		0x10
 #define PCF2127_BIT_WD_CTL_TF0			BIT(0)
@@ -185,6 +193,107 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	return 0;
 }
 
+static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	unsigned int buf[5], ctrl2;
+	int ret;
+
+	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
+	if (ret) {
+		dev_err(dev, "%s: ctrl2 read error\n", __func__);
+		return ret;
+	}
+	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);
+	if (ret) {
+		dev_err(dev, "%s: alarm read error\n", __func__);
+		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_wday = buf[4] & 0x07;
+
+	dev_dbg(dev, "%s: alarm is %d:%d:%d, mday=%d, wday=%d\n", __func__,
+		alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec,
+		alrm->time.tm_mday, alrm->time.tm_wday);
+
+	return 0;
+}
+
+static int pcf2127_rtc_alarm_irq_enable(struct device *dev, u32 enable)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	unsigned int ctrl2;
+	int ret;
+
+	dev_dbg(dev, "%s: %s\n", __func__, enable ? "enable" : "disable");
+
+	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
+	if (ret) {
+		dev_err(dev, "%s: ctrl2 read error\n", __func__);
+		return ret;
+	}
+
+	if (enable)
+		ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
+				   ctrl2 | PCF2127_BIT_CTRL2_AIE);
+	else
+		ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
+				   ctrl2 & ~PCF2127_BIT_CTRL2_AIE);
+
+	if (ret) {
+		dev_err(dev, "%s: failed to enable alarm (%d)\n", __func__,
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	unsigned int ctrl2;
+	uint8_t buf[5];
+	int ret;
+
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
+				 PCF2127_BIT_CTRL2_AF,
+				 (unsigned int)~PCF2127_BIT_CTRL2_AF);
+	if (ret) {
+		dev_err(dev, "%s: failed to clear alarm interrupt flag (%d)",
+			__func__, 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] = (alrm->time.tm_wday & 0x07);
+
+	dev_dbg(dev, "%s: alarm set for: %d:%d:%d, mday=%d, wday=%d\n",
+		__func__, alrm->time.tm_hour, alrm->time.tm_min,
+		alrm->time.tm_sec, alrm->time.tm_mday, alrm->time.tm_wday);
+
+	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);
+	if (ret) {
+		dev_err(dev, "%s: failed to write alarm registers (%d)",
+			__func__, ret);
+		return ret;
+	}
+
+	pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled);
+
+	return 0;
+}
+
 #ifdef CONFIG_RTC_INTF_DEV
 static int pcf2127_rtc_ioctl(struct device *dev,
 				unsigned int cmd, unsigned long arg)
@@ -211,9 +320,12 @@ static int pcf2127_rtc_ioctl(struct device *dev,
 #endif
 
 static const struct rtc_class_ops pcf2127_rtc_ops = {
-	.ioctl		= pcf2127_rtc_ioctl,
-	.read_time	= pcf2127_rtc_read_time,
-	.set_time	= pcf2127_rtc_set_time,
+	.ioctl            = pcf2127_rtc_ioctl,
+	.read_time        = pcf2127_rtc_read_time,
+	.set_time         = pcf2127_rtc_set_time,
+	.read_alarm       = pcf2127_rtc_read_alarm,
+	.set_alarm        = pcf2127_rtc_set_alarm,
+	.alarm_irq_enable = pcf2127_rtc_alarm_irq_enable,
 };
 
 static int pcf2127_nvmem_read(void *priv, unsigned int offset,
@@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
 	pcf2127->rtc->ops = &pcf2127_rtc_ops;
 
+	device_init_wakeup(dev, true);
+
 	pcf2127->wdd.parent = dev;
 	pcf2127->wdd.info = &pcf2127_wdt_info;
 	pcf2127->wdd.ops = &pcf2127_watchdog_ops;
-- 
2.27.0


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

* [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on
  2020-06-07 17:06 [PATCH 0/3] rtc: pcf2127: add alarm support liambeguin
  2020-06-07 17:06 ` [PATCH 1/3] rtc: pcf2127: add pca2129 device id liambeguin
  2020-06-07 17:06 ` [PATCH 2/3] rtc: pcf2127: add alarm support liambeguin
@ 2020-06-07 17:06 ` liambeguin
  2020-06-09 21:07   ` Alexandre Belloni
  2 siblings, 1 reply; 11+ messages in thread
From: liambeguin @ 2020-06-07 17:06 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc

From: Liam Beguin <lvb@xiphos.com>

From: Liam Beguin <lvb@xiphos.com>

Signed-off-by: Liam Beguin <lvb@xiphos.com>
---
 drivers/rtc/rtc-pcf2127.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 3eeb085a7c72..f004a4030970 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -546,6 +546,14 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
 	pcf2127->rtc->ops = &pcf2127_rtc_ops;
 
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
+				 PCF2127_BIT_CTRL2_AIE, 0);
+	if (ret) {
+		dev_err(dev, "%s: failed to clear interrupt enable bit (%d)",
+			__func__, ret);
+		return ret;
+	}
+
 	device_init_wakeup(dev, true);
 
 	pcf2127->wdd.parent = dev;
-- 
2.27.0


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

* Re: [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-07 17:06 ` [PATCH 2/3] rtc: pcf2127: add alarm support liambeguin
@ 2020-06-09 20:42   ` Bruno Thomsen
  2020-06-10 15:38     ` Liam Beguin
  2020-06-09 21:05   ` Alexandre Belloni
  1 sibling, 1 reply; 11+ messages in thread
From: Bruno Thomsen @ 2020-06-09 20:42 UTC (permalink / raw)
  To: liambeguin; +Cc: Alessandro Zummo, Alexandre Belloni, linux-rtc

Hi Liam,

See comments below.

Den søn. 7. jun. 2020 kl. 19.06 skrev <liambeguin@gmail.com>:
>
> From: Liam Beguin <lvb@xiphos.com>
>
> From: Liam Beguin <lvb@xiphos.com>
>
> Add alarm support for the pcf2127 RTC chip family.
> Tested on pca2129.
>
> Signed-off-by: Liam Beguin <lvb@xiphos.com>
> ---
>  drivers/rtc/rtc-pcf2127.c | 120 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 117 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
> index 396a1144a213..3eeb085a7c72 100644
> --- a/drivers/rtc/rtc-pcf2127.c
> +++ b/drivers/rtc/rtc-pcf2127.c
> @@ -28,7 +28,9 @@
>  #define PCF2127_BIT_CTRL1_TSF1                 BIT(4)
>  /* Control register 2 */
>  #define PCF2127_REG_CTRL2              0x01
> +#define PCF2127_BIT_CTRL2_AIE                  BIT(1)
>  #define PCF2127_BIT_CTRL2_TSIE                 BIT(2)
> +#define PCF2127_BIT_CTRL2_AF                   BIT(4)
>  #define PCF2127_BIT_CTRL2_TSF2                 BIT(5)
>  /* Control register 3 */
>  #define PCF2127_REG_CTRL3              0x02
> @@ -46,6 +48,12 @@
>  #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
> +#define PCF2127_REG_ALARM_HR           0x0C
> +#define PCF2127_REG_ALARM_DM           0x0D
> +#define PCF2127_REG_ALARM_DW           0x0E
>  /* Watchdog registers */
>  #define PCF2127_REG_WD_CTL             0x10
>  #define PCF2127_BIT_WD_CTL_TF0                 BIT(0)
> @@ -185,6 +193,107 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
>         return 0;
>  }
>
> +static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> +       unsigned int buf[5], ctrl2;
> +       int ret;
> +
> +       ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
> +       if (ret) {
> +               dev_err(dev, "%s: ctrl2 read error\n", __func__);
> +               return ret;
> +       }

Reading CTRL2 register causes watchdog to stop.

Aways call pcf2127_wdt_active_ping() after CTRL2 access to ensure the watchdog
is running if enabled.

> +       ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);

Replace 5 with sizeof(buf).

> +       if (ret) {
> +               dev_err(dev, "%s: alarm read error\n", __func__);
> +               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_wday = buf[4] & 0x07;
> +
> +       dev_dbg(dev, "%s: alarm is %d:%d:%d, mday=%d, wday=%d\n", __func__,
> +               alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec,
> +               alrm->time.tm_mday, alrm->time.tm_wday);
> +
> +       return 0;
> +}
> +
> +static int pcf2127_rtc_alarm_irq_enable(struct device *dev, u32 enable)
> +{
> +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> +       unsigned int ctrl2;
> +       int ret;
> +
> +       dev_dbg(dev, "%s: %s\n", __func__, enable ? "enable" : "disable");

Delete debug trace.

> +
> +       ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
> +       if (ret) {
> +               dev_err(dev, "%s: ctrl2 read error\n", __func__);
> +               return ret;
> +       }
> +
> +       if (enable)
> +               ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
> +                                  ctrl2 | PCF2127_BIT_CTRL2_AIE);
> +       else
> +               ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
> +                                  ctrl2 & ~PCF2127_BIT_CTRL2_AIE);
> +
> +       if (ret) {
> +               dev_err(dev, "%s: failed to enable alarm (%d)\n", __func__,
> +                       ret);
> +               return ret;
> +       }

Replace regmap_read() and regmap_write() with a regmap_update_bits().

So something like:

ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
                                          enabled ? PCF2127_REG_CTRL2 : 0);

And remember to call pcf2127_wdt_active_ping().

> +
> +       return 0;
> +}
> +
> +static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> +       unsigned int ctrl2;
> +       uint8_t buf[5];
> +       int ret;
> +
> +       ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
> +                                PCF2127_BIT_CTRL2_AF,
> +                                (unsigned int)~PCF2127_BIT_CTRL2_AF);

If you just want to clear the AF bit in CTRL2, just do:

ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
                                           PCF2127_BIT_CTRL2_AF, 0);

> +       if (ret) {
> +               dev_err(dev, "%s: failed to clear alarm interrupt flag (%d)",
> +                       __func__, 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] = (alrm->time.tm_wday & 0x07);
> +
> +       dev_dbg(dev, "%s: alarm set for: %d:%d:%d, mday=%d, wday=%d\n",
> +               __func__, alrm->time.tm_hour, alrm->time.tm_min,
> +               alrm->time.tm_sec, alrm->time.tm_mday, alrm->time.tm_wday);
> +
> +       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);

Replace 5 with sizeof(buf).

/Bruno

> +       if (ret) {
> +               dev_err(dev, "%s: failed to write alarm registers (%d)",
> +                       __func__, ret);
> +               return ret;
> +       }
> +
> +       pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled);
> +
> +       return 0;
> +}
> +
>  #ifdef CONFIG_RTC_INTF_DEV
>  static int pcf2127_rtc_ioctl(struct device *dev,
>                                 unsigned int cmd, unsigned long arg)
> @@ -211,9 +320,12 @@ static int pcf2127_rtc_ioctl(struct device *dev,
>  #endif
>
>  static const struct rtc_class_ops pcf2127_rtc_ops = {
> -       .ioctl          = pcf2127_rtc_ioctl,
> -       .read_time      = pcf2127_rtc_read_time,
> -       .set_time       = pcf2127_rtc_set_time,
> +       .ioctl            = pcf2127_rtc_ioctl,
> +       .read_time        = pcf2127_rtc_read_time,
> +       .set_time         = pcf2127_rtc_set_time,
> +       .read_alarm       = pcf2127_rtc_read_alarm,
> +       .set_alarm        = pcf2127_rtc_set_alarm,
> +       .alarm_irq_enable = pcf2127_rtc_alarm_irq_enable,
>  };
>
>  static int pcf2127_nvmem_read(void *priv, unsigned int offset,
> @@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>
>         pcf2127->rtc->ops = &pcf2127_rtc_ops;
>
> +       device_init_wakeup(dev, true);
> +
>         pcf2127->wdd.parent = dev;
>         pcf2127->wdd.info = &pcf2127_wdt_info;
>         pcf2127->wdd.ops = &pcf2127_watchdog_ops;
> --
> 2.27.0
>

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

* Re: [PATCH 1/3] rtc: pcf2127: add pca2129 device id
  2020-06-07 17:06 ` [PATCH 1/3] rtc: pcf2127: add pca2129 device id liambeguin
@ 2020-06-09 20:48   ` Bruno Thomsen
  0 siblings, 0 replies; 11+ messages in thread
From: Bruno Thomsen @ 2020-06-09 20:48 UTC (permalink / raw)
  To: liambeguin; +Cc: Alessandro Zummo, Alexandre Belloni, linux-rtc

Den søn. 7. jun. 2020 kl. 19.06 skrev <liambeguin@gmail.com>:
>
> From: Liam Beguin <lvb@xiphos.com>
>
> From: Liam Beguin <lvb@xiphos.com>
>
> The PCA2129 is the automotive grade version of the PCF2129.
> add it to the list of compatibles.
>
> Signed-off-by: Liam Beguin <lvb@xiphos.com>
> ---
>  drivers/rtc/rtc-pcf2127.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
> index 4e50d6768f13..396a1144a213 100644
> --- a/drivers/rtc/rtc-pcf2127.c
> +++ b/drivers/rtc/rtc-pcf2127.c
> @@ -546,6 +546,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  static const struct of_device_id pcf2127_of_match[] = {
>         { .compatible = "nxp,pcf2127" },
>         { .compatible = "nxp,pcf2129" },
> +       { .compatible = "nxp,pca2129" },

Remember to document new compatible string here:
Documentation/devicetree/bindings/rtc/trivial-rtc.yaml

/Bruno

>         {}
>  };
>  MODULE_DEVICE_TABLE(of, pcf2127_of_match);
> @@ -656,6 +657,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
>  static const struct i2c_device_id pcf2127_i2c_id[] = {
>         { "pcf2127", 1 },
>         { "pcf2129", 0 },
> +       { "pca2129", 0 },
>         { }
>  };
>  MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
> @@ -720,6 +722,7 @@ static int pcf2127_spi_probe(struct spi_device *spi)
>  static const struct spi_device_id pcf2127_spi_id[] = {
>         { "pcf2127", 1 },
>         { "pcf2129", 0 },
> +       { "pca2129", 0 },
>         { }
>  };
>  MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
> --
> 2.27.0
>

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

* Re: [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-07 17:06 ` [PATCH 2/3] rtc: pcf2127: add alarm support liambeguin
  2020-06-09 20:42   ` Bruno Thomsen
@ 2020-06-09 21:05   ` Alexandre Belloni
  2020-06-10 15:49     ` Liam Beguin
  1 sibling, 1 reply; 11+ messages in thread
From: Alexandre Belloni @ 2020-06-09 21:05 UTC (permalink / raw)
  To: liambeguin; +Cc: a.zummo, linux-rtc

On 07/06/2020 13:06:09-0400, liambeguin@gmail.com wrote:
>  static int pcf2127_nvmem_read(void *priv, unsigned int offset,
> @@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  
>  	pcf2127->rtc->ops = &pcf2127_rtc_ops;
>  
> +	device_init_wakeup(dev, true);
> +

This can't be done unconditionally, You need to have been able to
request an interrupt or the wakeup-source property needs to be present.

The interrupt handler is also missing from the patch.


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

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

* Re: [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on
  2020-06-07 17:06 ` [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on liambeguin
@ 2020-06-09 21:07   ` Alexandre Belloni
  0 siblings, 0 replies; 11+ messages in thread
From: Alexandre Belloni @ 2020-06-09 21:07 UTC (permalink / raw)
  To: liambeguin; +Cc: a.zummo, linux-rtc

On 07/06/2020 13:06:10-0400, liambeguin@gmail.com wrote:
> From: Liam Beguin <lvb@xiphos.com>
> 
> From: Liam Beguin <lvb@xiphos.com>

Always include a commit message.

> 
> Signed-off-by: Liam Beguin <lvb@xiphos.com>
> ---
>  drivers/rtc/rtc-pcf2127.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
> index 3eeb085a7c72..f004a4030970 100644
> --- a/drivers/rtc/rtc-pcf2127.c
> +++ b/drivers/rtc/rtc-pcf2127.c
> @@ -546,6 +546,14 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  
>  	pcf2127->rtc->ops = &pcf2127_rtc_ops;
>  
> +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
> +				 PCF2127_BIT_CTRL2_AIE, 0);
> +	if (ret) {
> +		dev_err(dev, "%s: failed to clear interrupt enable bit (%d)",
> +			__func__, ret);
> +		return ret;
> +	}
> +

The driver simply must not do that or alarms will be missed.

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

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

* Re: [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-09 20:42   ` Bruno Thomsen
@ 2020-06-10 15:38     ` Liam Beguin
  0 siblings, 0 replies; 11+ messages in thread
From: Liam Beguin @ 2020-06-10 15:38 UTC (permalink / raw)
  To: Bruno Thomsen; +Cc: Alessandro Zummo, Alexandre Belloni, linux-rtc

Hi Bruno,

Thanks for your comments, I've updated the patch and will send a v2
soon.

On Tue Jun 9, 2020 at 10:42 PM Bruno Thomsen wrote:
> Hi Liam,
> 
> See comments below.
> 
> Den søn. 7. jun. 2020 kl. 19.06 skrev <liambeguin@gmail.com>:
> >
> > From: Liam Beguin <lvb@xiphos.com>
> >
> > From: Liam Beguin <lvb@xiphos.com>
> >
> > Add alarm support for the pcf2127 RTC chip family.
> > Tested on pca2129.
> >
> > Signed-off-by: Liam Beguin <lvb@xiphos.com>
> > ---
> >  drivers/rtc/rtc-pcf2127.c | 120 +++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 117 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
> > index 396a1144a213..3eeb085a7c72 100644
> > --- a/drivers/rtc/rtc-pcf2127.c
> > +++ b/drivers/rtc/rtc-pcf2127.c
> > @@ -28,7 +28,9 @@
> >  #define PCF2127_BIT_CTRL1_TSF1                 BIT(4)
> >  /* Control register 2 */
> >  #define PCF2127_REG_CTRL2              0x01
> > +#define PCF2127_BIT_CTRL2_AIE                  BIT(1)
> >  #define PCF2127_BIT_CTRL2_TSIE                 BIT(2)
> > +#define PCF2127_BIT_CTRL2_AF                   BIT(4)
> >  #define PCF2127_BIT_CTRL2_TSF2                 BIT(5)
> >  /* Control register 3 */
> >  #define PCF2127_REG_CTRL3              0x02
> > @@ -46,6 +48,12 @@
> >  #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
> > +#define PCF2127_REG_ALARM_HR           0x0C
> > +#define PCF2127_REG_ALARM_DM           0x0D
> > +#define PCF2127_REG_ALARM_DW           0x0E
> >  /* Watchdog registers */
> >  #define PCF2127_REG_WD_CTL             0x10
> >  #define PCF2127_BIT_WD_CTL_TF0                 BIT(0)
> > @@ -185,6 +193,107 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
> >         return 0;
> >  }
> >
> > +static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > +{
> > +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> > +       unsigned int buf[5], ctrl2;
> > +       int ret;
> > +
> > +       ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
> > +       if (ret) {
> > +               dev_err(dev, "%s: ctrl2 read error\n", __func__);
> > +               return ret;
> > +       }
> 
> Reading CTRL2 register causes watchdog to stop.
> 
> Aways call pcf2127_wdt_active_ping() after CTRL2 access to ensure the watchdog
> is running if enabled.
> 
> > +       ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);
> 
> Replace 5 with sizeof(buf).
> 
> > +       if (ret) {
> > +               dev_err(dev, "%s: alarm read error\n", __func__);
> > +               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_wday = buf[4] & 0x07;
> > +
> > +       dev_dbg(dev, "%s: alarm is %d:%d:%d, mday=%d, wday=%d\n", __func__,
> > +               alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec,
> > +               alrm->time.tm_mday, alrm->time.tm_wday);
> > +
> > +       return 0;
> > +}
> > +
> > +static int pcf2127_rtc_alarm_irq_enable(struct device *dev, u32 enable)
> > +{
> > +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> > +       unsigned int ctrl2;
> > +       int ret;
> > +
> > +       dev_dbg(dev, "%s: %s\n", __func__, enable ? "enable" : "disable");
> 
> Delete debug trace.
> 
> > +
> > +       ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
> > +       if (ret) {
> > +               dev_err(dev, "%s: ctrl2 read error\n", __func__);
> > +               return ret;
> > +       }
> > +
> > +       if (enable)
> > +               ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
> > +                                  ctrl2 | PCF2127_BIT_CTRL2_AIE);
> > +       else
> > +               ret = regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
> > +                                  ctrl2 & ~PCF2127_BIT_CTRL2_AIE);
> > +
> > +       if (ret) {
> > +               dev_err(dev, "%s: failed to enable alarm (%d)\n", __func__,
> > +                       ret);
> > +               return ret;
> > +       }
> 
> Replace regmap_read() and regmap_write() with a regmap_update_bits().
> 
> So something like:
> 
> ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
>                                           enabled ? PCF2127_REG_CTRL2 : 0);
> 
> And remember to call pcf2127_wdt_active_ping().
> 
> > +
> > +       return 0;
> > +}
> > +
> > +static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > +{
> > +       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
> > +       unsigned int ctrl2;
> > +       uint8_t buf[5];
> > +       int ret;
> > +
> > +       ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
> > +                                PCF2127_BIT_CTRL2_AF,
> > +                                (unsigned int)~PCF2127_BIT_CTRL2_AF);
> 
> If you just want to clear the AF bit in CTRL2, just do:
> 
> ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
>                                            PCF2127_BIT_CTRL2_AF, 0);
> 
> > +       if (ret) {
> > +               dev_err(dev, "%s: failed to clear alarm interrupt flag (%d)",
> > +                       __func__, 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] = (alrm->time.tm_wday & 0x07);
> > +
> > +       dev_dbg(dev, "%s: alarm set for: %d:%d:%d, mday=%d, wday=%d\n",
> > +               __func__, alrm->time.tm_hour, alrm->time.tm_min,
> > +               alrm->time.tm_sec, alrm->time.tm_mday, alrm->time.tm_wday);
> > +
> > +       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_ALARM_SC, buf, 5);
> 
> Replace 5 with sizeof(buf).
> 
> /Bruno
> 

Thanks again for your time,
Liam

> > +       if (ret) {
> > +               dev_err(dev, "%s: failed to write alarm registers (%d)",
> > +                       __func__, ret);
> > +               return ret;
> > +       }
> > +
> > +       pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled);
> > +
> > +       return 0;
> > +}
> > +
> >  #ifdef CONFIG_RTC_INTF_DEV
> >  static int pcf2127_rtc_ioctl(struct device *dev,
> >                                 unsigned int cmd, unsigned long arg)
> > @@ -211,9 +320,12 @@ static int pcf2127_rtc_ioctl(struct device *dev,
> >  #endif
> >
> >  static const struct rtc_class_ops pcf2127_rtc_ops = {
> > -       .ioctl          = pcf2127_rtc_ioctl,
> > -       .read_time      = pcf2127_rtc_read_time,
> > -       .set_time       = pcf2127_rtc_set_time,
> > +       .ioctl            = pcf2127_rtc_ioctl,
> > +       .read_time        = pcf2127_rtc_read_time,
> > +       .set_time         = pcf2127_rtc_set_time,
> > +       .read_alarm       = pcf2127_rtc_read_alarm,
> > +       .set_alarm        = pcf2127_rtc_set_alarm,
> > +       .alarm_irq_enable = pcf2127_rtc_alarm_irq_enable,
> >  };
> >
> >  static int pcf2127_nvmem_read(void *priv, unsigned int offset,
> > @@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
> >
> >         pcf2127->rtc->ops = &pcf2127_rtc_ops;
> >
> > +       device_init_wakeup(dev, true);
> > +
> >         pcf2127->wdd.parent = dev;
> >         pcf2127->wdd.info = &pcf2127_wdt_info;
> >         pcf2127->wdd.ops = &pcf2127_watchdog_ops;
> > --
> > 2.27.0
> >

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

* Re: [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-09 21:05   ` Alexandre Belloni
@ 2020-06-10 15:49     ` Liam Beguin
  2020-06-10 16:32       ` Alexandre Belloni
  0 siblings, 1 reply; 11+ messages in thread
From: Liam Beguin @ 2020-06-10 15:49 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: a.zummo, linux-rtc

Hi Alexandre,

On Tue Jun 9, 2020 at 11:05 PM Alexandre Belloni wrote:
> On 07/06/2020 13:06:09-0400, liambeguin@gmail.com wrote:
> >  static int pcf2127_nvmem_read(void *priv, unsigned int offset,
> > @@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
> >  
> >  	pcf2127->rtc->ops = &pcf2127_rtc_ops;
> >  
> > +	device_init_wakeup(dev, true);
> > +
> 
> This can't be done unconditionally, You need to have been able to
> request an interrupt or the wakeup-source property needs to be present.
> 
> The interrupt handler is also missing from the patch.

Like I tried to explain in the cover letter, the interrupt line isn't
connected to the CPU on the board I'm using.
I'd be glad to add the interrupt handler to this patch. Is there a way I
can make it conditional?
Thanks,

Liam

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

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

* Re: [PATCH 2/3] rtc: pcf2127: add alarm support
  2020-06-10 15:49     ` Liam Beguin
@ 2020-06-10 16:32       ` Alexandre Belloni
  0 siblings, 0 replies; 11+ messages in thread
From: Alexandre Belloni @ 2020-06-10 16:32 UTC (permalink / raw)
  To: Liam Beguin; +Cc: a.zummo, linux-rtc

On 10/06/2020 11:49:06-0400, Liam Beguin wrote:
> Hi Alexandre,
> 
> On Tue Jun 9, 2020 at 11:05 PM Alexandre Belloni wrote:
> > On 07/06/2020 13:06:09-0400, liambeguin@gmail.com wrote:
> > >  static int pcf2127_nvmem_read(void *priv, unsigned int offset,
> > > @@ -434,6 +546,8 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
> > >  
> > >  	pcf2127->rtc->ops = &pcf2127_rtc_ops;
> > >  
> > > +	device_init_wakeup(dev, true);
> > > +
> > 
> > This can't be done unconditionally, You need to have been able to
> > request an interrupt or the wakeup-source property needs to be present.
> > 
> > The interrupt handler is also missing from the patch.
> 
> Like I tried to explain in the cover letter, the interrupt line isn't
> connected to the CPU on the board I'm using.
> I'd be glad to add the interrupt handler to this patch. Is there a way I
> can make it conditional?

It is necessarily conditional, as it won't be used if no interrupt is
provided.


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

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

end of thread, other threads:[~2020-06-10 16:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-07 17:06 [PATCH 0/3] rtc: pcf2127: add alarm support liambeguin
2020-06-07 17:06 ` [PATCH 1/3] rtc: pcf2127: add pca2129 device id liambeguin
2020-06-09 20:48   ` Bruno Thomsen
2020-06-07 17:06 ` [PATCH 2/3] rtc: pcf2127: add alarm support liambeguin
2020-06-09 20:42   ` Bruno Thomsen
2020-06-10 15:38     ` Liam Beguin
2020-06-09 21:05   ` Alexandre Belloni
2020-06-10 15:49     ` Liam Beguin
2020-06-10 16:32       ` Alexandre Belloni
2020-06-07 17:06 ` [PATCH 3/3] rtc: pcf2127: reset alarm interrupt at power on liambeguin
2020-06-09 21:07   ` 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).