linux-rtc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/12] rtc: pcf85063: switch to probe_new
@ 2019-04-01 16:08 Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

struct i2c_device_id argument of probe() is not used, so use probe_new()
instead.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index f6ce63c443a0..14a81fa916ca 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -207,8 +207,7 @@ static int pcf85063_load_capacitance(struct i2c_client *client)
 	return rc;
 }
 
-static int pcf85063_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
+static int pcf85063_probe(struct i2c_client *client)
 {
 	struct rtc_device *rtc;
 	int err;
@@ -236,12 +235,6 @@ static int pcf85063_probe(struct i2c_client *client,
 	return PTR_ERR_OR_ZERO(rtc);
 }
 
-static const struct i2c_device_id pcf85063_id[] = {
-	{ "pcf85063", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, pcf85063_id);
-
 #ifdef CONFIG_OF
 static const struct of_device_id pcf85063_of_match[] = {
 	{ .compatible = "nxp,pcf85063" },
@@ -255,8 +248,7 @@ static struct i2c_driver pcf85063_driver = {
 		.name	= "rtc-pcf85063",
 		.of_match_table = of_match_ptr(pcf85063_of_match),
 	},
-	.probe		= pcf85063_probe,
-	.id_table	= pcf85063_id,
+	.probe_new	= pcf85063_probe,
 };
 
 module_i2c_driver(pcf85063_driver);
-- 
2.20.1


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

* [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:16   ` Joe Perches
  2019-04-01 16:33   ` [PATCH v2 " Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 03/12] rtc: pcf85063: remove bogus i2c functionality check Alexandre Belloni
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Use SPDX-License-Identifier instead of a verbose license text.

The original text refers to version 2 so also update MODULE_LICENSE() to
"GPL v2" instead of "GPL".

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 14a81fa916ca..95aae84f7dc3 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * An I2C driver for the PCF85063 RTC
  * Copyright 2014 Rose Technology
  *
  * Author: Søren Andersen <san@rosetechnology.dk>
  * Maintainers: http://www.nslu2-linux.org/
- *
- * based on the other drivers in this same directory.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #include <linux/i2c.h>
 #include <linux/bcd.h>
@@ -255,4 +250,4 @@ module_i2c_driver(pcf85063_driver);
 
 MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>");
 MODULE_DESCRIPTION("PCF85063 RTC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
-- 
2.20.1


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

* [PATCH 03/12] rtc: pcf85063: remove bogus i2c functionality check
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 04/12] rtc: pcf85063: convert to devm_rtc_allocate_device Alexandre Belloni
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Only smbus reads and write are done in the driver, plain i2c functionality
is not required.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/rtc-pcf85063.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 95aae84f7dc3..c4cc0abe37cb 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -209,9 +209,6 @@ static int pcf85063_probe(struct i2c_client *client)
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-		return -ENODEV;
-
 	err = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
 	if (err < 0) {
 		dev_err(&client->dev, "RTC chip is not present\n");
-- 
2.20.1


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

* [PATCH 04/12] rtc: pcf85063: convert to devm_rtc_allocate_device
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 03/12] rtc: pcf85063: remove bogus i2c functionality check Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 05/12] rtc: pcf85063: set range Alexandre Belloni
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

This allows further improvement of the driver.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index c4cc0abe37cb..afd98e863482 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -28,8 +28,6 @@
 #define PCF85063_REG_SC			0x04 /* datetime */
 #define PCF85063_REG_SC_OS		0x80
 
-static struct i2c_driver pcf85063_driver;
-
 static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
 {
 	int rc;
@@ -220,11 +218,13 @@ static int pcf85063_probe(struct i2c_client *client)
 		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
 			 err);
 
-	rtc = devm_rtc_device_register(&client->dev,
-				       pcf85063_driver.driver.name,
-				       &pcf85063_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	rtc->ops = &pcf85063_rtc_ops;
 
-	return PTR_ERR_OR_ZERO(rtc);
+	return rtc_register_device(rtc);
 }
 
 #ifdef CONFIG_OF
-- 
2.20.1


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

* [PATCH 05/12] rtc: pcf85063: set range
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (2 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 04/12] rtc: pcf85063: convert to devm_rtc_allocate_device Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 06/12] rtc: pcf85063: switch to regmap Alexandre Belloni
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

This is a standard BCD RTC that will fail in 2100.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index afd98e863482..5e993162c5b2 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -113,9 +113,6 @@ static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	u8 regs[7];
 	u8 ctrl1;
 
-	if ((tm->tm_year < 100) || (tm->tm_year > 199))
-		return -EINVAL;
-
 	/*
 	 * to accurately set the time, reset the divider chain and keep it in
 	 * reset state until all time/date registers are written
@@ -223,6 +220,8 @@ static int pcf85063_probe(struct i2c_client *client)
 		return PTR_ERR(rtc);
 
 	rtc->ops = &pcf85063_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
 
 	return rtc_register_device(rtc);
 }
-- 
2.20.1


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

* [PATCH 06/12] rtc: pcf85063: switch to regmap
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (3 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 05/12] rtc: pcf85063: set range Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 07/12] rtc: pcf85063: differentiate pcf85063a and pcf85063tp Alexandre Belloni
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Switch to regmap to simplify register accesses and remove the need for
pcf85063_stop_clock/pcf85063_start_clock.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/Kconfig        |   1 +
 drivers/rtc/rtc-pcf85063.c | 154 +++++++++++++++----------------------
 2 files changed, 62 insertions(+), 93 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d00f1aefaaad..7b8e156dbf38 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -439,6 +439,7 @@ config RTC_DRV_PCF8523
 
 config RTC_DRV_PCF85063
 	tristate "NXP PCF85063"
+	select REGMAP_I2C
 	help
 	  If you say yes here you get support for the PCF85063 RTC chip
 
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 5e993162c5b2..632e1c8a3957 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -10,6 +10,8 @@
 #include <linux/bcd.h>
 #include <linux/rtc.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
 
 /*
  * Information for this driver was pulled from the following datasheets.
@@ -28,50 +30,14 @@
 #define PCF85063_REG_SC			0x04 /* datetime */
 #define PCF85063_REG_SC_OS		0x80
 
-static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
-{
-	int rc;
-	u8 reg;
-
-	rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
-	if (rc < 0) {
-		dev_err(&client->dev, "Failing to stop the clock\n");
-		return -EIO;
-	}
-
-	/* stop the clock */
-	reg = rc | PCF85063_REG_CTRL1_STOP;
-
-	rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
-	if (rc < 0) {
-		dev_err(&client->dev, "Failing to stop the clock\n");
-		return -EIO;
-	}
-
-	*ctrl1 = reg;
-
-	return 0;
-}
-
-static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
-{
-	int rc;
-
-	/* start the clock */
-	ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
-
-	rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
-	if (rc < 0) {
-		dev_err(&client->dev, "Failing to start the clock\n");
-		return -EIO;
-	}
-
-	return 0;
-}
+struct pcf85063 {
+	struct rtc_device	*rtc;
+	struct regmap		*regmap;
+};
 
 static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
 	int rc;
 	u8 regs[7];
 
@@ -81,16 +47,14 @@ static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	 * event, the access must be finished within one second. So, read all
 	 * time/date registers in one turn.
 	 */
-	rc = i2c_smbus_read_i2c_block_data(client, PCF85063_REG_SC,
-					   sizeof(regs), regs);
-	if (rc != sizeof(regs)) {
-		dev_err(&client->dev, "date/time register read error\n");
-		return -EIO;
-	}
+	rc = regmap_bulk_read(pcf85063->regmap, PCF85063_REG_SC, regs,
+			      sizeof(regs));
+	if (rc)
+		return rc;
 
 	/* if the clock has lost its power it makes no sense to use its time */
 	if (regs[0] & PCF85063_REG_SC_OS) {
-		dev_warn(&client->dev, "Power loss detected, invalid time\n");
+		dev_warn(&pcf85063->rtc->dev, "Power loss detected, invalid time\n");
 		return -EINVAL;
 	}
 
@@ -108,17 +72,18 @@ static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
 	int rc;
 	u8 regs[7];
-	u8 ctrl1;
 
 	/*
 	 * to accurately set the time, reset the divider chain and keep it in
 	 * reset state until all time/date registers are written
 	 */
-	rc = pcf85063_stop_clock(client, &ctrl1);
-	if (rc != 0)
+	rc = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
+				PCF85063_REG_CTRL1_STOP,
+				PCF85063_REG_CTRL1_STOP);
+	if (rc)
 		return rc;
 
 	/* hours, minutes and seconds */
@@ -140,23 +105,18 @@ static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	regs[6] = bin2bcd(tm->tm_year - 100);
 
 	/* write all registers at once */
-	rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
-					    sizeof(regs), regs);
-	if (rc < 0) {
-		dev_err(&client->dev, "date/time register write error\n");
+	rc = regmap_bulk_write(pcf85063->regmap, PCF85063_REG_SC,
+			       regs, sizeof(regs));
+	if (rc)
 		return rc;
-	}
 
 	/*
 	 * Write the control register as a separate action since the size of
 	 * the register space is different between the PCF85063TP and
 	 * PCF85063A devices.  The rollover point can not be used.
 	 */
