summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-max77686.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2016-03-02 09:36:24 +0100
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-14 17:08:27 +0100
commit726fe738bd5cc5deba86d7e621505392c0f7961f (patch)
tree7f64c4939272651d1e8b58abd3ae6b9fa9ac05dc /drivers/rtc/rtc-max77686.c
parentrtc: mt6397: Remove plaform module alias (diff)
downloadlinux-726fe738bd5cc5deba86d7e621505392c0f7961f.tar.xz
linux-726fe738bd5cc5deba86d7e621505392c0f7961f.zip
rtc: max77686: Add support for MAX20024/MAX77620 RTC IP
Maxim Semiconductor's PMIC MAX77686 has RTC IP which is reused in the MAX77620/MAX20024 PMICs. Add support for these devices in MAX77686 RTC driver. This device does not have RTC alarm pending status outside of RTC IP. The RTC IP is having separate I2C address for its register access. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc/rtc-max77686.c')
-rw-r--r--drivers/rtc/rtc-max77686.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 5e924f3cde90..9cd4c4ff8c1b 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -24,8 +24,12 @@
#include <linux/regmap.h>
#define MAX77686_I2C_ADDR_RTC (0x0C >> 1)
+#define MAX77620_I2C_ADDR_RTC 0x68
#define MAX77686_INVALID_I2C_ADDR (-1)
+/* Define non existing register */
+#define MAX77686_INVALID_REG (-1)
+
/* RTC Control Register */
#define BCD_EN_SHIFT 0
#define BCD_EN_MASK BIT(BCD_EN_SHIFT)
@@ -74,6 +78,10 @@ struct max77686_rtc_driver_data {
bool alarm_enable_reg;
/* I2C address for RTC block */
int rtc_i2c_addr;
+ /* RTC interrupt via platform resource */
+ bool rtc_irq_from_platform;
+ /* Pending alarm status register */
+ int alarm_pending_status_reg;
/* RTC IRQ CHIP for regmap */
const struct regmap_irq_chip *rtc_irq_chip;
};
@@ -185,10 +193,23 @@ static const struct max77686_rtc_driver_data max77686_drv_data = {
.mask = 0x7f,
.map = max77686_map,
.alarm_enable_reg = false,
+ .rtc_irq_from_platform = false,
+ .alarm_pending_status_reg = MAX77686_REG_STATUS2,
.rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
.rtc_irq_chip = &max77686_rtc_irq_chip,
};
+static const struct max77686_rtc_driver_data max77620_drv_data = {
+ .delay = 16000,
+ .mask = 0x7f,
+ .map = max77686_map,
+ .alarm_enable_reg = false,
+ .rtc_irq_from_platform = true,
+ .alarm_pending_status_reg = MAX77686_INVALID_REG,
+ .rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
+ .rtc_irq_chip = &max77686_rtc_irq_chip,
+};
+
static const unsigned int max77802_map[REG_RTC_END] = {
[REG_RTC_CONTROLM] = MAX77802_RTC_CONTROLM,
[REG_RTC_CONTROL] = MAX77802_RTC_CONTROL,
@@ -232,6 +253,8 @@ static const struct max77686_rtc_driver_data max77802_drv_data = {
.mask = 0xff,
.map = max77802_map,
.alarm_enable_reg = true,
+ .rtc_irq_from_platform = false,
+ .alarm_pending_status_reg = MAX77686_REG_STATUS2,
.rtc_i2c_addr = MAX77686_INVALID_I2C_ADDR,
.rtc_irq_chip = &max77802_rtc_irq_chip,
};
@@ -427,9 +450,15 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
alrm->pending = 0;
- ret = regmap_read(info->regmap, MAX77686_REG_STATUS2, &val);
+
+ if (info->drv_data->alarm_pending_status_reg == MAX77686_INVALID_REG)
+ goto out;
+
+ ret = regmap_read(info->regmap,
+ info->drv_data->alarm_pending_status_reg, &val);
if (ret < 0) {
- dev_err(info->dev, "Fail to read status2 reg(%d)\n", ret);
+ dev_err(info->dev,
+ "Fail to read alarm pending status reg(%d)\n", ret);
goto out;
}
@@ -648,7 +677,18 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
struct i2c_client *parent_i2c = to_i2c_client(parent);
int ret;
- info->rtc_irq = parent_i2c->irq;
+ if (info->drv_data->rtc_irq_from_platform) {
+ struct platform_device *pdev = to_platform_device(info->dev);
+
+ info->rtc_irq = platform_get_irq(pdev, 0);
+ if (info->rtc_irq < 0) {
+ dev_err(info->dev, "Failed to get rtc interrupts: %d\n",
+ info->rtc_irq);
+ return info->rtc_irq;
+ }
+ } else {
+ info->rtc_irq = parent_i2c->irq;
+ }
info->regmap = dev_get_regmap(parent, NULL);
if (!info->regmap) {
@@ -802,6 +842,7 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
static const struct platform_device_id rtc_id[] = {
{ "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, },
{ "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, },
+ { "max77620-rtc", .driver_data = (kernel_ulong_t)&max77620_drv_data, },
{},
};
MODULE_DEVICE_TABLE(platform, rtc_id);