Linux-RTC Archive on lore.kernel.org
 help / Atom feed
* [PATCH 1/5] rtc: ds1307: Move register definitions to start of file
@ 2019-01-25 14:35 Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 2/5] rtc: ds1307: forward declare chips array instead of a bunch of functions Uwe Kleine-König
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2019-01-25 14:35 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Marek Vasut, kernel, linux-rtc

This allows to use the register offsets in all functions
which is needed in one of the next patches.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/rtc/rtc-ds1307.c | 52 ++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 74b31dce484f..f7a47ee5cdf6 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -114,6 +114,32 @@ enum ds_type {
 #	define RX8025_BIT_VDET		0x40
 #	define RX8025_BIT_XST		0x20
 
+#define RX8130_REG_ALARM_MIN		0x07
+#define RX8130_REG_ALARM_HOUR		0x08
+#define RX8130_REG_ALARM_WEEK_OR_DAY	0x09
+#define RX8130_REG_EXTENSION		0x0c
+#define RX8130_REG_EXTENSION_WADA	BIT(3)
+#define RX8130_REG_FLAG			0x0d
+#define RX8130_REG_FLAG_AF		BIT(3)
+#define RX8130_REG_CONTROL0		0x0e
+#define RX8130_REG_CONTROL0_AIE		BIT(3)
+
+#define MCP794XX_REG_CONTROL		0x07
+#	define MCP794XX_BIT_ALM0_EN	0x10
+#	define MCP794XX_BIT_ALM1_EN	0x20
+#define MCP794XX_REG_ALARM0_BASE	0x0a
+#define MCP794XX_REG_ALARM0_CTRL	0x0d
+#define MCP794XX_REG_ALARM1_BASE	0x11
+#define MCP794XX_REG_ALARM1_CTRL	0x14
+#	define MCP794XX_BIT_ALMX_IF	BIT(3)
+#	define MCP794XX_BIT_ALMX_C0	BIT(4)
+#	define MCP794XX_BIT_ALMX_C1	BIT(5)
+#	define MCP794XX_BIT_ALMX_C2	BIT(6)
+#	define MCP794XX_BIT_ALMX_POL	BIT(7)
+#	define MCP794XX_MSK_ALMX_MATCH	(MCP794XX_BIT_ALMX_C0 | \
+					 MCP794XX_BIT_ALMX_C1 | \
+					 MCP794XX_BIT_ALMX_C2)
+
 #define M41TXX_REG_CONTROL	0x07
 #	define M41TXX_BIT_OUT		BIT(7)
 #	define M41TXX_BIT_FT		BIT(6)
@@ -680,16 +706,6 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
  * Alarm support for rx8130 devices.
  */
 
