Merge tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Jul 2019 17:03:50 +0000 (10:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Jul 2019 17:03:50 +0000 (10:03 -0700)
Pull RTC updates from Alexandre Belloni:
 "A quiet cycle this time.

   - ds1307: properly handle oscillator failure flags

   - imx-sc: alarm support

   - pcf2123: alarm support, correct offset handling

   - sun6i: add R40 support

   - simplify getting the adapter of an i2c client"

* tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (37 commits)
  rtc: wm831x: Add IRQF_ONESHOT flag
  rtc: stm32: remove one condition check in stm32_rtc_set_alarm()
  rtc: pcf2123: Fix build error
  rtc: interface: Change type of 'count' from int to u64
  rtc: pcf8563: Clear event flags and disable interrupts before requesting irq
  rtc: pcf8563: Fix interrupt trigger method
  rtc: pcf2123: fix negative offset rounding
  rtc: pcf2123: add alarm support
  rtc: pcf2123: use %ptR
  rtc: pcf2123: port to regmap
  rtc: pcf2123: remove sysfs register view
  rtc: rx8025: simplify getting the adapter of a client
  rtc: rx8010: simplify getting the adapter of a client
  rtc: rv8803: simplify getting the adapter of a client
  rtc: m41t80: simplify getting the adapter of a client
  rtc: fm3130: simplify getting the adapter of a client
  rtc: tegra: Drop MODULE_ALIAS
  rtc: sun6i: Add R40 compatible
  dt-bindings: rtc: sun6i: Add the R40 RTC compatible
  dt-bindings: rtc: Convert Allwinner A31 RTC to a schema
  ...

27 files changed:
Documentation/devicetree/bindings/rtc/allwinner,sun4i-a10-rtc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc.txt
Documentation/devicetree/bindings/rtc/rtc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/sun6i-rtc.txt [deleted file]
Documentation/devicetree/bindings/rtc/sunxi-rtc.txt [deleted file]
Documentation/devicetree/bindings/rtc/trivial-rtc.yaml [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/interface.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds2404.c
drivers/rtc/rtc-fm3130.c
drivers/rtc/rtc-imx-sc.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx8010.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-st-lpc.c
drivers/rtc/rtc-stm32.c
drivers/rtc/rtc-sun6i.c
drivers/rtc/rtc-tegra.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-tps65910.c
drivers/rtc/rtc-wm831x.c

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun4i-a10-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun4i-a10-rtc.yaml
new file mode 100644 (file)
index 0000000..46d69c3
--- /dev/null
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/allwinner,sun4i-a10-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A10 RTC Device Tree Bindings
+
+allOf:
+  - $ref: "rtc.yaml#"
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+properties:
+  compatible:
+    enum:
+      - allwinner,sun4i-a10-rtc
+      - allwinner,sun7i-a20-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    rtc: rtc@1c20d00 {
+        compatible = "allwinner,sun4i-a10-rtc";
+        reg = <0x01c20d00 0x20>;
+        interrupts = <24>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
new file mode 100644 (file)
index 0000000..924622f
--- /dev/null
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/allwinner,sun6i-a31-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A31 RTC Device Tree Bindings
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+properties:
+  "#clock-cells":
+    const: 1
+
+  compatible:
+    oneOf:
+      - const: allwinner,sun6i-a31-rtc
+      - const: allwinner,sun8i-a23-rtc
+      - const: allwinner,sun8i-h3-rtc
+      - const: allwinner,sun8i-r40-rtc
+      - const: allwinner,sun8i-v3-rtc
+      - const: allwinner,sun50i-h5-rtc
+      - items:
+          - const: allwinner,sun50i-a64-rtc
+          - const: allwinner,sun8i-h3-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    minItems: 1
+    maxItems: 2
+    items:
+      - description: RTC Alarm 0
+      - description: RTC Alarm 1
+
+  clocks:
+    maxItems: 1
+
+  clock-output-names:
+    minItems: 1
+    maxItems: 3
+    description:
+      The RTC provides up to three clocks
+        - the Low Frequency Oscillator or LOSC, at index 0,
+        - the Low Frequency Oscillator External output (X32KFOUT in
+          the datasheet), at index 1,
+        - the Internal Oscillator, at index 2.
+
+allOf:
+  - $ref: "rtc.yaml#"
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: allwinner,sun6i-a31-rtc
+
+    then:
+      properties:
+        clock-output-names:
+          minItems: 1
+          maxItems: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - allwinner,sun8i-a23-rtc
+              - allwinner,sun8i-r40-rtc
+              - allwinner,sun8i-v3-rtc
+
+    then:
+      properties:
+        clock-output-names:
+          minItems: 2
+          maxItems: 2
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - allwinner,sun8i-h3-rtc
+              - allwinner,sun50i-h5-rtc
+
+    then:
+      properties:
+        clock-output-names:
+          minItems: 3
+          maxItems: 3
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: allwinner,sun8i-r40-rtc
+
+    then:
+      properties:
+        interrupts:
+          minItems: 1
+          maxItems: 1
+
+    else:
+      properties:
+        interrupts:
+          minItems: 2
+          maxItems: 2
+
+required:
+  - "#clock-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-output-names
+
+additionalProperties: false
+
+examples:
+  - |
+    rtc: rtc@1f00000 {
+        compatible = "allwinner,sun6i-a31-rtc";
+        reg = <0x01f00000 0x400>;
+        interrupts = <0 40 4>, <0 41 4>;
+        clock-output-names = "osc32k";
+        clocks = <&ext_osc32k>;
+        #clock-cells = <1>;
+    };
+
+...
index a97fc6a9a75e63754c8732c32cb485f9fbea1d7e..b8d36fce5e2d232a6bf7860a6f6e711aab55a0cd 100644 (file)
@@ -1,72 +1 @@
-Generic device tree bindings for Real Time Clock devices
-========================================================
-
-This document describes generic bindings which can be used to describe Real Time
-Clock devices in a device tree.
-
-Required properties
--------------------
-
-- compatible : name of RTC device following generic names recommended practice.
-
-For other required properties e.g. to describe register sets,
-clocks, etc. check the binding documentation of the specific driver.
-
-Optional properties
--------------------
-
-- start-year : if provided, the default hardware range supported by the RTC is
-               shifted so the first usable year is the specified one.
-
-The following properties may not be supported by all drivers. However, if a
-driver wants to support one of the below features, it should adapt the bindings
-below.
-- trickle-resistor-ohms :   Selected resistor for trickle charger. Should be given
-                            if trickle charger should be enabled
-- trickle-diode-disable :   Do not use internal trickle charger diode Should be
-                            given if internal trickle charger diode should be
-                            disabled
-- wakeup-source :           Enables wake up of host system on alarm
-- quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
-                            expressed in femto Farad (fF).
-                            The default value shall be listed (if optional),
-                            and likewise all valid values.
-
-Trivial RTCs
-------------
-
-This is a list of trivial RTC devices that have simple device tree
-bindings, consisting only of a compatible field, an address and
-possibly an interrupt line.
-
-
-Compatible             Vendor / Chip
-==========             =============
-abracon,abb5zes3       AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
-abracon,abeoz9         AB-RTCMC-32.768kHz-EOZ9: Real Time Clock/Calendar Module with I2C Interface
-dallas,ds1374          I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
-dallas,ds1672          Dallas DS1672 Real-time Clock
-dallas,ds3232          Extremely Accurate I²C RTC with Integrated Crystal and SRAM
-epson,rx8010           I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-epson,rx8571           I2C-BUS INTERFACE REAL TIME CLOCK MODULE with Battery Backed RAM
-epson,rx8581           I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-emmicro,em3027         EM Microelectronic EM3027 Real-time Clock
-isil,isl1208           Intersil ISL1208 Low Power RTC with Battery Backed SRAM
-isil,isl1218           Intersil ISL1218 Low Power RTC with Battery Backed SRAM
-isil,isl12022          Intersil ISL12022 Real-time Clock
-microcrystal,rv3028    Real Time Clock Module with I2C-Bus
-microcrystal,rv3029    Real Time Clock Module with I2C-Bus
-microcrystal,rv8523    Real Time Clock
-nxp,pcf2127            Real-time clock
-nxp,pcf2129            Real-time clock
-nxp,pcf8563            Real-time clock/calendar
-pericom,pt7c4338       Real-time Clock Module
-ricoh,r2025sd          I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-ricoh,r2221tl          I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-ricoh,rs5c372a         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-ricoh,rs5c372b         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-ricoh,rv5c386          I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-ricoh,rv5c387a         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-sii,s35390a            2-wire CMOS real-time clock
-whwave,sd3078          I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-xircom,x1205           Xircom X1205 I2C RTC
+This file has been moved to rtc.yaml.
diff --git a/Documentation/devicetree/bindings/rtc/rtc.yaml b/Documentation/devicetree/bindings/rtc/rtc.yaml
new file mode 100644 (file)
index 0000000..ee237b2
--- /dev/null
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RTC Generic Binding
+
+maintainers:
+  - Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+description: |
+  This document describes generic bindings which can be used to
+  describe Real Time Clock devices in a device tree.
+
+properties:
+  $nodename:
+    pattern: "^rtc(@.*|-[0-9a-f])*$"
+
+  quartz-load-femtofarads:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      The capacitive load of the quartz(x-tal), expressed in femto
+      Farad (fF). The default value shall be listed (if optional),
+      and likewise all valid values.
+
+  start-year:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      If provided, the default hardware range supported by the RTC is
+      shifted so the first usable year is the specified one.
+
+  trickle-diode-disable:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Do not use internal trickle charger diode. Should be given if
+      internal trickle charger diode should be disabled.
+
+  trickle-resistor-ohms:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Selected resistor for trickle charger. Should be given
+      if trickle charger should be enabled.
+
+  wakeup-source:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enables wake up of host system on alarm.
+
+...
diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
deleted file mode 100644 (file)
index 6b732c4..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-* sun6i Real Time Clock
-
-RTC controller for the Allwinner A31
-
-Required properties:
-- compatible   : Should be one of the following combinations:
-                   - "allwinner,sun6i-a31-rtc"
-                   - "allwinner,sun8i-a23-rtc"
-                   - "allwinner,sun8i-h3-rtc"
-                   - "allwinner,sun8i-r40-rtc", "allwinner,sun8i-h3-rtc"
-                   - "allwinner,sun8i-v3-rtc"
-                   - "allwinner,sun50i-a64-rtc", "allwinner,sun8i-h3-rtc"
-                   - "allwinner,sun50i-h5-rtc"
-
-                 Where there are two or more compatible strings, this
-                 denotes the hardware covered by the most specific one
-                 is backward-compatible with the latter ones, and the
-                 implementation for the latter ones can be used, albeit
-                 with reduced functionality.
-
-- reg          : physical base address of the controller and length of
-                 memory mapped region.
-- interrupts   : IRQ lines for the RTC alarm 0 and alarm 1, in that order.
-
-Required properties for new device trees
-- clocks       : phandle to the 32kHz external oscillator
-- clock-output-names : names of up to three clock outputs. See below.
-- #clock-cells  : must be equal to 1.
-
-The RTC provides the following clocks at the given indices:
-- 0: LOSC
-- 1: LOSC external output, known as X32KFOUT in the datasheet.
-     This clock is not available on the A31 and is deprecated for old
-     device trees still using the "allwinner,sun6i-a31-rtc" compatible.
-- 2: InternalOSC, or internal RC oscillator (A64/H3/H5 only)
-
-Example:
-
-rtc: rtc@1f00000 {
-       compatible = "allwinner,sun6i-a31-rtc";
-       reg = <0x01f00000 0x400>;
-       interrupts = <0 40 4>, <0 41 4>;
-       clock-output-names = "osc32k";
-       clocks = <&ext_osc32k>;
-       #clock-cells = <1>;
-};
diff --git a/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt b/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt
deleted file mode 100644 (file)
index 4a8d79c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-* sun4i/sun7i Real Time Clock
-
-RTC controller for the Allwinner A10/A20
-
-Required properties:
-- compatible : Should be "allwinner,sun4i-a10-rtc" or "allwinner,sun7i-a20-rtc"
-- reg: physical base address of the controller and length of memory mapped
-  region.
-- interrupts: IRQ line for the RTC.
-
-Example:
-
-rtc: rtc@1c20d00 {
-       compatible = "allwinner,sun4i-a10-rtc";
-       reg = <0x01c20d00 0x20>;
-       interrupts = <24>;
-};
diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
new file mode 100644 (file)
index 0000000..0c12ce9
--- /dev/null
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/trivial-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Trivial RTCs
+
+maintainers:
+  - Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+description: |
+  This is a list of trivial RTC devices that have simple device tree
+  bindings, consisting only of a compatible field, an address and
+  possibly an interrupt line.
+
+allOf:
+  - $ref: "rtc.yaml#"
+
+properties:
+  compatible:
+    enum:
+      # AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
+      - abracon,abb5zes3
+      # AB-RTCMC-32.768kHz-EOZ9: Real Time Clock/Calendar Module with I2C Interface
+      - abracon,abeoz9
+      # I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
+      - dallas,ds1374
+      # Dallas DS1672 Real-time Clock
+      - dallas,ds1672
+      # Extremely Accurate I²C RTC with Integrated Crystal and SRAM
+      - dallas,ds3232
+      # I2C-BUS INTERFACE REAL TIME CLOCK MODULE
+      - epson,rx8010
+      # I2C-BUS INTERFACE REAL TIME CLOCK MODULE with Battery Backed RAM
+      - epson,rx8571
+      # I2C-BUS INTERFACE REAL TIME CLOCK MODULE
+      - epson,rx8581
+      # Intersil ISL1208 Low Power RTC with Battery Backed SRAM
+      - isil,isl1208
+      # Intersil ISL1218 Low Power RTC with Battery Backed SRAM
+      - isil,isl1218
+      # Intersil ISL12022 Real-time Clock
+      - isil,isl12022
+      # Real Time Clock Module with I2C-Bus
+      - microcrystal,rv3028
+      # Real Time Clock Module with I2C-Bus
+      - microcrystal,rv3029
+      # Real Time Clock
+      - microcrystal,rv8523
+      # Real-time clock
+      - nxp,pcf2127
+      # Real-time clock
+      - nxp,pcf2129
+      # Real-time clock/calendar
+      - nxp,pcf8563
+      # Real-time Clock Module
+      - pericom,pt7c4338
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,r2025sd
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,r2221tl
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,rs5c372a
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,rs5c372b
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,rv5c386
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - ricoh,rv5c387a
+      # 2-wire CMOS real-time clock
+      - sii,s35390a
+      # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+      - whwave,sd3078
+      # Xircom X1205 I2C RTC
+      - xircom,x1205
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  start-year: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+...
index 3254a30ebb1b1df75709a11de2f271ff197517e8..e72f65b61176d12e2bc296de9f25eda572db88f3 100644 (file)
@@ -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.
index 4124f4dd376b33c532e94da4783ea6467186393f..72b7ddc4311656cedbb4b14d597461b50d8bc7bb 100644 (file)
@@ -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);
 
index 93d338e7732b5b921fd825dc27f6c663a7681116..1f7e8aefc1eb692c13cc691d97ccbfc93288414a 100644 (file)
@@ -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];
index 1e9f429ada646f97dedd17fee6b3b95ecf165393..9df0c44512b8acb10b3c4d599775eeea65402d5d 100644 (file)
@@ -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;
index 1caa21b82c7d1fdfcf35474e90771d4c41bc07a4..677ec2da13d8385516b9636acefae61bb99bbcf4 100644 (file)
@@ -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))
index 19642bfd913ae9da6ffc208c761a8ba92b01f516..c933045fe04b73e77a1a263f56b7d4ccfbfda33a 100644 (file)
@@ -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>
 #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;
 }
 
