All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com
Cc: Lee Jones <lee.jones@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Linus Walleij <linus.walleij@linaro.org>,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>,
	Jacek Anaszewski <jacek.anaszewski@gmail.com>,
	Pavel Machek <pavel@ucw.cz>, Dan Murphy <dmurphy@ti.com>,
	Alessandro Zummo <a.zummo@towertech.it>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org,
	linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org
Subject: [RFC PATCH 09/13] mfd: rtc: support RTC on ROHM BD71828 with BD70528 driver
Date: Thu, 17 Oct 2019 12:52:21 +0300	[thread overview]
Message-ID: <9ccc83f3dfd0fd0dc8178adf41b52115f960c45a.1571302099.git.matti.vaittinen@fi.rohmeurope.com> (raw)
In-Reply-To: <cover.1571302099.git.matti.vaittinen@fi.rohmeurope.com>

ROHM BD71828 PMIC RTC block is from many parts similar to one
on BD70528. Support BD71828 RTC using BD70528 RTC driver and
avoid re-inventing the wheel.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
---
 drivers/rtc/Kconfig              |   5 +-
 drivers/rtc/rtc-bd70528.c        | 369 ++++++++++++++++++++++---------
 include/linux/mfd/rohm-bd70528.h |  12 +-
 include/linux/mfd/rohm-bd71828.h |   4 +-
 include/linux/mfd/rohm-shared.h  |  22 ++
 5 files changed, 299 insertions(+), 113 deletions(-)
 create mode 100644 include/linux/mfd/rohm-shared.h

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e72f65b61176..5c5b18a99bf9 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -498,11 +498,12 @@ config RTC_DRV_M41T80_WDT
 	help
 	  If you say Y here you will get support for the
 	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.
+
 config RTC_DRV_BD70528
-	tristate "ROHM BD70528 PMIC RTC"
+	tristate "ROHM BD70528 and BD71828 PMIC RTC"
 	help
 	  If you say Y here you will get support for the RTC
-	  on ROHM BD70528 Power Management IC.
+	  block on ROHM BD70528 and BD71828 Power Management IC.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-bd70528.
diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c
index f9bdd555e1a2..2940b57002ac 100644
--- a/drivers/rtc/rtc-bd70528.c
+++ b/drivers/rtc/rtc-bd70528.c
@@ -2,10 +2,11 @@
 //
 // Copyright (C) 2018 ROHM Semiconductors
 //
-// RTC driver for ROHM BD70528 PMIC
+// RTC driver for ROHM BD70528 and BD71828 PMICs
 
 #include <linux/bcd.h>
 #include <linux/mfd/rohm-bd70528.h>
+#include <linux/mfd/rohm-bd71828.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -15,16 +16,16 @@
 /*
  * We read regs RTC_SEC => RTC_YEAR
  * this struct is ordered according to chip registers.
- * Keep it u8 only to avoid padding issues.
+ * Keep it u8 only (or packed) to avoid padding issues.
  */
-struct bd70528_rtc_day {
+struct bd7xx28_rtc_day {
 	u8 sec;
 	u8 min;
 	u8 hour;
 } __packed;
 
-struct bd70528_rtc_data {
-	struct bd70528_rtc_day time;
+struct bd7xx28_rtc_data {
+	struct bd7xx28_rtc_day time;
 	u8 week;
 	u8 day;
 	u8 month;
@@ -32,19 +33,28 @@ struct bd70528_rtc_data {
 } __packed;
 
 struct bd70528_rtc_wake {
-	struct bd70528_rtc_day time;
+	struct bd7xx28_rtc_day time;
 	u8 ctrl;
 } __packed;
 
+struct bd71828_rtc_alm {
+	struct bd7xx28_rtc_data alm0;
+	struct bd7xx28_rtc_data alm1;
+	u8 alm_mask;
+	u8 alm1_mask;
+} __packed;
+
 struct bd70528_rtc_alm {
-	struct bd70528_rtc_data data;
+	struct bd7xx28_rtc_data data;
 	u8 alm_mask;
 	u8 alm_repeat;
 } __packed;
 
-struct bd70528_rtc {
+struct bd7xx28_rtc {
 	struct rohm_regmap_dev *mfd;
 	struct device *dev;
+	u8 reg_time_start;
+	bool has_rtc_timers;
 };
 
 static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
@@ -118,7 +128,7 @@ static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528,
 			    ctrl_reg);
 }
 
-static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
+static int bd70528_set_rtc_based_timers(struct bd7xx28_rtc *r, int new_state,
 					int *old_state)
 {
 	int ret;
@@ -127,122 +137,162 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
 			      old_state);
 	if (ret) {
 		dev_err(r->dev,
-			"Failed to disable WDG for RTC setting (%d)\n", ret);
+			"Failed to disable WDG for RTC setting (%d)\n",
+			ret);
 		return ret;
 	}
-	ret = bd70528_set_elapsed_tmr(r->mfd,
-				      new_state & BD70528_ELAPSED_STATE_BIT,
+	ret = bd70528_set_elapsed_tmr(r->mfd, new_state &
+				      BD70528_ELAPSED_STATE_BIT,
 				      old_state);
 	if (ret) {
 		dev_err(r->dev,
 			"Failed to disable 'elapsed timer' for RTC setting\n");
 		return ret;
 	}
-	ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT,
-			       old_state);
+
+	ret = bd70528_set_wake(r->mfd, new_state &
+			       BD70528_WAKE_STATE_BIT, old_state);
 	if (ret) {
 		dev_err(r->dev,
-			"Failed to disable 'wake timer' for RTC setting\n");
+			"Failed to disable 'wake timer'\n");
 		return ret;
 	}
 
 	return ret;
 }
 