-#define RX8130_REG_ALARM_MIN		0x07
-#define RX8130_REG_ALARM_HOUR		0x08
-#define RX8130_REG_ALARM_WEEK_OR_DAY	0x09
-#define RX8130_REG_EXTENSION		0x0c
-#define RX8130_REG_EXTENSION_WADA	BIT(3)
-#define RX8130_REG_FLAG			0x0d
-#define RX8130_REG_FLAG_AF		BIT(3)
-#define RX8130_REG_CONTROL0		0x0e
-#define RX8130_REG_CONTROL0_AIE		BIT(3)
-
 static irqreturn_t rx8130_irq(int irq, void *dev_id)
 {
 	struct ds1307           *ds1307 = dev_id;
@@ -839,22 +855,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
  * Alarm support for mcp794xx devices.
  */
 
-#define MCP794XX_REG_CONTROL		0x07
-#	define MCP794XX_BIT_ALM0_EN	0x10
-#	define MCP794XX_BIT_ALM1_EN	0x20
-#define MCP794XX_REG_ALARM0_BASE	0x0a
-#define MCP794XX_REG_ALARM0_CTRL	0x0d
-#define MCP794XX_REG_ALARM1_BASE	0x11
-#define MCP794XX_REG_ALARM1_CTRL	0x14
-#	define MCP794XX_BIT_ALMX_IF	BIT(3)
-#	define MCP794XX_BIT_ALMX_C0	BIT(4)
-#	define MCP794XX_BIT_ALMX_C1	BIT(5)
-#	define MCP794XX_BIT_ALMX_C2	BIT(6)
-#	define MCP794XX_BIT_ALMX_POL	BIT(7)
-#	define MCP794XX_MSK_ALMX_MATCH	(MCP794XX_BIT_ALMX_C0 | \
-					 MCP794XX_BIT_ALMX_C1 | \
-					 MCP794XX_BIT_ALMX_C2)
-
 static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
 {
 	struct ds1307           *ds1307 = dev_id;
-- 
2.20.1


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

* [PATCH 2/5] rtc: ds1307: forward declare chips array instead of a bunch of functions
  2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
@ 2019-01-25 14:35 ` Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 3/5] rtc: ds1307: correct register offset for rx8130 Uwe Kleine-König
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2019-01-25 14:35 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Marek Vasut, kernel, linux-rtc

There used to be 16 declarations for static functions. By just adding a
declaration for the chips array and reordering the functions the 16
function declarations can be dropped.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/rtc/rtc-ds1307.c | 992 +++++++++++++++++++--------------------
 1 file changed, 482 insertions(+), 510 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index f7a47ee5cdf6..a4883d59d88d 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -184,289 +184,7 @@ struct chip_desc {
 						    bool);
 };
 
-static int ds1307_get_time(struct device *dev, struct rtc_time *t);
-static int ds1307_set_time(struct device *dev, struct rtc_time *t);
-static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled);
-static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode);
-static irqreturn_t rx8130_irq(int irq, void *dev_id);
-static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled);
-static irqreturn_t mcp794xx_irq(int irq, void *dev_id);
-static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t);
-static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled);
-static int m41txx_rtc_read_offset(struct device *dev, long *offset);
-static int m41txx_rtc_set_offset(struct device *dev, long offset);
-
-static const struct rtc_class_ops rx8130_rtc_ops = {
-	.read_time      = ds1307_get_time,
-	.set_time       = ds1307_set_time,
-	.read_alarm     = rx8130_read_alarm,
-	.set_alarm      = rx8130_set_alarm,
-	.alarm_irq_enable = rx8130_alarm_irq_enable,
-};
-
-static const struct rtc_class_ops mcp794xx_rtc_ops = {
-	.read_time      = ds1307_get_time,
-	.set_time       = ds1307_set_time,
-	.read_alarm     = mcp794xx_read_alarm,
-	.set_alarm      = mcp794xx_set_alarm,
-	.alarm_irq_enable = mcp794xx_alarm_irq_enable,
-};
-
-static const struct rtc_class_ops m41txx_rtc_ops = {
-	.read_time      = ds1307_get_time,
-	.set_time       = ds1307_set_time,
-	.read_alarm	= ds1337_read_alarm,
-	.set_alarm	= ds1337_set_alarm,
-	.alarm_irq_enable = ds1307_alarm_irq_enable,
-	.read_offset	= m41txx_rtc_read_offset,
-	.set_offset	= m41txx_rtc_set_offset,
-};
-
-static const struct chip_desc chips[last_ds_type] = {
-	[ds_1307] = {
-		.nvram_offset	= 8,
-		.nvram_size	= 56,
-	},
-	[ds_1308] = {
-		.nvram_offset	= 8,
-		.nvram_size	= 56,
-	},
-	[ds_1337] = {
-		.alarm		= 1,
-		.century_reg	= DS1307_REG_MONTH,
-		.century_bit	= DS1337_BIT_CENTURY,
-	},
-	[ds_1338] = {
-		.nvram_offset	= 8,
-		.nvram_size	= 56,
-	},
-	[ds_1339] = {
-		.alarm		= 1,
-		.century_reg	= DS1307_REG_MONTH,
-		.century_bit	= DS1337_BIT_CENTURY,
-		.bbsqi_bit	= DS1339_BIT_BBSQI,
-		.trickle_charger_reg = 0x10,
-		.do_trickle_setup = &do_trickle_setup_ds1339,
-	},
-	[ds_1340] = {
-		.century_reg	= DS1307_REG_HOUR,
-		.century_enable_bit = DS1340_BIT_CENTURY_EN,
-		.century_bit	= DS1340_BIT_CENTURY,
-		.do_trickle_setup = &do_trickle_setup_ds1339,
-		.trickle_charger_reg = 0x08,
-	},
-	[ds_1341] = {
-		.century_reg	= DS1307_REG_MONTH,
-		.century_bit	= DS1337_BIT_CENTURY,
-	},
-	[ds_1388] = {
-		.offset		= 1,
-		.trickle_charger_reg = 0x0a,
-	},
-	[ds_3231] = {
-		.alarm		= 1,
-		.century_reg	= DS1307_REG_MONTH,
-		.century_bit	= DS1337_BIT_CENTURY,
-		.bbsqi_bit	= DS3231_BIT_BBSQW,
-	},
-	[rx_8130] = {
-		.alarm		= 1,
-		/* this is battery backed SRAM */
-		.nvram_offset	= 0x20,
-		.nvram_size	= 4,	/* 32bit (4 word x 8 bit) */
-		.offset		= 0x10,
-		.irq_handler = rx8130_irq,
-		.rtc_ops = &rx8130_rtc_ops,
-	},
-	[m41t0] = {
-		.rtc_ops	= &m41txx_rtc_ops,
-	},
-	[m41t00] = {
-		.rtc_ops	= &m41txx_rtc_ops,
-	},
-	[m41t11] = {
-		/* this is battery backed SRAM */
-		.nvram_offset	= 8,
-		.nvram_size	= 56,
-		.rtc_ops	= &m41txx_rtc_ops,
-	},
-	[mcp794xx] = {
-		.alarm		= 1,
-		/* this is battery backed SRAM */
-		.nvram_offset	= 0x20,
-		.nvram_size	= 0x40,
-		.irq_handler = mcp794xx_irq,
-		.rtc_ops = &mcp794xx_rtc_ops,
-	},
-};
-
-static const struct i2c_device_id ds1307_id[] = {
-	{ "ds1307", ds_1307 },
-	{ "ds1308", ds_1308 },
-	{ "ds1337", ds_1337 },
-	{ "ds1338", ds_1338 },
-	{ "ds1339", ds_1339 },
-	{ "ds1388", ds_1388 },
-	{ "ds1340", ds_1340 },
-	{ "ds1341", ds_1341 },
-	{ "ds3231", ds_3231 },
-	{ "m41t0", m41t0 },
-	{ "m41t00", m41t00 },
-	{ "m41t11", m41t11 },
-	{ "mcp7940x", mcp794xx },
-	{ "mcp7941x", mcp794xx },
-	{ "pt7c4338", ds_1307 },
-	{ "rx8025", rx_8025 },
-	{ "isl12057", ds_1337 },
-	{ "rx8130", rx_8130 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, ds1307_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id ds1307_of_match[] = {
-	{
-		.compatible = "dallas,ds1307",
-		.data = (void *)ds_1307
-	},
-	{
-		.compatible = "dallas,ds1308",
-		.data = (void *)ds_1308
-	},
-	{
-		.compatible = "dallas,ds1337",
-		.data = (void *)ds_1337
-	},
-	{
-		.compatible = "dallas,ds1338",
-		.data = (void *)ds_1338
-	},
-	{
-		.compatible = "dallas,ds1339",
-		.data = (void *)ds_1339
-	},
-	{
-		.compatible = "dallas,ds1388",
-		.data = (void *)ds_1388
-	},
-	{
-		.compatible = "dallas,ds1340",
-		.data = (void *)ds_1340
-	},
-	{
-		.compatible = "dallas,ds1341",
-		.data = (void *)ds_1341
-	},
-	{
-		.compatible = "maxim,ds3231",
-		.data = (void *)ds_3231
-	},
-	{
-		.compatible = "st,m41t0",
-		.data = (void *)m41t0
-	},
-	{
-		.compatible = "st,m41t00",
-		.data = (void *)m41t00
-	},
-	{
-		.compatible = "st,m41t11",
-		.data = (void *)m41t11
-	},
-	{
-		.compatible = "microchip,mcp7940x",
-		.data = (void *)mcp794xx
-	},
-	{
-		.compatible = "microchip,mcp7941x",
-		.data = (void *)mcp794xx
-	},
-	{
-		.compatible = "pericom,pt7c4338",
-		.data = (void *)ds_1307
-	},
-	{
-		.compatible = "epson,rx8025",
-		.data = (void *)rx_8025
-	},
-	{
-		.compatible = "isil,isl12057",
-		.data = (void *)ds_1337
-	},
-	{
-		.compatible = "epson,rx8130",
-		.data = (void *)rx_8130
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, ds1307_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id ds1307_acpi_ids[] = {
-	{ .id = "DS1307", .driver_data = ds_1307 },
-	{ .id = "DS1308", .driver_data = ds_1308 },
-	{ .id = "DS1337", .driver_data = ds_1337 },
-	{ .id = "DS1338", .driver_data = ds_1338 },
-	{ .id = "DS1339", .driver_data = ds_1339 },
-	{ .id = "DS1388", .driver_data = ds_1388 },
-	{ .id = "DS1340", .driver_data = ds_1340 },
-	{ .id = "DS1341", .driver_data = ds_1341 },
-	{ .id = "DS3231", .driver_data = ds_3231 },
-	{ .id = "M41T0", .driver_data = m41t0 },
-	{ .id = "M41T00", .driver_data = m41t00 },
-	{ .id = "M41T11", .driver_data = m41t11 },
-	{ .id = "MCP7940X", .driver_data = mcp794xx },
-	{ .id = "MCP7941X", .driver_data = mcp794xx },
-	{ .id = "PT7C4338", .driver_data = ds_1307 },
-	{ .id = "RX8025", .driver_data = rx_8025 },
-	{ .id = "ISL12057", .driver_data = ds_1337 },
-	{ .id = "RX8130", .driver_data = rx_8130 },
-	{ }
-};
-MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids);
-#endif
-
-/*
- * The ds1337 and ds1339 both have two alarms, but we only use the first
- * one (with a "seconds" field).  For ds1337 we expect nINTA is our alarm
- * signal; ds1339 chips have only one alarm signal.
- */
-static irqreturn_t ds1307_irq(int irq, void *dev_id)
-{
-	struct ds1307		*ds1307 = dev_id;
-	struct mutex		*lock = &ds1307->rtc->ops_lock;
-	int			stat, ret;
-
-	mutex_lock(lock);
-	ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat);
-	if (ret)
-		goto out;
-
-	if (stat & DS1337_BIT_A1I) {
-		stat &= ~DS1337_BIT_A1I;
-		regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat);
-
-		ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,
-					 DS1337_BIT_A1IE, 0);
-		if (ret)
-			goto out;
-
-		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
-	}
-
-out:
-	mutex_unlock(lock);
-
-	return IRQ_HANDLED;
-}
-
-/*----------------------------------------------------------------------*/
+static const struct chip_desc chips[last_ds_type];
 
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
@@ -692,19 +410,28 @@ static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
 				  enabled ? DS1337_BIT_A1IE : 0);
 }
 
-static const struct rtc_class_ops ds13xx_rtc_ops = {
-	.read_time	= ds1307_get_time,
-	.set_time	= ds1307_set_time,
-	.read_alarm	= ds1337_read_alarm,
-	.set_alarm	= ds1337_set_alarm,
-	.alarm_irq_enable = ds1307_alarm_irq_enable,
-};
-
-/*----------------------------------------------------------------------*/
+static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
+{
+	u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
+		DS1307_TRICKLE_CHARGER_NO_DIODE;
 
-/*
- * Alarm support for rx8130 devices.
- */
+	switch (ohms) {
+	case 250:
+		setup |= DS1307_TRICKLE_CHARGER_250_OHM;
+		break;
+	case 2000:
+		setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
+		break;
+	case 4000:
+		setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
+		break;
+	default:
+		dev_warn(ds1307->dev,
+			 "Unsupported ohm value %u in dt\n", ohms);
+		return 0;
+	}
+	return setup;
+}
 
 static irqreturn_t rx8130_irq(int irq, void *dev_id)
 {
@@ -829,58 +556,479 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 				 sizeof(ctl));
 }
 
-static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
+static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	int ret, reg;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, &reg);
+	if (ret < 0)
+		return ret;
+
+	if (enabled)
+		reg |= RX8130_REG_CONTROL0_AIE;
+	else
+		reg &= ~RX8130_REG_CONTROL0_AIE;
+
+	return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg);
+}
+
+static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
+{
+	struct ds1307           *ds1307 = dev_id;
+	struct mutex            *lock = &ds1307->rtc->ops_lock;
+	int reg, ret;
+
+	mutex_lock(lock);
+
+	/* Check and clear alarm 0 interrupt flag. */
+	ret = regmap_read(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, &reg);
+	if (ret)
+		goto out;
+	if (!(reg & MCP794XX_BIT_ALMX_IF))
+		goto out;
+	reg &= ~MCP794XX_BIT_ALMX_IF;
+	ret = regmap_write(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, reg);
+	if (ret)
+		goto out;
+
+	/* Disable alarm 0. */
+	ret = regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
+				 MCP794XX_BIT_ALM0_EN, 0);
+	if (ret)
+		goto out;
+
+	rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+
+out:
+	mutex_unlock(lock);
+
+	return IRQ_HANDLED;
+}
+
+static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	u8 regs[10];
+	int ret;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	/* Read control and alarm 0 registers. */
+	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
+			       sizeof(regs));
+	if (ret)
+		return ret;
+
+	t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN);
+
+	/* Report alarm 0 time assuming 24-hour and day-of-month modes. */
+	t->time.tm_sec = bcd2bin(regs[3] & 0x7f);
+	t->time.tm_min = bcd2bin(regs[4] & 0x7f);
+	t->time.tm_hour = bcd2bin(regs[5] & 0x3f);
+	t->time.tm_wday = bcd2bin(regs[6] & 0x7) - 1;
+	t->time.tm_mday = bcd2bin(regs[7] & 0x3f);
+	t->time.tm_mon = bcd2bin(regs[8] & 0x1f) - 1;
+	t->time.tm_year = -1;
+	t->time.tm_yday = -1;
+	t->time.tm_isdst = -1;
+
+	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
+		"enabled=%d polarity=%d irq=%d match=%lu\n", __func__,
+		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled,
+		!!(regs[6] & MCP794XX_BIT_ALMX_POL),
+		!!(regs[6] & MCP794XX_BIT_ALMX_IF),
+		(regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4);
+
+	return 0;
+}
+
+/*
+ * We may have a random RTC weekday, therefore calculate alarm weekday based
+ * on current weekday we read from the RTC timekeeping regs
+ */
+static int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm)
+{
+	struct rtc_time tm_now;
+	int days_now, days_alarm, ret;
+
+	ret = ds1307_get_time(dev, &tm_now);
+	if (ret)
+		return ret;
+
+	days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60);
+	days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60);
+
+	return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1;
+}
+
+static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned char regs[10];
+	int wday, ret;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	wday = mcp794xx_alm_weekday(dev, &t->time);
+	if (wday < 0)
+		return wday;
+
+	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
+		"enabled=%d pending=%d\n", __func__,
+		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
+		t->enabled, t->pending);
+
+	/* Read control and alarm 0 registers. */
+	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
+			       sizeof(regs));
+	if (ret)
+		return ret;
+
+	/* Set alarm 0, using 24-hour and day-of-month modes. */
+	regs[3] = bin2bcd(t->time.tm_sec);
+	regs[4] = bin2bcd(t->time.tm_min);
+	regs[5] = bin2bcd(t->time.tm_hour);
+	regs[6] = wday;
+	regs[7] = bin2bcd(t->time.tm_mday);
+	regs[8] = bin2bcd(t->time.tm_mon + 1);
+
+	/* Clear the alarm 0 interrupt flag. */
+	regs[6] &= ~MCP794XX_BIT_ALMX_IF;
+	/* Set alarm match: second, minute, hour, day, date, month. */
+	regs[6] |= MCP794XX_MSK_ALMX_MATCH;
+	/* Disable interrupt. We will not enable until completely programmed */
+	regs[0] &= ~MCP794XX_BIT_ALM0_EN;
+
+	ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
+				sizeof(regs));
+	if (ret)
+		return ret;
+
+	if (!t->enabled)
+		return 0;
+	regs[0] |= MCP794XX_BIT_ALM0_EN;
+	return regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs[0]);
+}
+
+static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-	int ret, reg;
 
 	if (!test_bit(HAS_ALARM, &ds1307->flags))
 		return -EINVAL;
 
-	ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, &reg);
-	if (ret < 0)
-		return ret;
+	return regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
+				  MCP794XX_BIT_ALM0_EN,
+				  enabled ? MCP794XX_BIT_ALM0_EN : 0);
+}
 
-	if (enabled)
-		reg |= RX8130_REG_CONTROL0_AIE;
+static int m41txx_rtc_read_offset(struct device *dev, long *offset)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned int ctrl_reg;
+	u8 val;
+
+	regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
+
+	val = ctrl_reg & M41TXX_M_CALIBRATION;
+
+	/* check if positive */
+	if (ctrl_reg & M41TXX_BIT_CALIB_SIGN)
+		*offset = (val * M41TXX_POS_OFFSET_STEP_PPB);
 	else
-		reg &= ~RX8130_REG_CONTROL0_AIE;
+		*offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB);
 
-	return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg);
+	return 0;
+}
+
+static int m41txx_rtc_set_offset(struct device *dev, long offset)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned int ctrl_reg;
+
+	if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET))
+		return -ERANGE;
+
+	if (offset >= 0) {
+		ctrl_reg = DIV_ROUND_CLOSEST(offset,
+					     M41TXX_POS_OFFSET_STEP_PPB);
+		ctrl_reg |= M41TXX_BIT_CALIB_SIGN;
+	} else {
+		ctrl_reg = DIV_ROUND_CLOSEST(abs(offset),
+					     M41TXX_NEG_OFFSET_STEP_PPB);
+	}
+
+	return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL,
+				  M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN,
+				  ctrl_reg);
 }
 
-/*----------------------------------------------------------------------*/
+static const struct rtc_class_ops rx8130_rtc_ops = {
+	.read_time      = ds1307_get_time,
+	.set_time       = ds1307_set_time,
+	.read_alarm     = rx8130_read_alarm,
+	.set_alarm      = rx8130_set_alarm,
+	.alarm_irq_enable = rx8130_alarm_irq_enable,
+};
+
+static const struct rtc_class_ops mcp794xx_rtc_ops = {
+	.read_time      = ds1307_get_time,
+	.set_time       = ds1307_set_time,
+	.read_alarm     = mcp794xx_read_alarm,
+	.set_alarm      = mcp794xx_set_alarm,
+	.alarm_irq_enable = mcp794xx_alarm_irq_enable,
+};
+
+static const struct rtc_class_ops m41txx_rtc_ops = {
+	.read_time      = ds1307_get_time,
+	.set_time       = ds1307_set_time,
+	.read_alarm	= ds1337_read_alarm,
+	.set_alarm	= ds1337_set_alarm,
+	.alarm_irq_enable = ds1307_alarm_irq_enable,
+	.read_offset	= m41txx_rtc_read_offset,
+	.set_offset	= m41txx_rtc_set_offset,
+};
+
+static const struct chip_desc chips[last_ds_type] = {
+	[ds_1307] = {
+		.nvram_offset	= 8,
+		.nvram_size	= 56,
+	},
+	[ds_1308] = {
+		.nvram_offset	= 8,
+		.nvram_size	= 56,
+	},
+	[ds_1337] = {
+		.alarm		= 1,
+		.century_reg	= DS1307_REG_MONTH,
+		.century_bit	= DS1337_BIT_CENTURY,
+	},
+	[ds_1338] = {
+		.nvram_offset	= 8,
+		.nvram_size	= 56,
+	},
+	[ds_1339] = {
+		.alarm		= 1,
+		.century_reg	= DS1307_REG_MONTH,
+		.century_bit	= DS1337_BIT_CENTURY,
+		.bbsqi_bit	= DS1339_BIT_BBSQI,
+		.trickle_charger_reg = 0x10,
+		.do_trickle_setup = &do_trickle_setup_ds1339,
+	},
+	[ds_1340] = {
+		.century_reg	= DS1307_REG_HOUR,
+		.century_enable_bit = DS1340_BIT_CENTURY_EN,
+		.century_bit	= DS1340_BIT_CENTURY,
+		.do_trickle_setup = &do_trickle_setup_ds1339,
+		.trickle_charger_reg = 0x08,
+	},
+	[ds_1341] = {
+		.century_reg	= DS1307_REG_MONTH,
+		.century_bit	= DS1337_BIT_CENTURY,
+	},
+	[ds_1388] = {
+		.offset		= 1,
+		.trickle_charger_reg = 0x0a,
+	},
+	[ds_3231] = {
+		.alarm		= 1,
+		.century_reg	= DS1307_REG_MONTH,
+		.century_bit	= DS1337_BIT_CENTURY,
+		.bbsqi_bit	= DS3231_BIT_BBSQW,
+	},
+	[rx_8130] = {
+		.alarm		= 1,
+		/* this is battery backed SRAM */
+		.nvram_offset	= 0x20,
+		.nvram_size	= 4,	/* 32bit (4 word x 8 bit) */
+		.offset		= 0x10,
+		.irq_handler = rx8130_irq,
+		.rtc_ops = &rx8130_rtc_ops,
+	},
+	[m41t0] = {
+		.rtc_ops	= &m41txx_rtc_ops,
+	},
+	[m41t00] = {
+		.rtc_ops	= &m41txx_rtc_ops,
+	},
+	[m41t11] = {
+		/* this is battery backed SRAM */
+		.nvram_offset	= 8,
+		.nvram_size	= 56,
+		.rtc_ops	= &m41txx_rtc_ops,
+	},
+	[mcp794xx] = {
+		.alarm		= 1,
+		/* this is battery backed SRAM */
+		.nvram_offset	= 0x20,
+		.nvram_size	= 0x40,
+		.irq_handler = mcp794xx_irq,
+		.rtc_ops = &mcp794xx_rtc_ops,
+	},
+};
+
+static const struct i2c_device_id ds1307_id[] = {
+	{ "ds1307", ds_1307 },
+	{ "ds1308", ds_1308 },
+	{ "ds1337", ds_1337 },
+	{ "ds1338", ds_1338 },
+	{ "ds1339", ds_1339 },
+	{ "ds1388", ds_1388 },
+	{ "ds1340", ds_1340 },
+	{ "ds1341", ds_1341 },
+	{ "ds3231", ds_3231 },
+	{ "m41t0", m41t0 },
+	{ "m41t00", m41t00 },
+	{ "m41t11", m41t11 },
+	{ "mcp7940x", mcp794xx },
+	{ "mcp7941x", mcp794xx },
+	{ "pt7c4338", ds_1307 },
+	{ "rx8025", rx_8025 },
+	{ "isl12057", ds_1337 },
+	{ "rx8130", rx_8130 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1307_of_match[] = {
+	{
+		.compatible = "dallas,ds1307",
+		.data = (void *)ds_1307
+	},
+	{
+		.compatible = "dallas,ds1308",
+		.data = (void *)ds_1308
+	},
+	{
+		.compatible = "dallas,ds1337",
+		.data = (void *)ds_1337
+	},
+	{
+		.compatible = "dallas,ds1338",
+		.data = (void *)ds_1338
+	},
+	{
+		.compatible = "dallas,ds1339",
+		.data = (void *)ds_1339
+	},
+	{
+		.compatible = "dallas,ds1388",
+		.data = (void *)ds_1388
+	},
+	{
+		.compatible = "dallas,ds1340",
+		.data = (void *)ds_1340
+	},
+	{
+		.compatible = "dallas,ds1341",
+		.data = (void *)ds_1341
+	},
+	{
+		.compatible = "maxim,ds3231",
+		.data = (void *)ds_3231
+	},
+	{
+		.compatible = "st,m41t0",
+		.data = (void *)m41t0
+	},
+	{
+		.compatible = "st,m41t00",
+		.data = (void *)m41t00
+	},
+	{
+		.compatible = "st,m41t11",
+		.data = (void *)m41t11
+	},
+	{
+		.compatible = "microchip,mcp7940x",
+		.data = (void *)mcp794xx
+	},
+	{
+		.compatible = "microchip,mcp7941x",
+		.data = (void *)mcp794xx
+	},
+	{
+		.compatible = "pericom,pt7c4338",
+		.data = (void *)ds_1307
+	},
+	{
+		.compatible = "epson,rx8025",
+		.data = (void *)rx_8025
+	},
+	{
+		.compatible = "isil,isl12057",
+		.data = (void *)ds_1337
+	},
+	{
+		.compatible = "epson,rx8130",
+		.data = (void *)rx_8130
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ds1307_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id ds1307_acpi_ids[] = {
+	{ .id = "DS1307", .driver_data = ds_1307 },
+	{ .id = "DS1308", .driver_data = ds_1308 },
+	{ .id = "DS1337", .driver_data = ds_1337 },
+	{ .id = "DS1338", .driver_data = ds_1338 },
+	{ .id = "DS1339", .driver_data = ds_1339 },
+	{ .id = "DS1388", .driver_data = ds_1388 },
+	{ .id = "DS1340", .driver_data = ds_1340 },
+	{ .id = "DS1341", .driver_data = ds_1341 },
+	{ .id = "DS3231", .driver_data = ds_3231 },
+	{ .id = "M41T0", .driver_data = m41t0 },
+	{ .id = "M41T00", .driver_data = m41t00 },
+	{ .id = "M41T11", .driver_data = m41t11 },
+	{ .id = "MCP7940X", .driver_data = mcp794xx },
+	{ .id = "MCP7941X", .driver_data = mcp794xx },
+	{ .id = "PT7C4338", .driver_data = ds_1307 },
+	{ .id = "RX8025", .driver_data = rx_8025 },
+	{ .id = "ISL12057", .driver_data = ds_1337 },
+	{ .id = "RX8130", .driver_data = rx_8130 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids);
+#endif
 
 /*
- * Alarm support for mcp794xx devices.
+ * The ds1337 and ds1339 both have two alarms, but we only use the first
+ * one (with a "seconds" field).  For ds1337 we expect nINTA is our alarm
+ * signal; ds1339 chips have only one alarm signal.
  */
-
-static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
+static irqreturn_t ds1307_irq(int irq, void *dev_id)
 {
-	struct ds1307           *ds1307 = dev_id;
-	struct mutex            *lock = &ds1307->rtc->ops_lock;
-	int reg, ret;
+	struct ds1307		*ds1307 = dev_id;
+	struct mutex		*lock = &ds1307->rtc->ops_lock;
+	int			stat, ret;
 
 	mutex_lock(lock);
-
-	/* Check and clear alarm 0 interrupt flag. */
-	ret = regmap_read(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, &reg);
-	if (ret)
-		goto out;
-	if (!(reg & MCP794XX_BIT_ALMX_IF))
-		goto out;
-	reg &= ~MCP794XX_BIT_ALMX_IF;
-	ret = regmap_write(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, reg);
+	ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat);
 	if (ret)
 		goto out;
 
-	/* Disable alarm 0. */
-	ret = regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
-				 MCP794XX_BIT_ALM0_EN, 0);
-	if (ret)
-		goto out;
+	if (stat & DS1337_BIT_A1I) {
+		stat &= ~DS1337_BIT_A1I;
+		regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat);
 
-	rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+		ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,
+					 DS1337_BIT_A1IE, 0);
+		if (ret)
+			goto out;
+
+		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+	}
 
 out:
 	mutex_unlock(lock);
@@ -888,167 +1036,15 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
-	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-	u8 regs[10];
-	int ret;
-
-	if (!test_bit(HAS_ALARM, &ds1307->flags))
-		return -EINVAL;
-
-	/* Read control and alarm 0 registers. */
-	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
-			       sizeof(regs));
-	if (ret)
-		return ret;
-
-	t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN);
-
-	/* Report alarm 0 time assuming 24-hour and day-of-month modes. */
-	t->time.tm_sec = bcd2bin(regs[3] & 0x7f);
-	t->time.tm_min = bcd2bin(regs[4] & 0x7f);
-	t->time.tm_hour = bcd2bin(regs[5] & 0x3f);
-	t->time.tm_wday = bcd2bin(regs[6] & 0x7) - 1;
-	t->time.tm_mday = bcd2bin(regs[7] & 0x3f);
-	t->time.tm_mon = bcd2bin(regs[8] & 0x1f) - 1;
-	t->time.tm_year = -1;
-	t->time.tm_yday = -1;
-	t->time.tm_isdst = -1;
-
-	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
-		"enabled=%d polarity=%d irq=%d match=%lu\n", __func__,
-		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
-		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled,
-		!!(regs[6] & MCP794XX_BIT_ALMX_POL),
-		!!(regs[6] & MCP794XX_BIT_ALMX_IF),
-		(regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4);
-
-	return 0;
-}
-
-/*
- * We may have a random RTC weekday, therefore calculate alarm weekday based
- * on current weekday we read from the RTC timekeeping regs
- */
-static int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm)
-{
-	struct rtc_time tm_now;
-	int days_now, days_alarm, ret;
-
-	ret = ds1307_get_time(dev, &tm_now);
-	if (ret)
-		return ret;
-
-	days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60);
-	days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60);
-
-	return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1;
-}
-
-static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
-	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-	unsigned char regs[10];
-	int wday, ret;
-
-	if (!test_bit(HAS_ALARM, &ds1307->flags))
-		return -EINVAL;
-
-	wday = mcp794xx_alm_weekday(dev, &t->time);
-	if (wday < 0)
-		return wday;
-
-	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
-		"enabled=%d pending=%d\n", __func__,
-		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
-		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
-		t->enabled, t->pending);
-
-	/* Read control and alarm 0 registers. */
-	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
-			       sizeof(regs));
-	if (ret)
-		return ret;
-
-	/* Set alarm 0, using 24-hour and day-of-month modes. */
-	regs[3] = bin2bcd(t->time.tm_sec);
-	regs[4] = bin2bcd(t->time.tm_min);
-	regs[5] = bin2bcd(t->time.tm_hour);
-	regs[6] = wday;
-	regs[7] = bin2bcd(t->time.tm_mday);
-	regs[8] = bin2bcd(t->time.tm_mon + 1);
-
-	/* Clear the alarm 0 interrupt flag. */
-	regs[6] &= ~MCP794XX_BIT_ALMX_IF;
-	/* Set alarm match: second, minute, hour, day, date, month. */
-	regs[6] |= MCP794XX_MSK_ALMX_MATCH;
-	/* Disable interrupt. We will not enable until completely programmed */
-	regs[0] &= ~MCP794XX_BIT_ALM0_EN;
-
-	ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
-				sizeof(regs));
-	if (ret)
-		return ret;
-
-	if (!t->enabled)
-		return 0;
-	regs[0] |= MCP794XX_BIT_ALM0_EN;
-	return regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs[0]);
-}
-
-static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-
-	if (!test_bit(HAS_ALARM, &ds1307->flags))
-		return -EINVAL;
-
-	return regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
-				  MCP794XX_BIT_ALM0_EN,
-				  enabled ? MCP794XX_BIT_ALM0_EN : 0);
-}
-
-static int m41txx_rtc_read_offset(struct device *dev, long *offset)
-{
-	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-	unsigned int ctrl_reg;
-	u8 val;
-
-	regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
-
-	val = ctrl_reg & M41TXX_M_CALIBRATION;
-
-	/* check if positive */
-	if (ctrl_reg & M41TXX_BIT_CALIB_SIGN)
-		*offset = (val * M41TXX_POS_OFFSET_STEP_PPB);
-	else
-		*offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB);
-
-	return 0;
-}
-
-static int m41txx_rtc_set_offset(struct device *dev, long offset)
-{
-	struct ds1307 *ds1307 = dev_get_drvdata(dev);
-	unsigned int ctrl_reg;
-
-	if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET))
-		return -ERANGE;
-
-	if (offset >= 0) {
-		ctrl_reg = DIV_ROUND_CLOSEST(offset,
-					     M41TXX_POS_OFFSET_STEP_PPB);
-		ctrl_reg |= M41TXX_BIT_CALIB_SIGN;
-	} else {
-		ctrl_reg = DIV_ROUND_CLOSEST(abs(offset),
-					     M41TXX_NEG_OFFSET_STEP_PPB);
-	}
+/*----------------------------------------------------------------------*/
 
-	return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL,
-				  M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN,
-				  ctrl_reg);
-}
+static const struct rtc_class_ops ds13xx_rtc_ops = {
+	.read_time	= ds1307_get_time,
+	.set_time	= ds1307_set_time,
+	.read_alarm	= ds1337_read_alarm,
+	.set_alarm	= ds1337_set_alarm,
+	.alarm_irq_enable = ds1307_alarm_irq_enable,
+};
 
 static ssize_t frequency_test_store(struct device *dev,
 				    struct device_attribute *attr,
@@ -1137,30 +1133,6 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
 
 /*----------------------------------------------------------------------*/
 
-static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307,
-				  u32 ohms, bool diode)
-{
-	u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
-		DS1307_TRICKLE_CHARGER_NO_DIODE;
-
-	switch (ohms) {
-	case 250:
-		setup |= DS1307_TRICKLE_CHARGER_250_OHM;
-		break;
-	case 2000:
-		setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
-		break;
-	case 4000:
-		setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
-		break;
-	default:
-		dev_warn(ds1307->dev,
-			 "Unsupported ohm value %u in dt\n", ohms);
-		return 0;
-	}
-	return setup;
-}
-
 static u8 ds1307_trickle_init(struct ds1307 *ds1307,
 			      const struct chip_desc *chip)
 {
-- 
2.20.1


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

* [PATCH 3/5] rtc: ds1307: correct register offset for rx8130
  2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 2/5] rtc: ds1307: forward declare chips array instead of a bunch of functions Uwe Kleine-König
@ 2019-01-25 14:35 ` Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 4/5] rtc: ds1307: rx8130: honor Voltage Loss Flag when reading the time Uwe Kleine-König
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2019-01-25 14:35 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Marek Vasut, kernel, linux-rtc