index 9fdc284c943bd83d268fc0030e3581115d452d42..5f46f85f814b12d94c9e1cafc8ae9bc0b79e79cf 100644 (file)
@@ -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;
index f431263e2d398a6de711025ad25c091d1733040d..fb542a930bf0ea00038c807306afcf17137c360c 100644 (file)
@@ -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)
 
 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);
index c569dfe8c2ae2d8cd31623f719a4f15ad65a276e..ac159d24286dd16c1202da227a4b1353a78e204a 100644 (file)
@@ -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",
index 0b102c3cf5a44ba111ab80e5c4dfb61327881cd8..fc52434001082a54fe767c0cd1d7a830bdc5a21c 100644 (file)
@@ -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 = {
index b15ad8e109380b0c41f9c1c85ed89b3d5bb5efd7..8102469e27c05060f9e2dcfc2f3a03e5bc434474 100644 (file)
@@ -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;
        struct rx8010_data *rx8010;
        int err = 0;
 
index cb082ad19471fd539e2f28a7cbb2600ea3364c08..b9bda10589e0ddfbb6de363dbfcf782d0972964e 100644 (file)
@@ -501,7 +501,7 @@ static void rx8025_sysfs_unregister(struct device *dev)
 static int rx8025_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 rx8025_data *rx8025;
        int err = 0;
 
index 8c37acb4a0078f3b26ce3f80e6c984c0fcd2e1da..84806ff763cf708fada1a8af80a453980052ab71 100644 (file)
 #define S35390A_ALRM_BYTE_MINS 2
 
 /* flags for STATUS1 */
-#define S35390A_FLAG_POC       0x01
-#define S35390A_FLAG_BLD       0x02
-#define S35390A_FLAG_INT2      0x04
-#define S35390A_FLAG_24H       0x40
-#define S35390A_FLAG_RESET     0x80
+#define S35390A_FLAG_POC       BIT(0)
+#define S35390A_FLAG_BLD       BIT(1)
+#define S35390A_FLAG_INT2      BIT(2)
+#define S35390A_FLAG_24H       BIT(6)
+#define S35390A_FLAG_RESET     BIT(7)
 
 /* flag for STATUS2 */
-#define S35390A_FLAG_TEST      0x01
-
-#define S35390A_INT2_MODE_MASK         0xF0
+#define S35390A_FLAG_TEST      BIT(0)
 
+/* INT2 pin output mode */
+#define S35390A_INT2_MODE_MASK         0x0E
 #define S35390A_INT2_MODE_NOINTR       0x00
-#define S35390A_INT2_MODE_FREQ         0x10
-#define S35390A_INT2_MODE_ALARM                0x40
-#define S35390A_INT2_MODE_PMIN_EDG     0x20
+#define S35390A_INT2_MODE_ALARM                BIT(1) /* INT2AE */
+#define S35390A_INT2_MODE_PMIN_EDG     BIT(2) /* INT2ME */
+#define S35390A_INT2_MODE_FREQ         BIT(3) /* INT2FE */
+#define S35390A_INT2_MODE_PMIN         (BIT(3) | BIT(2)) /* INT2FE | INT2ME */
 
 static const struct i2c_device_id s35390a_id[] = {
        { "s35390a", 0 },
@@ -284,6 +285,9 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
                alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
                alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
 
+       if (alm->time.tm_sec != 0)
+               dev_warn(&client->dev, "Alarms are only supported on a per minute basis!\n");
+
        /* disable interrupt (which deasserts the irq line) */
        err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
        if (err < 0)
@@ -299,9 +303,6 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        else
                sts = S35390A_INT2_MODE_NOINTR;
 
-       /* This chip expects the bits of each byte to be in reverse order */
-       sts = bitrev8(sts);
-
        /* set interupt mode*/
        err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
        if (err < 0)
@@ -339,7 +340,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        if (err < 0)
                return err;
 
-       if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
+       if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
                /*
                 * When the alarm isn't enabled, the register to configure
                 * the alarm time isn't accessible.
@@ -431,14 +432,14 @@ static int s35390a_probe(struct i2c_client *client,
        unsigned int i;
        struct s35390a *s35390a;
        char buf, status1;
+       struct device *dev = &client->dev;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
                goto exit;
        }
 
-       s35390a = devm_kzalloc(&client->dev, sizeof(struct s35390a),
-                               GFP_KERNEL);
+       s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL);
        if (!s35390a) {
                err = -ENOMEM;
                goto exit;
@@ -452,8 +453,8 @@ static int s35390a_probe(struct i2c_client *client,
                s35390a->client[i] = i2c_new_dummy(client->adapter,
                                        client->addr + i);
                if (!s35390a->client[i]) {
-                       dev_err(&client->dev, "Address %02x unavailable\n",
-                                               client->addr + i);
+                       dev_err(dev, "Address %02x unavailable\n",
+                               client->addr + i);
                        err = -EBUSY;
                        goto exit_dummy;
                }
@@ -462,7 +463,7 @@ static int s35390a_probe(struct i2c_client *client,
        err_read = s35390a_read_status(s35390a, &status1);
        if (err_read < 0) {
                err = err_read;
-               dev_err(&client->dev, "error resetting chip\n");
+               dev_err(dev, "error resetting chip\n");
                goto exit_dummy;
        }
 
@@ -476,28 +477,30 @@ static int s35390a_probe(struct i2c_client *client,
                buf = 0;
                err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
                if (err < 0) {
-                       dev_err(&client->dev, "error disabling alarm");
+                       dev_err(dev, "error disabling alarm");
                        goto exit_dummy;
                }
        } else {
                err = s35390a_disable_test_mode(s35390a);
                if (err < 0) {
-                       dev_err(&client->dev, "error disabling test mode\n");
+                       dev_err(dev, "error disabling test mode\n");
                        goto exit_dummy;
                }
        }
 
-       device_set_wakeup_capable(&client->dev, 1);
+       device_set_wakeup_capable(dev, 1);
 
-       s35390a->rtc = devm_rtc_device_register(&client->dev,
-                                       s35390a_driver.driver.name,
-                                       &s35390a_rtc_ops, THIS_MODULE);
+       s35390a->rtc = devm_rtc_device_register(dev, s35390a_driver.driver.name,
+                                               &s35390a_rtc_ops, THIS_MODULE);
 
        if (IS_ERR(s35390a->rtc)) {
                err = PTR_ERR(s35390a->rtc);
                goto exit_dummy;
        }
 
+       /* supports per-minute alarms only, therefore set uie_unsupported */
+       s35390a->rtc->uie_unsupported = 1;
+
        if (status1 & S35390A_FLAG_INT2)
                rtc_update_irq(s35390a->rtc, 1, RTC_AF);
 
index 5fe021821831d95f93088ee156dd1c7b84f9b0fb..49474a31c66d32065ba3152a8ce8e37a4bde6217 100644 (file)
@@ -162,10 +162,6 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        now_secs = rtc_tm_to_time64(&now);
        alarm_secs = rtc_tm_to_time64(&t->time);
 
-       /* Invalid alarm time */
-       if (now_secs > alarm_secs)
-               return -EINVAL;
-
        memcpy(&rtc->alarm, t, sizeof(struct rtc_wkalrm));
 
        /* Now many secs to fire */
index 8e6c9b3bcc29a4d2fec1c52cd2118f4a35cee00e..773a1990b93f1a08c768e368dc1a912b6c7d0ec8 100644 (file)
@@ -519,11 +519,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        /* Write to Alarm register */
        writel_relaxed(alrmar, rtc->base + regs->alrmar);
 
-       if (alrm->enabled)
-               stm32_rtc_alarm_irq_enable(dev, 1);
-       else
-               stm32_rtc_alarm_irq_enable(dev, 0);
-
+       stm32_rtc_alarm_irq_enable(dev, alrm->enabled);
 end:
        stm32_rtc_wpr_lock(rtc);
 
index 8128ec200ba21ff3ca85c8345fa9cf5faae26d1a..c0e75c373605909b99cff0f3a87198a05c913aa9 100644 (file)
@@ -672,6 +672,7 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
        { .compatible = "allwinner,sun6i-a31-rtc" },
        { .compatible = "allwinner,sun8i-a23-rtc" },
        { .compatible = "allwinner,sun8i-h3-rtc" },
+       { .compatible = "allwinner,sun8i-r40-rtc" },
        { .compatible = "allwinner,sun8i-v3-rtc" },
        { .compatible = "allwinner,sun50i-h5-rtc" },
        { /* sentinel */ },
index f0ce76865434ac46470ae8af2af0d1c93b5beb9d..8fa1b3febf69d42ce76efa50859c67aea8f77290 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * An RTC driver for the NVIDIA Tegra 200 series internal RTC.
  *
- * Copyright (c) 2010, NVIDIA Corporation.
+ * Copyright (c) 2010-2019, NVIDIA Corporation.
  */
 
 #include <linux/clk.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 
-/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */
+/* Set to 1 = busy every eight 32 kHz clocks during copy of sec+msec to AHB. */
 #define TEGRA_RTC_REG_BUSY                     0x004
 #define TEGRA_RTC_REG_SECONDS                  0x008
-/* when msec is read, the seconds are buffered into shadow seconds. */
+/* When msec is read, the seconds are buffered into shadow seconds. */
 #define TEGRA_RTC_REG_SHADOW_SECONDS           0x00c
 #define TEGRA_RTC_REG_MILLI_SECONDS            0x010
 #define TEGRA_RTC_REG_SECONDS_ALARM0           0x014
 #define TEGRA_RTC_INTR_STATUS_SEC_ALARM0       (1<<0)
 
 struct tegra_rtc_info {
-       struct platform_device  *pdev;
-       struct rtc_device       *rtc_dev;
-       void __iomem            *rtc_base; /* NULL if not initialized. */
-       struct clk              *clk;
-       int                     tegra_rtc_irq; /* alarm and periodic irq */
-       spinlock_t              tegra_rtc_lock;
+       struct platform_device *pdev;
+       struct rtc_device *rtc;
+       void __iomem *base; /* NULL if not initialized */
+       struct clk *clk;
+       int irq; /* alarm and periodic IRQ */
+       spinlock_t lock;
 };
 
-/* RTC hardware is busy when it is updating its values over AHB once
- * every eight 32kHz clocks (~250uS).
- * outside of these updates the CPU is free to write.
- * CPU is always free to read.
+/*
+ * RTC hardware is busy when it is updating its values over AHB once every
+ * eight 32 kHz clocks (~250 us). Outside of these updates the CPU is free to
+ * write. CPU is always free to read.
  */
 static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info)
 {
-       return readl(info->rtc_base + TEGRA_RTC_REG_BUSY) & 1;
+       return readl(info->base + TEGRA_RTC_REG_BUSY) & 1;
 }
 
-/* Wait for hardware to be ready for writing.
- * This function tries to maximize the amount of time before the next update.
- * It does this by waiting for the RTC to become busy with its periodic update,
- * then returning once the RTC first becomes not busy.
+/*
+ * Wait for hardware to be ready for writing. This function tries to maximize
+ * the amount of time before the next update. It does this by waiting for the
+ * RTC to become busy with its periodic update, then returning once the RTC
+ * first becomes not busy.
+ *
  * This periodic update (where the seconds and milliseconds are copied to the
- * AHB side) occurs every eight 32kHz clocks (~250uS).
- * The behavior of this function allows us to make some assumptions without
- * introducing a race, because 250uS is plenty of time to read/write a value.
+ * AHB side) occurs every eight 32 kHz clocks (~250 us). The behavior of this
+ * function allows us to make some assumptions without introducing a race,
+ * because 250 us is plenty of time to read/write a value.
  */
 static int tegra_rtc_wait_while_busy(struct device *dev)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
+       int retries = 500; /* ~490 us is the worst case, ~250 us is best */
 
-       int retries = 500; /* ~490 us is the worst case, ~250 us is best. */
-
-       /* first wait for the RTC to become busy. this is when it
-        * posts its updated seconds+msec registers to AHB side. */
+       /*
+        * First wait for the RTC to become busy. This is when it posts its
+        * updated seconds+msec registers to AHB side.
+        */
        while (tegra_rtc_check_busy(info)) {
                if (!retries--)
                        goto retry_failed;
+
                udelay(1);
        }
 
@@ -91,28 +95,30 @@ static int tegra_rtc_wait_while_busy(struct device *dev)
        return 0;
 
 retry_failed:
-       dev_err(dev, "write failed:retry count exceeded.\n");
+       dev_err(dev, "write failed: retry count exceeded\n");
        return -ETIMEDOUT;
 }
 
 static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned long sec, msec;