-	rc = pcf85063_start_clock(client, ctrl1);
-	if (rc != 0)
-		return rc;
-
-	return 0;
+	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
+				  PCF85063_REG_CTRL1_STOP, 0);
 }
 
 static const struct rtc_class_ops pcf85063_rtc_ops = {
@@ -164,66 +124,74 @@ static const struct rtc_class_ops pcf85063_rtc_ops = {
 	.set_time	= pcf85063_rtc_set_time
 };
 
-static int pcf85063_load_capacitance(struct i2c_client *client)
+static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
+				     const struct device_node *np)
 {
-	u32 load;
-	int rc;
-	u8 reg;
-
-	rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
-	if (rc < 0)
-		return rc;
-
-	reg = rc;
-	load = 7000;
-	of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads",
-			     &load);
+	u32 load = 7000;
+	u8 reg = 0;
 
+	of_property_read_u32(np, "quartz-load-femtofarads", &load);
 	switch (load) {
 	default:
-		dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
+		dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
 			 load);
 		/* fall through */
 	case 7000:
-		reg &= ~PCF85063_REG_CTRL1_CAP_SEL;
 		break;
 	case 12500:
-		reg |= PCF85063_REG_CTRL1_CAP_SEL;
+		reg = PCF85063_REG_CTRL1_CAP_SEL;
 		break;
 	}
 