-static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
+static int bd7xx28_re_enable_rtc_based_timers(struct bd7xx28_rtc *r,
 					      int old_state)
 {
+	if (!r->has_rtc_timers)
+		return 0;
+
 	return bd70528_set_rtc_based_timers(r, old_state, NULL);
 }
 
-static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
+static int bd7xx28_disable_rtc_based_timers(struct bd7xx28_rtc *r,
 					    int *old_state)
 {
+	if (!r->has_rtc_timers)
+		return 0;
+
 	return bd70528_set_rtc_based_timers(r, 0, old_state);
 }
 
-static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
+static inline void tmday2rtc(struct rtc_time *t, struct bd7xx28_rtc_day *d)
 {
-	d->sec &= ~BD70528_MASK_RTC_SEC;
-	d->min &= ~BD70528_MASK_RTC_MINUTE;
-	d->hour &= ~BD70528_MASK_RTC_HOUR;
+	d->sec &= ~ROHM_BD1_MASK_RTC_SEC;
+	d->min &= ~ROHM_BD1_MASK_RTC_MINUTE;
+	d->hour &= ~ROHM_BD1_MASK_RTC_HOUR;
 	d->sec |= bin2bcd(t->tm_sec);
 	d->min |= bin2bcd(t->tm_min);
 	d->hour |= bin2bcd(t->tm_hour);
 }
 
-static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r)
+static inline void tm2rtc(struct rtc_time *t, struct bd7xx28_rtc_data *r)
 {
-	r->day &= ~BD70528_MASK_RTC_DAY;
-	r->week &= ~BD70528_MASK_RTC_WEEK;
-	r->month &= ~BD70528_MASK_RTC_MONTH;
+	r->day &= ~ROHM_BD1_MASK_RTC_DAY;
+	r->week &= ~ROHM_BD1_MASK_RTC_WEEK;
+	r->month &= ~ROHM_BD1_MASK_RTC_MONTH;
 	/*
 	 * PM and 24H bits are not used by Wake - thus we clear them
 	 * here and not in tmday2rtc() which is also used by wake.
 	 */
-	r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H);
+	r->time.hour &= ~(ROHM_BD1_MASK_RTC_HOUR_PM |
+			  ROHM_BD1_MASK_RTC_HOUR_24H);
 
 	tmday2rtc(t, &r->time);
 	/*
 	 * We do always set time in 24H mode.
 	 */
-	r->time.hour |= BD70528_MASK_RTC_HOUR_24H;
+	r->time.hour |= ROHM_BD1_MASK_RTC_HOUR_24H;
 	r->day |= bin2bcd(t->tm_mday);
 	r->week |= bin2bcd(t->tm_wday);
 	r->month |= bin2bcd(t->tm_mon + 1);
 	r->year = bin2bcd(t->tm_year - 100);
+
 }
 
-static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
+static inline void rtc2tm(struct bd7xx28_rtc_data *r, struct rtc_time *t)
 {
-	t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC);
-	t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE);
-	t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR);
+	t->tm_sec = bcd2bin(r->time.sec & ROHM_BD1_MASK_RTC_SEC);
+	t->tm_min = bcd2bin(r->time.min & ROHM_BD1_MASK_RTC_MINUTE);
+	t->tm_hour = bcd2bin(r->time.hour & ROHM_BD1_MASK_RTC_HOUR);
 	/*
-	 * If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM
+	 * If RTC is in 12H mode, then bit ROHM_BD1_MASK_RTC_HOUR_PM
 	 * is not BCD value but tells whether it is AM or PM
 	 */