-       unsigned long sl_irq_flags;
+       unsigned long flags;
+       u32 sec, msec;
 
-       /* RTC hardware copies seconds to shadow seconds when a read
-        * of milliseconds occurs. use a lock to keep other threads out. */
-       spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+       /*
+        * RTC hardware copies seconds to shadow seconds when a read of
+        * milliseconds occurs. use a lock to keep other threads out.
+        */
+       spin_lock_irqsave(&info->lock, flags);
 
-       msec = readl(info->rtc_base + TEGRA_RTC_REG_MILLI_SECONDS);
-       sec = readl(info->rtc_base + TEGRA_RTC_REG_SHADOW_SECONDS);
+       msec = readl(info->base + TEGRA_RTC_REG_MILLI_SECONDS);
+       sec = readl(info->base + TEGRA_RTC_REG_SHADOW_SECONDS);
 
-       spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+       spin_unlock_irqrestore(&info->lock, flags);
 
        rtc_time64_to_tm(sec, tm);
 
-       dev_vdbg(dev, "time read as %lu. %ptR\n", sec, tm);
+       dev_vdbg(dev, "time read as %u, %ptR\n", sec, tm);
 
        return 0;
 }
@@ -120,21 +126,21 @@ static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned long sec;
+       u32 sec;
        int ret;
 