-	rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
-
-	return rc;
+	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
+				  PCF85063_REG_CTRL1_CAP_SEL, reg);
 }
 
+static const struct regmap_config regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0x11,
+};
+
 static int pcf85063_probe(struct i2c_client *client)
 {
-	struct rtc_device *rtc;
+	struct pcf85063 *pcf85063;
+	unsigned int tmp;
 	int err;
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
-	err = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
-	if (err < 0) {
+	pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
+				GFP_KERNEL);
+	if (!pcf85063)
+		return -ENOMEM;
+
+	pcf85063->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(pcf85063->regmap))
+		return PTR_ERR(pcf85063->regmap);
+
+	i2c_set_clientdata(client, pcf85063);
+
+	err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp);
+	if (err) {
 		dev_err(&client->dev, "RTC chip is not present\n");
 		return err;
 	}
 
-	err = pcf85063_load_capacitance(client);
+	pcf85063->rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(pcf85063->rtc))
+		return PTR_ERR(pcf85063->rtc);
+
+	err = pcf85063_load_capacitance(pcf85063, client->dev.of_node);
 	if (err < 0)
 		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
 			 err);
 
-	rtc = devm_rtc_allocate_device(&client->dev);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
-
-	rtc->ops = &pcf85063_rtc_ops;
-	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	rtc->range_max = RTC_TIMESTAMP_END_2099;
+	pcf85063->rtc->ops = &pcf85063_rtc_ops;
+	pcf85063->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	pcf85063->rtc->range_max = RTC_TIMESTAMP_END_2099;
 
-	return rtc_register_device(rtc);
+	return rtc_register_device(pcf85063->rtc);
 }
 
 #ifdef CONFIG_OF
-- 
2.20.1


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

* [PATCH 07/12] rtc: pcf85063: differentiate pcf85063a and pcf85063tp
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (4 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 06/12] rtc: pcf85063: switch to regmap Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 08/12] rtc: pcf85063: add alarm support Alexandre Belloni
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

As stated in a comment pcf85063a and pcf85063tp don't have the same number
of registers. Especially, pcf85063tp doesn't have alarm support.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 .../devicetree/bindings/rtc/nxp,pcf85063.txt  |  5 ++-
 drivers/rtc/rtc-pcf85063.c                    | 33 +++++++++++++++----
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
index d3e380ad712d..1e31afbfffe9 100644
--- a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
@@ -1,7 +1,10 @@
 * NXP PCF85063 Real Time Clock
 
 Required properties:
-- compatible: Should contain "nxp,pcf85063".
+- compatible: Should one of contain:
+	"nxp,pcf85063",
+	"nxp,pcf85063a",
+	"nxp,pcf85063tp"
 - reg: I2C address for chip.
 
 Optional property:
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 632e1c8a3957..7519da905128 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -30,6 +30,10 @@
 #define PCF85063_REG_SC			0x04 /* datetime */
 #define PCF85063_REG_SC_OS		0x80
 
+struct pcf85063_config {
+	struct regmap_config regmap;
+};
+
 struct pcf85063 {
 	struct rtc_device	*rtc;
 	struct regmap		*regmap;
@@ -147,10 +151,20 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
 				  PCF85063_REG_CTRL1_CAP_SEL, reg);
 }
 
-static const struct regmap_config regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = 0x11,
+static const struct pcf85063_config pcf85063a_config = {
+	.regmap = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0x11,
+	},
+};
+
+static const struct pcf85063_config pcf85063tp_config = {
+	.regmap = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0x0a,
+	},
 };
 
 static int pcf85063_probe(struct i2c_client *client)
@@ -158,6 +172,8 @@ static int pcf85063_probe(struct i2c_client *client)
 	struct pcf85063 *pcf85063;
 	unsigned int tmp;
 	int err;
