Merge tag 'rtc-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 May 2017 02:37:14 +0000 (19:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 May 2017 02:37:14 +0000 (19:37 -0700)
Pull RTC updates from Alexandre Belloni:
 "RTC subsystem update:
   - Add OF device ID table for i2c drivers

  New RTC driver:
   - Motorola CPCAP PMIC RTC

  RTC driver updates:
   - cmos: fix IRQ selection
   - ds1307: Add ST m41t0 support
   - ds1374: fix watchdog configuration
   - sh: Add rza series support"

* tag 'rtc-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (33 commits)
  rtc: gemini: add return value validation
  rtc: snvs: fix an incorrect check of return value
  rtc: ds1374: wdt: Fix stop/start ioctl always returning -EINVAL
  rtc: ds1374: wdt: Fix issue with timeout scaling from secs to wdt ticks
  rtc: sh: mark PM functions as unused
  rtc: hid-sensor-time: remove some dead code
  rtc: m41t80: Add proper compatible for rv4162
  rtc: ds1307: Add m41t0 to OF device ID table
  rtc: ds1307: support m41t0 variant
  rtc: cpcap: fix improper use of IRQ_NONE for request_threaded_irq
  rtc: cmos: Do not assume irq 8 for rtc when there are no legacy irqs
  x86: i8259: export legacy_pic symbol
  dt-bindings: rtc: document the rtc-sh bindings
  rtc: sh: add support for rza series
  rtc: cpcap: kfreeing devm allocated memory
  rtc: wm8350: Remove unused to_wm8350_from_rtc_dev
  rtc: cpcap: new rtc driver
  dt-bindings: Add vendor prefix for Motorola
  rtc: omap: mark PM methods as __maybe_unused
  rtc: omap: remove incorrect __exit markups
  ...

28 files changed:
Documentation/devicetree/bindings/rtc/cpcap-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-sh.txt [new file with mode: 0644]
Documentation/devicetree/bindings/trivial-devices.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
arch/x86/kernel/i8259.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-cpcap.c [new file with mode: 0644]
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-gemini.c
drivers/rtc/rtc-hid-sensor-time.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx8010.c
drivers/rtc/rtc-rx8581.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-wm8350.c

diff --git a/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt b/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
new file mode 100644 (file)
index 0000000..45750ff
--- /dev/null
@@ -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/rtc/rtc-sh.txt b/Documentation/devicetree/bindings/rtc/rtc-sh.txt
new file mode 100644 (file)
index 0000000..7676c7d
--- /dev/null
@@ -0,0 +1,28 @@
+* Real Time Clock for Renesas SH and ARM SoCs
+
+Required properties:
+- compatible: Should be "renesas,r7s72100-rtc" and "renesas,sh-rtc" as a
+  fallback.
+- reg: physical base address and length of memory mapped region.
+- interrupts: 3 interrupts for alarm, period, and carry.
+- interrupt-names: The interrupts should be labeled as "alarm", "period", and
+  "carry".
+- clocks: The functional clock source for the RTC controller must be listed
+  first (if exists). Additionally, potential clock counting sources are to be
+  listed.
+- clock-names: The functional clock must be labeled as "fck". Other clocks
+  may be named in accordance to the SoC hardware manuals.
+
+
+Example:
+rtc: rtc@fcff1000 {
+       compatible = "renesas,r7s72100-rtc", "renesas,sh-rtc";
+       reg = <0xfcff1000 0x2e>;
+       interrupts = <GIC_SPI 276 IRQ_TYPE_EDGE_RISING
+                     GIC_SPI 277 IRQ_TYPE_EDGE_RISING
+                     GIC_SPI 278 IRQ_TYPE_EDGE_RISING>;
+       interrupt-names = "alarm", "period", "carry";
+       clocks = <&mstp6_clks R7S72100_CLK_RTC>, <&rtc_x1_clk>,
+                <&rtc_x3_clk>, <&extal_clk>;
+       clock-names = "fck", "rtc_x1", "rtc_x3", "extal";
+};
index ad10fbe..3e0a34c 100644 (file)
@@ -160,6 +160,7 @@ sii,s35390a         2-wire CMOS real-time clock
 silabs,si7020          Relative Humidity and Temperature Sensors
 skyworks,sky81452      Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 st,24c256              i2c serial eeprom  (24cxx)