While rx8130 has a register offset of 0x10 in its chip_desc, this isn't
used when regmap accesses are done. So add 0x10 to access the right
locations.

Fixes: ee0981be7704 ("rtc: ds1307: Add support for Epson RX8130CE")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/rtc/rtc-ds1307.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index a4883d59d88d..81e20653700d 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -114,14 +114,15 @@ enum ds_type {
 #	define RX8025_BIT_VDET		0x40
 #	define RX8025_BIT_XST		0x20
 
-#define RX8130_REG_ALARM_MIN		0x07
-#define RX8130_REG_ALARM_HOUR		0x08
-#define RX8130_REG_ALARM_WEEK_OR_DAY	0x09
-#define RX8130_REG_EXTENSION		0x0c
+#define RX8130_REG_ALARM_MIN		0x17
+#define RX8130_REG_ALARM_HOUR		0x18
+#define RX8130_REG_ALARM_WEEK_OR_DAY	0x19
+#define RX8130_REG_EXTENSION		0x1c
 #define RX8130_REG_EXTENSION_WADA	BIT(3)
-#define RX8130_REG_FLAG			0x0d
+#define RX8130_REG_FLAG			0x1d
+#define RX8130_REG_FLAG_VLF		BIT(1)
 #define RX8130_REG_FLAG_AF		BIT(3)
-#define RX8130_REG_CONTROL0		0x0e
+#define RX8130_REG_CONTROL0		0x1e
 #define RX8130_REG_CONTROL0_AIE		BIT(3)
 
 #define MCP794XX_REG_CONTROL		0x07
-- 
2.20.1


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

* [PATCH 4/5] rtc: ds1307: rx8130: honor Voltage Loss Flag when reading the time
  2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 2/5] rtc: ds1307: forward declare chips array instead of a bunch of functions Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 3/5] rtc: ds1307: correct register offset for rx8130 Uwe Kleine-König