-       /* convert tm to seconds. */
+       /* convert tm to seconds */
        sec = rtc_tm_to_time64(tm);
 
-       dev_vdbg(dev, "time set to %lu. %ptR\n", sec, tm);
+       dev_vdbg(dev, "time set to %u, %ptR\n", sec, tm);
 
-       /* seconds only written if wait succeeded. */
+       /* seconds only written if wait succeeded */
        ret = tegra_rtc_wait_while_busy(dev);
        if (!ret)
-               writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS);
+               writel(sec, info->base + TEGRA_RTC_REG_SECONDS);
 
        dev_vdbg(dev, "time read back as %d\n",
-               readl(info->rtc_base + TEGRA_RTC_REG_SECONDS));
+                readl(info->base + TEGRA_RTC_REG_SECONDS));
 
        return ret;
 }
@@ -142,22 +148,21 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned long sec;
-       unsigned tmp;
+       u32 sec, value;
 
-       sec = readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+       sec = readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
 
        if (sec == 0) {
-               /* alarm is disabled. */
+               /* alarm is disabled */
                alarm->enabled = 0;
        } else {
-               /* alarm is enabled. */
+               /* alarm is enabled */
                alarm->enabled = 1;
                rtc_time64_to_tm(sec, &alarm->time);
        }
 