-	if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) {
+	if (!(r->time.hour & ROHM_BD1_MASK_RTC_HOUR_24H)) {
 		t->tm_hour %= 12;
-		if (r->time.hour & BD70528_MASK_RTC_HOUR_PM)
+		if (r->time.hour & ROHM_BD1_MASK_RTC_HOUR_PM)
 			t->tm_hour += 12;
 	}
-	t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY);
-	t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1;
-	t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR);
-	t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
+	t->tm_mday = bcd2bin(r->day & ROHM_BD1_MASK_RTC_DAY);
+	t->tm_mon = bcd2bin(r->month & ROHM_BD1_MASK_RTC_MONTH) - 1;
+	t->tm_year = 100 + bcd2bin(r->year & ROHM_BD1_MASK_RTC_YEAR);
+	t->tm_wday = bcd2bin(r->week & ROHM_BD1_MASK_RTC_WEEK);
 }
 
-static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
+static int bd71828_set_alarm(struct bd7xx28_rtc *r, struct rtc_wkalrm *a)
+{
+	int ret;
+	struct bd71828_rtc_alm alm;
+	struct rohm_regmap_dev *bd71828 = r->mfd;
+
+	ret = regmap_bulk_read(bd71828->regmap, BD71828_REG_RTC_ALM_START,
+			       &alm, sizeof(alm));
+	if (ret) {
+		dev_err(r->dev, "Failed to read alarm regs\n");
+		return ret;
+	}
+
+	tm2rtc(&a->time, &alm.alm0);
+
+	if (!a->enabled)
+		alm.alm_mask &= ~ROHM_BD1_MASK_ALM_EN;
+	else
+		alm.alm_mask |= ROHM_BD1_MASK_ALM_EN;
+
+	pr_debug("%s: new ALM0 EN bits are 0x%x\n", __func__, alm.alm_mask);
+
+	ret = regmap_bulk_write(bd71828->regmap, BD71828_REG_RTC_ALM_START,
+				&alm, sizeof(alm));
+	if (ret)
+		dev_err(r->dev, "Failed to set alarm time\n");
+
+	return ret;
+
+}
+static int bd70528_set_alarm(struct bd7xx28_rtc *r, struct rtc_wkalrm *a)
 {
 	struct bd70528_rtc_wake wake;
 	struct bd70528_rtc_alm alm;
 	int ret;
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
 	struct rohm_regmap_dev *bd70528 = r->mfd;
 
-	ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_WAKE_START,
+	ret = regmap_bulk_read(bd70528->regmap,
+			       BD70528_REG_RTC_WAKE_START,
 			       &wake, sizeof(wake));
 	if (ret) {
-		dev_err(dev, "Failed to read wake regs\n");
+		dev_err(r->dev, "Failed to read wake regs\n");
 		return ret;
 	}
+	tmday2rtc(&a->time, &wake.time);
 
 	ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
 			       &alm, sizeof(alm));
 	if (ret) {
-		dev_err(dev, "Failed to read alarm regs\n");
+		dev_err(r->dev, "Failed to read alarm regs\n");
 		return ret;
 	}
 
 	tm2rtc(&a->time, &alm.data);
-	tmday2rtc(&a->time, &wake.time);
 
 	if (a->enabled) {
-		alm.alm_mask &= ~BD70528_MASK_ALM_EN;
+		alm.alm_mask &= ~ROHM_BD1_MASK_ALM_EN;
 		wake.ctrl |= BD70528_MASK_WAKE_EN;
 	} else {
-		alm.alm_mask |= BD70528_MASK_ALM_EN;
+		alm.alm_mask |= ROHM_BD1_MASK_ALM_EN;
 		wake.ctrl &= ~BD70528_MASK_WAKE_EN;
 	}
 
@@ -250,28 +300,69 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
 				BD70528_REG_RTC_WAKE_START, &wake,
 				sizeof(wake));
 	if (ret) {
-		dev_err(dev, "Failed to set wake time\n");
+		dev_err(r->dev, "Failed to set wake time\n");
 		return ret;
 	}
 	ret = regmap_bulk_write(bd70528->regmap, BD70528_REG_RTC_ALM_START,
 				&alm, sizeof(alm));
 	if (ret)
-		dev_err(dev, "Failed to set alarm time\n");
+		dev_err(r->dev, "Failed to set alarm time\n");
 
 	return ret;
 }
