summaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-bd70528.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-29 01:59:13 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-29 01:59:13 +0300
commit71a5cc28e88b0db69c3f83d4061ad4cc684af09f (patch)
tree3cc40d902e7cba992c27c946f69ef65fc7d2a807 /drivers/rtc/rtc-bd70528.c
parentbe18cd1fcae2ed7db58d92d20733dfa8aa0a5173 (diff)
parentf9386c91574fe6da9f4fca9a47734816b0db0019 (diff)
downloadlinux-71a5cc28e88b0db69c3f83d4061ad4cc684af09f.tar.xz
Merge tag 'mfd-next-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core Framework: - Add support for Software Nodes to MFD Core - Remove support for Device Properties from MFD Core - Use standard APIs in MFD Core New Drivers: - Add support for ROHM BD9576MUF and BD9573MUF PMICs - Add support for Netronix Embedded Controller, PWM and RTC - Add support for Actions Semi ATC260x PMICs and OnKey New Device Support: - Add support for DG1 PCIe Graphics Card to Intel PMT - Add support for ROHM BD71815 PMIC to ROHM BD71828 - Add support for Tolino Shine 2 HD to Netronix Embedded Controller - Add support for AX10 BMC Secure Updates to Intel M10 BMC Removed Device Support: - Remove Arizona Extcon support from MFD - Remove ST-E AB8500 Power Supply code from MFD - Remove AB3100 altogether New Functionality: - Add support for SMBus and I2C modes to Dialog DA9063 - Switch to using Software Nodes in Intel (various) New/converted Device Tree bindings: - rohm bd71815-pmic, rohm bd9576-pmic, netronix ntxec, actions atc260x, ricoh rn5t618, qcom pm8xxx - Fix-ups: - Fix error handling/path; intel_pmt - Simplify code; rohm-bd718x7, ab8500-core, intel-m10-bmc - Trivial clean-ups (reordering, spelling); rohm-generic, rn5t618, max8997 - Use correct data-type; db8500-prcmu - Remove superfluous code; lp87565, intel_quark_i2c_gpi, lpc_sch, twl - Use generic APIs/defines; lm3533-core, intel_quark_i2c_gpio - Regmap related fix-ups; intel-m10-bmc, sec-core - Reorder resource freeing during remove; intel_quark_i2c_gpio - Make table indexing more robust; intel_quark_i2c_gpio - Fix reference imbalances; arizona-irq - Staticify and (un)constify things; arizona-spi, stmpe, ene-kb3930, intel-lpss-acpi, intel-lpss-pci, atc260x-i2c, intel_quark_i2c_gpio Bug Fixes: - Fix incorrect (register) values; intel-m10-bmc - Kconfig related fixes; ABX500_CORE - Do not clear the Auto Reload Register; stm32-timers" * tag 'mfd-next-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (84 commits) mfd: intel-m10-bmc: Add support for MAX10 BMC Secure Updates Revert "mfd: max8997: Add of_compatible to Extcon and Charger mfd_cell" mfd: twl: Remove unused inline function twl4030charger_usb_en() dt-bindings: mfd: Convert pm8xxx bindings to yaml dt-bindings: mfd: Add compatible for pmk8350 rtc i2c: designware: Get rid of legacy platform data mfd: intel_quark_i2c_gpio: Convert I²C to use software nodes mfd: lpc_sch: Partially revert "Add support for Intel Quark X1000" mfd: arizona: Fix rumtime PM imbalance on error mfd: max8997: Replace 8998 with 8997 mfd: core: Use acpi_find_child_device() for child devices lookup mfd: intel_quark_i2c_gpio: Don't play dirty trick with const mfd: intel_quark_i2c_gpio: Enable MSI interrupt mfd: intel_quark_i2c_gpio: Reuse BAR definitions for MFD cell indexing mfd: ntxec: Support for EC in Tolino Shine 2 HD mfd: stm32-timers: Avoid clearing auto reload register mfd: intel_quark_i2c_gpio: Replace I²C speeds with descriptive definitions mfd: intel_quark_i2c_gpio: Remove unused struct device member mfd: intel_quark_i2c_gpio: Unregister resources in reversed order mfd: Kconfig: ABX500_CORE should depend on ARCH_U8500 ...
Diffstat (limited to 'drivers/rtc/rtc-bd70528.c')
-rw-r--r--drivers/rtc/rtc-bd70528.c104
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);