-       tmp = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
-       alarm->pending = (tmp & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0;
+       value = readl(info->base + TEGRA_RTC_REG_INTR_STATUS);
+       alarm->pending = (value & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0;
 
        return 0;
 }
@@ -165,22 +170,22 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned status;
-       unsigned long sl_irq_flags;
+       unsigned long flags;
+       u32 status;
 
        tegra_rtc_wait_while_busy(dev);
-       spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+       spin_lock_irqsave(&info->lock, flags);
 
-       /* read the original value, and OR in the flag. */
-       status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+       /* read the original value, and OR in the flag */
+       status = readl(info->base + TEGRA_RTC_REG_INTR_MASK);
        if (enabled)
                status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */
        else
                status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */
 
-       writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+       writel(status, info->base + TEGRA_RTC_REG_INTR_MASK);
 
-       spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+       spin_unlock_irqrestore(&info->lock, flags);
 
        return 0;
 }
@@ -188,7 +193,7 @@ static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned long sec;
+       u32 sec;
 
        if (alarm->enabled)
                sec = rtc_tm_to_time64(&alarm->time);
@@ -196,16 +201,16 @@ static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
                sec = 0;
 
        tegra_rtc_wait_while_busy(dev);
-       writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+       writel(sec, info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
        dev_vdbg(dev, "alarm read back as %d\n",
-               readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+                readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0));
 
        /* if successfully written and alarm is enabled ... */
        if (sec) {
                tegra_rtc_alarm_irq_enable(dev, 1);
-               dev_vdbg(dev, "alarm set as %lu. %ptR\n", sec, &alarm->time);
+               dev_vdbg(dev, "alarm set as %u, %ptR\n", sec, &alarm->time);
        } else {
-               /* disable alarm if 0 or write error. */
+               /* disable alarm if 0 or write error */
                dev_vdbg(dev, "alarm disabled\n");
                tegra_rtc_alarm_irq_enable(dev, 0);
        }