+static int bd7xx28_set_alarm(struct device *dev, struct rtc_wkalrm *a)
+{
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
+	struct rohm_regmap_dev *bd_dev = r->mfd;
+
+	switch (bd_dev->chip_type) {
+	case ROHM_CHIP_TYPE_BD70528:
+		return bd70528_set_alarm(r, a);
+	case ROHM_CHIP_TYPE_BD71828:
+		return bd71828_set_alarm(r, a);
+	default:
+		dev_err(dev, "Unknown RTC chip\n");
+		break;
+	}
+
+	return -ENOENT;
+}
 
-static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
+static int bd71828_read_alarm(struct bd7xx28_rtc *r, struct rtc_wkalrm *a)
+{
+	int ret;
+	struct bd71828_rtc_alm alm;
+	struct rohm_regmap_dev *bd71828 = r->mfd;
+
+	ret = regmap_bulk_read(bd71828->regmap, BD71828_REG_RTC_ALM_START,
+			       &alm, sizeof(alm));
+	if (ret) {
+		dev_err(r->dev, "Failed to read alarm regs\n");
+		return ret;
+	}
+
+	rtc2tm(&alm.alm0, &a->time);
+	a->time.tm_mday = -1;
+	a->time.tm_mon = -1;
+	a->time.tm_year = -1;
+	a->enabled = !!(alm.alm_mask & ROHM_BD1_MASK_ALM_EN);
+	a->pending = 0;
+	pr_debug("%s: ALM0 EN bits are 0x%x, returniong enabled %d\n", __func__,
+		alm.alm_mask, a->enabled);
+
+	return 0;
+}
+
+static int bd70528_read_alarm(struct bd7xx28_rtc *r, struct rtc_wkalrm *a)
 {
-	struct bd70528_rtc_alm alm;
 	int ret;
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
+	struct bd70528_rtc_alm alm;
 	struct rohm_regmap_dev *bd70528 = r->mfd;
 
 	ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
 			       &alm, sizeof(alm));
 	if (ret) {
-		dev_err(dev, "Failed to read alarm regs\n");
+		dev_err(r->dev, "Failed to read alarm regs\n");
 		return ret;
 	}
 
@@ -279,25 +370,42 @@ static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
 	a->time.tm_mday = -1;
 	a->time.tm_mon = -1;
 	a->time.tm_year = -1;
-	a->enabled = !(alm.alm_mask & BD70528_MASK_ALM_EN);
+	a->enabled = !(alm.alm_mask & ROHM_BD1_MASK_ALM_EN);
 	a->pending = 0;
 
 	return 0;
 }
 