+	const struct pcf85063_config *config = &pcf85063tp_config;
+	const void *data = of_device_get_match_data(&client->dev);
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
@@ -166,7 +182,10 @@ static int pcf85063_probe(struct i2c_client *client)
 	if (!pcf85063)
 		return -ENOMEM;
 
-	pcf85063->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (data)
+		config = data;
+
+	pcf85063->regmap = devm_regmap_init_i2c(client, &config->regmap);
 	if (IS_ERR(pcf85063->regmap))
 		return PTR_ERR(pcf85063->regmap);
 
@@ -196,7 +215,9 @@ static int pcf85063_probe(struct i2c_client *client)
 
 #ifdef CONFIG_OF
 static const struct of_device_id pcf85063_of_match[] = {
-	{ .compatible = "nxp,pcf85063" },
+	{ .compatible = "nxp,pcf85063", .data = &pcf85063tp_config },
+	{ .compatible = "nxp,pcf85063tp", .data = &pcf85063tp_config },
+	{ .compatible = "nxp,pcf85063a", .data = &pcf85063a_config },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf85063_of_match);
-- 
2.20.1


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

* [PATCH 08/12] rtc: pcf85063: add alarm support
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (5 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 07/12] rtc: pcf85063: differentiate pcf85063a and pcf85063tp Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 09/12] rtc: pcf85063: Add Micro Crystal RV8263 support Alexandre Belloni
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Add support for the alarms. The match on the weekday is not used as it it
not necessarily properly set.

The tested RTC shows a behaviour where setting an alarm on the second right
after an alarm that fired is not working, probably because of the circuit
that ensures an alarm only fires once. This is why uie_unsupported is set.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 7519da905128..536db43c84ee 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -11,6 +11,7 @@
 #include <linux/rtc.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/regmap.h>
 
 /*
@@ -27,11 +28,19 @@
 #define PCF85063_REG_CTRL1_CAP_SEL	BIT(0)
 #define PCF85063_REG_CTRL1_STOP		BIT(5)
 
+#define PCF85063_REG_CTRL2		0x01
+#define PCF85063_CTRL2_AF		BIT(6)
+#define PCF85063_CTRL2_AIE		BIT(7)
+
 #define PCF85063_REG_SC			0x04 /* datetime */
 #define PCF85063_REG_SC_OS		0x80
 
+#define PCF85063_REG_ALM_S		0x0b
+#define PCF85063_AEN			BIT(7)
+
 struct pcf85063_config {
 	struct regmap_config regmap;
+	unsigned has_alarms:1;
 };
 
 struct pcf85063 {
@@ -123,11 +132,103 @@ static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
 				  PCF85063_REG_CTRL1_STOP, 0);
 }
 
+static int pcf85063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+	u8 buf[4];
+	unsigned int val;
+	int ret;
+
+	ret = regmap_bulk_read(pcf85063->regmap, PCF85063_REG_ALM_S,
+			       buf, sizeof(buf));
+	if (ret)
+		return ret;
+
+	alrm->time.tm_sec = bcd2bin(buf[0]);
+	alrm->time.tm_min = bcd2bin(buf[1]);
+	alrm->time.tm_hour = bcd2bin(buf[2]);
+	alrm->time.tm_mday = bcd2bin(buf[3]);
+
+	ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val);
+	if (ret)
+		return ret;
+
+	alrm->enabled =  !!(val & PCF85063_CTRL2_AIE);
+
+	return 0;
+}
+
+static int pcf85063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+	u8 buf[5];
+	int 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] = PCF85063_AEN; /* Do not match on week day */
+
+	ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
+				 PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, 0);
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_write(pcf85063->regmap, PCF85063_REG_ALM_S,
+				buf, sizeof(buf));
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
+				  PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF,
+				  alrm->enabled ? PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF : PCF85063_CTRL2_AF);
+}
+
+static int pcf85063_rtc_alarm_irq_enable(struct device *dev,
+					 unsigned int enabled)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+
+	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
+				  PCF85063_CTRL2_AIE,
+				  enabled ? PCF85063_CTRL2_AIE : 0);
+}
+
+static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id)
+{
+	struct pcf85063 *pcf85063 = dev_id;
+	unsigned int val;
+	int err;
+
+	err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val);
+	if (err)
+		return IRQ_NONE;
+
+	if (val & PCF85063_CTRL2_AF) {
+		rtc_update_irq(pcf85063->rtc, 1, RTC_IRQF | RTC_AF);
+		regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
+				   PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF,
+				   0);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
 static const struct rtc_class_ops pcf85063_rtc_ops = {
 	.read_time	= pcf85063_rtc_read_time,
 	.set_time	= pcf85063_rtc_set_time
 };
 