@@ -227,39 +232,39 @@ static irqreturn_t tegra_rtc_irq_handler(int irq, void *data)
 {
        struct device *dev = data;
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
-       unsigned long events = 0;
-       unsigned status;
-       unsigned long sl_irq_flags;
+       unsigned long events = 0, flags;
+       u32 status;
 
-       status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+       status = readl(info->base + TEGRA_RTC_REG_INTR_STATUS);
        if (status) {
-               /* clear the interrupt masks and status on any irq. */
+               /* clear the interrupt masks and status on any IRQ */
                tegra_rtc_wait_while_busy(dev);
-               spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
-               writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
-               writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
-               spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+
+               spin_lock_irqsave(&info->lock, flags);
+               writel(0, info->base + TEGRA_RTC_REG_INTR_MASK);
+               writel(status, info->base + TEGRA_RTC_REG_INTR_STATUS);
+               spin_unlock_irqrestore(&info->lock, flags);
        }
 
-       /* check if Alarm */
-       if ((status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0))
+       /* check if alarm */
+       if (status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0)
                events |= RTC_IRQF | RTC_AF;
 
-       /* check if Periodic */
-       if ((status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM))
+       /* check if periodic */
+       if (status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM)
                events |= RTC_IRQF | RTC_PF;
 
-       rtc_update_irq(info->rtc_dev, 1, events);
+       rtc_update_irq(info->rtc, 1, events);
 
        return IRQ_HANDLED;
 }
 
 static const struct rtc_class_ops tegra_rtc_ops = {
-       .read_time      = tegra_rtc_read_time,
-       .set_time       = tegra_rtc_set_time,
-       .read_alarm     = tegra_rtc_read_alarm,
-       .set_alarm      = tegra_rtc_set_alarm,
-       .proc           = tegra_rtc_proc,
+       .read_time = tegra_rtc_read_time,
+       .set_time = tegra_rtc_set_time,
+       .read_alarm = tegra_rtc_read_alarm,
+       .set_alarm = tegra_rtc_set_alarm,
+       .proc = tegra_rtc_proc,
        .alarm_irq_enable = tegra_rtc_alarm_irq_enable,
 };
 