@ 2019-01-25 14:35 ` Uwe Kleine-König
  2019-01-25 14:35 ` [PATCH 5/5] rtc: ds1307: rx8130: Fix alarm handling Uwe Kleine-König
  2019-02-07 20:37 ` [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Alexandre Belloni
  4 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2019-01-25 14:35 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Marek Vasut, kernel, linux-rtc

When voltage dropped since the RTC was last set the reported time is not
reliable. In this case return an error indicator instead of a bogus
time.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/rtc/rtc-ds1307.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 81e20653700d..974eafda9de4 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -194,6 +194,20 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 	const struct chip_desc *chip = &chips[ds1307->type];
 	u8 regs[7];
 
+	if (ds1307->type == rx_8130) {
+		unsigned int regflag;
+		ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, &regflag);
+		if (ret) {
+			dev_err(dev, "%s error %d\n", "read", ret);
+			return ret;
+		}
+
+		if (regflag & RX8130_REG_FLAG_VLF) {
+			dev_warn_once(dev, "oscillator failed, set time!\n");
+			return -EINVAL;
+		}
+	}
+
 	/* read the RTC date and time registers all at once */
 	ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
 			       sizeof(regs));
@@ -293,6 +307,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
 		dev_err(dev, "%s error %d\n", "write", result);
 		return result;
 	}
+
+	if (ds1307->type == rx_8130) {
+		/* clear Voltage Loss Flag as data is available now */
+		result = regmap_write(ds1307->regmap, RX8130_REG_FLAG,
+				      ~(u8)RX8130_REG_FLAG_VLF);
+		if (result) {
+			dev_err(dev, "%s error %d\n", "write", result);
+			return result;
+		}
+	}
+
 	return 0;
 }
 
-- 
2.20.1


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

* [PATCH 5/5] rtc: ds1307: rx8130: Fix alarm handling
  2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
                   ` (2 preceding siblings ...)
  2019-01-25 14:35 ` [PATCH 4/5] rtc: ds1307: rx8130: honor Voltage Loss Flag when reading the time Uwe Kleine-König
@ 2019-01-25 14:35 ` Uwe Kleine-König
  2019-02-07 20:37 ` [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Alexandre Belloni
  4 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2019-01-25 14:35 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Marek Vasut, kernel, linux-rtc

When the EXTENSION.WADA bit is set, register 0x19 contains a bitmap of
week days, not a day of month. As Linux only handles a single alarm
without repetition using day of month is more flexible, so clear this
bit. (Otherwise a value depending on time.tm_wday would have to be
written to register 0x19.)

Also optimize setting the AIE bit to use a single register write instead
of a bulk write of three registers.

Fixes: ee0981be7704 ("rtc: ds1307: Add support for Epson RX8130CE")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/rtc/rtc-ds1307.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 974eafda9de4..07530fe1da2a 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -554,8 +554,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 	if (ret < 0)
 		return ret;
 
-	ctl[0] &= ~RX8130_REG_EXTENSION_WADA;
-	ctl[1] |= RX8130_REG_FLAG_AF;
+	ctl[0] &= RX8130_REG_EXTENSION_WADA;
+	ctl[1] &= ~RX8130_REG_FLAG_AF;
 	ctl[2] &= ~RX8130_REG_CONTROL0_AIE;
 
 	ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
@@ -578,8 +578,7 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 
 	ctl[2] |= RX8130_REG_CONTROL0_AIE;
 
-	return regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
-				 sizeof(ctl));
+	return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, ctl[2]);
 }
 
 static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
-- 
2.20.1


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

* Re: [PATCH 1/5] rtc: ds1307: Move register definitions to start of file
  2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
                   ` (3 preceding siblings ...)
  2019-01-25 14:35 ` [PATCH 5/5] rtc: ds1307: rx8130: Fix alarm handling Uwe Kleine-König
@ 2019-02-07 20:37 ` Alexandre Belloni
  4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Belloni @ 2019-02-07 20:37 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: Marek Vasut, kernel, linux-rtc