+static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
+	.read_time	= pcf85063_rtc_read_time,
+	.set_time	= pcf85063_rtc_set_time,
+	.read_alarm	= pcf85063_rtc_read_alarm,
+	.set_alarm	= pcf85063_rtc_set_alarm,
+	.alarm_irq_enable = pcf85063_rtc_alarm_irq_enable,
+};
+
 static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
 				     const struct device_node *np)
 {
@@ -157,6 +258,7 @@ static const struct pcf85063_config pcf85063a_config = {
 		.val_bits = 8,
 		.max_register = 0x11,
 	},
+	.has_alarms = 1,
 };
 
 static const struct pcf85063_config pcf85063tp_config = {
@@ -209,6 +311,25 @@ static int pcf85063_probe(struct i2c_client *client)
 	pcf85063->rtc->ops = &pcf85063_rtc_ops;
 	pcf85063->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 	pcf85063->rtc->range_max = RTC_TIMESTAMP_END_2099;
+	pcf85063->rtc->uie_unsupported = 1;
+
+	if (config->has_alarms && client->irq > 0) {
+		err = devm_request_threaded_irq(&client->dev, client->irq,
+						NULL, pcf85063_rtc_handle_irq,
+						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+						"pcf85063", pcf85063);
+		if (err) {
+			dev_warn(&pcf85063->rtc->dev,
+				 "unable to request IRQ, alarms disabled\n");
+		} else {
+			pcf85063->rtc->ops = &pcf85063_rtc_ops_alarm;
+			device_init_wakeup(&client->dev, true);
+			err = dev_pm_set_wake_irq(&client->dev, client->irq);
+			if (err)
+				dev_err(&pcf85063->rtc->dev,
+					"failed to enable irq wake\n");
+		}
+	}
 
 	return rtc_register_device(pcf85063->rtc);
 }
-- 
2.20.1


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

* [PATCH 09/12] rtc: pcf85063: Add Micro Crystal RV8263 support
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (6 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 08/12] rtc: pcf85063: add alarm support Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 10/12] rtc: pcf85063: add nvram support Alexandre Belloni
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

The Micro Crystal RV8263 has the same IC as the pcf85063 but has an on
board crystal. This means that the CAP_SEL bit has to be cleared so the
correct capacitance is selected for the crystal.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 .../devicetree/bindings/rtc/nxp,pcf85063.txt  |  3 +-
 drivers/rtc/rtc-pcf85063.c                    | 32 ++++++++++++++++---
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
index 1e31afbfffe9..627bb533eff7 100644
--- a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
@@ -4,7 +4,8 @@ Required properties:
 - compatible: Should one of contain:
 	"nxp,pcf85063",
 	"nxp,pcf85063a",
-	"nxp,pcf85063tp"
+	"nxp,pcf85063tp",
+	"microcrystal,rv8263"
 - reg: I2C address for chip.
 
 Optional property:
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 536db43c84ee..0ac763c10744 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -5,6 +5,9 @@
  *
  * Author: Søren Andersen <san@rosetechnology.dk>
  * Maintainers: http://www.nslu2-linux.org/
+ *
+ * Copyright (C) 2019 Micro Crystal AG
+ * Author: Alexandre Belloni <alexandre.belloni@bootlin.com>
  */
 #include <linux/i2c.h>
 #include <linux/bcd.h>
@@ -22,7 +25,10 @@
  *
  *  PCF85063A -- Rev. 6 — 18 November 2015
  *  PCF85063TP -- Rev. 4 — 6 May 2015
-*/
+ *
+ *  https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-8263-C7_App-Manual.pdf
+ *  RV8263 -- Rev. 1.0 — January 2019
+ */
 
 #define PCF85063_REG_CTRL1		0x00 /* status */
 #define PCF85063_REG_CTRL1_CAP_SEL	BIT(0)
@@ -41,6 +47,7 @@
 struct pcf85063_config {
 	struct regmap_config regmap;
 	unsigned has_alarms:1;
+	unsigned force_cap_7000:1;
 };
 
 struct pcf85063 {
@@ -230,12 +237,17 @@ static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
 };
 
 static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
-				     const struct device_node *np)
+				     const struct device_node *np,
+				     unsigned int force_cap)
 {
 	u32 load = 7000;
 	u8 reg = 0;
 
-	of_property_read_u32(np, "quartz-load-femtofarads", &load);
+	if (force_cap)
+		load = force_cap;
+	else
+		of_property_read_u32(np, "quartz-load-femtofarads", &load);
+
 	switch (load) {
 	default:
 		dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
@@ -269,6 +281,16 @@ static const struct pcf85063_config pcf85063tp_config = {
 	},
 };
 
+static const struct pcf85063_config rv8263_config = {
+	.regmap = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0x11,
+	},
+	.has_alarms = 1,
+	.force_cap_7000 = 1,
+};
+
 static int pcf85063_probe(struct i2c_client *client)
 {
 	struct pcf85063 *pcf85063;
@@ -303,7 +325,8 @@ static int pcf85063_probe(struct i2c_client *client)
 	if (IS_ERR(pcf85063->rtc))
 		return PTR_ERR(pcf85063->rtc);
 
-	err = pcf85063_load_capacitance(pcf85063, client->dev.of_node);
+	err = pcf85063_load_capacitance(pcf85063, client->dev.of_node,
+					config->force_cap_7000 ? 7000 : 0);
 	if (err < 0)
 		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
 			 err);