@@ -269,21 +274,20 @@ static const struct of_device_id tegra_rtc_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
 
-static int __init tegra_rtc_probe(struct platform_device *pdev)
+static int tegra_rtc_probe(struct platform_device *pdev)
 {
        struct tegra_rtc_info *info;
        struct resource *res;
        int ret;
 
-       info = devm_kzalloc(&pdev->dev, sizeof(struct tegra_rtc_info),
-               GFP_KERNEL);
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       info->rtc_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(info->rtc_base))
-               return PTR_ERR(info->rtc_base);
+       info->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(info->base))
+               return PTR_ERR(info->base);
 
        ret = platform_get_irq(pdev, 0);
        if (ret <= 0) {
@@ -291,14 +295,14 @@ static int __init tegra_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       info->tegra_rtc_irq = ret;
+       info->irq = ret;
 
-       info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
-       if (IS_ERR(info->rtc_dev))
-               return PTR_ERR(info->rtc_dev);
+       info->rtc = devm_rtc_allocate_device(&pdev->dev);
+       if (IS_ERR(info->rtc))
+               return PTR_ERR(info->rtc);
 
-       info->rtc_dev->ops = &tegra_rtc_ops;
-       info->rtc_dev->range_max = U32_MAX;
+       info->rtc->ops = &tegra_rtc_ops;
+       info->rtc->range_max = U32_MAX;
 
        info->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(info->clk))
@@ -308,33 +312,30 @@ static int __init tegra_rtc_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       /* set context info. */
+       /* set context info */
        info->pdev = pdev;
-       spin_lock_init(&info->tegra_rtc_lock);
+       spin_lock_init(&info->lock);
 
        platform_set_drvdata(pdev, info);
 
