summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig3
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-ds1307.c129
-rw-r--r--drivers/rtc/rtc-ds2404.c5
-rw-r--r--drivers/rtc/rtc-fm3130.c8
-rw-r--r--drivers/rtc/rtc-imx-sc.c87
-rw-r--r--drivers/rtc/rtc-m41t80.c2
-rw-r--r--drivers/rtc/rtc-pcf2123.c354
-rw-r--r--drivers/rtc/rtc-pcf8563.c13
-rw-r--r--drivers/rtc/rtc-rv8803.c2
-rw-r--r--drivers/rtc/rtc-rx8010.c2
-rw-r--r--drivers/rtc/rtc-rx8025.c2
-rw-r--r--drivers/rtc/rtc-s35390a.c55
-rw-r--r--drivers/rtc/rtc-st-lpc.c4
-rw-r--r--drivers/rtc/rtc-stm32.c6
-rw-r--r--drivers/rtc/rtc-sun6i.c1
-rw-r--r--drivers/rtc/rtc-tegra.c253
-rw-r--r--drivers/rtc/rtc-test.c1
-rw-r--r--drivers/rtc/rtc-tps65910.c2
-rw-r--r--drivers/rtc/rtc-wm831x.c3
20 files changed, 501 insertions, 433 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3254a30ebb1b..e72f65b61176 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -562,7 +562,7 @@ config RTC_DRV_TPS6586X
config RTC_DRV_TPS65910
tristate "TI TPS65910 RTC driver"
- depends on RTC_CLASS && MFD_TPS65910
+ depends on MFD_TPS65910
help
If you say yes here you get support for the RTC on the
TPS65910 chips.
@@ -820,6 +820,7 @@ config RTC_DRV_MAX6902
config RTC_DRV_PCF2123
tristate "NXP PCF2123"
+ select REGMAP_SPI
help
If you say yes here you get support for the NXP PCF2123
RTC chip.
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 4124f4dd376b..72b7ddc43116 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -633,7 +633,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
{
struct rtc_device *rtc;
ktime_t period;
- int count;
+ u64 count;
rtc = container_of(timer, struct rtc_device, pie_timer);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 93d338e7732b..1f7e8aefc1eb 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -222,6 +222,45 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
return -EINVAL;
}
+ tmp = regs[DS1307_REG_SECS];
+ switch (ds1307->type) {
+ case ds_1307:
+ case m41t0:
+ case m41t00:
+ case m41t11:
+ if (tmp & DS1307_BIT_CH)
+ return -EINVAL;
+ break;
+ case ds_1308:
+ case ds_1338:
+ if (tmp & DS1307_BIT_CH)
+ return -EINVAL;
+
+ ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp);
+ if (ret)
+ return ret;
+ if (tmp & DS1338_BIT_OSF)
+ return -EINVAL;
+ break;
+ case ds_1340:
+ if (tmp & DS1340_BIT_nEOSC)
+ return -EINVAL;
+
+ ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
+ if (ret)
+ return ret;
+ if (tmp & DS1340_BIT_OSF)
+ return -EINVAL;
+ break;
+ case mcp794xx:
+ if (!(tmp & MCP794XX_BIT_ST))
+ return -EINVAL;
+
+ break;
+ default:
+ break;
+ }
+
t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f);
t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);
tmp = regs[DS1307_REG_HOUR] & 0x3f;
@@ -286,7 +325,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
if (t->tm_year > 199 && chip->century_bit)
regs[chip->century_reg] |= chip->century_bit;
- if (ds1307->type == mcp794xx) {
+ switch (ds1307->type) {
+ case ds_1308:
+ case ds_1338:
+ regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
+ DS1338_BIT_OSF, 0);
+ break;
+ case ds_1340:
+ regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
+ DS1340_BIT_OSF, 0);
+ break;
+ case mcp794xx:
/*
* these bits were cleared when preparing the date/time
* values and need to be set again before writing the
@@ -294,6 +343,9 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
*/
regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST;
regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN;
+ break;
+ default:
+ break;
}
dev_dbg(dev, "%s: %7ph\n", "write", regs);
@@ -1702,7 +1754,6 @@ static int ds1307_probe(struct i2c_client *client,
break;
}
-read_rtc:
/* read RTC registers */
err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
sizeof(regs));
@@ -1711,75 +1762,11 @@ read_rtc:
goto exit;
}
- /*
- * minimal sanity checking; some chips (like DS1340) don't
- * specify the extra bits as must-be-zero, but there are
- * still a few values that are clearly out-of-range.
- */
- tmp = regs[DS1307_REG_SECS];
- switch (ds1307->type) {
- case ds_1307:
- case m41t0:
- case m41t00:
- case m41t11:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1307_BIT_CH) {
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
- break;
- case ds_1308:
- case ds_1338:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1307_BIT_CH)
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
-
- /* oscillator fault? clear flag, and warn */
- if (regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
- regmap_write(ds1307->regmap, DS1307_REG_CONTROL,
- regs[DS1307_REG_CONTROL] &
- ~DS1338_BIT_OSF);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
- break;
- case ds_1340:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1340_BIT_nEOSC)
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
-
- err = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
- if (err) {
- dev_dbg(ds1307->dev, "read error %d\n", err);
- goto exit;
- }
-
- /* oscillator fault? clear flag, and warn */
- if (tmp & DS1340_BIT_OSF) {
- regmap_write(ds1307->regmap, DS1340_REG_FLAG, 0);
- dev_warn(ds1307->dev, "SET TIME!\n");
- }
- break;
- case mcp794xx:
- /* make sure that the backup battery is enabled */
- if (!(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
- regmap_write(ds1307->regmap, DS1307_REG_WDAY,
- regs[DS1307_REG_WDAY] |
- MCP794XX_BIT_VBATEN);
- }
-
- /* clock halted? turn it on, so clock can tick. */
- if (!(tmp & MCP794XX_BIT_ST)) {
- regmap_write(ds1307->regmap, DS1307_REG_SECS,
- MCP794XX_BIT_ST);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
-
- break;
- default:
- break;
+ if (ds1307->type == mcp794xx &&
+ !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
+ regmap_write(ds1307->regmap, DS1307_REG_WDAY,
+ regs[DS1307_REG_WDAY] |
+ MCP794XX_BIT_VBATEN);
}
tmp = regs[DS1307_REG_HOUR];
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c
index 1e9f429ada64..9df0c44512b8 100644
--- a/drivers/rtc/rtc-ds2404.c
+++ b/drivers/rtc/rtc-ds2404.c
@@ -182,9 +182,10 @@ static void ds2404_enable_osc(struct device *dev)
static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
{
unsigned long time = 0;
+ __le32 hw_time = 0;
- ds2404_read_memory(dev, 0x203, 4, (u8 *)&time);
- time = le32_to_cpu(time);
+ ds2404_read_memory(dev, 0x203, 4, (u8 *)&hw_time);
+ time = le32_to_cpu(hw_time);
rtc_time64_to_tm(time, dt);
return 0;
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index 1caa21b82c7d..677ec2da13d8 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -104,8 +104,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
fm3130_rtc_mode(dev, FM3130_MODE_READ);
/* read the RTC date and time registers all at once */
- tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
- fm3130->msg, 2);
+ tmp = i2c_transfer(fm3130->client->adapter, fm3130->msg, 2);
if (tmp != 2) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
@@ -197,8 +196,7 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
/* read the RTC alarm registers all at once */
- tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
- &fm3130->msg[2], 2);
+ tmp = i2c_transfer(fm3130->client->adapter, &fm3130->msg[2], 2);
if (tmp != 2) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
@@ -348,7 +346,7 @@ static int fm3130_probe(struct i2c_client *client,
struct fm3130 *fm3130;
int err = -ENODEV;
int tmp;
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c
index 19642bfd913a..c933045fe04b 100644
--- a/drivers/rtc/rtc-imx-sc.c
+++ b/drivers/rtc/rtc-imx-sc.c
@@ -3,6 +3,7 @@
* Copyright 2018 NXP.
*/
+#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/arm-smccc.h>
#include <linux/firmware/imx/sci.h>
#include <linux/module.h>
@@ -11,11 +12,15 @@
#include <linux/rtc.h>
#define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9
+#define IMX_SC_TIMER_FUNC_SET_RTC_ALARM 8
#define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6
#define IMX_SIP_SRTC 0xC2000002
#define IMX_SIP_SRTC_SET_TIME 0x0
+#define SC_IRQ_GROUP_RTC 2
+#define SC_IRQ_RTC 1
+
static struct imx_sc_ipc *rtc_ipc_handle;
static struct rtc_device *imx_sc_rtc;
@@ -24,6 +29,16 @@ struct imx_sc_msg_timer_get_rtc_time {
u32 time;
} __packed;
+struct imx_sc_msg_timer_rtc_set_alarm {
+ struct imx_sc_rpc_msg hdr;
+ u16 year;
+ u8 mon;
+ u8 day;
+ u8 hour;
+ u8 min;
+ u8 sec;
+} __packed;
+
static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct imx_sc_msg_timer_get_rtc_time msg;
@@ -60,9 +75,77 @@ static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm)
return res.a0;
}
+static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+ return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable);
+}
+
+static int imx_sc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ /*
+ * SCU firmware does NOT provide read alarm API, but .read_alarm
+ * callback is required by RTC framework to support alarm function,
+ * so just return here.
+ */
+ return 0;
+}
+
+static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct imx_sc_msg_timer_rtc_set_alarm msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+ struct rtc_time *alrm_tm = &alrm->time;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_TIMER;
+ hdr->func = IMX_SC_TIMER_FUNC_SET_RTC_ALARM;
+ hdr->size = 3;
+
+ msg.year = alrm_tm->tm_year + 1900;
+ msg.mon = alrm_tm->tm_mon + 1;
+ msg.day = alrm_tm->tm_mday;
+ msg.hour = alrm_tm->tm_hour;
+ msg.min = alrm_tm->tm_min;
+ msg.sec = alrm_tm->tm_sec;
+
+ ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true);
+ if (ret) {
+ dev_err(dev, "set rtc alarm failed, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = imx_sc_rtc_alarm_irq_enable(dev, alrm->enabled);
+ if (ret) {
+ dev_err(dev, "enable rtc alarm failed, ret %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct rtc_class_ops imx_sc_rtc_ops = {
.read_time = imx_sc_rtc_read_time,
.set_time = imx_sc_rtc_set_time,
+ .read_alarm = imx_sc_rtc_read_alarm,
+ .set_alarm = imx_sc_rtc_set_alarm,
+ .alarm_irq_enable = imx_sc_rtc_alarm_irq_enable,
+};
+
+static int imx_sc_rtc_alarm_notify(struct notifier_block *nb,
+ unsigned long event, void *group)
+{
+ /* ignore non-rtc irq */
+ if (!((event & SC_IRQ_RTC) && (*(u8 *)group == SC_IRQ_GROUP_RTC)))
+ return 0;
+
+ rtc_update_irq(imx_sc_rtc, 1, RTC_IRQF | RTC_AF);
+
+ return 0;
+}
+
+static struct notifier_block imx_sc_rtc_alarm_sc_notifier = {
+ .notifier_call = imx_sc_rtc_alarm_notify,
};
static int imx_sc_rtc_probe(struct platform_device *pdev)
@@ -73,6 +156,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev)
if (ret)
return ret;
+ device_init_wakeup(&pdev->dev, true);
+
imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(imx_sc_rtc))
return PTR_ERR(imx_sc_rtc);
@@ -87,6 +172,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev)
return ret;
}
+ imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier);
+
return 0;
}
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 9fdc284c943b..5f46f85f814b 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -872,7 +872,7 @@ static struct notifier_block wdt_notifier = {
static int m41t80_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct i2c_adapter *adapter = client->adapter;
int rc = 0;
struct rtc_time tm;
struct m41t80_data *m41t80_data = NULL;
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index f431263e2d39..fb542a930bf0 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -40,7 +40,7 @@
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
-#include <linux/sysfs.h>
+#include <linux/regmap.h>
/* REGISTERS */
#define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */
@@ -95,6 +95,7 @@
#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */
#define OFFSET_COARSE BIT(7) /* Coarse mode offset */
#define OFFSET_STEP (2170) /* Offset step in parts per billion */
+#define OFFSET_MASK GENMASK(6, 0) /* Offset value */
/* READ/WRITE ADDRESS BITS */
#define PCF2123_WRITE BIT(4)
@@ -103,120 +104,35 @@
static struct spi_driver pcf2123_driver;
-struct pcf2123_sysfs_reg {
- struct device_attribute attr;
- char name[2];
-};
-
struct pcf2123_plat_data {
struct rtc_device *rtc;
- struct pcf2123_sysfs_reg regs[16];
+ struct regmap *map;
};
-/*
- * Causes a 30 nanosecond delay to ensure that the PCF2123 chip select
- * is released properly after an SPI write. This function should be
- * called after EVERY read/write call over SPI.
- */
-static inline void pcf2123_delay_trec(void)
-{
- ndelay(30);
-}
-
-static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
-{
- struct spi_device *spi = to_spi_device(dev);
- int ret;
-
- reg |= PCF2123_READ;
- ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
- pcf2123_delay_trec();
-
- return ret;
-}
-
-static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
-{
- struct spi_device *spi = to_spi_device(dev);
- int ret;
-
- txbuf[0] |= PCF2123_WRITE;
- ret = spi_write(spi, txbuf, size);
- pcf2123_delay_trec();
-
- return ret;
-}
-
-static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val)
-{
- u8 txbuf[2];
-
- txbuf[0] = reg;
- txbuf[1] = val;
- return pcf2123_write(dev, txbuf, sizeof(txbuf));
-}
-
-static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
- char *buffer)
-{
- struct pcf2123_sysfs_reg *r;
- u8 rxbuf[1];
- unsigned long reg;
- int ret;
-
- r = container_of(attr, struct pcf2123_sysfs_reg, attr);
-
- ret = kstrtoul(r->name, 16, &reg);
- if (ret)
- return ret;
-
- ret = pcf2123_read(dev, reg, rxbuf, 1);
- if (ret < 0)
- return -EIO;
-
- return sprintf(buffer, "0x%x\n", rxbuf[0]);
-}
+static const struct regmap_config pcf2123_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = PCF2123_READ,
+ .write_flag_mask = PCF2123_WRITE,
+ .max_register = PCF2123_REG_CTDWN_TMR,
+};
-static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
- const char *buffer, size_t count)
+static int pcf2123_read_offset(struct device *dev, long *offset)
{
- struct pcf2123_sysfs_reg *r;
- unsigned long reg;
- unsigned long val;
-
- int ret;
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
+ int ret, val;
+ unsigned int reg;
- r = container_of(attr, struct pcf2123_sysfs_reg, attr);
-
- ret = kstrtoul(r->name, 16, &reg);
+ ret = regmap_read(pdata->map, PCF2123_REG_OFFSET, &reg);
if (ret)
return ret;
- ret = kstrtoul(buffer, 10, &val);
- if (ret)
- return ret;
-
- ret = pcf2123_write_reg(dev, reg, val);
- if (ret < 0)
- return -EIO;
- return count;
-}
-
-static int pcf2123_read_offset(struct device *dev, long *offset)
-{
- int ret;
- s8 reg;
-
- ret = pcf2123_read(dev, PCF2123_REG_OFFSET, &reg, 1);
- if (ret < 0)
- return ret;
+ val = sign_extend32((reg & OFFSET_MASK), OFFSET_SIGN_BIT);
if (reg & OFFSET_COARSE)
- reg <<= 1; /* multiply by 2 and sign extend */
- else
- reg = sign_extend32(reg, OFFSET_SIGN_BIT);
+ val *= 2;
- *offset = ((long)reg) * OFFSET_STEP;
+ *offset = ((long)val) * OFFSET_STEP;
return 0;
}
@@ -233,6 +149,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)
*/
static int pcf2123_set_offset(struct device *dev, long offset)
{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
s8 reg;
if (offset > OFFSET_STEP * 127)
@@ -240,7 +157,7 @@ static int pcf2123_set_offset(struct device *dev, long offset)
else if (offset < OFFSET_STEP * -128)
reg = -128;
else
- reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP);
+ reg = DIV_ROUND_CLOSEST(offset, OFFSET_STEP);
/* choose fine offset only for odd values in the normal range */
if (reg & 1 && reg <= 63 && reg >= -64) {
@@ -252,16 +169,18 @@ static int pcf2123_set_offset(struct device *dev, long offset)
reg |= OFFSET_COARSE;
}
- return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg);
+ return regmap_write(pdata->map, PCF2123_REG_OFFSET, (unsigned int)reg);
}
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
u8 rxbuf[7];
int ret;
- ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
- if (ret < 0)
+ ret = regmap_bulk_read(pdata->map, PCF2123_REG_SC, rxbuf,
+ sizeof(rxbuf));
+ if (ret)
return ret;
if (rxbuf[0] & OSC_HAS_STOPPED) {
@@ -279,82 +198,168 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year < 70)
tm->tm_year += 100; /* assume we are in 1970...2069 */
- dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
- __func__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm);
return 0;
}
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- u8 txbuf[8];
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
+ u8 txbuf[7];
int ret;
- dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
- __func__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm);
/* Stop the counter first */
- ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
- if (ret < 0)
+ ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP);
+ if (ret)
return ret;
/* Set the new time */
- txbuf[0] = PCF2123_REG_SC;
- txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
- txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
- txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
- txbuf[4] = bin2bcd(tm->tm_mday & 0x3F);
- txbuf[5] = tm->tm_wday & 0x07;
- txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
- txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
-
- ret = pcf2123_write(dev, txbuf, sizeof(txbuf));
- if (ret < 0)
+ txbuf[0] = bin2bcd(tm->tm_sec & 0x7F);
+ txbuf[1] = bin2bcd(tm->tm_min & 0x7F);
+ txbuf[2] = bin2bcd(tm->tm_hour & 0x3F);
+ txbuf[3] = bin2bcd(tm->tm_mday & 0x3F);
+ txbuf[4] = tm->tm_wday & 0x07;
+ txbuf[5] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
+ txbuf[6] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
+
+ ret = regmap_bulk_write(pdata->map, PCF2123_REG_SC, txbuf,
+ sizeof(txbuf));
+ if (ret)
return ret;
/* Start the counter */
- ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
- if (ret < 0)
+ ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
+ u8 rxbuf[4];
+ int ret;
+ unsigned int val = 0;
+
+ ret = regmap_bulk_read(pdata->map, PCF2123_REG_ALRM_MN, rxbuf,
+ sizeof(rxbuf));
+ if (ret)
+ return ret;
+
+ alm->time.tm_min = bcd2bin(rxbuf[0] & 0x7F);
+ alm->time.tm_hour = bcd2bin(rxbuf[1] & 0x3F);
+ alm->time.tm_mday = bcd2bin(rxbuf[2] & 0x3F);
+ alm->time.tm_wday = bcd2bin(rxbuf[3] & 0x07);
+
+ dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time);
+
+ ret = regmap_read(pdata->map, PCF2123_REG_CTRL2, &val);
+ if (ret)
+ return ret;
+
+ alm->enabled = !!(val & CTRL2_AIE);
+
+ return 0;
+}
+
+static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
+ u8 txbuf[4];
+ int ret;
+
+ dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time);
+
+ /* Ensure alarm flag is clear */
+ ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0);
+ if (ret)
return ret;
+ /* Disable alarm interrupt */
+ ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0);
+ if (ret)
+ return ret;
+
+ /* Set new alarm */
+ txbuf[0] = bin2bcd(alm->time.tm_min & 0x7F);
+ txbuf[1] = bin2bcd(alm->time.tm_hour & 0x3F);
+ txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F);
+ txbuf[3] = bin2bcd(alm->time.tm_wday & 0x07);
+
+ ret = regmap_bulk_write(pdata->map, PCF2123_REG_ALRM_MN, txbuf,
+ sizeof(txbuf));
+ if (ret)
+ return ret;
+
+ /* Enable alarm interrupt */
+ if (alm->enabled) {
+ ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2,
+ CTRL2_AIE, CTRL2_AIE);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
+static irqreturn_t pcf2123_rtc_irq(int irq, void *dev)
+{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
+ struct mutex *lock = &pdata->rtc->ops_lock;
+ unsigned int val = 0;
+ int ret = IRQ_NONE;
+
+ mutex_lock(lock);
+ regmap_read(pdata->map, PCF2123_REG_CTRL2, &val);
+
+ /* Alarm? */
+ if (val & CTRL2_AF) {
+ ret = IRQ_HANDLED;
+
+ /* Clear alarm flag */
+ regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0);
+
+ rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF);
+ }
+
+ mutex_unlock(lock);
+
+ return ret;
+}
+
static int pcf2123_reset(struct device *dev)
{
+ struct pcf2123_plat_data *pdata = dev_get_platdata(dev);
int ret;
- u8 rxbuf[2];
+ unsigned int val = 0;
- ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
- if (ret < 0)
+ ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
+ if (ret)
return ret;
/* Stop the counter */
dev_dbg(dev, "stopping RTC\n");
- ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
- if (ret < 0)
+ ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP);
+ if (ret)
return ret;
/* See if the counter was actually stopped */
dev_dbg(dev, "checking for presence of RTC\n");
- ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf));
- if (ret < 0)
+ ret = regmap_read(pdata->map, PCF2123_REG_CTRL1, &val);
+ if (ret)
return ret;
- dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n",
- rxbuf[0], rxbuf[1]);
- if (!(rxbuf[0] & CTRL1_STOP))
+ dev_dbg(dev, "received data from RTC (0x%08X)\n", val);
+ if (!(val & CTRL1_STOP))
return -ENODEV;
/* Start the counter */
- ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
- if (ret < 0)
+ ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR);
+ if (ret)
return ret;
return 0;
@@ -365,7 +370,8 @@ static const struct rtc_class_ops pcf2123_rtc_ops = {
.set_time = pcf2123_rtc_set_time,
.read_offset = pcf2123_read_offset,
.set_offset = pcf2123_set_offset,
-
+ .read_alarm = pcf2123_rtc_read_alarm,
+ .set_alarm = pcf2123_rtc_set_alarm,
};
static int pcf2123_probe(struct spi_device *spi)
@@ -373,7 +379,7 @@ static int pcf2123_probe(struct spi_device *spi)
struct rtc_device *rtc;
struct rtc_time tm;
struct pcf2123_plat_data *pdata;
- int ret, i;
+ int ret = 0;
pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
GFP_KERNEL);
@@ -381,6 +387,13 @@ static int pcf2123_probe(struct spi_device *spi)
return -ENOMEM;
spi->dev.platform_data = pdata;
+ pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config);
+
+ if (IS_ERR(pdata->map)) {
+ dev_err(&spi->dev, "regmap init failed.\n");
+ goto kfree_exit;
+ }
+
ret = pcf2123_rtc_read_time(&spi->dev, &tm);
if (ret < 0) {
ret = pcf2123_reset(&spi->dev);
@@ -405,47 +418,31 @@ static int pcf2123_probe(struct spi_device *spi)
pdata->rtc = rtc;
- for (i = 0; i < 16; i++) {
- sysfs_attr_init(&pdata->regs[i].attr.attr);
- sprintf(pdata->regs[i].name, "%1x", i);
- pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR;
- pdata->regs[i].attr.attr.name = pdata->regs[i].name;
- pdata->regs[i].attr.show = pcf2123_show;
- pdata->regs[i].attr.store = pcf2123_store;
- ret = device_create_file(&spi->dev, &pdata->regs[i].attr);
- if (ret) {
- dev_err(&spi->dev, "Unable to create sysfs %s\n",
- pdata->regs[i].name);
- goto sysfs_exit;
- }
+ /* Register alarm irq */
+ if (spi->irq > 0) {
+ ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
+ pcf2123_rtc_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ pcf2123_driver.driver.name, &spi->dev);
+ if (!ret)
+ device_init_wakeup(&spi->dev, true);
+ else
+ dev_err(&spi->dev, "could not request irq.\n");
}
- return 0;
+ /* The PCF2123's alarm only has minute accuracy. Must add timer
+ * support to this driver to generate interrupts more than once
+ * per minute.
+ */
+ pdata->rtc->uie_unsupported = 1;
-sysfs_exit:
- for (i--; i >= 0; i--)
- device_remove_file(&spi->dev, &pdata->regs[i].attr);
+ return 0;
kfree_exit:
spi->dev.platform_data = NULL;
return ret;
}
-static int pcf2123_remove(struct spi_device *spi)
-{
- struct pcf2123_plat_data *pdata = dev_get_platdata(&spi->dev);
- int i;
-
- if (pdata) {
- for (i = 0; i < 16; i++)
- if (pdata->regs[i].name[0])
- device_remove_file(&spi->dev,
- &pdata->regs[i].attr);
- }
-
- return 0;
-}
-
#ifdef CONFIG_OF
static const struct of_device_id pcf2123_dt_ids[] = {
{ .compatible = "nxp,rtc-pcf2123", },
@@ -461,7 +458,6 @@ static struct spi_driver pcf2123_driver = {
.of_match_table = of_match_ptr(pcf2123_dt_ids),
},
.probe = pcf2123_probe,
- .remove = pcf2123_remove,
};
module_spi_driver(pcf2123_driver);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index c569dfe8c2ae..ac159d24286d 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -560,7 +560,6 @@ static int pcf8563_probe(struct i2c_client *client,
struct pcf8563 *pcf8563;
int err;
unsigned char buf;
- unsigned char alm_pending;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -584,13 +583,13 @@ static int pcf8563_probe(struct i2c_client *client,
return err;
}
- err = pcf8563_get_alarm_mode(client, NULL, &alm_pending);
- if (err) {
- dev_err(&client->dev, "%s: read error\n", __func__);
+ /* Clear flags and disable interrupts */
+ buf = 0;
+ err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: write error\n", __func__);
return err;
}
- if (alm_pending)
- pcf8563_set_alarm_mode(client, 0);
pcf8563->rtc = devm_rtc_device_register(&client->dev,
pcf8563_driver.driver.name,
@@ -602,7 +601,7 @@ static int pcf8563_probe(struct i2c_client *client,
if (client->irq > 0) {
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf8563_irq,
- IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING,
+ IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
pcf8563_driver.driver.name, client);
if (err) {
dev_err(&client->dev, "unable to request IRQ %d\n",
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 0b102c3cf5a4..fc5243400108 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -517,7 +517,7 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
static int rv8803_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct i2c_adapter *adapter = client->adapter;
struct rv8803_data *rv8803;
int err, flags;
struct nvmem_config nvmem_cfg = {
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index b15ad8e10938..8102469e27c0 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -433,7 +433,7 @@ static struct rtc_class_ops rx8010_rtc_ops = {
static int rx8010_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct i2c_adapter *adapter = client->adapter;