@@ -339,6 +362,7 @@ static const struct of_device_id pcf85063_of_match[] = {
 	{ .compatible = "nxp,pcf85063", .data = &pcf85063tp_config },
 	{ .compatible = "nxp,pcf85063tp", .data = &pcf85063tp_config },
 	{ .compatible = "nxp,pcf85063a", .data = &pcf85063a_config },
+	{ .compatible = "microcrystal,rv8263", .data = &rv8263_config },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf85063_of_match);
-- 
2.20.1


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

* [PATCH 10/12] rtc: pcf85063: add nvram support
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (7 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 09/12] rtc: pcf85063: Add Micro Crystal RV8263 support Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 11/12] rtc: pcf85063: add offset correction support Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 12/12] rtc: pcf85063: add RTC_VL_READ/RTC_VL_CLR support Alexandre Belloni
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

The pcf85063 has one byte of nvram.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 0ac763c10744..04aaa83a5431 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -38,6 +38,8 @@
 #define PCF85063_CTRL2_AF		BIT(6)
 #define PCF85063_CTRL2_AIE		BIT(7)
 
+#define PCF85063_REG_RAM		0x03
+
 #define PCF85063_REG_SC			0x04 /* datetime */
 #define PCF85063_REG_SC_OS		0x80
 
@@ -236,6 +238,18 @@ static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
 	.alarm_irq_enable = pcf85063_rtc_alarm_irq_enable,
 };
 
+static int pcf85063_nvmem_read(void *priv, unsigned int offset,
+			       void *val, size_t bytes)
+{
+	return regmap_read(priv, PCF85063_REG_RAM, val);
+}
+
+static int pcf85063_nvmem_write(void *priv, unsigned int offset,
+				void *val, size_t bytes)
+{
+	return regmap_write(priv, PCF85063_REG_RAM, *(u8 *)val);
+}
+
 static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
 				     const struct device_node *np,
 				     unsigned int force_cap)
@@ -298,6 +312,13 @@ static int pcf85063_probe(struct i2c_client *client)
 	int err;
 	const struct pcf85063_config *config = &pcf85063tp_config;
 	const void *data = of_device_get_match_data(&client->dev);
+	struct nvmem_config nvmem_cfg = {
+		.name = "pcf85063_nvram",
+		.reg_read = pcf85063_nvmem_read,
+		.reg_write = pcf85063_nvmem_write,
+		.type = NVMEM_TYPE_BATTERY_BACKED,
+		.size = 1,
+	};
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
@@ -354,6 +375,9 @@ static int pcf85063_probe(struct i2c_client *client)
 		}
 	}
 
+	nvmem_cfg.priv = pcf85063->regmap;
+	rtc_nvmem_register(pcf85063->rtc, &nvmem_cfg);
+
 	return rtc_register_device(pcf85063->rtc);
 }
 
-- 
2.20.1


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