On 25/01/2019 15:35:54+0100, Uwe Kleine-König wrote:
> This allows to use the register offsets in all functions
> which is needed in one of the next patches.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/rtc/rtc-ds1307.c | 52 ++++++++++++++++++++--------------------
>  1 file changed, 26 insertions(+), 26 deletions(-)
> 

All applied, thanks.

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

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

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-25 14:35 [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Uwe Kleine-König
2019-01-25 14:35 ` [PATCH 2/5] rtc: ds1307: forward declare chips array instead of a bunch of functions Uwe Kleine-König
2019-01-25 14:35 ` [PATCH 3/5] rtc: ds1307: correct register offset for rx8130 Uwe Kleine-König
2019-01-25 14:35 ` [PATCH 4/5] rtc: ds1307: rx8130: honor Voltage Loss Flag when reading the time Uwe Kleine-König
2019-01-25 14:35 ` [PATCH 5/5] rtc: ds1307: rx8130: Fix alarm handling Uwe Kleine-König
2019-02-07 20:37 ` [PATCH 1/5] rtc: ds1307: Move register definitions to start of file Alexandre Belloni

Linux-RTC Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-rtc/0 linux-rtc/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-rtc linux-rtc/ https://lore.kernel.org/linux-rtc \
		linux-rtc@vger.kernel.org linux-rtc@archiver.kernel.org
	public-inbox-index linux-rtc


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-rtc


AGPL code for this site: git clone https://public-inbox.org/ public-inbox