diff options
Diffstat (limited to 'drivers/rtc/rtc-bd70528.c')
-rw-r--r-- | drivers/rtc/rtc-bd70528.c | 104 |
1 files changed, 64 insertions, 40 deletions
diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index 17cb67f5bf6e..6454afca02a6 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -6,6 +6,7 @@ #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> @@ -14,6 +15,12 @@ #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. * Keep it u8 only (or packed) to avoid padding issues. @@ -52,8 +59,10 @@ struct bd70528_rtc_alm { struct bd70528_rtc { struct rohm_regmap_dev *parent; + struct regmap *regmap; struct device *dev; u8 reg_time_start; + u8 bd718xx_alm_block_start; bool has_rtc_timers; }; @@ -234,10 +243,9 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a) int ret; struct bd71828_rtc_alm alm; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(parent->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; @@ -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(parent->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"); @@ -265,17 +273,16 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) struct bd70528_rtc_alm alm; int ret; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START, - &wake, sizeof(wake)); + ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_WAKE_START, &wake, + sizeof(wake)); if (ret) { dev_err(dev, "Failed to read wake regs\n"); return ret; } - ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, - &alm, sizeof(alm)); + ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, + sizeof(alm)); if (ret) { dev_err(dev, "Failed to read alarm regs\n"); return ret; @@ -292,15 +299,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) wake.ctrl &= ~BD70528_MASK_WAKE_EN; } - ret = regmap_bulk_write(parent->regmap, - BD70528_REG_RTC_WAKE_START, &wake, + ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_WAKE_START, &wake, sizeof(wake)); if (ret) { dev_err(dev, "Failed to set wake time\n"); return ret; } - ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START, - &alm, sizeof(alm)); + ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_ALM_START, &alm, + sizeof(alm)); if (ret) dev_err(dev, "Failed to set alarm time\n"); @@ -312,10 +318,9 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a) int ret; struct bd71828_rtc_alm alm; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(parent->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; @@ -336,10 +341,9 @@ static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a) struct bd70528_rtc_alm alm; int ret; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, - &alm, sizeof(alm)); + ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, + sizeof(alm)); if (ret) { dev_err(dev, "Failed to read alarm regs\n"); return ret; @@ -360,14 +364,12 @@ static int bd70528_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 *parent = r->parent; ret = bd70528_disable_rtc_based_timers(r, &old_states); if (ret) return ret; - tmpret = regmap_bulk_read(parent->regmap, - r->reg_time_start, &rtc_data, + tmpret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to read RTC time registers\n"); @@ -375,8 +377,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t) } tm2rtc(t, &rtc_data); - tmpret = regmap_bulk_write(parent->regmap, - r->reg_time_start, &rtc_data, + tmpret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to set RTC time\n"); @@ -410,13 +411,11 @@ static int bd70528_set_time(struct device *dev, struct rtc_time *t) static int bd70528_get_time(struct device *dev, struct rtc_time *t) { struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *parent = r->parent; struct bd70528_rtc_data rtc_data; int ret; /* read the RTC date and time registers all at once */ - ret = regmap_bulk_read(parent->regmap, - r->reg_time_start, &rtc_data, + ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (ret) { dev_err(dev, "Failed to read RTC time (err %d)\n", ret); @@ -443,7 +442,7 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled) dev_err(dev, "Failed to change wake state\n"); goto out_unlock; } - ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK, + ret = regmap_update_bits(r->regmap, BD70528_REG_RTC_ALM_MASK, BD70528_MASK_ALM_EN, enableval); if (ret) dev_err(dev, "Failed to change alarm state\n"); @@ -462,8 +461,9 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled) if (!enabled) enableval = 0; - ret = regmap_update_bits(r->parent->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"); @@ -498,7 +498,6 @@ static int bd70528_probe(struct platform_device *pdev) { struct bd70528_rtc *bd_rtc; const struct rtc_class_ops *rtc_ops; - struct rohm_regmap_dev *parent; const char *irq_name; int ret; struct rtc_device *rtc; @@ -508,20 +507,25 @@ static int bd70528_probe(struct platform_device *pdev) u8 hour_reg; enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; - parent = dev_get_drvdata(pdev->dev.parent); - if (!parent) { - dev_err(&pdev->dev, "No MFD driver data\n"); - return -EINVAL; - } bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL); if (!bd_rtc) return -ENOMEM; - bd_rtc->parent = parent; + bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!bd_rtc->regmap) { + dev_err(&pdev->dev, "No regmap\n"); + return -EINVAL; + } + bd_rtc->dev = &pdev->dev; switch (chip) { case ROHM_CHIP_TYPE_BD70528: + bd_rtc->parent = dev_get_drvdata(pdev->dev.parent); + if (!bd_rtc->parent) { + dev_err(&pdev->dev, "No MFD data\n"); + return -EINVAL; + } irq_name = "bd70528-rtc-alm"; bd_rtc->has_rtc_timers = true; bd_rtc->reg_time_start = BD70528_REG_RTC_START; @@ -529,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; @@ -547,7 +570,7 @@ static int bd70528_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bd_rtc); - ret = regmap_read(parent->regmap, hour_reg, &hr); + ret = regmap_read(bd_rtc->regmap, hour_reg, &hr); if (ret) { dev_err(&pdev->dev, "Failed to reag RTC clock\n"); @@ -595,7 +618,7 @@ static int bd70528_probe(struct platform_device *pdev) * from sub-registers when IRQ is disabled or freed. */ if (enable_main_irq) { - ret = regmap_update_bits(parent->regmap, + ret = regmap_update_bits(bd_rtc->regmap, BD70528_REG_INT_MAIN_MASK, BD70528_INT_RTC_MASK, 0); if (ret) { @@ -610,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); |