* [PATCH 11/12] rtc: pcf85063: add offset correction support
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (8 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 10/12] rtc: pcf85063: add nvram support Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  2019-04-01 16:08 ` [PATCH 12/12] rtc: pcf85063: add RTC_VL_READ/RTC_VL_CLR support Alexandre Belloni
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

The PCF850363 has an offset correction with two modes:

With mode 0, the correction is triggered once every two hours and then
correction pulses are applied once per minute until the programmed
correction values have been implemented. This gives a step of 4.34 ppm.

With mode 1, the correction is triggered once every four minutes and then
correction pulses are applied once per second up to a maximum of 60 pulses.
When correction values greater than 60 pulses are used, additional
correction pulses are made in the 59 th second. This gives a step of 4.069
ppm.

Use the correction closest to the requested value.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 04aaa83a5431..1bce53f8a7da 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -38,6 +38,12 @@
 #define PCF85063_CTRL2_AF		BIT(6)
 #define PCF85063_CTRL2_AIE		BIT(7)
 
+#define PCF85063_REG_OFFSET		0x02
+#define PCF85063_OFFSET_SIGN_BIT	6	/* 2's complement sign bit */
+#define PCF85063_OFFSET_MODE		BIT(7)
+#define PCF85063_OFFSET_STEP0		4340
+#define PCF85063_OFFSET_STEP1		4069
+
 #define PCF85063_REG_RAM		0x03
 
 #define PCF85063_REG_SC			0x04 /* datetime */
@@ -225,14 +231,64 @@ static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
+static int pcf85063_read_offset(struct device *dev, long *offset)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+	long val;
+	u32 reg;
+	int ret;
+
+	ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &reg);
+	if (ret < 0)
+		return ret;
+
+	val = sign_extend32(reg & ~PCF85063_OFFSET_MODE,
+			    PCF85063_OFFSET_SIGN_BIT);
+
+	if (reg & PCF85063_OFFSET_MODE)
+		*offset = val * PCF85063_OFFSET_STEP1;
+	else
+		*offset = val * PCF85063_OFFSET_STEP0;
+
+	return 0;
+}
+
+static int pcf85063_set_offset(struct device *dev, long offset)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+	s8 mode0, mode1, reg;
+	unsigned int error0, error1;
+
+	if (offset > PCF85063_OFFSET_STEP0 * 63)
+		return -ERANGE;
+	if (offset < PCF85063_OFFSET_STEP0 * -64)
+		return -ERANGE;
+
+	mode0 = DIV_ROUND_CLOSEST(offset, PCF85063_OFFSET_STEP0);
+	mode1 = DIV_ROUND_CLOSEST(offset, PCF85063_OFFSET_STEP1);
+
+	error0 = abs(offset - (mode0 * PCF85063_OFFSET_STEP0));
+	error1 = abs(offset - (mode1 * PCF85063_OFFSET_STEP1));
+	if (mode1 > 63 || mode1 < -64 || error0 < error1)
+		reg = mode0 & ~PCF85063_OFFSET_MODE;
+	else
+		reg = mode1 | PCF85063_OFFSET_MODE;
+
+	return regmap_write(pcf85063->regmap, PCF85063_REG_OFFSET, reg);
+}
+
 static const struct rtc_class_ops pcf85063_rtc_ops = {
 	.read_time	= pcf85063_rtc_read_time,
-	.set_time	= pcf85063_rtc_set_time
+	.set_time	= pcf85063_rtc_set_time,
+	.read_offset	= pcf85063_read_offset,
+	.set_offset	= pcf85063_set_offset,
 };
 
 static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
 	.read_time	= pcf85063_rtc_read_time,
 	.set_time	= pcf85063_rtc_set_time,
+	.read_offset	= pcf85063_read_offset,
+	.set_offset	= pcf85063_set_offset,
 	.read_alarm	= pcf85063_rtc_read_alarm,
 	.set_alarm	= pcf85063_rtc_set_alarm,
 	.alarm_irq_enable = pcf85063_rtc_alarm_irq_enable,
-- 
2.20.1


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

* [PATCH 12/12] rtc: pcf85063: add RTC_VL_READ/RTC_VL_CLR support
  2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
                   ` (9 preceding siblings ...)
  2019-04-01 16:08 ` [PATCH 11/12] rtc: pcf85063: add offset correction support Alexandre Belloni
@ 2019-04-01 16:08 ` Alexandre Belloni
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:08 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Allow reading the oscillator status bit. Also allow clearing it even if
that makes little sense and can't be done in a race free way.

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

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 1bce53f8a7da..e550db5c2bc2 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -277,11 +277,45 @@ static int pcf85063_set_offset(struct device *dev, long offset)
 	return regmap_write(pcf85063->regmap, PCF85063_REG_OFFSET, reg);
 }
 
+static int pcf85063_ioctl(struct device *dev, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
+	int status, ret = 0;
+
+	switch (cmd) {
+	case RTC_VL_READ:
+		ret = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &status);
+		if (ret < 0)
+			return ret;
+
+		if (status & PCF85063_REG_SC_OS)
+			dev_warn(&pcf85063->rtc->dev, "Voltage low, data loss detected.\n");
+
+		status &= PCF85063_REG_SC_OS;
+
+		if (copy_to_user((void __user *)arg, &status, sizeof(int)))
+			return -EFAULT;
+
+		return 0;
+
+	case RTC_VL_CLR:
+		ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_SC,
+					 PCF85063_REG_SC_OS, 0);
+
+		return ret;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
 static const struct rtc_class_ops pcf85063_rtc_ops = {
 	.read_time	= pcf85063_rtc_read_time,
 	.set_time	= pcf85063_rtc_set_time,
 	.read_offset	= pcf85063_read_offset,
 	.set_offset	= pcf85063_set_offset,
+	.ioctl		= pcf85063_ioctl,
 };
 
 static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