-       /* clear out the hardware. */
-       writel(0, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
-       writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
-       writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+       /* clear out the hardware */
+       writel(0, info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
+       writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS);
+       writel(0, info->base + TEGRA_RTC_REG_INTR_MASK);
 
        device_init_wakeup(&pdev->dev, 1);
 
-       ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
-                       tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH,
-                       dev_name(&pdev->dev), &pdev->dev);
+       ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler,
+                              IRQF_TRIGGER_HIGH, dev_name(&pdev->dev),
+                              &pdev->dev);
        if (ret) {
-               dev_err(&pdev->dev,
-                       "Unable to request interrupt for device (err=%d).\n",
-                       ret);
+               dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret);
                goto disable_clk;
        }
 
-       ret = rtc_register_device(info->rtc_dev);
+       ret = rtc_register_device(info->rtc);
        if (ret) {
-               dev_err(&pdev->dev, "Unable to register device (err=%d).\n",
-                       ret);
+               dev_err(&pdev->dev, "failed to register device: %d\n", ret);
                goto disable_clk;
        }
 
@@ -363,20 +364,20 @@ static int tegra_rtc_suspend(struct device *dev)
 
        tegra_rtc_wait_while_busy(dev);
 
-       /* only use ALARM0 as a wake source. */
-       writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+       /* only use ALARM0 as a wake source */
+       writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS);
        writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0,
-               info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+              info->base + TEGRA_RTC_REG_INTR_MASK);
 
        dev_vdbg(dev, "alarm sec = %d\n",
-               readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+                readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0));
 
-       dev_vdbg(dev, "Suspend (device_may_wakeup=%d) irq:%d\n",
-               device_may_wakeup(dev), info->tegra_rtc_irq);
+       dev_vdbg(dev, "Suspend (device_may_wakeup=%d) IRQ:%d\n",
+                device_may_wakeup(dev), info->irq);
 
-       /* leave the alarms on as a wake source. */
+       /* leave the alarms on as a wake source */
        if (device_may_wakeup(dev))
-               enable_irq_wake(info->tegra_rtc_irq);
+               enable_irq_wake(info->irq);
 
        return 0;
 }
@@ -386,10 +387,11 @@ static int tegra_rtc_resume(struct device *dev)
        struct tegra_rtc_info *info = dev_get_drvdata(dev);
 
        dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n",
-               device_may_wakeup(dev));
-       /* alarms were left on as a wake source, turn them off. */
+                device_may_wakeup(dev));
+
+       /* alarms were left on as a wake source, turn them off */
        if (device_may_wakeup(dev))
-               disable_irq_wake(info->tegra_rtc_irq);
+               disable_irq_wake(info->irq);
 
        return 0;
 }
@@ -399,22 +401,21 @@ static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
 
 static void tegra_rtc_shutdown(struct platform_device *pdev)
 {
-       dev_vdbg(&pdev->dev, "disabling interrupts.\n");
+       dev_vdbg(&pdev->dev, "disabling interrupts\n");
        tegra_rtc_alarm_irq_enable(&pdev->dev, 0);
 }
 
-MODULE_ALIAS("platform:tegra_rtc");
 static struct platform_driver tegra_rtc_driver = {
-       .remove         = tegra_rtc_remove,
-       .shutdown       = tegra_rtc_shutdown,
-       .driver         = {
-               .name   = "tegra_rtc",
+       .probe = tegra_rtc_probe,
+       .remove = tegra_rtc_remove,
+       .shutdown = tegra_rtc_shutdown,
+       .driver = {
+               .name = "tegra_rtc",
                .of_match_table = tegra_rtc_dt_match,
-               .pm     = &tegra_rtc_pm_ops,
+               .pm = &tegra_rtc_pm_ops,
        },
 };
-
-module_platform_driver_probe(tegra_rtc_driver, tegra_rtc_probe);
+module_platform_driver(tegra_rtc_driver);
 
 MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>");
 MODULE_DESCRIPTION("driver for Tegra internal RTC");
index b298e9902f45bedb218581a264798a8440f93bab..74b3a0603b738df99e552ede729534e9625ed76d 100644 (file)
@@ -133,6 +133,7 @@ static int test_probe(struct platform_device *plat_dev)
                break;
        default:
                rtd->rtc->ops = &test_rtc_ops;
+               device_init_wakeup(&plat_dev->dev, 1);
        }
 
        timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0);
index 8556d925e52a4d7adaf6affe30342e080f2d4517..7078f6da1cbcf507532835bd1f5f04dad7948ebd 100644 (file)
@@ -143,7 +143,7 @@ static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        struct tps65910 *tps = dev_get_drvdata(dev->parent);
        int ret;
 
-       ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data,
+       ret = regmap_bulk_read(tps->regmap, TPS65910_ALARM_SECONDS, alarm_data,
                NUM_TIME_REGS);
        if (ret < 0) {
                dev_err(dev, "rtc_read_alarm error %d\n", ret);
index d2e8b21c90c40e7e76e93cbd59521add4811a307..ccef887d2690112f736365912993a02de8b6938a 100644 (file)
@@ -435,7 +435,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL,
                                wm831x_alm_irq,
-                               IRQF_TRIGGER_RISING, "RTC alarm",
+                               IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                               "RTC alarm",
                                wm831x_rtc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",