+st,m41t0               Serial real-time clock (RTC)
 st,m41t00              Serial real-time clock (RTC)
 st,m41t62              Serial real-time clock (RTC) with alarm
 st,m41t80              M41T80 - SERIAL ACCESS RTC WITH ALARMS
index 12e2784..c03d201 100644 (file)
@@ -197,6 +197,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.
index be22f5a..4e3b8a5 100644 (file)
@@ -418,6 +418,7 @@ struct legacy_pic default_legacy_pic = {
 };
 
 struct legacy_pic *legacy_pic = &default_legacy_pic;
+EXPORT_SYMBOL(legacy_pic);
 
 static int __init i8259A_init_ops(void)
 {
index ee1b0e9..8d3b957 100644 (file)
@@ -1303,10 +1303,10 @@ config RTC_DRV_SA1100
 
 config RTC_DRV_SH
        tristate "SuperH On-Chip RTC"
-       depends on SUPERH && HAVE_CLK
+       depends on SUPERH || ARCH_RENESAS
        help
          Say Y here to enable support for the on-chip RTC found in
-         most SuperH processors.
+         most SuperH processors. This RTC is also found in RZ/A SoCs.
 
          To compile this driver as a module, choose M here: the
          module will be called rtc-sh.
@@ -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
index f07297b..13857d2 100644 (file)
@@ -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
index 2b22393..98ac8d5 100644 (file)
@@ -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,
index f4a96db..b3de973 100644 (file)
@@ -41,6 +41,9 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#ifdef CONFIG_X86
+#include <asm/i8259.h>
+#endif
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <linux/mc146818rtc.h>
@@ -1193,17 +1196,23 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        cmos_wake_setup(&pnp->dev);
 
-       if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0))
+       if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
+               unsigned int irq = 0;
+#ifdef CONFIG_X86
                /* Some machines contain a PNP entry for the RTC, but
                 * don't define the IRQ. It should always be safe to
-                * hardcode it in these cases
+                * hardcode it on systems with a legacy PIC.
                 */
+               if (nr_legacy_irqs())
+                       irq = 8;
+#endif
                return cmos_do_probe(&pnp->dev,
-                               pnp_get_resource(pnp, IORESOURCE_IO, 0), 8);
-       else
+                               pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
+       } else {
                return cmos_do_probe(&pnp->dev,
                                pnp_get_resource(pnp, IORESOURCE_IO, 0),
                                pnp_irq(pnp, 0));
+       }
 }
 
 static void cmos_pnp_remove(struct pnp_dev *pnp)
diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c
new file mode 100644 (file)
index 0000000..3a0333e
--- /dev/null
@@ -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, IRQF_TRIGGER_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, IRQF_TRIGGER_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");
index 4ad97be..77339b3 100644 (file)
@@ -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>
@@ -38,6 +39,7 @@ enum ds_type {
        ds_1340,
        ds_1388,
        ds_3231,
+       m41t0,
        m41t00,
        mcp794xx,
        rx_8025,
@@ -52,6 +54,7 @@ enum ds_type {
 #      define DS1340_BIT_nEOSC         0x80
 #      define MCP794XX_BIT_ST          0x80
 #define DS1307_REG_MIN         0x01    /* 00-59 */
+#      define M41T0_BIT_OF             0x80
 #define DS1307_REG_HOUR                0x02    /* 00-23, or 1-12{am,pm} */
 #      define DS1307_BIT_12HR          0x40    /* in REG_HOUR */
 #      define DS1307_BIT_PM            0x20    /* in REG_HOUR */
@@ -182,6 +185,7 @@ static const struct i2c_device_id ds1307_id[] = {
        { "ds1388", ds_1388 },
        { "ds1340", ds_1340 },
        { "ds3231", ds_3231 },
+       { "m41t0", m41t0 },
        { "m41t00", m41t00 },
        { "mcp7940x", mcp794xx },
        { "mcp7941x", mcp794xx },
@@ -192,6 +196,69 @@ 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,m41t0",
+               .data = (void *)m41t00
+       },
+       {
+               .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 },
@@ -201,6 +268,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
        { .id = "DS1388", .driver_data = ds_1388 },
        { .id = "DS1340", .driver_data = ds_1340 },
        { .id = "DS3231", .driver_data = ds_3231 },
+       { .id = "M41T0", .driver_data = m41t0 },
        { .id = "M41T00", .driver_data = m41t00 },
        { .id = "MCP7940X", .driver_data = mcp794xx },
        { .id = "MCP7941X", .driver_data = mcp794xx },
@@ -396,6 +464,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 
        dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);
 
+       /* if oscillator fail bit is set, no data can be trusted */
+       if (ds1307->type == m41t0 &&
+           ds1307->regs[DS1307_REG_MIN] & M41T0_BIT_OF) {
+               dev_warn_once(dev, "oscillator failed, set time!\n");
+               return -EINVAL;
+       }
+
        t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
        t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
        tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
@@ -1318,7 +1393,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 {
@@ -1513,6 +1593,7 @@ read_rtc:
        tmp = ds1307->regs[DS1307_REG_SECS];
        switch (ds1307->type) {
        case ds_1307:
+       case m41t0:
        case m41t00:
                /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH) {
@@ -1577,6 +1658,7 @@ read_rtc:
        tmp = ds1307->regs[DS1307_REG_HOUR];
        switch (ds1307->type) {
        case ds_1340:
+       case m41t0:
        case m41t00:
                /*
                 * NOTE: ignores century bits; fix before deploying
@@ -1711,6 +1793,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,
index 52429f0..38a2e9e 100644 (file)
@@ -525,6 +525,10 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                if (get_user(new_margin, (int __user *)arg))
                        return -EFAULT;
 
+               /* the hardware's tick rate is 4096 Hz, so
+                * the counter value needs to be scaled accordingly
+                */
+               new_margin <<= 12;
                if (new_margin < 1 || new_margin > 16777216)
                        return -EINVAL;
 
@@ -533,7 +537,8 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                ds1374_wdt_ping();
                /* fallthrough */
        case WDIOC_GETTIMEOUT:
-               return put_user(wdt_margin, (int __user *)arg);
+               /* when returning ... inverse is true */
+               return put_user((wdt_margin >> 12), (int __user *)arg);
        case WDIOC_SETOPTIONS:
                if (copy_from_user(&options, (int __user *)arg, sizeof(int)))
                        return -EFAULT;
@@ -541,14 +546,15 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                if (options & WDIOS_DISABLECARD) {
                        pr_info("disable watchdog\n");
                        ds1374_wdt_disable();
+                       return 0;
                }
 
                if (options & WDIOS_ENABLECARD) {
                        pr_info("enable watchdog\n");
                        ds1374_wdt_settimeout(wdt_margin);
                        ds1374_wdt_ping();
+                       return 0;
                }
-
                return -EINVAL;
        }
        return -ENOTTY;
@@ -704,6 +710,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,
index 5c18ac7..7bf46bf 100644 (file)
@@ -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,
 };
index 9bb39a0..deff431 100644 (file)
@@ -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,
index ccf0dba..5279390 100644 (file)
@@ -139,6 +139,8 @@ static int gemini_rtc_probe(struct platform_device *pdev)
 
        rtc->rtc_base = devm_ioremap(dev, res->start,
                                     resource_size(res));
+       if (!rtc->rtc_base)
+               return -ENOMEM;
 
        ret = devm_request_irq(dev, rtc->rtc_irq, gemini_rtc_interrupt,
                               IRQF_SHARED, pdev->name, dev);
index c398f74..2751dba 100644 (file)
@@ -291,9 +291,9 @@ static int hid_time_probe(struct platform_device *pdev)
                                        "hid-sensor-time", &hid_time_rtc_ops,
                                        THIS_MODULE);
 
-       if (IS_ERR_OR_NULL(time_state->rtc)) {
+       if (IS_ERR(time_state->rtc)) {
                hid_device_io_stop(hsdev->hdev);
-               ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
+               ret = PTR_ERR(time_state->rtc);
                time_state->rtc = NULL;
                dev_err(&pdev->dev, "rtc device register failed!\n");
                goto err_rtc;
index 2893785..8dd299c 100644 (file)
@@ -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,
index 58698d2..5ec4653 100644 (file)
@@ -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,66 @@ 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 = "microcrystal,rv4162",
+               .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+       },
+       /* DT compatibility only, do not use compatibles below: */
+       {
+               .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 +845,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 +957,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,
index 73594f3..13f7cd1 100644 (file)
@@ -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",
index c8c7574..d4eff8d 100644 (file)
@@ -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,
index 1f9f7b4..85fa1da 100644 (file)
@@ -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,
index f9277e5..9ad97ab 100644 (file)
@@ -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,
index d08da37..1ed3403 100644 (file)
@@ -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,
index 0c362a3..9998d79 100644 (file)
@@ -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,
index 5dab466..449820e 100644 (file)
@@ -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,
index c626e43..6c2d398 100644 (file)
 #include <linux/log2.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#ifdef CONFIG_SUPERH
 #include <asm/rtc.h>
+#else
+/* Default values for RZ/A RTC */
+#define rtc_reg_size           sizeof(u16)
+#define RTC_BIT_INVERTED        0      /* no chip bugs */
+#define RTC_CAP_4_DIGIT_YEAR    (1 << 0)
+#define RTC_DEF_CAPABILITIES    RTC_CAP_4_DIGIT_YEAR
+#endif
 
 #define DRV_NAME       "sh-rtc"
 
@@ -570,6 +578,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        rtc->alarm_irq = platform_get_irq(pdev, 2);
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res)
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(res == NULL)) {
                dev_err(&pdev->dev, "No IO resource\n");
                return -ENOENT;
@@ -587,12 +597,15 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        if (unlikely(!rtc->regbase))
                return -EINVAL;
 
-       clk_id = pdev->id;
-       /* With a single device, the clock id is still "rtc0" */
-       if (clk_id < 0)
-               clk_id = 0;
+       if (!pdev->dev.of_node) {
+               clk_id = pdev->id;
+               /* With a single device, the clock id is still "rtc0" */
+               if (clk_id < 0)
+                       clk_id = 0;
 
-       snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
+               snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
+       } else
+               snprintf(clk_name, sizeof(clk_name), "fck");
 
        rtc->clk = devm_clk_get(&pdev->dev, clk_name);
        if (IS_ERR(rtc->clk)) {
@@ -608,6 +621,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        clk_enable(rtc->clk);
 
        rtc->capabilities = RTC_DEF_CAPABILITIES;
+
+#ifdef CONFIG_SUPERH
        if (dev_get_platdata(&pdev->dev)) {
                struct sh_rtc_platform_info *pinfo =
                        dev_get_platdata(&pdev->dev);
@@ -618,6 +633,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
                 */
                rtc->capabilities |= pinfo->capabilities;
        }
+#endif
 
        if (rtc->carry_irq <= 0) {
                /* register shared periodic/carry/alarm irq */
@@ -718,8 +734,7 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
        }
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int sh_rtc_suspend(struct device *dev)
+static int __maybe_unused sh_rtc_suspend(struct device *dev)
 {
        if (device_may_wakeup(dev))
                sh_rtc_set_irq_wake(dev, 1);
@@ -727,21 +742,27 @@ static int sh_rtc_suspend(struct device *dev)
        return 0;
 }
 
-static int sh_rtc_resume(struct device *dev)
+static int __maybe_unused sh_rtc_resume(struct device *dev)
 {
        if (device_may_wakeup(dev))
                sh_rtc_set_irq_wake(dev, 0);
 
        return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(sh_rtc_pm_ops, sh_rtc_suspend, sh_rtc_resume);
 
+static const struct of_device_id sh_rtc_of_match[] = {
+       { .compatible = "renesas,sh-rtc", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sh_rtc_of_match);
+
 static struct platform_driver sh_rtc_platform_driver = {
        .driver         = {
                .name   = DRV_NAME,
                .pm     = &sh_rtc_pm_ops,
+               .of_match_table = sh_rtc_of_match,
        },
        .remove         = __exit_p(sh_rtc_remove),
 };
index d51b07d..d8ef9e0 100644 (file)
@@ -258,7 +258,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
                of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
        }
 
-       if (!data->regmap) {
+       if (IS_ERR(data->regmap)) {
                dev_err(&pdev->dev, "Can't find snvs syscon\n");
                return -ENODEV;
        }
index fa247de..483c799 100644 (file)
@@ -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
  */