@@ -292,6 +326,7 @@ static const struct rtc_class_ops pcf85063_rtc_ops_alarm = {
 	.read_alarm	= pcf85063_rtc_read_alarm,
 	.set_alarm	= pcf85063_rtc_set_alarm,
 	.alarm_irq_enable = pcf85063_rtc_alarm_irq_enable,
+	.ioctl		= pcf85063_ioctl,
 };
 
 static int pcf85063_nvmem_read(void *priv, unsigned int offset,
-- 
2.20.1


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

* Re: [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier
  2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
@ 2019-04-01 16:16   ` Joe Perches
  2019-04-01 16:29     ` Alexandre Belloni
  2019-04-01 16:33   ` [PATCH v2 " Alexandre Belloni
  1 sibling, 1 reply; 15+ messages in thread
From: Joe Perches @ 2019-04-01 16:16 UTC (permalink / raw)
  To: Alexandre Belloni, linux-rtc; +Cc: linux-kernel

On Mon, 2019-04-01 at 18:08 +0200, Alexandre Belloni wrote:
> Use SPDX-License-Identifier instead of a verbose license text.
> 
> The original text refers to version 2 so also update MODULE_LICENSE() to
> "GPL v2" instead of "GPL".

This is not necessary as GPL is the same as GPL v2

commit bf7fbeeae6db644ef5995085de2bc5c6121f8c8d
Author: Thomas Gleixner <tglx@linutronix.de>
Date:   Fri Feb 8 17:02:56 2019 +0100

    module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity
    
and documentation/process/license-rules.rst:

   The valid license strings for MODULE_LICENSE() are:

    ============================= =============================================
    "GPL"			  Module is licensed under GPL version 2. This
				  does not express any distinction between
				  GPL-2.0-only or GPL-2.0-or-later. The exact
				  license information can only be determined
				  via the license information in the
				  corresponding source files.

    "GPL v2"			  Same as "GPL". It exists for historic
				  reasons.



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

* Re: [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier
  2019-04-01 16:16   ` Joe Perches
@ 2019-04-01 16:29     ` Alexandre Belloni
  0 siblings, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:29 UTC (permalink / raw)
  To: Joe Perches; +Cc: linux-rtc, linux-kernel

On 01/04/2019 09:16:58-0700, Joe Perches wrote:
> On Mon, 2019-04-01 at 18:08 +0200, Alexandre Belloni wrote:
> > Use SPDX-License-Identifier instead of a verbose license text.
> > 
> > The original text refers to version 2 so also update MODULE_LICENSE() to
> > "GPL v2" instead of "GPL".
> 
> This is not necessary as GPL is the same as GPL v2
> 

Ok, thanks for clearing that up.

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

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

* [PATCH v2 02/12] rtc: pcf85063: convert to SPDX identifier
  2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
  2019-04-01 16:16   ` Joe Perches
@ 2019-04-01 16:33   ` Alexandre Belloni
  1 sibling, 0 replies; 15+ messages in thread
From: Alexandre Belloni @ 2019-04-01 16:33 UTC (permalink / raw)
  To: linux-rtc; +Cc: linux-kernel, Alexandre Belloni

Use SPDX-License-Identifier instead of a verbose license text.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/rtc/rtc-pcf85063.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 14a81fa916ca..ba65aa4a3040 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * An I2C driver for the PCF85063 RTC
  * Copyright 2014 Rose Technology
  *
  * Author: Søren Andersen <san@rosetechnology.dk>
  * Maintainers: http://www.nslu2-linux.org/
- *
- * based on the other drivers in this same directory.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #include <linux/i2c.h>
 #include <linux/bcd.h>
-- 
2.20.1


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

end of thread, other threads:[~2019-04-01 16:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-04-01 16:08 [PATCH 01/12] rtc: pcf85063: switch to probe_new Alexandre Belloni
2019-04-01 16:08 ` [PATCH 02/12] rtc: pcf85063: convert to SPDX identifier Alexandre Belloni
2019-04-01 16:16   ` Joe Perches
2019-04-01 16:29     ` Alexandre Belloni
2019-04-01 16:33   ` [PATCH v2 " Alexandre Belloni
2019-04-01 16:08 ` [PATCH 03/12] rtc: pcf85063: remove bogus i2c functionality check Alexandre Belloni
2019-04-01 16:08 ` [PATCH 04/12] rtc: pcf85063: convert to devm_rtc_allocate_device Alexandre Belloni
2019-04-01 16:08 ` [PATCH 05/12] rtc: pcf85063: set range Alexandre Belloni
2019-04-01 16:08 ` [PATCH 06/12] rtc: pcf85063: switch to regmap Alexandre Belloni
2019-04-01 16:08 ` [PATCH 07/12] rtc: pcf85063: differentiate pcf85063a and pcf85063tp Alexandre Belloni
2019-04-01 16:08 ` [PATCH 08/12] rtc: pcf85063: add alarm support Alexandre Belloni
2019-04-01 16:08 ` [PATCH 09/12] rtc: pcf85063: Add Micro Crystal RV8263 support Alexandre Belloni
2019-04-01 16:08 ` [PATCH 10/12] rtc: pcf85063: add nvram support Alexandre Belloni
2019-04-01 16:08 ` [PATCH 11/12] rtc: pcf85063: add offset correction support Alexandre Belloni
2019-04-01 16:08 ` [PATCH 12/12] rtc: pcf85063: add RTC_VL_READ/RTC_VL_CLR support 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).