Skip to content

Commit

Permalink
rtc: bd70528: Support RTC on ROHM BD71815
Browse files Browse the repository at this point in the history
BD71815 contains similar RTC block as BD71828. Only the address offsets
seem different. Support also BD71815 RTC using rtc-bd70528.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
  • Loading branch information
M-Vaittinen authored and Lee Jones committed Apr 14, 2021
1 parent 42391f7 commit c56dc06
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
6 changes: 3 additions & 3 deletions drivers/rtc/Kconfig
Expand Up @@ -501,11 +501,11 @@ config RTC_DRV_M41T80_WDT
watchdog timer in the ST M41T60 and M41T80 RTC chips series.

config RTC_DRV_BD70528
tristate "ROHM BD70528 PMIC RTC"
depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
tristate "ROHM BD70528, BD71815 and BD71828 PMIC RTC"
depends on MFD_ROHM_BD71828 || MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
help
If you say Y here you will get support for the RTC
block on ROHM BD70528 and BD71828 Power Management IC.
block on ROHM BD70528, BD71815 and BD71828 Power Management IC.

This driver can also be built as a module. If so, the module
will be called rtc-bd70528.
Expand Down
45 changes: 37 additions & 8 deletions drivers/rtc/rtc-bd70528.c
Expand Up @@ -6,13 +6,20 @@

#include <linux/bcd.h>
#include <linux/mfd/rohm-bd70528.h>
#include <linux/mfd/rohm-bd71815.h>
#include <linux/mfd/rohm-bd71828.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/rtc.h>

/*
* On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0
* block start
*/
#define BD718XX_ALM_EN_OFFSET 14

/*
* We read regs RTC_SEC => RTC_YEAR
* this struct is ordered according to chip registers.
Expand Down Expand Up @@ -55,6 +62,7 @@ struct bd70528_rtc {
struct regmap *regmap;
struct device *dev;
u8 reg_time_start;
u8 bd718xx_alm_block_start;
bool has_rtc_timers;
};

Expand Down Expand Up @@ -236,8 +244,8 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
struct bd71828_rtc_alm alm;
struct bd70528_rtc *r = dev_get_drvdata(dev);

ret = regmap_bulk_read(r->regmap, BD71828_REG_RTC_ALM_START,
&alm, sizeof(alm));
ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
Expand All @@ -250,8 +258,8 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
else
alm.alm_mask |= BD70528_MASK_ALM_EN;

ret = regmap_bulk_write(r->regmap, BD71828_REG_RTC_ALM_START,
&alm, sizeof(alm));
ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm,
sizeof(alm));
if (ret)
dev_err(dev, "Failed to set alarm time\n");

Expand Down Expand Up @@ -311,8 +319,8 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
struct bd71828_rtc_alm alm;
struct bd70528_rtc *r = dev_get_drvdata(dev);

ret = regmap_bulk_read(r->regmap, BD71828_REG_RTC_ALM_START,
&alm, sizeof(alm));
ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
Expand Down Expand Up @@ -453,8 +461,9 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
if (!enabled)
enableval = 0;

ret = regmap_update_bits(r->regmap, BD71828_REG_RTC_ALM0_MASK,
BD70528_MASK_ALM_EN, enableval);
ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start +
BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN,
enableval);
if (ret)
dev_err(dev, "Failed to change alarm state\n");

Expand Down Expand Up @@ -524,9 +533,28 @@ static int bd70528_probe(struct platform_device *pdev)
enable_main_irq = true;
rtc_ops = &bd70528_rtc_ops;
break;
case ROHM_CHIP_TYPE_BD71815:
irq_name = "bd71815-rtc-alm-0";
bd_rtc->reg_time_start = BD71815_REG_RTC_START;

/*
* See also BD718XX_ALM_EN_OFFSET:
* This works for BD71828 and BD71815 as they have same offset
* between ALM0 start and ALM0_MASK. If new ICs are to be
* added this requires proper check as ALM0_MASK is not located
* at the end of ALM0 block - but after all ALM blocks so if
* amount of ALMs differ the offset to enable/disable is likely
* to be incorrect and enable/disable must be given as own
* reg address here.
*/
bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START;
hour_reg = BD71815_REG_HOUR;
rtc_ops = &bd71828_rtc_ops;
break;
case ROHM_CHIP_TYPE_BD71828:
irq_name = "bd71828-rtc-alm-0";
bd_rtc->reg_time_start = BD71828_REG_RTC_START;
bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;
hour_reg = BD71828_REG_RTC_HOUR;
rtc_ops = &bd71828_rtc_ops;
break;
Expand Down Expand Up @@ -605,6 +633,7 @@ static int bd70528_probe(struct platform_device *pdev)
static const struct platform_device_id bd718x7_rtc_id[] = {
{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },
{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
{ },
};
MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
Expand Down

0 comments on commit c56dc06

Please sign in to comment.