aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2017-03-23 14:38:06 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2017-03-23 14:38:06 +1100
commit1b45c3e50734533ce7b2228787fa341e0cd70778 (patch)
treed17bb8d15dbcbb8f47f3c177d67b432dbf98e499
parent4646c65026468c5408c7a4ffa28ff93c5c3b61a5 (diff)
parent65e9e65cebbea755db638875a44b227a1027570e (diff)
Merge remote-tracking branch 'rtc/rtc-next'
-rw-r--r--Documentation/devicetree/bindings/rtc/cpcap-rtc.txt18
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-bq32k.c7
-rw-r--r--drivers/rtc/rtc-cpcap.c330
-rw-r--r--drivers/rtc/rtc-ds1307.c68
-rw-r--r--drivers/rtc/rtc-ds1374.c1
-rw-r--r--drivers/rtc/rtc-ds1672.c9
-rw-r--r--drivers/rtc/rtc-ds3232.c7
-rw-r--r--drivers/rtc/rtc-isl1208.c12
-rw-r--r--drivers/rtc/rtc-m41t80.c63
-rw-r--r--drivers/rtc/rtc-omap.c22
-rw-r--r--drivers/rtc/rtc-rs5c372.c37
-rw-r--r--drivers/rtc/rtc-rv3029c2.c9
-rw-r--r--drivers/rtc/rtc-rv8803.c21
-rw-r--r--drivers/rtc/rtc-rx8010.c7
-rw-r--r--drivers/rtc/rtc-rx8581.c7
-rw-r--r--drivers/rtc/rtc-s35390a.c8
-rw-r--r--drivers/rtc/rtc-wm8350.c2
20 files changed, 611 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt b/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
new file mode 100644
index 000000000000..45750ff3112d
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
@@ -0,0 +1,18 @@
+Motorola CPCAP PMIC RTC
+-----------------------
+
+This module is part of the CPCAP. For more details about the whole
+chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
+
+Requires node properties:
+- compatible: should contain "motorola,cpcap-rtc"
+- interrupts: An interrupt specifier for alarm and 1 Hz irq
+
+Example:
+
+&cpcap {
+ cpcap_rtc: rtc {
+ compatible = "motorola,cpcap-rtc";
+ interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 86d12f810c27..0ad67d550bf8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -194,6 +194,7 @@ minix MINIX Technology Ltd.
miramems MiraMEMS Sensing Technology Co., Ltd.
mitsubishi Mitsubishi Electric Corporation
mosaixtech Mosaix Technologies, Inc.
+motorola Motorola, Inc.
moxa Moxa
mpl MPL AG
mqmaker mqmaker Inc.
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ee1b0e9dde79..050bec749fae 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1731,6 +1731,13 @@ config RTC_DRV_STM32
This driver can also be built as a module, if so, the module
will be called "rtc-stm32".
+config RTC_DRV_CPCAP
+ depends on MFD_CPCAP
+ tristate "Motorola CPCAP RTC"
+ help
+ Say y here for CPCAP rtc found on some Motorola phones
+ and tablets such as Droid 4.
+
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index f07297b1460a..13857d2fce09 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
+obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 2b223935001f..98ac8d5c7901 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -310,9 +310,16 @@ static const struct i2c_device_id bq32k_id[] = {
};
MODULE_DEVICE_TABLE(i2c, bq32k_id);
+static const struct of_device_id bq32k_of_match[] = {
+ { .compatible = "ti,bq32000" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bq32k_of_match);
+
static struct i2c_driver bq32k_driver = {
.driver = {
.name = "bq32k",
+ .of_match_table = of_match_ptr(bq32k_of_match),
},
.probe = bq32k_probe,
.remove = bq32k_remove,
diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c
new file mode 100644
index 000000000000..5d163be98e9f
--- /dev/null
+++ b/drivers/rtc/rtc-cpcap.c
@@ -0,0 +1,330 @@
+/*
+ * Motorola CPCAP PMIC RTC driver
+ *
+ * Based on cpcap-regulator.c from Motorola Linux kernel tree
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * Rewritten for mainline kernel
+ * - use DT
+ * - use regmap
+ * - use standard interrupt framework
+ * - use managed device resources
+ * - remove custom "secure clock daemon" helpers
+ *
+ * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/mfd/motorola-cpcap.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#define SECS_PER_DAY 86400
+#define DAY_MASK 0x7FFF
+#define TOD1_MASK 0x00FF
+#define TOD2_MASK 0x01FF
+
+struct cpcap_time {
+ int day;
+ int tod1;
+ int tod2;
+};
+
+struct cpcap_rtc {
+ struct regmap *regmap;
+ struct rtc_device *rtc_dev;
+ u16 vendor;
+ int alarm_irq;
+ bool alarm_enabled;
+ int update_irq;
+ bool update_enabled;
+};
+
+static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
+{
+ unsigned long int tod;
+ unsigned long int time;
+
+ tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
+ time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
+
+ rtc_time_to_tm(time, rtc);
+}
+
+static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
+{
+ unsigned long time;
+
+ rtc_tm_to_time(rtc, &time);
+
+ cpcap->day = time / SECS_PER_DAY;
+ time %= SECS_PER_DAY;
+ cpcap->tod2 = (time >> 8) & TOD2_MASK;
+ cpcap->tod1 = time & TOD1_MASK;
+}
+
+static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct cpcap_rtc *rtc = dev_get_drvdata(dev);
+
+ if (rtc->alarm_enabled == enabled)
+ return 0;
+
+ if (enabled)
+ enable_irq(rtc->alarm_irq);
+ else
+ disable_irq(rtc->alarm_irq);
+
+ rtc->alarm_enabled = !!enabled;
+
+ return 0;
+}
+
+static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct cpcap_rtc *rtc;
+ struct cpcap_time cpcap_tm;
+ int temp_tod2;
+ int ret;
+
+ rtc = dev_get_drvdata(dev);
+
+ ret = regmap_read(rtc->regmap, CPCAP_REG_TOD2, &temp_tod2);
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD1, &cpcap_tm.tod1);
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD2, &cpcap_tm.tod2);
+
+ if (temp_tod2 > cpcap_tm.tod2)
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
+
+ if (ret) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ cpcap2rtc_time(tm, &cpcap_tm);
+
+ return rtc_valid_tm(tm);
+}
+
+static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct cpcap_rtc *rtc;
+ struct cpcap_time cpcap_tm;
+ int ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ rtc2cpcap_time(&cpcap_tm, tm);
+
+ if (rtc->alarm_enabled)
+ disable_irq(rtc->alarm_irq);
+ if (rtc->update_enabled)
+ disable_irq(rtc->update_irq);
+
+ if (rtc->vendor == CPCAP_VENDOR_ST) {
+ /* The TOD1 and TOD2 registers MUST be written in this order
+ * for the change to properly set.
+ */
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+ TOD1_MASK, cpcap_tm.tod1);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
+ TOD2_MASK, cpcap_tm.tod2);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
+ DAY_MASK, cpcap_tm.day);
+ } else {
+ /* Clearing the upper lower 8 bits of the TOD guarantees that
+ * the upper half of TOD (TOD2) will not increment for 0xFF RTC
+ * ticks (255 seconds). During this time we can safely write
+ * to DAY, TOD2, then TOD1 (in that order) and expect RTC to be
+ * synchronized to the exact time requested upon the final write
+ * to TOD1.
+ */
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+ TOD1_MASK, 0);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
+ DAY_MASK, cpcap_tm.day);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
+ TOD2_MASK, cpcap_tm.tod2);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+ TOD1_MASK, cpcap_tm.tod1);
+ }
+
+ if (rtc->update_enabled)
+ enable_irq(rtc->update_irq);
+ if (rtc->alarm_enabled)
+ enable_irq(rtc->alarm_irq);
+
+ return ret;
+}
+
+static int cpcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct cpcap_rtc *rtc;
+ struct cpcap_time cpcap_tm;
+ int ret;
+
+ rtc = dev_get_drvdata(dev);
+
+ alrm->enabled = rtc->alarm_enabled;
+
+ ret = regmap_read(rtc->regmap, CPCAP_REG_DAYA, &cpcap_tm.day);
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA2, &cpcap_tm.tod2);
+ ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA1, &cpcap_tm.tod1);
+
+ if (ret) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ cpcap2rtc_time(&alrm->time, &cpcap_tm);
+ return rtc_valid_tm(&alrm->time);
+}
+
+static int cpcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct cpcap_rtc *rtc;
+ struct cpcap_time cpcap_tm;
+ int ret;
+
+ rtc = dev_get_drvdata(dev);
+
+ rtc2cpcap_time(&cpcap_tm, &alrm->time);
+
+ if (rtc->alarm_enabled)
+ disable_irq(rtc->alarm_irq);
+
+ ret = regmap_update_bits(rtc->regmap, CPCAP_REG_DAYA, DAY_MASK,
+ cpcap_tm.day);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA2, TOD2_MASK,
+ cpcap_tm.tod2);
+ ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA1, TOD1_MASK,
+ cpcap_tm.tod1);
+
+ if (!ret) {
+ enable_irq(rtc->alarm_irq);
+ rtc->alarm_enabled = true;
+ }
+
+ return ret;
+}
+
+static const struct rtc_class_ops cpcap_rtc_ops = {
+ .read_time = cpcap_rtc_read_time,
+ .set_time = cpcap_rtc_set_time,
+ .read_alarm = cpcap_rtc_read_alarm,
+ .set_alarm = cpcap_rtc_set_alarm,
+ .alarm_irq_enable = cpcap_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t cpcap_rtc_alarm_irq(int irq, void *data)
+{
+ struct cpcap_rtc *rtc = data;
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cpcap_rtc_update_irq(int irq, void *data)
+{
+ struct cpcap_rtc *rtc = data;
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+ return IRQ_HANDLED;
+}
+
+static int cpcap_rtc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cpcap_rtc *rtc;
+ int err;
+
+ rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->regmap = dev_get_regmap(dev->parent, NULL);
+ if (!rtc->regmap)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, rtc);
+ rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc",
+ &cpcap_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor);
+ if (err)
+ return err;
+
+ rtc->alarm_irq = platform_get_irq(pdev, 0);
+ err = devm_request_threaded_irq(dev, rtc->alarm_irq, NULL,
+ cpcap_rtc_alarm_irq, IRQ_NONE,
+ "rtc_alarm", rtc);
+ if (err) {
+ dev_err(dev, "Could not request alarm irq: %d\n", err);
+ return err;
+ }
+ disable_irq(rtc->alarm_irq);
+
+ /* Stock Android uses the 1 Hz interrupt for "secure clock daemon",
+ * which is not supported by the mainline kernel. The mainline kernel
+ * does not use the irq at the moment, but we explicitly request and
+ * disable it, so that its masked and does not wake up the processor
+ * every second.
+ */
+ rtc->update_irq = platform_get_irq(pdev, 1);
+ err = devm_request_threaded_irq(dev, rtc->update_irq, NULL,
+ cpcap_rtc_update_irq, IRQ_NONE,
+ "rtc_1hz", rtc);
+ if (err) {
+ dev_err(dev, "Could not request update irq: %d\n", err);
+ return err;
+ }
+ disable_irq(rtc->update_irq);
+
+ err = device_init_wakeup(dev, 1);
+ if (err) {
+ dev_err(dev, "wakeup initialization failed (%d)\n", err);
+ /* ignore error and continue without wakeup support */
+ }
+
+ return 0;
+}
+
+static const struct of_device_id cpcap_rtc_of_match[] = {
+ { .compatible = "motorola,cpcap-rtc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cpcap_rtc_of_match);
+
+static struct platform_driver cpcap_rtc_driver = {
+ .probe = cpcap_rtc_probe,
+ .driver = {
+ .name = "cpcap-rtc",
+ .of_match_table = cpcap_rtc_of_match,
+ },
+};
+
+module_platform_driver(cpcap_rtc_driver);
+
+MODULE_ALIAS("platform:cpcap-rtc");
+MODULE_DESCRIPTION("CPCAP RTC driver");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 4ad97be48043..f085b487bbe7 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -16,6 +16,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/rtc/ds1307.h>
#include <linux/rtc.h>
#include <linux/slab.h>
@@ -192,6 +193,65 @@ static const struct i2c_device_id ds1307_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ds1307_id);
+#ifdef CONFIG_OF
+static const struct of_device_id ds1307_of_match[] = {
+ {
+ .compatible = "dallas,ds1307",
+ .data = (void *)ds_1307
+ },
+ {
+ .compatible = "dallas,ds1337",
+ .data = (void *)ds_1337
+ },
+ {
+ .compatible = "dallas,ds1338",
+ .data = (void *)ds_1338
+ },
+ {
+ .compatible = "dallas,ds1339",
+ .data = (void *)ds_1339
+ },
+ {
+ .compatible = "dallas,ds1388",
+ .data = (void *)ds_1388
+ },
+ {
+ .compatible = "dallas,ds1340",
+ .data = (void *)ds_1340
+ },
+ {
+ .compatible = "maxim,ds3231",
+ .data = (void *)ds_3231
+ },
+ {
+ .compatible = "st,m41t00",
+ .data = (void *)m41t00
+ },
+ {
+ .compatible = "microchip,mcp7940x",
+ .data = (void *)mcp794xx
+ },
+ {
+ .compatible = "microchip,mcp7941x",
+ .data = (void *)mcp794xx
+ },
+ {
+ .compatible = "pericom,pt7c4338",
+ .data = (void *)ds_1307
+ },
+ {
+ .compatible = "epson,rx8025",
+ .data = (void *)rx_8025
+ },
+ {
+ .compatible = "isil,isl12057",
+ .data = (void *)ds_1337
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ds1307_of_match);
+#endif
+
#ifdef CONFIG_ACPI
static const struct acpi_device_id ds1307_acpi_ids[] = {
{ .id = "DS1307", .driver_data = ds_1307 },
@@ -1318,7 +1378,12 @@ static int ds1307_probe(struct i2c_client *client,
i2c_set_clientdata(client, ds1307);
ds1307->client = client;
- if (id) {
+
+ if (client->dev.of_node) {
+ ds1307->type = (enum ds_type)
+ of_device_get_match_data(&client->dev);
+ chip = &chips[ds1307->type];
+ } else if (id) {
chip = &chips[id->driver_data];
ds1307->type = id->driver_data;
} else {
@@ -1711,6 +1776,7 @@ static int ds1307_remove(struct i2c_client *client)
static struct i2c_driver ds1307_driver = {
.driver = {
.name = "rtc-ds1307",
+ .of_match_table = of_match_ptr(ds1307_of_match),
.acpi_match_table = ACPI_PTR(ds1307_acpi_ids),
},
.probe = ds1307_probe,
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 52429f0a57cc..4cd115e93223 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -704,6 +704,7 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
static struct i2c_driver ds1374_driver = {
.driver = {
.name = "rtc-ds1374",
+ .of_match_table = of_match_ptr(ds1374_of_match),
.pm = &ds1374_pm,
},
.probe = ds1374_probe,
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 5c18ac7394c4..7bf46bfe11a4 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -196,10 +196,17 @@ static struct i2c_device_id ds1672_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ds1672_id);
+static const struct of_device_id ds1672_of_match[] = {
+ { .compatible = "dallas,ds1672" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ds1672_of_match);
+
static struct i2c_driver ds1672_driver = {
.driver = {
.name = "rtc-ds1672",
- },
+ .of_match_table = of_match_ptr(ds1672_of_match),
+ },
.probe = &ds1672_probe,
.id_table = ds1672_id,
};
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 9bb39a06b994..deff431a37c4 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -442,9 +442,16 @@ static const struct i2c_device_id ds3232_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ds3232_id);
+static const struct of_device_id ds3232_of_match[] = {
+ { .compatible = "dallas,ds3232" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ds3232_of_match);
+
static struct i2c_driver ds3232_driver = {
.driver = {
.name = "rtc-ds3232",
+ .of_match_table = of_match_ptr(ds3232_of_match),
.pm = &ds3232_pm_ops,
},
.probe = ds3232_i2c_probe,
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 2893785f0eba..8dd299c6a1f3 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -687,10 +687,18 @@ static const struct i2c_device_id isl1208_id[] = {
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
+static const struct of_device_id isl1208_of_match[] = {
+ { .compatible = "isil,isl1208" },
+ { .compatible = "isil,isl1218" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, isl1208_of_match);
+
static struct i2c_driver isl1208_driver = {
.driver = {
- .name = "rtc-isl1208",
- },
+ .name = "rtc-isl1208",
+ .of_match_table = of_match_ptr(isl1208_of_match),
+ },
.probe = isl1208_probe,
.remove = isl1208_remove,
.id_table = isl1208_id,
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 58698d21c2c3..5b070aa711f9 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/mutex.h>
@@ -86,8 +87,61 @@ static const struct i2c_device_id m41t80_id[] = {
};
MODULE_DEVICE_TABLE(i2c, m41t80_id);
+static const struct of_device_id m41t80_of_match[] = {
+ {
+ .compatible = "st,m41t62",
+ .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT)
+ },
+ {
+ .compatible = "st,m41t65",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_WD)
+ },
+ {
+ .compatible = "st,m41t80",
+ .data = (void *)(M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t81",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t81s",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t82",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t83",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t84",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t85",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,m41t87",
+ .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+ },
+ {
+ .compatible = "st,rv4162",
+ .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+ },
+ {
+ .compatible = "rv4162",
+ .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, m41t80_of_match);
+
struct m41t80_data {
- u8 features;
+ unsigned long features;
struct rtc_device *rtc;
};
@@ -786,7 +840,11 @@ static int m41t80_probe(struct i2c_client *client,
if (!m41t80_data)
return -ENOMEM;
- m41t80_data->features = id->driver_data;
+ if (client->dev.of_node)
+ m41t80_data->features = (unsigned long)
+ of_device_get_match_data(&client->dev);
+ else
+ m41t80_data->features = id->driver_data;
i2c_set_clientdata(client, m41t80_data);
if (client->irq > 0) {
@@ -894,6 +952,7 @@ static int m41t80_remove(struct i2c_client *client)
static struct i2c_driver m41t80_driver = {
.driver = {
.name = "rtc-m41t80",
+ .of_match_table = of_match_ptr(m41t80_of_match),
.pm = &m41t80_pm,
},
.probe = m41t80_probe,
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 73594f38c453..13f7cd11c07e 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -844,7 +844,7 @@ err:
return ret;
}
-static int __exit omap_rtc_remove(struct platform_device *pdev)
+static int omap_rtc_remove(struct platform_device *pdev)
{
struct omap_rtc *rtc = platform_get_drvdata(pdev);
u8 reg;
@@ -882,8 +882,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int omap_rtc_suspend(struct device *dev)
+static int __maybe_unused omap_rtc_suspend(struct device *dev)
{
struct omap_rtc *rtc = dev_get_drvdata(dev);
@@ -906,7 +905,7 @@ static int omap_rtc_suspend(struct device *dev)
return 0;
}
-static int omap_rtc_resume(struct device *dev)
+static int __maybe_unused omap_rtc_resume(struct device *dev)
{
struct omap_rtc *rtc = dev_get_drvdata(dev);
@@ -921,10 +920,8 @@ static int omap_rtc_resume(struct device *dev)
return 0;
}
-#endif
-#ifdef CONFIG_PM
-static int omap_rtc_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_rtc_runtime_suspend(struct device *dev)
{
struct omap_rtc *rtc = dev_get_drvdata(dev);
@@ -934,16 +931,9 @@ static int omap_rtc_runtime_suspend(struct device *dev)
return 0;
}
-static int omap_rtc_runtime_resume(struct device *dev)
-{
- return 0;
-}
-#endif
-
static const struct dev_pm_ops omap_rtc_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(omap_rtc_suspend, omap_rtc_resume)
- SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend,
- omap_rtc_runtime_resume, NULL)
+ SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend, NULL, NULL)
};
static void omap_rtc_shutdown(struct platform_device *pdev)
@@ -964,7 +954,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver omap_rtc_driver = {
.probe = omap_rtc_probe,
- .remove = __exit_p(omap_rtc_remove),
+ .remove = omap_rtc_remove,
.shutdown = omap_rtc_shutdown,
.driver = {
.name = "omap_rtc",
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index c8c757466783..d4eff8d7131f 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -15,6 +15,7 @@
#include <linux/bcd.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/of_device.h>
/*
* Ricoh has a family of I2C based RTCs, which differ only slightly from
@@ -83,6 +84,35 @@ static const struct i2c_device_id rs5c372_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+static const struct of_device_id rs5c372_of_match[] = {
+ {
+ .compatible = "ricoh,r2025sd",
+ .data = (void *)rtc_r2025sd
+ },
+ {
+ .compatible = "ricoh,r2221tl",
+ .data = (void *)rtc_r2221tl
+ },
+ {
+ .compatible = "ricoh,rs5c372a",
+ .data = (void *)rtc_rs5c372a
+ },
+ {
+ .compatible = "ricoh,rs5c372b",
+ .data = (void *)rtc_rs5c372b
+ },
+ {
+ .compatible = "ricoh,rv5c386",
+ .data = (void *)rtc_rv5c386
+ },
+ {
+ .compatible = "ricoh,rv5c387a",
+ .data = (void *)rtc_rv5c387a
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rs5c372_of_match);
+
/* REVISIT: this assumes that:
* - we're in the 21st century, so it's safe to ignore the century
* bit for rv5c38[67] (REG_MONTH bit 7);
@@ -581,7 +611,11 @@ static int rs5c372_probe(struct i2c_client *client,
rs5c372->client = client;
i2c_set_clientdata(client, rs5c372);
- rs5c372->type = id->driver_data;
+ if (client->dev.of_node)
+ rs5c372->type = (enum rtc_type)
+ of_device_get_match_data(&client->dev);
+ else
+ rs5c372->type = id->driver_data;
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs = &rs5c372->buf[1];
@@ -673,6 +707,7 @@ static int rs5c372_remove(struct i2c_client *client)
static struct i2c_driver rs5c372_driver = {
.driver = {
.name = "rtc-rs5c372",
+ .of_match_table = of_match_ptr(rs5c372_of_match),
},
.probe = rs5c372_probe,
.remove = rs5c372_remove,
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 1f9f7b4bf3fb..85fa1da03762 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -875,9 +875,18 @@ static struct i2c_device_id rv3029_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rv3029_id);
+static const struct of_device_id rv3029_of_match[] = {
+ { .compatible = "rv3029" },
+ { .compatible = "rv3029c2" },
+ { .compatible = "mc,rv3029c2" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rv3029_of_match);
+
static struct i2c_driver rv3029_driver = {
.driver = {
.name = "rtc-rv3029c2",
+ .of_match_table = of_match_ptr(rv3029_of_match),
},
.probe = rv3029_i2c_probe,
.id_table = rv3029_id,
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index f9277e536f7e..9ad97ab29866 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/rtc.h>
#define RV8803_I2C_TRY_COUNT 4
@@ -556,7 +557,11 @@ static int rv8803_probe(struct i2c_client *client,
mutex_init(&rv8803->flags_lock);
rv8803->client = client;
- rv8803->type = id->driver_data;
+ if (client->dev.of_node)
+ rv8803->type = (enum rv8803_type)
+ of_device_get_match_data(&client->dev);
+ else
+ rv8803->type = id->driver_data;
i2c_set_clientdata(client, rv8803);
flags = rv8803_read_reg(client, RV8803_FLAG);
@@ -627,9 +632,23 @@ static const struct i2c_device_id rv8803_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rv8803_id);
+static const struct of_device_id rv8803_of_match[] = {
+ {
+ .compatible = "microcrystal,rv8803",
+ .data = (void *)rx_8900
+ },
+ {
+ .compatible = "epson,rx8900",
+ .data = (void *)rx_8900
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rv8803_of_match);
+
static struct i2c_driver rv8803_driver = {
.driver = {
.name = "rtc-rv8803",
+ .of_match_table = of_match_ptr(rv8803_of_match),
},
.probe = rv8803_probe,
.remove = rv8803_remove,
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index d08da371912c..1ed3403ff8ac 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -59,6 +59,12 @@ static const struct i2c_device_id rx8010_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rx8010_id);
+static const struct of_device_id rx8010_of_match[] = {
+ { .compatible = "epson,rx8010" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rx8010_of_match);
+
struct rx8010_data {
struct i2c_client *client;
struct rtc_device *rtc;
@@ -487,6 +493,7 @@ static int rx8010_probe(struct i2c_client *client,
static struct i2c_driver rx8010_driver = {
.driver = {
.name = "rtc-rx8010",
+ .of_match_table = of_match_ptr(rx8010_of_match),
},
.probe = rx8010_probe,
.id_table = rx8010_id,
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 0c362a3d1f17..9998d7937688 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -308,9 +308,16 @@ static const struct i2c_device_id rx8581_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rx8581_id);
+static const struct of_device_id rx8581_of_match[] = {
+ { .compatible = "epson,rx8581" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rx8581_of_match);
+
static struct i2c_driver rx8581_driver = {
.driver = {
.name = "rtc-rx8581",
+ .of_match_table = of_match_ptr(rx8581_of_match),
},
.probe = rx8581_probe,
.id_table = rx8581_id,
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index 5dab4665ca3b..449820eeefe8 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -58,6 +58,13 @@ static const struct i2c_device_id s35390a_id[] = {
};
MODULE_DEVICE_TABLE(i2c, s35390a_id);
+static const struct of_device_id s35390a_of_match[] = {
+ { .compatible = "s35390a" },
+ { .compatible = "sii,s35390a" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, s35390a_of_match);
+
struct s35390a {
struct i2c_client *client[8];
struct rtc_device *rtc;
@@ -502,6 +509,7 @@ static int s35390a_remove(struct i2c_client *client)
static struct i2c_driver s35390a_driver = {
.driver = {
.name = "rtc-s35390a",
+ .of_match_table = of_match_ptr(s35390a_of_match),
},
.probe = s35390a_probe,
.remove = s35390a_remove,
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index fa247deb9cf4..483c7993516b 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -30,8 +30,6 @@
#define WM8350_SET_TIME_RETRIES 5
#define WM8350_GET_TIME_RETRIES 5
-#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev)
-
/*
* Read current time and date in RTC
*/