-static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
+static int bd7xx28_read_alarm(struct device *dev, struct rtc_wkalrm *a)
+{
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
+	struct rohm_regmap_dev *bd_dev = r->mfd;
+
+	switch (bd_dev->chip_type) {
+	case ROHM_CHIP_TYPE_BD70528:
+		return bd70528_read_alarm(r, a);
+	case ROHM_CHIP_TYPE_BD71828:
+		return bd71828_read_alarm(r, a);
+	default:
+		dev_err(dev, "Unknown RTC chip\n");
+		break;
+	}
+	return -ENOENT;
+}
+
+static int bd7xx28_set_time_locked(struct device *dev, struct rtc_time *t)
 {
 	int ret, tmpret, old_states;
-	struct bd70528_rtc_data rtc_data;
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
-	struct rohm_regmap_dev *bd70528 = r->mfd;
+	struct bd7xx28_rtc_data rtc_data;
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
+	struct rohm_regmap_dev *bd7xx28 = r->mfd;
 
-	ret = bd70528_disable_rtc_based_timers(r, &old_states);
+	ret = bd7xx28_disable_rtc_based_timers(r, &old_states);
 	if (ret)
 		return ret;
 
-	tmpret = regmap_bulk_read(bd70528->regmap,
-				  BD70528_REG_RTC_START, &rtc_data,
+	tmpret = regmap_bulk_read(bd7xx28->regmap,
+				  r->reg_time_start, &rtc_data,
 				  sizeof(rtc_data));
 	if (tmpret) {
 		dev_err(dev, "Failed to read RTC time registers\n");
@@ -305,8 +413,8 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
 	}
 	tm2rtc(t, &rtc_data);
 
-	tmpret = regmap_bulk_write(bd70528->regmap,
-				   BD70528_REG_RTC_START, &rtc_data,
+	tmpret = regmap_bulk_write(bd7xx28->regmap,
+				   r->reg_time_start, &rtc_data,
 				   sizeof(rtc_data));
 	if (tmpret) {
 		dev_err(dev, "Failed to set RTC time\n");
@@ -314,34 +422,37 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
 	}
 
 renable_out:
-	ret = bd70528_re_enable_rtc_based_timers(r, old_states);
+	ret = bd7xx28_re_enable_rtc_based_timers(r, old_states);
 	if (tmpret)
 		ret = tmpret;
 
 	return ret;
 }
 
-static int bd70528_set_time(struct device *dev, struct rtc_time *t)
+static int bd7xx28_set_time(struct device *dev, struct rtc_time *t)
 {
 	int ret;
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
 
+	pr_debug("%s called\n", __func__);
 	bd70528_wdt_lock(r->mfd);
-	ret = bd70528_set_time_locked(dev, t);
+	ret = bd7xx28_set_time_locked(dev, t);
 	bd70528_wdt_unlock(r->mfd);
 	return ret;
 }
 
-static int bd70528_get_time(struct device *dev, struct rtc_time *t)
+static int bd7xx28_get_time(struct device *dev, struct rtc_time *t)
 {
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
-	struct rohm_regmap_dev *bd70528 = r->mfd;
-	struct bd70528_rtc_data rtc_data;
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
+	struct rohm_regmap_dev *bd7xx28 = r->mfd;
+	struct bd7xx28_rtc_data rtc_data;
 	int ret;
 
+	pr_debug("%s called\n", __func__);
+
 	/* read the RTC date and time registers all at once */
-	ret = regmap_bulk_read(bd70528->regmap,
-			       BD70528_REG_RTC_START, &rtc_data,
+	ret = regmap_bulk_read(bd7xx28->regmap,
+			       r->reg_time_start, &rtc_data,
 			       sizeof(rtc_data));
 	if (ret) {
 		dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
@@ -353,55 +464,94 @@ static int bd70528_get_time(struct device *dev, struct rtc_time *t)
 	return 0;
 }
 
-static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
+static int bd70528_alm_enable(struct bd7xx28_rtc *r, unsigned int enabled)
 {
 	int ret;
-	unsigned int enableval = BD70528_MASK_ALM_EN;
-	struct bd70528_rtc *r = dev_get_drvdata(dev);
+	unsigned int enableval = ROHM_BD1_MASK_ALM_EN;
 
 	if (enabled)
 		enableval = 0;
 
 	bd70528_wdt_lock(r->mfd);
-	ret = bd70528_set_wake(r->mfd, enabled, NULL);
+	ret = bd70528_set_wake(r->mfd, !enableval, NULL);
 	if (ret) {
-		dev_err(dev, "Failed to change wake state\n");
+		dev_err(r->dev, "Failed to change wake state\n");
 		goto out_unlock;
 	}
 	ret = regmap_update_bits(r->mfd->regmap, BD70528_REG_RTC_ALM_MASK,
-				 BD70528_MASK_ALM_EN, enableval);
+				 ROHM_BD1_MASK_ALM_EN, enableval);
 	if (ret)
-		dev_err(dev, "Failed to change alarm state\n");
+		dev_err(r->dev, "Failed to change alarm state\n");
 
 out_unlock:
 	bd70528_wdt_unlock(r->mfd);
 	return ret;
 }
 
-static const struct rtc_class_ops bd70528_rtc_ops = {
-	.read_time		= bd70528_get_time,
-	.set_time		= bd70528_set_time,
-	.read_alarm		= bd70528_read_alarm,
-	.set_alarm		= bd70528_set_alarm,
-	.alarm_irq_enable	= bd70528_alm_enable,
+static int bd71828_alm_enable(struct bd7xx28_rtc *r, unsigned int enabled)
+{
+	int ret;
+	unsigned int enableval = ROHM_BD1_MASK_ALM_EN;
+
+	if (!enabled)
+		enableval = 0;
+
+	pr_debug("%s called (enabled=0x%x)\n", __func__, enabled);
+	ret = regmap_update_bits(r->mfd->regmap, BD71828_REG_RTC_ALM0_MASK,
+				 ROHM_BD1_MASK_ALM_EN, enableval);
+	if (ret)
+		dev_err(r->dev, "Failed to change alarm state\n");
+
+	pr_debug("%s: Wrote alm mask reg addr 0x%x val 0x%x\n",
+		__func__, BD71828_REG_RTC_ALM0_MASK, enableval);
+
+	return ret;
+}
+
+static int bd7xx28_alm_enable(struct device *dev, unsigned int enabled)
+{
+	struct bd7xx28_rtc *r = dev_get_drvdata(dev);
+
+	switch (r->mfd->chip_type) {
+	case ROHM_CHIP_TYPE_BD70528:
+		return bd70528_alm_enable(r, enabled);
+	case ROHM_CHIP_TYPE_BD71828:
+		return bd71828_alm_enable(r, enabled);
+	default:
+		dev_err(dev, "Unknown RTC chip\n");
+	}
+
+	return -ENOENT;
+}
+
+static const struct rtc_class_ops bd7xx28_rtc_ops = {
+	.read_time		= bd7xx28_get_time,
+	.set_time		= bd7xx28_set_time,
+	.read_alarm		= bd7xx28_read_alarm,
+	.set_alarm		= bd7xx28_set_alarm,
+	.alarm_irq_enable	= bd7xx28_alm_enable,
 };
 
 static irqreturn_t alm_hndlr(int irq, void *data)
 {
 	struct rtc_device *rtc = data;
 
+	pr_debug("bd71828 RTC IRQ fired\n");
 	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF);
 	return IRQ_HANDLED;
 }
 
-static int bd70528_probe(struct platform_device *pdev)
+static int bd7xx28_probe(struct platform_device *pdev)
 {
-	struct bd70528_rtc *bd_rtc;
+	struct bd7xx28_rtc *bd_rtc;
 	struct rohm_regmap_dev *mfd;
+	const char *irq_name;
 	int ret;
 	struct rtc_device *rtc;
 	int irq;
 	unsigned int hr;
+	bool enable_main_irq = false;
+	u8 hour_reg;
 
 	mfd = dev_get_drvdata(pdev->dev.parent);
 	if (!mfd) {
@@ -415,7 +565,25 @@ static int bd70528_probe(struct platform_device *pdev)
 	bd_rtc->mfd = mfd;
 	bd_rtc->dev = &pdev->dev;
 
-	irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm");
+	switch (mfd->chip_type) {
+	case ROHM_CHIP_TYPE_BD70528:
+		irq_name = "bd70528-rtc-alm";
+		bd_rtc->has_rtc_timers = true;
+		bd_rtc->reg_time_start = BD70528_REG_RTC_START;
+		hour_reg = BD70528_REG_RTC_HOUR;
+		enable_main_irq = true;
+		break;
+	case ROHM_CHIP_TYPE_BD71828:
+		irq_name = "bd71828-rtc-alm-0";
+		bd_rtc->reg_time_start = BD71828_REG_RTC_START;
+		hour_reg = BD71828_REG_RTC_HOUR;
+		break;
+	default:
+		dev_err(&pdev->dev, "Unknown chip\n");
+		return -ENOENT;
+	}
+
+	irq = platform_get_irq_byname(pdev, irq_name);
 
 	if (irq < 0) {
 		dev_err(&pdev->dev, "Failed to get irq\n");
@@ -424,20 +592,20 @@ static int bd70528_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, bd_rtc);
 
-	ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr);
+	ret = regmap_read(mfd->regmap, hour_reg, &hr);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to reag RTC clock\n");
 		return ret;
 	}
 
-	if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
+	if (!(hr & ROHM_BD1_MASK_RTC_HOUR_24H)) {
 		struct rtc_time t;
 
-		ret = bd70528_get_time(&pdev->dev, &t);
+		ret = bd7xx28_get_time(&pdev->dev, &t);
 
 		if (!ret)
-			ret = bd70528_set_time(&pdev->dev, &t);
+			ret = bd7xx28_set_time(&pdev->dev, &t);
 
 		if (ret) {
 			dev_err(&pdev->dev,
@@ -457,7 +625,7 @@ static int bd70528_probe(struct platform_device *pdev)
 
 	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 	rtc->range_max = RTC_TIMESTAMP_END_2099;
-	rtc->ops = &bd70528_rtc_ops;
+	rtc->ops = &bd7xx28_rtc_ops;
 
 	/* Request alarm IRQ prior to registerig the RTC */
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
@@ -471,12 +639,15 @@ static int bd70528_probe(struct platform_device *pdev)
 	 *  leave them enabled as irq-controller should disable irqs
 	 *  from sub-registers when IRQ is disabled or freed.
 	 */
-	ret = regmap_update_bits(mfd->regmap,
+	if (enable_main_irq) {
+		ret = regmap_update_bits(mfd->regmap,
 				 BD70528_REG_INT_MAIN_MASK,
 				 BD70528_INT_RTC_MASK, 0);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
-		return ret;
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to enable RTC interrupts\n");
+			return ret;
+		}
 	}
 
 	ret = rtc_register_device(rtc);
@@ -490,11 +661,11 @@ static struct platform_driver bd70528_rtc = {
 	.driver = {
 		.name = "bd70528-rtc"
 	},
-	.probe = bd70528_probe,
+	.probe = bd7xx28_probe,
 };
 
 module_platform_driver(bd70528_rtc);
 
 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
-MODULE_DESCRIPTION("BD70528 RTC driver");
+MODULE_DESCRIPTION("ROHM BD70528 and BD71828 PMIC RTC driver");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h
index 1013e60c5b25..8d8c0e0b2df6 100644
--- a/include/linux/mfd/rohm-bd70528.h
+++ b/include/linux/mfd/rohm-bd70528.h
@@ -8,6 +8,7 @@
 #include <linux/device.h>
 #include <linux/mfd/rohm-generic.h>
 #include <linux/regmap.h>
+#include <linux/mfd/rohm-shared.h>
 
 enum {
 	BD70528_BUCK1,
@@ -313,16 +314,6 @@ enum {
 
 /* RTC masks to mask out reserved bits */
 
-#define BD70528_MASK_RTC_SEC		0x7f
-#define BD70528_MASK_RTC_MINUTE		0x7f
-#define BD70528_MASK_RTC_HOUR_24H	0x80
-#define BD70528_MASK_RTC_HOUR_PM	0x20
-#define BD70528_MASK_RTC_HOUR		0x1f
-#define BD70528_MASK_RTC_DAY		0x3f
-#define BD70528_MASK_RTC_WEEK		0x07
-#define BD70528_MASK_RTC_MONTH		0x1f
-#define BD70528_MASK_RTC_YEAR		0xff
-#define BD70528_MASK_RTC_COUNT_L	0x7f
 
 #define BD70528_MASK_ELAPSED_TIMER_EN	0x1
 /* Mask second, min and hour fields
@@ -332,7 +323,6 @@ enum {
  * wake-up we limit ALM to 24H and only
  * unmask sec, min and hour
  */
-#define BD70528_MASK_ALM_EN		0x7
 #define BD70528_MASK_WAKE_EN		0x1
 
 /* WDT masks */
diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h
index bbbd4f118550..bd9dfd53759d 100644
--- a/include/linux/mfd/rohm-bd71828.h
+++ b/include/linux/mfd/rohm-bd71828.h
@@ -5,6 +5,7 @@
 #define __LINUX_MFD_BD71828_H__
 
 #include <linux/mfd/rohm-generic.h>
+#include <linux/mfd/rohm-shared.h>
 
 /* Regulator IDs */
 enum {
@@ -160,6 +161,7 @@ enum {
 #define BD71828_REG_RTC_YEAR		0x52
 
 #define BD71828_REG_RTC_ALM0_SEC	0x53
+#define BD71828_REG_RTC_ALM_START	BD71828_REG_RTC_ALM0_SEC
 #define BD71828_REG_RTC_ALM0_MINUTE	0x54
 #define BD71828_REG_RTC_ALM0_HOUR	0x55
 #define BD71828_REG_RTC_ALM0_WEEK	0x56
@@ -178,6 +180,7 @@ enum {
 #define BD71828_REG_RTC_ALM1_MASK	0x62
 
 #define BD71828_REG_RTC_ALM2		0x63
+#define BD71828_REG_RTC_START		BD71828_REG_RTC_SEC
 
 /* Charger/Battey */
 #define BD71828_REG_CHG_STATE		0x65
@@ -207,7 +210,6 @@ enum {
 #define BD71828_REG_INT_MASK_TEMP	0xdd
 #define BD71828_REG_INT_MASK_RTC	0xde
 
-
 #define BD71828_REG_INT_MAIN		0xdf
 #define BD71828_REG_INT_BUCK		0xe0
 #define BD71828_REG_INT_DCIN1		0xe1
diff --git a/include/linux/mfd/rohm-shared.h b/include/linux/mfd/rohm-shared.h
new file mode 100644
index 000000000000..5f61fa81d6a2
--- /dev/null
+++ b/include/linux/mfd/rohm-shared.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2018 ROHM Semiconductors */
+
+
+/*
+ * RTC definitions shared between
+ *
+ * BD70528
+ * and BD71828
+ */
+
+#define ROHM_BD1_MASK_RTC_SEC		0x7f
+#define ROHM_BD1_MASK_RTC_MINUTE	0x7f
+#define ROHM_BD1_MASK_RTC_HOUR_24H	0x80
+#define ROHM_BD1_MASK_RTC_HOUR_PM	0x20
+#define ROHM_BD1_MASK_RTC_HOUR		0x3f
+#define ROHM_BD1_MASK_RTC_DAY		0x3f
+#define ROHM_BD1_MASK_RTC_WEEK		0x07
+#define ROHM_BD1_MASK_RTC_MONTH		0x1f
+#define ROHM_BD1_MASK_RTC_YEAR		0xff
+#define ROHM_BD1_MASK_ALM_EN		0x7
+
-- 
2.21.0


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

  parent reply	other threads:[~2019-10-17  9:52 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-17  9:40 [RFC PATCH 00/13] Support ROHM BD71828 PMIC Matti Vaittinen
2019-10-17  9:41 ` [RFC PATCH 01/13] mfd: bd71828: Support ROHM BD71828 PMIC - core Matti Vaittinen
2019-10-17  9:42 ` [RFC PATCH 02/13] mfd: input: bd71828: Add power-key support Matti Vaittinen
2019-10-17  9:43 ` [RFC PATCH 03/13] clk: bd718x7: Support ROHM BD71828 clk block Matti Vaittinen
2019-10-17  9:44 ` [RFC PATCH 04/13] regulator: bd718x7: Split driver to common and bd718x7 specific parts Matti Vaittinen
2019-10-17  9:44 ` [RFC PATCH 05/13] regulator: bd71828: Basic support for ROHM bd71828 PMIC regulators Matti Vaittinen
2019-10-17  9:48 ` [RFC PATCH 06/13] regulator: bd71828: Add GPIO based run-level control for regulators Matti Vaittinen
2019-10-17  9:50 ` [RFC PATCH 07/13] regulator: bd71828: enhanced run-level support Matti Vaittinen
2019-10-17  9:51 ` [RFC PATCH 08/13] regulator: bd71828: Support in-kernel APIs to change run-level Matti Vaittinen
2019-10-17  9:52 ` Matti Vaittinen [this message]
2019-10-17 10:12   ` [RFC PATCH 09/13] mfd: rtc: support RTC on ROHM BD71828 with BD70528 driver Alexandre Belloni
2019-10-17 10:36     ` Vaittinen, Matti
2019-10-17 10:48       ` Alexandre Belloni
2019-10-21  5:29         ` Vaittinen, Matti
2019-10-23 10:27         ` Vaittinen, Matti
2019-10-29 13:50           ` Alexandre Belloni
2019-10-29 14:08             ` Vaittinen, Matti
2019-10-17  9:53 ` [RFC PATCH 10/13] gpio: bd71828: Initial support for ROHM BD71828 PMIC GPIOs Matti Vaittinen
2019-10-17 12:45   ` Bartosz Golaszewski
2019-10-21  7:00     ` Vaittinen, Matti
2019-10-21 14:36       ` Bartosz Golaszewski
2019-10-21 14:56         ` Vaittinen, Matti
2019-10-22 13:19         ` Vaittinen, Matti
2019-10-17  9:53 ` [RFC PATCH 11/13] led: bd71828: Support LED outputs on ROHM BD71828 PMIC Matti Vaittinen
2019-10-17 14:04   ` Dan Murphy
2019-10-17 14:28     ` Alexandre Belloni
2019-10-21  8:00     ` Vaittinen, Matti
2019-10-21 19:09       ` Jacek Anaszewski
2019-10-22 12:40         ` Vaittinen, Matti
2019-10-22 17:40           ` Jacek Anaszewski
2019-10-23  8:37             ` Vaittinen, Matti
2019-10-23 21:59               ` Jacek Anaszewski
2019-10-24  8:15                 ` Vaittinen, Matti
2019-10-24 22:04                   ` Jacek Anaszewski
2019-10-25  7:07                     ` Vaittinen, Matti
2019-10-25 13:24                       ` Rob Herring
2019-10-25 14:37                         ` Vaittinen, Matti
2019-10-25 15:47                           ` Rob Herring
2019-10-29 13:29                             ` Vaittinen, Matti
2019-10-17  9:55 ` [RFC PATCH 12/13] dt-bindings: mfd: Document ROHM BD71282 bindings Matti Vaittinen
2019-10-17 14:18   ` Dan Murphy
2019-10-21  8:03     ` Vaittinen, Matti
2019-10-17  9:57 ` [RFC PATCH 13/13] dt-bindings: regulator: Document ROHM BD71282 regulator bindings Matti Vaittinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9ccc83f3dfd0fd0dc8178adf41b52115f960c45a.1571302099.git.matti.vaittinen@fi.rohmeurope.com \
    --to=matti.vaittinen@fi.rohmeurope.com \
    --cc=a.zummo@towertech.it \
    --cc=alexandre.belloni@bootlin.com \
    --cc=bgolaszewski@baylibre.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dmurphy@ti.com \
    --cc=jacek.anaszewski@gmail.com \
    --cc=lee.jones@linaro.org \
    --cc=lgirdwood@gmail.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=linux-rtc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mazziesaccount@gmail.com \
    --cc=mturquette@baylibre.com \
    --cc=pavel@ucw.cz \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.