Merge tag 'rtc-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Aug 2022 01:17:42 +0000 (18:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Aug 2022 01:17:42 +0000 (18:17 -0700)
Pull RTC updates from Alexandre Belloni:
 "New drivers:
   - Microchip PolarFire
   - Nuvoton NCT3018Y
   - TI K3 RTC

  Subsystem:
   - Replace flush_scheduled_work() with flush_work()
   - Remove deprecated ida_simple_get()/ida_simple_remove() calls

  Drivers:
   - use simple i2c probe where possible
   - sun6i: add R329 support
   - zynqmp: add calibration support
   - vr41xx: remove unused driver"

* tag 'rtc-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (31 commits)
  rtc: spear: set range max
  rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0
  rtc: zynqmp: initialize fract_tick
  rtc: Add NCT3018Y real time clock driver
  dt-bindings: rtc: nuvoton: add NCT3018Y Real Time Clock
  dt-bindings: rtc: nxp,pcf85063: Convert to DT schema
  dt-bindings: rtc: microcrystal,rv3032: Add missing type to 'trickle-voltage-millivolt'
  rtc: rx8025: fix 12/24 hour mode detection on RX-8035
  rtc: cros-ec: Only warn once in .remove() about notifier_chain problems
  rtc: vr41xx: remove driver
  rtc: mpfs: remove 'pending' variable from mpfs_rtc_wakeup_irq_handler()
  rtc: rv8803: fix missing unlock on error in rv8803_set_time()
  rtc: zynqmp: Add calibration set and get support
  rtc: zynqmp: Updated calibration value
  dt-bindings: rtc: zynqmp: Add clock information
  rtc: sun6i: add support for R329 RTC
  rtc: Directly use ida_alloc()/free()
  rtc: Introduce ti-k3-rtc
  dt-bindings: rtc: Add TI K3 RTC description
  dt-bindings: rtc: qcom-pm8xxx-rtc: Update the maintainers section
  ...

48 files changed:
Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt [deleted file]
Documentation/devicetree/bindings/rtc/nxp,pcf85063.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml
Documentation/devicetree/bindings/rtc/rtc-mt6397.txt
Documentation/devicetree/bindings/rtc/ti,k3-rtc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/xlnx,zynqmp-rtc.yaml
MAINTAINERS
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/dev.c
drivers/rtc/rtc-ab-b5ze-s3.c
drivers/rtc/rtc-ab-eoz9.c
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-core.h
drivers/rtc/rtc-cros-ec.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-em3027.c
drivers/rtc/rtc-fm3130.c
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-isl12022.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-max6900.c
drivers/rtc/rtc-mc146818-lib.c
drivers/rtc/rtc-mpfs.c [new file with mode: 0644]
drivers/rtc/rtc-nct3018y.c [new file with mode: 0644]
drivers/rtc/rtc-pcf8523.c
drivers/rtc/rtc-pcf85363.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx6110.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-rx8581.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-sd3078.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-sun6i.c
drivers/rtc/rtc-ti-k3.c [new file with mode: 0644]
drivers/rtc/rtc-vr41xx.c [deleted file]
drivers/rtc/rtc-x1205.c
drivers/rtc/rtc-zynqmp.c

index 9593840..60f9027 100644 (file)
@@ -32,6 +32,7 @@ properties:
       - 11000
 
   trickle-voltage-millivolt:
+    $ref: /schemas/types.yaml#/definitions/uint32
     enum:
       - 1750
       - 3000
diff --git a/Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml b/Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml
new file mode 100644 (file)
index 0000000..7a1857f
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/nuvoton,nct3018y.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NUVOTON NCT3018Y Real Time Clock
+
+allOf:
+  - $ref: "rtc.yaml#"
+
+maintainers:
+  - Medad CChien <ctcchien@nuvoton.com>
+  - Mia Lin <mimi05633@gmail.com>
+
+properties:
+  compatible:
+    const: nuvoton,nct3018y
+
+  reg:
+    maxItems: 1
+
+  start-year: true
+
+  reset-source: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        rtc@6f {
+            compatible = "nuvoton,nct3018y";
+            reg = <0x6f>;
+        };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.txt
deleted file mode 100644 (file)
index 217b7cd..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-* NXP PCF85063 Real Time Clock
-
-Required properties:
-- compatible: Should one of contain:
-       "nxp,pca85073a",
-       "nxp,pcf85063",
-       "nxp,pcf85063a",
-       "nxp,pcf85063tp",
-       "microcrystal,rv8263"
-- reg: I2C address for chip.
-
-Optional property:
-- quartz-load-femtofarads: The capacitive load of the quartz(x-tal),
-  expressed in femto Farad (fF). Valid values are 7000 and 12500.
-  Default value (if no value is specified) is 7000fF.
-
-Optional child node:
-- clock: Provide this if the square wave pin is used as boot-enabled fixed clock.
-
-Example:
-
-pcf85063: rtc@51 {
-       compatible = "nxp,pcf85063";
-       reg = <0x51>;
-       quartz-load-femtofarads = <12500>;
-
-               clock {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <32768>;
-               };
-};
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf85063.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf85063.yaml
new file mode 100644 (file)
index 0000000..2f892f8
--- /dev/null
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/nxp,pcf85063.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCF85063 Real Time Clock
+
+maintainers:
+  - Alexander Stein <alexander.stein@ew.tq-group.com>
+
+properties:
+  compatible:
+    enum:
+      - microcrystal,rv8263
+      - nxp,pcf85063
+      - nxp,pcf85063a
+      - nxp,pcf85063tp
+      - nxp,pca85073a
+
+  reg:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 0
+
+  clock-output-names:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  quartz-load-femtofarads:
+    description:
+      The capacitive load of the quartz(x-tal).
+    enum: [7000, 12500]
+    default: 7000
+
+  clock:
+    $ref: /schemas/clock/fixed-clock.yaml
+    description:
+      Provide this if the square wave pin is used as boot-enabled
+      fixed clock.
+
+  wakeup-source: true
+
+allOf:
+  - $ref: rtc.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - microcrystal,rv8263
+    then:
+      properties:
+        quartz-load-femtofarads: false
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - nxp,pcf85063
+    then:
+      properties:
+        quartz-load-femtofarads:
+          const: 7000
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        rtc@51 {
+          compatible = "nxp,pcf85063a";
+          reg = <0x51>;
+          quartz-load-femtofarads = <12500>;
+
+          clock {
+            compatible = "fixed-clock";
+            #clock-cells = <0>;
+            clock-frequency = <32768>;
+          };
+        };
+      };
index 6fa7d9f..23ab5bb 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Qualcomm PM8xxx PMIC RTC device
 
 maintainers:
-  - Satya Priya <skakit@codeaurora.org>
+  - Satya Priya <quic_c_skakit@quicinc.com>
 
 properties:
   compatible:
index 55a0c88..7212076 100644 (file)
@@ -14,6 +14,8 @@ For MediaTek PMIC wrapper bus bindings, see:
 Required properties:
 - compatible: Should be one of follows
        "mediatek,mt6323-rtc": for MT6323 PMIC
+       "mediatek,mt6358-rtc": for MT6358 PMIC
+       "mediatek,mt6366-rtc", "mediatek,mt6358-rtc": for MT6366 PMIC
        "mediatek,mt6397-rtc": for MT6397 PMIC
 
 Example:
diff --git a/Documentation/devicetree/bindings/rtc/ti,k3-rtc.yaml b/Documentation/devicetree/bindings/rtc/ti,k3-rtc.yaml
new file mode 100644 (file)
index 0000000..d995ef0
--- /dev/null
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/ti,k3-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments K3 Real Time Clock
+
+maintainers:
+  - Nishanth Menon <nm@ti.com>
+
+description: |
+  This RTC appears in the AM62x family of SoCs.
+
+allOf:
+  - $ref: "rtc.yaml#"
+
+properties:
+  compatible:
+    enum:
+      - ti,am62-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: VBUS Interface clock
+      - description: 32k Clock source (external or internal).
+
+  clock-names:
+    items:
+      - const: vbus
+      - const: osc32k
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    rtc@2b1f0000 {
+        compatible = "ti,am62-rtc";
+        reg = <0x2b1f0000 0x100>;
+        interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&bar 0>;
+        clocks = <&foo 0>, <&foo 1>;
+        clock-names = "vbus", "osc32k";
+        wakeup-source;
+    };
index bdb72d3..7ed0230 100644 (file)
@@ -23,8 +23,15 @@ properties:
   reg:
     maxItems: 1
 
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: rtc
+
   interrupts:
-    minItems: 2
+    maxItems: 2
 
   interrupt-names:
     items:
@@ -39,6 +46,7 @@ properties:
     minimum: 0x1
     maximum: 0x1FFFFF
     default: 0x198233
+    deprecated: true
 
 required:
   - compatible
@@ -61,5 +69,7 @@ examples:
         interrupts = <0 26 4>, <0 27 4>;
         interrupt-names = "alarm", "sec";
         calibration = <0x198233>;
+        clock-names = "rtc";
+        clocks = <&rtc_clk>;
       };
     };
index 08a5d70..80e4f67 100644 (file)
@@ -2486,11 +2486,13 @@ S:      Supported
 F:     Documentation/devicetree/bindings/*/*/*npcm*
 F:     Documentation/devicetree/bindings/*/*npcm*
 F:     Documentation/devicetree/bindings/arm/npcm/*
+F:     Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml
 F:     arch/arm/boot/dts/nuvoton-npcm*
 F:     arch/arm/mach-npcm/
 F:     arch/arm64/boot/dts/nuvoton/
 F:     drivers/*/*npcm*
 F:     drivers/*/*/*npcm*
+F:     drivers/rtc/rtc-nct3018y.c
 F:     include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
 F:     include/dt-bindings/clock/nuvoton,npcm845-clk.h
 
@@ -17529,6 +17531,7 @@ F:      drivers/char/hw_random/mpfs-rng.c
 F:     drivers/clk/microchip/clk-mpfs.c
 F:     drivers/mailbox/mailbox-mpfs.c
 F:     drivers/pci/controller/pcie-microchip-host.c
+F:     drivers/rtc/rtc-mpfs.c
 F:     drivers/soc/microchip/
 F:     drivers/spi/spi-microchip-core.c
 F:     drivers/usb/musb/mpfs.c
index a00f901..b8de251 100644 (file)
@@ -383,6 +383,16 @@ config RTC_DRV_MAX77686
          This driver can also be built as a module. If so, the module
          will be called rtc-max77686.
 
+config RTC_DRV_NCT3018Y
+       tristate "Nuvoton NCT3018Y"
+       depends on OF
+       help
+          If you say yes here you get support for the Nuvoton NCT3018Y I2C RTC
+          chip.
+
+          This driver can also be built as a module, if so, the module will be
+          called "rtc-nct3018y".
+
 config RTC_DRV_RK808
        tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
        depends on MFD_RK808
@@ -1478,16 +1488,6 @@ config RTC_DRV_SUNPLUS
          This driver can also be built as a module. If so, the module
          will be called rtc-sunplus.
 
-config RTC_DRV_VR41XX
-       tristate "NEC VR41XX"
-       depends on CPU_VR41XX || COMPILE_TEST
-       help
-         If you say Y here you will get access to the real time clock
-         built into your NEC VR41XX CPU.
-
-         To compile this driver as a module, choose M here: the
-         module will be called rtc-vr41xx.
-
 config RTC_DRV_PL030
        tristate "ARM AMBA PL030 RTC"
        depends on ARM_AMBA
@@ -1929,6 +1929,17 @@ config RTC_DRV_ASPEED
          This driver can also be built as a module, if so, the module
          will be called "rtc-aspeed".
 
+config RTC_DRV_TI_K3
+       tristate "TI K3 RTC"
+       depends on ARCH_K3 || COMPILE_TEST
+       select REGMAP_MMIO
+       help
+         If you say yes here you get support for the Texas Instruments's
+         Real Time Clock for K3 architecture.
+
+         This driver can also be built as a module, if so, the module
+         will be called "rtc-ti-k3".
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
@@ -1973,4 +1984,14 @@ config RTC_DRV_MSC313
          This driver can also be built as a module, if so, the module
          will be called "rtc-msc313".
 
+config RTC_DRV_POLARFIRE_SOC
+       tristate "Microchip PolarFire SoC built-in RTC"
+       depends on SOC_MICROCHIP_POLARFIRE
+       help
+         If you say yes here you will get support for the
+         built-in RTC on Polarfire SoC.
+
+         This driver can also be built as a module, if so, the module
+         will be called "rtc-mpfs".
+
 endif # RTC_CLASS
index fb04467..aab22bc 100644 (file)
@@ -112,6 +112,7 @@ obj-$(CONFIG_RTC_DRV_MV)    += rtc-mv.o
 obj-$(CONFIG_RTC_DRV_MXC)      += rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_MXC_V2)   += rtc-mxc_v2.o
 obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o
+obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
 obj-$(CONFIG_RTC_DRV_NTXEC)    += rtc-ntxec.o
 obj-$(CONFIG_RTC_DRV_OMAP)     += rtc-omap.o
 obj-$(CONFIG_RTC_DRV_OPAL)     += rtc-opal.o
@@ -130,6 +131,7 @@ obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o
 obj-$(CONFIG_RTC_DRV_PL030)    += rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)    += rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)   += rtc-pm8xxx.o
+obj-$(CONFIG_RTC_DRV_POLARFIRE_SOC)    += rtc-mpfs.o
 obj-$(CONFIG_RTC_DRV_PS3)      += rtc-ps3.o
 obj-$(CONFIG_RTC_DRV_PXA)      += rtc-pxa.o
 obj-$(CONFIG_RTC_DRV_R7301)    += rtc-r7301.o
@@ -172,11 +174,11 @@ obj-$(CONFIG_RTC_DRV_SUNPLUS)     += rtc-sunplus.o
 obj-$(CONFIG_RTC_DRV_SUNXI)    += rtc-sunxi.o
 obj-$(CONFIG_RTC_DRV_TEGRA)    += rtc-tegra.o
 obj-$(CONFIG_RTC_DRV_TEST)     += rtc-test.o
+obj-$(CONFIG_RTC_DRV_TI_K3)    += rtc-ti-k3.o
 obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
 obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
 obj-$(CONFIG_RTC_DRV_TWL4030)  += rtc-twl.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
-obj-$(CONFIG_RTC_DRV_VR41XX)   += rtc-vr41xx.o
 obj-$(CONFIG_RTC_DRV_VT8500)   += rtc-vt8500.o
 obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o
 obj-$(CONFIG_RTC_DRV_WM831X)   += rtc-wm831x.o
index 3c8eec2..e48223c 100644 (file)
@@ -36,7 +36,7 @@ static void rtc_device_release(struct device *dev)
 
        cancel_work_sync(&rtc->irqwork);
 
-       ida_simple_remove(&rtc_ida, rtc->id);
+       ida_free(&rtc_ida, rtc->id);
        mutex_destroy(&rtc->ops_lock);
        kfree(rtc);
 }
@@ -262,7 +262,7 @@ static int rtc_device_get_id(struct device *dev)
        }
 
        if (id < 0)
-               id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
+               id = ida_alloc(&rtc_ida, GFP_KERNEL);
 
        return id;
 }
@@ -368,7 +368,7 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
 
        rtc = rtc_allocate_device();
        if (!rtc) {
-               ida_simple_remove(&rtc_ida, id);
+               ida_free(&rtc_ida, id);
                return ERR_PTR(-ENOMEM);
        }
 
index 69325ae..4aad9bb 100644 (file)
@@ -96,7 +96,7 @@ static int clear_uie(struct rtc_device *rtc)
                }
                if (rtc->uie_task_active) {
                        spin_unlock_irq(&rtc->irq_lock);
-                       flush_scheduled_work();
+                       flush_work(&rtc->uie_task);
                        spin_lock_irq(&rtc->irq_lock);
                }
                rtc->uie_irq_active = 0;
@@ -566,9 +566,3 @@ void __init rtc_dev_init(void)
        if (err < 0)
                pr_err("failed to allocate char dev region\n");
 }
-
-void __exit rtc_dev_exit(void)
-{
-       if (rtc_devt)
-               unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
-}
index 6e3e320..f2b0971 100644 (file)
@@ -817,8 +817,7 @@ static const struct regmap_config abb5zes3_rtc_regmap_config = {
        .val_bits = 8,
 };
 
-static int abb5zes3_probe(struct i2c_client *client,
-                         const struct i2c_device_id *id)
+static int abb5zes3_probe(struct i2c_client *client)
 {
        struct abb5zes3_rtc_data *data = NULL;
        struct device *dev = &client->dev;
@@ -945,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = {
                .pm = &abb5zes3_rtc_pm_ops,
                .of_match_table = of_match_ptr(abb5zes3_dt_match),
        },
-       .probe    = abb5zes3_probe,
+       .probe_new = abb5zes3_probe,
        .id_table = abb5zes3_id,
 };
 module_i2c_driver(abb5zes3_driver);
index e188ab5..2f8deb8 100644 (file)
@@ -495,8 +495,7 @@ static void abeoz9_hwmon_register(struct device *dev,
 
 #endif
 
-static int abeoz9_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int abeoz9_probe(struct i2c_client *client)
 {
        struct abeoz9_rtc_data *data = NULL;
        struct device *dev = &client->dev;
@@ -580,7 +579,7 @@ static struct i2c_driver abeoz9_driver = {
                .name = "rtc-ab-eoz9",
                .of_match_table = of_match_ptr(abeoz9_dt_match),
        },
-       .probe    = abeoz9_probe,
+       .probe_new = abeoz9_probe,
        .id_table = abeoz9_id,
 };
 
index 2235c96..e0bbb11 100644 (file)
@@ -249,8 +249,7 @@ static void bq32k_sysfs_unregister(struct device *dev)
        device_remove_file(dev, &dev_attr_trickle_charge_bypass);
 }
 
-static int bq32k_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int bq32k_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
        struct rtc_device *rtc;
@@ -322,7 +321,7 @@ static struct i2c_driver bq32k_driver = {
                .name   = "bq32k",
                .of_match_table = of_match_ptr(bq32k_of_match),
        },
-       .probe          = bq32k_probe,
+       .probe_new      = bq32k_probe,
        .remove         = bq32k_remove,
        .id_table       = bq32k_id,
 };
index 7c006c2..bdb1df8 100644 (file)
@@ -1260,9 +1260,6 @@ static void use_acpi_alarm_quirks(void)
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return;
 
-       if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
-               return;
-
        if (!is_hpet_enabled())
                return;
 
index 0abf989..4b10a1b 100644 (file)
@@ -2,7 +2,6 @@
 #ifdef CONFIG_RTC_INTF_DEV
 
 extern void __init rtc_dev_init(void);
-extern void __exit rtc_dev_exit(void);
 extern void rtc_dev_prepare(struct rtc_device *rtc);
 
 #else
@@ -11,10 +10,6 @@ static inline void rtc_dev_init(void)
 {
 }
 
-static inline void rtc_dev_exit(void)
-{
-}
-
 static inline void rtc_dev_prepare(struct rtc_device *rtc)
 {
 }
index 7062679..887f519 100644 (file)
@@ -375,10 +375,8 @@ static int cros_ec_rtc_remove(struct platform_device *pdev)
        ret = blocking_notifier_chain_unregister(
                                &cros_ec_rtc->cros_ec->event_notifier,
                                &cros_ec_rtc->notifier);
-       if (ret) {
+       if (ret)
                dev_err(dev, "failed to unregister notifier\n");
-               return ret;
-       }
 
        return 0;
 }
index 8db5a63..b19de51 100644 (file)
@@ -467,8 +467,7 @@ static const struct watchdog_ops ds1374_wdt_ops = {
  *
  *****************************************************************************
  */
-static int ds1374_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int ds1374_probe(struct i2c_client *client)
 {
        struct ds1374 *ds1374;
        int ret;
@@ -575,7 +574,7 @@ static struct i2c_driver ds1374_driver = {
                .of_match_table = of_match_ptr(ds1374_of_match),
                .pm = &ds1374_pm,
        },
-       .probe = ds1374_probe,
+       .probe_new = ds1374_probe,
        .remove = ds1374_remove,
        .id_table = ds1374_id,
 };
index 4cd8efb..a3bb2cd 100644 (file)
@@ -106,8 +106,7 @@ static const struct rtc_class_ops ds1672_rtc_ops = {
        .set_time = ds1672_set_time,
 };
 
-static int ds1672_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int ds1672_probe(struct i2c_client *client)
 {
        int err = 0;
        struct rtc_device *rtc;
@@ -150,7 +149,7 @@ static struct i2c_driver ds1672_driver = {
                   .name = "rtc-ds1672",
                   .of_match_table = of_match_ptr(ds1672_of_match),
        },
-       .probe = &ds1672_probe,
+       .probe_new = ds1672_probe,
        .id_table = ds1672_id,
 };
 
index 168bc27..dd31a60 100644 (file)
@@ -566,8 +566,7 @@ static const struct dev_pm_ops ds3232_pm_ops = {
 
 #if IS_ENABLED(CONFIG_I2C)
 
-static int ds3232_i2c_probe(struct i2c_client *client,
-                           const struct i2c_device_id *id)
+static int ds3232_i2c_probe(struct i2c_client *client)
 {
        struct regmap *regmap;
        static const struct regmap_config config = {
@@ -604,7 +603,7 @@ static struct i2c_driver ds3232_driver = {
                .of_match_table = of_match_ptr(ds3232_of_match),
                .pm     = &ds3232_pm_ops,
        },
-       .probe = ds3232_i2c_probe,
+       .probe_new = ds3232_i2c_probe,
        .id_table = ds3232_id,
 };
 
index 9f176bc..53f9f93 100644 (file)
@@ -111,8 +111,7 @@ static const struct rtc_class_ops em3027_rtc_ops = {
        .set_time = em3027_set_time,
 };
 
-static int em3027_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int em3027_probe(struct i2c_client *client)
 {
        struct rtc_device *rtc;
 
@@ -148,7 +147,7 @@ static struct i2c_driver em3027_driver = {
                   .name = "rtc-em3027",
                   .of_match_table = of_match_ptr(em3027_of_match),
        },
-       .probe = &em3027_probe,
+       .probe_new = em3027_probe,
        .id_table = em3027_id,
 };
 
index 677ec2d..f59bb81 100644 (file)
@@ -340,8 +340,7 @@ static const struct rtc_class_ops fm3130_rtc_ops = {
 
 static struct i2c_driver fm3130_driver;
 
-static int fm3130_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int fm3130_probe(struct i2c_client *client)
 {
        struct fm3130           *fm3130;
        int                     err = -ENODEV;
@@ -518,7 +517,7 @@ static struct i2c_driver fm3130_driver = {
        .driver = {
                .name   = "rtc-fm3130",
        },
-       .probe          = fm3130_probe,
+       .probe_new      = fm3130_probe,
        .id_table       = fm3130_id,
 };
 
index 90e602e..cc710d6 100644 (file)
@@ -495,8 +495,7 @@ static int hym8563_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
 
-static int hym8563_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int hym8563_probe(struct i2c_client *client)
 {
        struct hym8563 *hym8563;
        int ret;
@@ -572,7 +571,7 @@ static struct i2c_driver hym8563_driver = {
                .pm     = &hym8563_pm_ops,
                .of_match_table = hym8563_dt_idtable,
        },
-       .probe          = hym8563_probe,
+       .probe_new      = hym8563_probe,
        .id_table       = hym8563_id,
 };
 
index 961bd5d..79461de 100644 (file)
@@ -232,8 +232,7 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
        .set_time       = isl12022_rtc_set_time,
 };
 
-static int isl12022_probe(struct i2c_client *client,
-                         const struct i2c_device_id *id)
+static int isl12022_probe(struct i2c_client *client)
 {
        struct isl12022 *isl12022;
 
@@ -275,7 +274,7 @@ static struct i2c_driver isl12022_driver = {
                .of_match_table = of_match_ptr(isl12022_dt_match),
 #endif
        },
-       .probe          = isl12022_probe,
+       .probe_new      = isl12022_probe,
        .id_table       = isl12022_id,
 };
 
index 182dfa6..f448a52 100644 (file)
@@ -880,10 +880,14 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (rc)
                return rc;
 
-       if (client->irq > 0)
+       if (client->irq > 0) {
                rc = isl1208_setup_irq(client, client->irq);
-       if (rc)
-               return rc;
+               if (rc)
+                       return rc;
+
+       } else {
+               clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, isl1208->rtc->features);
+       }
 
        if (evdet_irq > 0 && evdet_irq != client->irq)
                rc = isl1208_setup_irq(client, evdet_irq);
index 4beadfa..0a33851 100644 (file)
@@ -197,8 +197,7 @@ static const struct rtc_class_ops max6900_rtc_ops = {
        .set_time = max6900_rtc_set_time,
 };
 
-static int
-max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int max6900_probe(struct i2c_client *client)
 {
        struct rtc_device *rtc;
 
@@ -225,7 +224,7 @@ static struct i2c_driver max6900_driver = {
        .driver = {
                   .name = "rtc-max6900",
                   },
-       .probe = max6900_probe,
+       .probe_new = max6900_probe,
        .id_table = max6900_id,
 };
 
index 522449b..f1c09f1 100644 (file)
@@ -21,13 +21,13 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
        unsigned long flags;
        unsigned char seconds;
 
-       for (i = 0; i < 10; i++) {
+       for (i = 0; i < 100; i++) {
                spin_lock_irqsave(&rtc_lock, flags);
 
                /*
                 * Check whether there is an update in progress during which the
                 * readout is unspecified. The maximum update time is ~2ms. Poll
-                * every msec for completion.
+                * every 100 usec for completion.
                 *
                 * Store the second value before checking UIP so a long lasting
                 * NMI which happens to hit after the UIP check cannot make
@@ -37,7 +37,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
 
                if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
                        spin_unlock_irqrestore(&rtc_lock, flags);
-                       mdelay(1);
+                       udelay(100);
                        continue;
                }
 
@@ -56,7 +56,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
                 */
                if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
                        spin_unlock_irqrestore(&rtc_lock, flags);
-                       mdelay(1);
+                       udelay(100);
                        continue;
                }
 
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
new file mode 100644 (file)
index 0000000..f14d192
--- /dev/null
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip MPFS RTC driver
+ *
+ * Copyright (c) 2021-2022 Microchip Corporation. All rights reserved.
+ *
+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
+ *         & Conor Dooley <conor.dooley@microchip.com>
+ */
+#include "linux/bits.h"
+#include "linux/iopoll.h"
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/slab.h>
+#include <linux/rtc.h>
+
+#define CONTROL_REG            0x00
+#define MODE_REG               0x04
+#define PRESCALER_REG          0x08
+#define ALARM_LOWER_REG                0x0c
+#define ALARM_UPPER_REG                0x10
+#define COMPARE_LOWER_REG      0x14
+#define COMPARE_UPPER_REG      0x18
+#define DATETIME_LOWER_REG     0x20
+#define DATETIME_UPPER_REG     0x24
+
+#define CONTROL_RUNNING_BIT    BIT(0)
+#define CONTROL_START_BIT      BIT(0)
+#define CONTROL_STOP_BIT       BIT(1)
+#define CONTROL_ALARM_ON_BIT   BIT(2)
+#define CONTROL_ALARM_OFF_BIT  BIT(3)
+#define CONTROL_RESET_BIT      BIT(4)
+#define CONTROL_UPLOAD_BIT     BIT(5)
+#define CONTROL_DOWNLOAD_BIT   BIT(6)
+#define CONTROL_MATCH_BIT      BIT(7)
+#define CONTROL_WAKEUP_CLR_BIT BIT(8)
+#define CONTROL_WAKEUP_SET_BIT BIT(9)
+#define CONTROL_UPDATED_BIT    BIT(10)
+
+#define MODE_CLOCK_CALENDAR    BIT(0)
+#define MODE_WAKE_EN           BIT(1)
+#define MODE_WAKE_RESET                BIT(2)
+#define MODE_WAKE_CONTINUE     BIT(3)
+
+#define MAX_PRESCALER_COUNT    GENMASK(25, 0)
+#define DATETIME_UPPER_MASK    GENMASK(29, 0)
+#define ALARM_UPPER_MASK       GENMASK(10, 0)
+
+#define UPLOAD_TIMEOUT_US      50
+
+struct mpfs_rtc_dev {
+       struct rtc_device *rtc;
+       void __iomem *base;
+};
+
+static void mpfs_rtc_start(struct mpfs_rtc_dev *rtcdev)
+{
+       u32 ctrl;
+
+       ctrl = readl(rtcdev->base + CONTROL_REG);
+       ctrl &= ~CONTROL_STOP_BIT;
+       ctrl |= CONTROL_START_BIT;
+       writel(ctrl, rtcdev->base + CONTROL_REG);
+}
+
+static void mpfs_rtc_clear_irq(struct mpfs_rtc_dev *rtcdev)
+{
+       u32 val = readl(rtcdev->base + CONTROL_REG);
+
+       val &= ~(CONTROL_ALARM_ON_BIT | CONTROL_STOP_BIT);
+       val |= CONTROL_ALARM_OFF_BIT;
+       writel(val, rtcdev->base + CONTROL_REG);
+       /*
+        * Ensure that the posted write to the CONTROL_REG register completed before
+        * returning from this function. Not doing this may result in the interrupt
+        * only being cleared some time after this function returns.
+        */
+       (void)readl(rtcdev->base + CONTROL_REG);
+}
+
+static int mpfs_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+       struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+       u64 time;
+
+       time = readl(rtcdev->base + DATETIME_LOWER_REG);
+       time |= ((u64)readl(rtcdev->base + DATETIME_UPPER_REG) & DATETIME_UPPER_MASK) << 32;
+       rtc_time64_to_tm(time, tm);
+
+       return 0;
+}
+
+static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+       struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+       u32 ctrl, prog;
+       u64 time;
+       int ret;
+
+       time = rtc_tm_to_time64(tm);
+
+       writel((u32)time, rtcdev->base + DATETIME_LOWER_REG);
+       writel((u32)(time >> 32) & DATETIME_UPPER_MASK, rtcdev->base + DATETIME_UPPER_REG);
+
+       ctrl = readl(rtcdev->base + CONTROL_REG);
+       ctrl &= ~CONTROL_STOP_BIT;
+       ctrl |= CONTROL_UPLOAD_BIT;
+       writel(ctrl, rtcdev->base + CONTROL_REG);
+
+       ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US,
+                               false, rtcdev->base + CONTROL_REG);
+       if (ret) {
+               dev_err(dev, "timed out uploading time to rtc");
+               return ret;
+       }
+       mpfs_rtc_start(rtcdev);
+
+       return 0;
+}
+
+static int mpfs_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+       u32 mode = readl(rtcdev->base + MODE_REG);
+       u64 time;
+
+       alrm->enabled = mode & MODE_WAKE_EN;
+
+       time = (u64)readl(rtcdev->base + ALARM_LOWER_REG) << 32;
+       time |= (readl(rtcdev->base + ALARM_UPPER_REG) & ALARM_UPPER_MASK);
+       rtc_time64_to_tm(time, &alrm->time);
+
+       return 0;
+}
+
+static int mpfs_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+       u32 mode, ctrl;
+       u64 time;
+
+       /* Disable the alarm before updating */
+       ctrl = readl(rtcdev->base + CONTROL_REG);
+       ctrl |= CONTROL_ALARM_OFF_BIT;
+       writel(ctrl, rtcdev->base + CONTROL_REG);
+
+       time = rtc_tm_to_time64(&alrm->time);
+
+       writel((u32)time, rtcdev->base + ALARM_LOWER_REG);
+       writel((u32)(time >> 32) & ALARM_UPPER_MASK, rtcdev->base + ALARM_UPPER_REG);
+
+       /* Bypass compare register in alarm mode */
+       writel(GENMASK(31, 0), rtcdev->base + COMPARE_LOWER_REG);
+       writel(GENMASK(29, 0), rtcdev->base + COMPARE_UPPER_REG);
+
+       /* Configure the RTC to enable the alarm. */
+       ctrl = readl(rtcdev->base + CONTROL_REG);
+       mode = readl(rtcdev->base + MODE_REG);
+       if (alrm->enabled) {
+               mode = MODE_WAKE_EN | MODE_WAKE_CONTINUE;
+               /* Enable the alarm */
+               ctrl &= ~CONTROL_ALARM_OFF_BIT;
+               ctrl |= CONTROL_ALARM_ON_BIT;
+       }
+       ctrl &= ~CONTROL_STOP_BIT;
+       ctrl |= CONTROL_START_BIT;
+       writel(ctrl, rtcdev->base + CONTROL_REG);
+       writel(mode, rtcdev->base + MODE_REG);
+
+       return 0;
+}
+
+static int mpfs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+       u32 ctrl;
+
+       ctrl = readl(rtcdev->base + CONTROL_REG);
+       ctrl &= ~(CONTROL_ALARM_ON_BIT | CONTROL_ALARM_OFF_BIT | CONTROL_STOP_BIT);
+
+       if (enabled)
+               ctrl |= CONTROL_ALARM_ON_BIT;
+       else
+               ctrl |= CONTROL_ALARM_OFF_BIT;
+
+       writel(ctrl, rtcdev->base + CONTROL_REG);
+
+       return 0;
+}
+
+static inline struct clk *mpfs_rtc_init_clk(struct device *dev)
+{
+       struct clk *clk;
+       int ret;
+
+       clk = devm_clk_get(dev, "rtc");
+       if (IS_ERR(clk))
+               return clk;
+
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ERR_PTR(ret);
+
+       devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
+       return clk;
+}
+
+static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *dev)
+{
+       struct mpfs_rtc_dev *rtcdev = dev;
+
+       mpfs_rtc_clear_irq(rtcdev);
+
+       rtc_update_irq(rtcdev->rtc, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops mpfs_rtc_ops = {
+       .read_time              = mpfs_rtc_readtime,
+       .set_time               = mpfs_rtc_settime,
+       .read_alarm             = mpfs_rtc_readalarm,
+       .set_alarm              = mpfs_rtc_setalarm,
+       .alarm_irq_enable       = mpfs_rtc_alarm_irq_enable,
+};
+
+static int mpfs_rtc_probe(struct platform_device *pdev)
+{
+       struct mpfs_rtc_dev *rtcdev;
+       struct clk *clk;
+       u32 prescaler;
+       int wakeup_irq, ret;
+
+       rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
+       if (!rtcdev)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, rtcdev);
+
+       rtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);
+       if (IS_ERR(rtcdev->rtc))
+               return PTR_ERR(rtcdev->rtc);
+
+       rtcdev->rtc->ops = &mpfs_rtc_ops;
+
+       /* range is capped by alarm max, lower reg is 31:0 & upper is 10:0 */
+       rtcdev->rtc->range_max = GENMASK_ULL(42, 0);
+
+       clk = mpfs_rtc_init_clk(&pdev->dev);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rtcdev->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(rtcdev->base)) {
+               dev_dbg(&pdev->dev, "invalid ioremap resources\n");
+               return PTR_ERR(rtcdev->base);
+       }
+
+       wakeup_irq = platform_get_irq(pdev, 0);
+       if (wakeup_irq <= 0) {
+               dev_dbg(&pdev->dev, "could not get wakeup irq\n");
+               return wakeup_irq;
+       }
+       ret = devm_request_irq(&pdev->dev, wakeup_irq, mpfs_rtc_wakeup_irq_handler, 0,
+                              dev_name(&pdev->dev), rtcdev);
+       if (ret) {
+               dev_dbg(&pdev->dev, "could not request wakeup irq\n");
+               return ret;
+       }
+
+       /* prescaler hardware adds 1 to reg value */
+       prescaler = clk_get_rate(devm_clk_get(&pdev->dev, "rtcref")) - 1;
+
+       if (prescaler > MAX_PRESCALER_COUNT) {
+               dev_dbg(&pdev->dev, "invalid prescaler %d\n", prescaler);
+               return -EINVAL;
+       }
+
+       writel(prescaler, rtcdev->base + PRESCALER_REG);
+       dev_info(&pdev->dev, "prescaler set to: 0x%X \r\n", prescaler);
+
+       device_init_wakeup(&pdev->dev, true);
+       ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq);
+       if (ret)
+               dev_err(&pdev->dev, "failed to enable irq wake\n");
+
+       return devm_rtc_register_device(rtcdev->rtc);
+}
+
+static int mpfs_rtc_remove(struct platform_device *pdev)
+{
+       dev_pm_clear_wake_irq(&pdev->dev);
+
+       return 0;
+}
+
+static const struct of_device_id mpfs_rtc_of_match[] = {
+       { .compatible = "microchip,mpfs-rtc" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
+
+static struct platform_driver mpfs_rtc_driver = {
+       .probe = mpfs_rtc_probe,
+       .remove = mpfs_rtc_remove,
+       .driver = {
+               .name = "mpfs_rtc",
+               .of_match_table = mpfs_rtc_of_match,
+       },
+};
+
+module_platform_driver(mpfs_rtc_driver);
+
+MODULE_DESCRIPTION("Real time clock for Microchip Polarfire SoC");
+MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
+MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c
new file mode 100644 (file)
index 0000000..d43acd3
--- /dev/null
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2022 Nuvoton Technology Corporation
+
+#include <linux/bcd.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+#define NCT3018Y_REG_SC                0x00 /* seconds */
+#define NCT3018Y_REG_SCA       0x01 /* alarm */
+#define NCT3018Y_REG_MN                0x02
+#define NCT3018Y_REG_MNA       0x03 /* alarm */
+#define NCT3018Y_REG_HR                0x04
+#define NCT3018Y_REG_HRA       0x05 /* alarm */
+#define NCT3018Y_REG_DW                0x06
+#define NCT3018Y_REG_DM                0x07
+#define NCT3018Y_REG_MO                0x08
+#define NCT3018Y_REG_YR                0x09
+#define NCT3018Y_REG_CTRL      0x0A /* timer control */
+#define NCT3018Y_REG_ST                0x0B /* status */
+#define NCT3018Y_REG_CLKO      0x0C /* clock out */
+
+#define NCT3018Y_BIT_AF                BIT(7)
+#define NCT3018Y_BIT_ST                BIT(7)
+#define NCT3018Y_BIT_DM                BIT(6)
+#define NCT3018Y_BIT_HF                BIT(5)
+#define NCT3018Y_BIT_DSM       BIT(4)
+#define NCT3018Y_BIT_AIE       BIT(3)
+#define NCT3018Y_BIT_OFIE      BIT(2)
+#define NCT3018Y_BIT_CIE       BIT(1)
+#define NCT3018Y_BIT_TWO       BIT(0)
+
+#define NCT3018Y_REG_BAT_MASK          0x07
+#define NCT3018Y_REG_CLKO_F_MASK       0x03 /* frequenc mask */
+#define NCT3018Y_REG_CLKO_CKE          0x80 /* clock out enabled */
+
+struct nct3018y {
+       struct rtc_device *rtc;
+       struct i2c_client *client;
+#ifdef CONFIG_COMMON_CLK
+       struct clk_hw clkout_hw;
+#endif
+};
+
+static int nct3018y_set_alarm_mode(struct i2c_client *client, bool on)
+{
+       int err, flags;
+
+       dev_dbg(&client->dev, "%s:on:%d\n", __func__, on);
+
+       flags =  i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
+       if (flags < 0) {
+               dev_dbg(&client->dev,
+                       "Failed to read NCT3018Y_REG_CTRL\n");
+               return flags;
+       }
+
+       if (on)
+               flags |= NCT3018Y_BIT_AIE;
+       else
+               flags &= ~NCT3018Y_BIT_AIE;
+
+       flags |= NCT3018Y_BIT_CIE;
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n");
+               return err;
+       }
+
+       flags =  i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
+       if (flags < 0) {
+               dev_dbg(&client->dev,
+                       "Failed to read NCT3018Y_REG_ST\n");
+               return flags;
+       }
+
+       flags &= ~(NCT3018Y_BIT_AF);
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, flags);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_ST\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *alarm_enable,
+                                  unsigned char *alarm_flag)
+{
+       int flags;
+
+       if (alarm_enable) {
+               dev_dbg(&client->dev, "%s:NCT3018Y_REG_CTRL\n", __func__);
+               flags =  i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
+               if (flags < 0)
+                       return flags;
+               *alarm_enable = flags & NCT3018Y_BIT_AIE;
+       }
+
+       if (alarm_flag) {
+               dev_dbg(&client->dev, "%s:NCT3018Y_REG_ST\n", __func__);
+               flags =  i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
+               if (flags < 0)
+                       return flags;
+               *alarm_flag = flags & NCT3018Y_BIT_AF;
+       }
+
+       dev_dbg(&client->dev, "%s:alarm_enable:%x alarm_flag:%x\n",
+               __func__, *alarm_enable, *alarm_flag);
+
+       return 0;
+}
+
+static irqreturn_t nct3018y_irq(int irq, void *dev_id)
+{
+       struct nct3018y *nct3018y = i2c_get_clientdata(dev_id);
+       struct i2c_client *client = nct3018y->client;
+       int err;
+       unsigned char alarm_flag;
+       unsigned char alarm_enable;
+
+       dev_dbg(&client->dev, "%s:irq:%d\n", __func__, irq);
+       err = nct3018y_get_alarm_mode(nct3018y->client, &alarm_enable, &alarm_flag);
+       if (err)
+               return IRQ_NONE;
+
+       if (alarm_flag) {
+               dev_dbg(&client->dev, "%s:alarm flag:%x\n",
+                       __func__, alarm_flag);
+               rtc_update_irq(nct3018y->rtc, 1, RTC_IRQF | RTC_AF);
+               nct3018y_set_alarm_mode(nct3018y->client, 0);
+               dev_dbg(&client->dev, "%s:IRQ_HANDLED\n", __func__);
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+/*
+ * In the routines that deal directly with the nct3018y hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int nct3018y_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf[10];
+       int err;
+
+       err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_ST, 1, buf);
+       if (err < 0)
+               return err;
+
+       if (!buf[0]) {
+               dev_dbg(&client->dev, " voltage <=1.7, date/time is not reliable.\n");
+               return -EINVAL;
+       }
+
+       err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SC, sizeof(buf), buf);
+       if (err < 0)
+               return err;
+
+       tm->tm_sec = bcd2bin(buf[0] & 0x7F);
+       tm->tm_min = bcd2bin(buf[2] & 0x7F);
+       tm->tm_hour = bcd2bin(buf[4] & 0x3F);
+       tm->tm_wday = buf[6] & 0x07;
+       tm->tm_mday = bcd2bin(buf[7] & 0x3F);
+       tm->tm_mon = bcd2bin(buf[8] & 0x1F) - 1;
+       tm->tm_year = bcd2bin(buf[9]) + 100;
+
+       return 0;
+}
+
+static int nct3018y_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf[4] = {0};
+       int err;
+
+       buf[0] = bin2bcd(tm->tm_sec);
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SC, buf[0]);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SC\n");
+               return err;
+       }
+
+       buf[0] = bin2bcd(tm->tm_min);
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MN, buf[0]);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MN\n");
+               return err;
+       }
+
+       buf[0] = bin2bcd(tm->tm_hour);
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HR, buf[0]);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HR\n");
+               return err;
+       }
+
+       buf[0] = tm->tm_wday & 0x07;
+       buf[1] = bin2bcd(tm->tm_mday);
+       buf[2] = bin2bcd(tm->tm_mon + 1);
+       buf[3] = bin2bcd(tm->tm_year - 100);
+       err = i2c_smbus_write_i2c_block_data(client, NCT3018Y_REG_DW,
+                                            sizeof(buf), buf);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write for day and mon and year\n");
+               return -EIO;
+       }
+
+       return err;
+}
+
+static int nct3018y_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf[5];
+       int err;
+
+       err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SCA,
+                                           sizeof(buf), buf);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to read date\n");
+               return -EIO;
+       }
+
+       dev_dbg(&client->dev, "%s: raw data is sec=%02x, min=%02x hr=%02x\n",
+               __func__, buf[0], buf[2], buf[4]);
+
+       tm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
+       tm->time.tm_min = bcd2bin(buf[2] & 0x7F);
+       tm->time.tm_hour = bcd2bin(buf[4] & 0x3F);
+
+       err = nct3018y_get_alarm_mode(client, &tm->enabled, &tm->pending);
+       if (err < 0)
+               return err;
+
+       dev_dbg(&client->dev, "%s:s=%d m=%d, hr=%d, enabled=%d, pending=%d\n",
+               __func__, tm->time.tm_sec, tm->time.tm_min,
+               tm->time.tm_hour, tm->enabled, tm->pending);
+
+       return 0;
+}
+
+static int nct3018y_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int err;
+
+       dev_dbg(dev, "%s, sec=%d, min=%d hour=%d tm->enabled:%d\n",
+               __func__, tm->time.tm_sec, tm->time.tm_min, tm->time.tm_hour,
+               tm->enabled);
+
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SCA, bin2bcd(tm->time.tm_sec));
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SCA\n");
+               return err;
+       }
+
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MNA, bin2bcd(tm->time.tm_min));
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MNA\n");
+               return err;
+       }
+
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HRA, bin2bcd(tm->time.tm_hour));
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HRA\n");
+               return err;
+       }
+
+       return nct3018y_set_alarm_mode(client, tm->enabled);
+}
+
+static int nct3018y_irq_enable(struct device *dev, unsigned int enabled)
+{
+       dev_dbg(dev, "%s: alarm enable=%d\n", __func__, enabled);
+
+       return nct3018y_set_alarm_mode(to_i2c_client(dev), enabled);
+}
+
+static int nct3018y_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int status, flags = 0;
+
+       switch (cmd) {
+       case RTC_VL_READ:
+               status = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
+               if (status < 0)
+                       return status;
+
+               if (!(status & NCT3018Y_REG_BAT_MASK))
+                       flags |= RTC_VL_DATA_INVALID;
+
+               return put_user(flags, (unsigned int __user *)arg);
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
+#ifdef CONFIG_COMMON_CLK
+/*
+ * Handling of the clkout
+ */
+
+#define clkout_hw_to_nct3018y(_hw) container_of(_hw, struct nct3018y, clkout_hw)
+
+static const int clkout_rates[] = {
+       32768,
+       1024,
+       32,
+       1,
+};
+
+static unsigned long nct3018y_clkout_recalc_rate(struct clk_hw *hw,
+                                                unsigned long parent_rate)
+{
+       struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
+       struct i2c_client *client = nct3018y->client;
+       int flags;
+
+       flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
+       if (flags < 0)
+               return 0;
+
+       flags &= NCT3018Y_REG_CLKO_F_MASK;
+       return clkout_rates[flags];
+}
+
+static long nct3018y_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+                                      unsigned long *prate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+               if (clkout_rates[i] <= rate)
+                       return clkout_rates[i];
+
+       return 0;
+}
+
+static int nct3018y_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate)
+{
+       struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
+       struct i2c_client *client = nct3018y->client;
+       int i, flags;
+
+       flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
+       if (flags < 0)
+               return flags;
+
+       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+               if (clkout_rates[i] == rate) {
+                       flags &= ~NCT3018Y_REG_CLKO_F_MASK;
+                       flags |= i;
+                       return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, flags);
+               }
+
+       return -EINVAL;
+}
+
+static int nct3018y_clkout_control(struct clk_hw *hw, bool enable)
+{
+       struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
+       struct i2c_client *client = nct3018y->client;
+       int flags;
+
+       flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
+       if (flags < 0)
+               return flags;
+
+       if (enable)
+               flags |= NCT3018Y_REG_CLKO_CKE;
+       else
+               flags &= ~NCT3018Y_REG_CLKO_CKE;
+
+       return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, flags);
+}
+
+static int nct3018y_clkout_prepare(struct clk_hw *hw)
+{
+       return nct3018y_clkout_control(hw, 1);
+}
+
+static void nct3018y_clkout_unprepare(struct clk_hw *hw)
+{
+       nct3018y_clkout_control(hw, 0);
+}
+
+static int nct3018y_clkout_is_prepared(struct clk_hw *hw)
+{
+       struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
+       struct i2c_client *client = nct3018y->client;
+       int flags;
+
+       flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
+       if (flags < 0)
+               return flags;
+
+       return flags & NCT3018Y_REG_CLKO_CKE;
+}
+
+static const struct clk_ops nct3018y_clkout_ops = {
+       .prepare = nct3018y_clkout_prepare,
+       .unprepare = nct3018y_clkout_unprepare,
+       .is_prepared = nct3018y_clkout_is_prepared,
+       .recalc_rate = nct3018y_clkout_recalc_rate,
+       .round_rate = nct3018y_clkout_round_rate,
+       .set_rate = nct3018y_clkout_set_rate,
+};
+
+static struct clk *nct3018y_clkout_register_clk(struct nct3018y *nct3018y)
+{
+       struct i2c_client *client = nct3018y->client;
+       struct device_node *node = client->dev.of_node;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       init.name = "nct3018y-clkout";
+       init.ops = &nct3018y_clkout_ops;
+       init.flags = 0;
+       init.parent_names = NULL;
+       init.num_parents = 0;
+       nct3018y->clkout_hw.init = &init;
+
+       /* optional override of the clockname */
+       of_property_read_string(node, "clock-output-names", &init.name);
+
+       /* register the clock */
+       clk = devm_clk_register(&client->dev, &nct3018y->clkout_hw);
+
+       if (!IS_ERR(clk))
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+       return clk;
+}
+#endif
+
+static const struct rtc_class_ops nct3018y_rtc_ops = {
+       .read_time      = nct3018y_rtc_read_time,
+       .set_time       = nct3018y_rtc_set_time,
+       .read_alarm     = nct3018y_rtc_read_alarm,
+       .set_alarm      = nct3018y_rtc_set_alarm,
+       .alarm_irq_enable = nct3018y_irq_enable,
+       .ioctl          = nct3018y_ioctl,
+};
+
+static int nct3018y_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       struct nct3018y *nct3018y;
+       int err, flags;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+                                    I2C_FUNC_SMBUS_BYTE |
+                                    I2C_FUNC_SMBUS_BLOCK_DATA))
+               return -ENODEV;
+
+       nct3018y = devm_kzalloc(&client->dev, sizeof(struct nct3018y),
+                               GFP_KERNEL);
+       if (!nct3018y)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, nct3018y);
+       nct3018y->client = client;
+       device_set_wakeup_capable(&client->dev, 1);
+
+       flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
+       if (flags < 0) {
+               dev_dbg(&client->dev, "%s: read error\n", __func__);
+               return flags;
+       } else if (flags & NCT3018Y_BIT_TWO) {
+               dev_dbg(&client->dev, "%s: NCT3018Y_BIT_TWO is set\n", __func__);
+       }
+
+       flags = NCT3018Y_BIT_TWO;
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n");
+               return err;
+       }
+
+       flags = 0;
+       err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, flags);
+       if (err < 0) {
+               dev_dbg(&client->dev, "%s: write error\n", __func__);
+               return err;
+       }
+
+       nct3018y->rtc = devm_rtc_allocate_device(&client->dev);
+       if (IS_ERR(nct3018y->rtc))
+               return PTR_ERR(nct3018y->rtc);
+
+       nct3018y->rtc->ops = &nct3018y_rtc_ops;
+       nct3018y->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+       nct3018y->rtc->range_max = RTC_TIMESTAMP_END_2099;
+
+       if (client->irq > 0) {
+               err = devm_request_threaded_irq(&client->dev, client->irq,
+                                               NULL, nct3018y_irq,
+                                               IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+                                               "nct3018y", client);
+               if (err) {
+                       dev_dbg(&client->dev, "unable to request IRQ %d\n", client->irq);
+                       return err;
+               }
+       } else {
+               clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, nct3018y->rtc->features);
+               clear_bit(RTC_FEATURE_ALARM, nct3018y->rtc->features);
+       }
+
+#ifdef CONFIG_COMMON_CLK
+       /* register clk in common clk framework */
+       nct3018y_clkout_register_clk(nct3018y);
+#endif
+
+       return devm_rtc_register_device(nct3018y->rtc);
+}
+
+static const struct i2c_device_id nct3018y_id[] = {
+       { "nct3018y", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, nct3018y_id);
+
+static const struct of_device_id nct3018y_of_match[] = {
+       { .compatible = "nuvoton,nct3018y" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, nct3018y_of_match);
+
+static struct i2c_driver nct3018y_driver = {
+       .driver         = {
+               .name   = "rtc-nct3018y",
+               .of_match_table = of_match_ptr(nct3018y_of_match),
+       },
+       .probe          = nct3018y_probe,
+       .id_table       = nct3018y_id,
+};
+
+module_i2c_driver(nct3018y_driver);
+
+MODULE_AUTHOR("Medad CChien <ctcchien@nuvoton.com>");
+MODULE_AUTHOR("Mia Lin <mimi05633@gmail.com>");
+MODULE_DESCRIPTION("Nuvoton NCT3018Y RTC driver");
+MODULE_LICENSE("GPL");
index b1b1943..6174b3f 100644 (file)
@@ -390,8 +390,7 @@ static const struct regmap_config regmap_config = {
         .max_register = 0x13,
 };
 
-static int pcf8523_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int pcf8523_probe(struct i2c_client *client)
 {
        struct pcf8523 *pcf8523;
        struct rtc_device *rtc;
@@ -485,7 +484,7 @@ static struct i2c_driver pcf8523_driver = {
                .name = "rtc-pcf8523",
                .of_match_table = pcf8523_of_match,
        },
-       .probe = pcf8523_probe,
+       .probe_new = pcf8523_probe,
        .id_table = pcf8523_id,
 };
 module_i2c_driver(pcf8523_driver);
index bb3e9ba..c05b722 100644 (file)
@@ -350,8 +350,7 @@ static const struct pcf85x63_config pcf_85363_config = {
        .num_nvram = 2
 };
 
-static int pcf85363_probe(struct i2c_client *client,
-                         const struct i2c_device_id *id)
+static int pcf85363_probe(struct i2c_client *client)
 {
        struct pcf85363 *pcf85363;
        const struct pcf85x63_config *config = &pcf_85363_config;
@@ -436,7 +435,7 @@ static struct i2c_driver pcf85363_driver = {
                .name   = "pcf85363",
                .of_match_table = of_match_ptr(dev_ids),
        },
-       .probe  = pcf85363_probe,
+       .probe_new = pcf85363_probe,
 };
 
 module_i2c_driver(pcf85363_driver);
index 9d06813..11fa978 100644 (file)
@@ -509,8 +509,7 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
        .alarm_irq_enable = pcf8563_irq_enable,
 };
 
-static int pcf8563_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int pcf8563_probe(struct i2c_client *client)
 {
        struct pcf8563 *pcf8563;
        int err;
@@ -606,7 +605,7 @@ static struct i2c_driver pcf8563_driver = {
                .name   = "rtc-pcf8563",
                .of_match_table = of_match_ptr(pcf8563_of_match),
        },
-       .probe          = pcf8563_probe,
+       .probe_new      = pcf8563_probe,
        .id_table       = pcf8563_id,
 };
 
index c80ca20..87074d1 100644 (file)
@@ -275,8 +275,7 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
        .set_time       = pcf8583_rtc_set_time,
 };
 
-static int pcf8583_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int pcf8583_probe(struct i2c_client *client)
 {
        struct pcf8583 *pcf8583;
 
@@ -307,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
        .driver = {
                .name   = "pcf8583",
        },
-       .probe          = pcf8583_probe,
+       .probe_new      = pcf8583_probe,
        .id_table       = pcf8583_id,
 };
 
index 8cb84c9..eb483a3 100644 (file)
@@ -784,8 +784,7 @@ static const struct regmap_config config = {
 
 #if IS_ENABLED(CONFIG_I2C)
 
-static int rv3029_i2c_probe(struct i2c_client *client,
-                           const struct i2c_device_id *id)
+static int rv3029_i2c_probe(struct i2c_client *client)
 {
        struct regmap *regmap;
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
@@ -819,7 +818,7 @@ static struct i2c_driver rv3029_driver = {
                .name = "rv3029",
                .of_match_table = of_match_ptr(rv3029_of_match),
        },
-       .probe          = rv3029_i2c_probe,
+       .probe_new      = rv3029_i2c_probe,
        .id_table       = rv3029_id,
 };
 
index f69e0b1..3527a05 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/bcd.h>
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/log2.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -33,6 +34,7 @@
 #define RV8803_EXT                     0x0D
 #define RV8803_FLAG                    0x0E
 #define RV8803_CTRL                    0x0F
+#define RV8803_OSC_OFFSET              0x2C
 
 #define RV8803_EXT_WADA                        BIT(6)
 
 #define RV8803_CTRL_TIE                        BIT(4)
 #define RV8803_CTRL_UIE                        BIT(5)
 
+#define RX8803_CTRL_CSEL               GENMASK(7, 6)
+
 #define RX8900_BACKUP_CTRL             0x18
 #define RX8900_FLAG_SWOFF              BIT(2)
 #define RX8900_FLAG_VDETOFF            BIT(3)
 
 enum rv8803_type {
        rv_8803,
+       rx_8803,
        rx_8804,
        rx_8900
 };
@@ -64,6 +69,7 @@ struct rv8803_data {
        struct rtc_device *rtc;
        struct mutex flags_lock;
        u8 ctrl;
+       u8 backup;
        enum rv8803_type type;
 };
 
@@ -136,6 +142,44 @@ static int rv8803_write_regs(const struct i2c_client *client,
        return ret;
 }
 
+static int rv8803_regs_init(struct rv8803_data *rv8803)
+{
+       int ret;
+
+       ret = rv8803_write_reg(rv8803->client, RV8803_OSC_OFFSET, 0x00);
+       if (ret)
+               return ret;
+
+       ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+                              FIELD_PREP(RX8803_CTRL_CSEL, 1)); /* 2s */
+       if (ret)
+               return ret;
+
+       ret = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3,
+                               (u8[]){ 0, 0, 0 });
+       if (ret)
+               return ret;
+
+       return rv8803_write_reg(rv8803->client, RV8803_RAM, 0x00);
+}
+
+static int rv8803_regs_configure(struct rv8803_data *rv8803);
+
+static int rv8803_regs_reset(struct rv8803_data *rv8803)
+{
+       /*
+        * The RV-8803 resets all registers to POR defaults after voltage-loss,
+        * the Epson RTCs don't, so we manually reset the remainder here.
+        */
+       if (rv8803->type == rx_8803 || rv8803->type == rx_8900) {
+               int ret = rv8803_regs_init(rv8803);
+               if (ret)
+                       return ret;
+       }
+
+       return rv8803_regs_configure(rv8803);
+}
+
 static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
 {
        struct i2c_client *client = dev_id;
@@ -269,6 +313,14 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
                return flags;
        }
 
+       if (flags & RV8803_FLAG_V2F) {
+               ret = rv8803_regs_reset(rv8803);
+               if (ret) {
+                       mutex_unlock(&rv8803->flags_lock);
+                       return ret;
+               }
+       }
+
        ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
                               flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
 
@@ -498,18 +550,32 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
        if (err < 0)
                return err;
 
-       flags = ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF) & (u8)err;
-
-       if (of_property_read_bool(node, "epson,vdet-disable"))
-               flags |= RX8900_FLAG_VDETOFF;
-
-       if (of_property_read_bool(node, "trickle-diode-disable"))
-               flags |= RX8900_FLAG_SWOFF;
+       flags = (u8)err;
+       flags &= ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF);
+       flags |= rv8803->backup;
 
        return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL,
                                         flags);
 }
 
+/* configure registers with values different than the Power-On reset defaults */
+static int rv8803_regs_configure(struct rv8803_data *rv8803)
+{
+       int err;
+
+       err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
+       if (err)
+               return err;
+
+       err = rx8900_trickle_charger_init(rv8803);
+       if (err) {
+               dev_err(&rv8803->client->dev, "failed to init charger\n");
+               return err;
+       }
+
+       return 0;
+}
+
 static int rv8803_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -576,15 +642,15 @@ static int rv8803_probe(struct i2c_client *client,
        if (!client->irq)
                clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
 
-       err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
-       if (err)
-               return err;
+       if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable"))
+               rv8803->backup |= RX8900_FLAG_VDETOFF;
 
-       err = rx8900_trickle_charger_init(rv8803);
-       if (err) {
-               dev_err(&client->dev, "failed to init charger\n");
+       if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
+               rv8803->backup |= RX8900_FLAG_SWOFF;
+
+       err = rv8803_regs_configure(rv8803);
+       if (err)
                return err;
-       }
 
        rv8803->rtc->ops = &rv8803_rtc_ops;
        rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
@@ -603,7 +669,7 @@ static int rv8803_probe(struct i2c_client *client,
 static const struct i2c_device_id rv8803_id[] = {
        { "rv8803", rv_8803 },
        { "rv8804", rx_8804 },
-       { "rx8803", rv_8803 },
+       { "rx8803", rx_8803 },
        { "rx8900", rx_8900 },
        { }
 };
@@ -616,7 +682,7 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
        },
        {
                .compatible = "epson,rx8803",
-               .data = (void *)rv_8803
+               .data = (void *)rx_8803
        },
        {
                .compatible = "epson,rx8804",
index 758fd6e..cc63455 100644 (file)
@@ -419,8 +419,7 @@ static struct regmap_config regmap_i2c_config = {
        .read_flag_mask = 0x80,
 };
 
-static int rx6110_i2c_probe(struct i2c_client *client,
-                           const struct i2c_device_id *id)
+static int rx6110_i2c_probe(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
        struct rx6110_data *rx6110;
@@ -464,7 +463,7 @@ static struct i2c_driver rx6110_i2c_driver = {
                .name = RX6110_DRIVER_NAME,
                .acpi_match_table = rx6110_i2c_acpi_match,
        },
-       .probe          = rx6110_i2c_probe,
+       .probe_new      = rx6110_i2c_probe,
        .id_table       = rx6110_i2c_id,
 };
 
index b32117c..dde86f3 100644 (file)
@@ -55,6 +55,8 @@
 #define RX8025_BIT_CTRL2_XST   BIT(5)
 #define RX8025_BIT_CTRL2_VDET  BIT(6)
 
+#define RX8035_BIT_HOUR_1224   BIT(7)
+
 /* Clock precision adjustment */
 #define RX8025_ADJ_RESOLUTION  3050 /* in ppb */
 #define RX8025_ADJ_DATA_MAX    62
@@ -78,6 +80,7 @@ struct rx8025_data {
        struct rtc_device *rtc;
        enum rx_model model;
        u8 ctrl1;
+       int is_24;
 };
 
 static s32 rx8025_read_reg(const struct i2c_client *client, u8 number)
@@ -226,7 +229,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
 
        dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 0x7f);
        dt->tm_min = bcd2bin(date[RX8025_REG_MIN] & 0x7f);
-       if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
+       if (rx8025->is_24)
                dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x3f);
        else
                dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x1f) % 12
@@ -254,7 +257,7 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
         */
        date[RX8025_REG_SEC] = bin2bcd(dt->tm_sec);
        date[RX8025_REG_MIN] = bin2bcd(dt->tm_min);
-       if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
+       if (rx8025->is_24)
                date[RX8025_REG_HOUR] = bin2bcd(dt->tm_hour);
        else
                date[RX8025_REG_HOUR] = (dt->tm_hour >= 12 ? 0x20 : 0)
@@ -279,6 +282,7 @@ static int rx8025_init_client(struct i2c_client *client)
        struct rx8025_data *rx8025 = i2c_get_clientdata(client);
        u8 ctrl[2], ctrl2;
        int need_clear = 0;
+       int hour_reg;
        int err;
 
        err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl);
@@ -303,6 +307,16 @@ static int rx8025_init_client(struct i2c_client *client)
 
                err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2);
        }
+
+       if (rx8025->model == model_rx_8035) {
+               /* In RX-8035, 12/24 flag is in the hour register */
+               hour_reg = rx8025_read_reg(client, RX8025_REG_HOUR);
+               if (hour_reg < 0)
+                       return hour_reg;
+               rx8025->is_24 = (hour_reg & RX8035_BIT_HOUR_1224);
+       } else {
+               rx8025->is_24 = (ctrl[1] & RX8025_BIT_CTRL1_1224);
+       }
 out:
        return err;
 }
@@ -329,7 +343,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        /* Hardware alarms precision is 1 minute! */
        t->time.tm_sec = 0;
        t->time.tm_min = bcd2bin(ald[0] & 0x7f);
-       if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
+       if (rx8025->is_24)
                t->time.tm_hour = bcd2bin(ald[1] & 0x3f);
        else
                t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
@@ -350,7 +364,7 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        int err;
 
        ald[0] = bin2bcd(t->time.tm_min);
-       if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
+       if (rx8025->is_24)
                ald[1] = bin2bcd(t->time.tm_hour);
        else
                ald[1] = (t->time.tm_hour >= 12 ? 0x20 : 0)
index aed4898..14edb75 100644 (file)
@@ -248,8 +248,7 @@ static const struct rx85x1_config rx8571_config = {
        .num_nvram = 2
 };
 
-static int rx8581_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int rx8581_probe(struct i2c_client *client)
 {
        struct rx8581 *rx8581;
        const struct rx85x1_config *config = &rx8581_config;
@@ -326,7 +325,7 @@ static struct i2c_driver rx8581_driver = {
                .name   = "rtc-rx8581",
                .of_match_table = of_match_ptr(rx8581_of_match),
        },
-       .probe          = rx8581_probe,
+       .probe_new      = rx8581_probe,
        .id_table       = rx8581_id,
 };
 
index 26278c7..81d97b1 100644 (file)
@@ -420,8 +420,7 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
        .ioctl          = s35390a_rtc_ioctl,
 };
 
-static int s35390a_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int s35390a_probe(struct i2c_client *client)
 {
        int err, err_read;
        unsigned int i;
@@ -502,7 +501,7 @@ static struct i2c_driver s35390a_driver = {
                .name   = "rtc-s35390a",
                .of_match_table = of_match_ptr(s35390a_of_match),
        },
-       .probe          = s35390a_probe,
+       .probe_new      = s35390a_probe,
        .id_table       = s35390a_id,
 };
 
index 24e8528..e2f90d7 100644 (file)
@@ -163,8 +163,7 @@ static const struct regmap_config regmap_config = {
        .max_register = 0x11,
 };
 
-static int sd3078_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int sd3078_probe(struct i2c_client *client)
 {
        int ret;
        struct sd3078 *sd3078;
@@ -218,7 +217,7 @@ static struct i2c_driver sd3078_driver = {
                .name   = "sd3078",
                .of_match_table = of_match_ptr(rtc_dt_match),
        },
-       .probe      = sd3078_probe,
+       .probe_new  = sd3078_probe,
        .id_table   = sd3078_id,
 };
 
index d4777b0..736fe53 100644 (file)
@@ -388,7 +388,7 @@ static int spear_rtc_probe(struct platform_device *pdev)
 
        config->rtc->ops = &spear_rtc_ops;
        config->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000;
-       config->rtc->range_min = RTC_TIMESTAMP_END_9999;
+       config->rtc->range_max = RTC_TIMESTAMP_END_9999;
 
        status = devm_rtc_register_device(config->rtc);
        if (status)
index 5754072..ed55160 100644 (file)
@@ -875,6 +875,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
        { .compatible = "allwinner,sun50i-h6-rtc" },
        { .compatible = "allwinner,sun50i-h616-rtc",
                .data = (void *)RTC_LINEAR_DAY },
+       { .compatible = "allwinner,sun50i-r329-rtc",
+               .data = (void *)RTC_LINEAR_DAY },
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
diff --git a/drivers/rtc/rtc-ti-k3.c b/drivers/rtc/rtc-ti-k3.c
new file mode 100644 (file)
index 0000000..7a0f181
--- /dev/null
@@ -0,0 +1,680 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments K3 RTC driver
+ *
+ * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+
+/* Registers */
+#define REG_K3RTC_S_CNT_LSW            0x08
+#define REG_K3RTC_S_CNT_MSW            0x0c
+#define REG_K3RTC_COMP                 0x10
+#define REG_K3RTC_ON_OFF_S_CNT_LSW     0x20
+#define REG_K3RTC_ON_OFF_S_CNT_MSW     0x24
+#define REG_K3RTC_SCRATCH0             0x30
+#define REG_K3RTC_SCRATCH7             0x4c
+#define REG_K3RTC_GENERAL_CTL          0x50
+#define REG_K3RTC_IRQSTATUS_RAW_SYS    0x54
+#define REG_K3RTC_IRQSTATUS_SYS                0x58
+#define REG_K3RTC_IRQENABLE_SET_SYS    0x5c
+#define REG_K3RTC_IRQENABLE_CLR_SYS    0x60
+#define REG_K3RTC_SYNCPEND             0x68
+#define REG_K3RTC_KICK0                        0x70
+#define REG_K3RTC_KICK1                        0x74
+
+/* Freeze when lsw is read and unfreeze when msw is read */
+#define K3RTC_CNT_FMODE_S_CNT_VALUE    (0x2 << 24)
+
+/* Magic values for lock/unlock */
+#define K3RTC_KICK0_UNLOCK_VALUE       0x83e70b13
+#define K3RTC_KICK1_UNLOCK_VALUE       0x95a4f1e0
+
+/* Multiplier for ppb conversions */
+#define K3RTC_PPB_MULT                 (1000000000LL)
+/* Min and max values supported with 'offset' interface (swapped sign) */
+#define K3RTC_MIN_OFFSET               (-277761)
+#define K3RTC_MAX_OFFSET               (277778)
+
+/**
+ * struct ti_k3_rtc_soc_data - Private of compatible data for ti-k3-rtc
+ * @unlock_irq_erratum:        Has erratum for unlock infinite IRQs (erratum i2327)
+ */
+struct ti_k3_rtc_soc_data {
+       const bool unlock_irq_erratum;
+};
+
+static const struct regmap_config ti_k3_rtc_regmap_config = {
+       .name = "peripheral-registers",
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = REG_K3RTC_KICK1,
+};
+
+enum ti_k3_rtc_fields {
+       K3RTC_KICK0,
+       K3RTC_KICK1,
+       K3RTC_S_CNT_LSW,
+       K3RTC_S_CNT_MSW,
+       K3RTC_O32K_OSC_DEP_EN,
+       K3RTC_UNLOCK,
+       K3RTC_CNT_FMODE,
+       K3RTC_PEND,
+       K3RTC_RELOAD_FROM_BBD,
+       K3RTC_COMP,
+
+       K3RTC_ALM_S_CNT_LSW,
+       K3RTC_ALM_S_CNT_MSW,
+       K3RTC_IRQ_STATUS_RAW,
+       K3RTC_IRQ_STATUS,
+       K3RTC_IRQ_ENABLE_SET,
+       K3RTC_IRQ_ENABLE_CLR,
+
+       K3RTC_IRQ_STATUS_ALT,
+       K3RTC_IRQ_ENABLE_CLR_ALT,
+
+       K3_RTC_MAX_FIELDS
+};
+
+static const struct reg_field ti_rtc_reg_fields[] = {
+       [K3RTC_KICK0] = REG_FIELD(REG_K3RTC_KICK0, 0, 31),
+       [K3RTC_KICK1] = REG_FIELD(REG_K3RTC_KICK1, 0, 31),
+       [K3RTC_S_CNT_LSW] = REG_FIELD(REG_K3RTC_S_CNT_LSW, 0, 31),
+       [K3RTC_S_CNT_MSW] = REG_FIELD(REG_K3RTC_S_CNT_MSW, 0, 15),
+       [K3RTC_O32K_OSC_DEP_EN] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 21, 21),
+       [K3RTC_UNLOCK] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 23, 23),
+       [K3RTC_CNT_FMODE] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 24, 25),
+       [K3RTC_PEND] = REG_FIELD(REG_K3RTC_SYNCPEND, 0, 1),
+       [K3RTC_RELOAD_FROM_BBD] = REG_FIELD(REG_K3RTC_SYNCPEND, 31, 31),
+       [K3RTC_COMP] = REG_FIELD(REG_K3RTC_COMP, 0, 31),
+
+       /* We use on to off as alarm trigger */
+       [K3RTC_ALM_S_CNT_LSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_LSW, 0, 31),
+       [K3RTC_ALM_S_CNT_MSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_MSW, 0, 15),
+       [K3RTC_IRQ_STATUS_RAW] = REG_FIELD(REG_K3RTC_IRQSTATUS_RAW_SYS, 0, 0),
+       [K3RTC_IRQ_STATUS] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 0, 0),
+       [K3RTC_IRQ_ENABLE_SET] = REG_FIELD(REG_K3RTC_IRQENABLE_SET_SYS, 0, 0),
+       [K3RTC_IRQ_ENABLE_CLR] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 0, 0),
+       /* Off to on is alternate */
+       [K3RTC_IRQ_STATUS_ALT] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 1, 1),
+       [K3RTC_IRQ_ENABLE_CLR_ALT] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 1, 1),
+};
+
+/**
+ * struct ti_k3_rtc - Private data for ti-k3-rtc
+ * @irq:               IRQ
+ * @sync_timeout_us:   data sync timeout period in uSec
+ * @rate_32k:          32k clock rate in Hz
+ * @rtc_dev:           rtc device
+ * @regmap:            rtc mmio regmap
+ * @r_fields:          rtc register fields
+ * @soc:               SoC compatible match data
+ */
+struct ti_k3_rtc {
+       unsigned int irq;
+       u32 sync_timeout_us;
+       unsigned long rate_32k;
+       struct rtc_device *rtc_dev;
+       struct regmap *regmap;
+       struct regmap_field *r_fields[K3_RTC_MAX_FIELDS];
+       const struct ti_k3_rtc_soc_data *soc;
+};
+
+static int k3rtc_field_read(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f)
+{
+       int ret;
+       int val;
+
+       ret = regmap_field_read(priv->r_fields[f], &val);
+       /*
+        * We shouldn't be seeing regmap fail on us for mmio reads
+        * This is possible if clock context fails, but that isn't the case for us
+        */
+       if (WARN_ON_ONCE(ret))
+               return ret;
+       return val;
+}
+
+static void k3rtc_field_write(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f, u32 val)
+{
+       regmap_field_write(priv->r_fields[f], val);
+}
+
+/**
+ * k3rtc_fence  - Ensure a register sync took place between the two domains
+ * @priv:      pointer to priv data
+ *
+ * Return: 0 if the sync took place, else returns -ETIMEDOUT
+ */
+static int k3rtc_fence(struct ti_k3_rtc *priv)
+{
+       int ret;
+
+       ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_PEND], ret,
+                                            !ret, 2, priv->sync_timeout_us);
+
+       return ret;
+}
+
+static inline int k3rtc_check_unlocked(struct ti_k3_rtc *priv)
+{
+       int ret;
+
+       ret = k3rtc_field_read(priv, K3RTC_UNLOCK);
+       if (ret < 0)
+               return ret;
+
+       return (ret) ? 0 : 1;
+}
+
+static int k3rtc_unlock_rtc(struct ti_k3_rtc *priv)
+{
+       int ret;
+
+       ret = k3rtc_check_unlocked(priv);
+       if (!ret)
+               return ret;
+
+       k3rtc_field_write(priv, K3RTC_KICK0, K3RTC_KICK0_UNLOCK_VALUE);
+       k3rtc_field_write(priv, K3RTC_KICK1, K3RTC_KICK1_UNLOCK_VALUE);
+
+       /* Skip fence since we are going to check the unlock bit as fence */
+       ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_UNLOCK], ret,
+                                            !ret, 2, priv->sync_timeout_us);
+
+       return ret;
+}
+
+static int k3rtc_configure(struct device *dev)
+{
+       int ret;
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+
+       /*
+        * HWBUG: The compare state machine is broken if the RTC module
+        * is NOT unlocked in under one second of boot - which is pretty long
+        * time from the perspective of Linux driver (module load, u-boot
+        * shell all can take much longer than this.
+        *
+        * In such occurrence, it is assumed that the RTC module is unusable
+        */
+       if (priv->soc->unlock_irq_erratum) {
+               ret = k3rtc_check_unlocked(priv);
+               /* If there is an error OR if we are locked, return error */
+               if (ret) {
+                       dev_err(dev,
+                               HW_ERR "Erratum i2327 unlock QUIRK! Cannot operate!!\n");
+                       return -EFAULT;
+               }
+       } else {
+               /* May need to explicitly unlock first time */
+               ret = k3rtc_unlock_rtc(priv);
+               if (ret) {
+                       dev_err(dev, "Failed to unlock(%d)!\n", ret);
+                       return ret;
+               }
+       }
+
+       /* Enable Shadow register sync on 32k clock boundary */
+       k3rtc_field_write(priv, K3RTC_O32K_OSC_DEP_EN, 0x1);
+
+       /*
+        * Wait at least clock sync time before proceeding further programming.
+        * This ensures that the 32k based sync is active.
+        */
+       usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 5);
+
+       /* We need to ensure fence here to make sure sync here */
+       ret = k3rtc_fence(priv);
+       if (ret) {
+               dev_err(dev,
+                       "Failed fence osc_dep enable(%d) - is 32k clk working?!\n", ret);
+               return ret;
+       }
+
+       /*
+        * FMODE setting: Reading lower seconds will freeze value on higher
+        * seconds. This also implies that we must *ALWAYS* read lower seconds
+        * prior to reading higher seconds
+        */
+       k3rtc_field_write(priv, K3RTC_CNT_FMODE, K3RTC_CNT_FMODE_S_CNT_VALUE);
+
+       /* Clear any spurious IRQ sources if any */
+       k3rtc_field_write(priv, K3RTC_IRQ_STATUS_ALT, 0x1);
+       k3rtc_field_write(priv, K3RTC_IRQ_STATUS, 0x1);
+       /* Disable all IRQs */
+       k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR_ALT, 0x1);
+       k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR, 0x1);
+
+       /* And.. Let us Sync the writes in */
+       return k3rtc_fence(priv);
+}
+
+static int ti_k3_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 seconds_lo, seconds_hi;
+
+       seconds_lo = k3rtc_field_read(priv, K3RTC_S_CNT_LSW);
+       seconds_hi = k3rtc_field_read(priv, K3RTC_S_CNT_MSW);
+
+       rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, tm);
+
+       return 0;
+}
+
+static int ti_k3_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       time64_t seconds;
+
+       seconds = rtc_tm_to_time64(tm);
+
+       /*
+        * Read operation on LSW will freeze the RTC, so to update
+        * the time, we cannot use field operations. Just write since the
+        * reserved bits are ignored.
+        */
+       regmap_write(priv->regmap, REG_K3RTC_S_CNT_LSW, seconds);
+       regmap_write(priv->regmap, REG_K3RTC_S_CNT_MSW, seconds >> 32);
+
+       return k3rtc_fence(priv);
+}
+
+static int ti_k3_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 reg;
+       u32 offset = enabled ? K3RTC_IRQ_ENABLE_SET : K3RTC_IRQ_ENABLE_CLR;
+
+       reg = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
+       if ((enabled && reg) || (!enabled && !reg))
+               return 0;
+
+       k3rtc_field_write(priv, offset, 0x1);
+
+       /*
+        * Ensure the write sync is through - NOTE: it should be OK to have
+        * ISR to fire as we are checking sync (which should be done in a 32k
+        * cycle or so).
+        */
+       return k3rtc_fence(priv);
+}
+
+static int ti_k3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 seconds_lo, seconds_hi;
+
+       seconds_lo = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_LSW);
+       seconds_hi = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_MSW);
+
+       rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, &alarm->time);
+
+       alarm->enabled = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
+
+       return 0;
+}
+
+static int ti_k3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       time64_t seconds;
+       int ret;
+
+       seconds = rtc_tm_to_time64(&alarm->time);
+
+       k3rtc_field_write(priv, K3RTC_ALM_S_CNT_LSW, seconds);
+       k3rtc_field_write(priv, K3RTC_ALM_S_CNT_MSW, (seconds >> 32));
+
+       /* Make sure the alarm time is synced in */
+       ret = k3rtc_fence(priv);
+       if (ret) {
+               dev_err(dev, "Failed to fence(%d)! Potential config issue?\n", ret);
+               return ret;
+       }
+
+       /* Alarm IRQ enable will do a sync */
+       return ti_k3_rtc_alarm_irq_enable(dev, alarm->enabled);
+}
+
+static int ti_k3_rtc_read_offset(struct device *dev, long *offset)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 ticks_per_hr = priv->rate_32k * 3600;
+       int comp;
+       s64 tmp;
+
+       comp = k3rtc_field_read(priv, K3RTC_COMP);
+
+       /* Convert from RTC calibration register format to ppb format */
+       tmp = comp * (s64)K3RTC_PPB_MULT;
+       if (tmp < 0)
+               tmp -= ticks_per_hr / 2LL;
+       else
+               tmp += ticks_per_hr / 2LL;
+       tmp = div_s64(tmp, ticks_per_hr);
+
+       /* Offset value operates in negative way, so swap sign */
+       *offset = (long)-tmp;
+
+       return 0;
+}
+
+static int ti_k3_rtc_set_offset(struct device *dev, long offset)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 ticks_per_hr = priv->rate_32k * 3600;
+       int comp;
+       s64 tmp;
+
+       /* Make sure offset value is within supported range */
+       if (offset < K3RTC_MIN_OFFSET || offset > K3RTC_MAX_OFFSET)
+               return -ERANGE;
+
+       /* Convert from ppb format to RTC calibration register format */
+       tmp = offset * (s64)ticks_per_hr;
+       if (tmp < 0)
+               tmp -= K3RTC_PPB_MULT / 2LL;
+       else
+               tmp += K3RTC_PPB_MULT / 2LL;
+       tmp = div_s64(tmp, K3RTC_PPB_MULT);
+
+       /* Offset value operates in negative way, so swap sign */
+       comp = (int)-tmp;
+
+       k3rtc_field_write(priv, K3RTC_COMP, comp);
+
+       return k3rtc_fence(priv);
+}
+
+static irqreturn_t ti_k3_rtc_interrupt(s32 irq, void *dev_id)
+{
+       struct device *dev = dev_id;
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+       u32 reg;
+       int ret;
+
+       /*
+        * IRQ assertion can be very fast, however, the IRQ Status clear
+        * de-assert depends on 32k clock edge in the 32k domain
+        * If we clear the status prior to the first 32k clock edge,
+        * the status bit is cleared, but the IRQ stays re-asserted.
+        *
+        * To prevent this condition, we need to wait for clock sync time.
+        * We can either do that by polling the 32k observability signal for
+        * a toggle OR we could just sleep and let the processor do other
+        * stuff.
+        */
+       usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 2);
+
+       /* Lets make sure that this is a valid interrupt */
+       reg = k3rtc_field_read(priv, K3RTC_IRQ_STATUS);
+
+       if (!reg) {
+               u32 raw = k3rtc_field_read(priv, K3RTC_IRQ_STATUS_RAW);
+
+               dev_err(dev,
+                       HW_ERR
+                       "Erratum i2327/IRQ trig: status: 0x%08x / 0x%08x\n", reg, raw);
+               return IRQ_NONE;
+       }
+
+       /*
+        * Write 1 to clear status reg
+        * We cannot use a field operation here due to a potential race between
+        * 32k domain and vbus domain.
+        */
+       regmap_write(priv->regmap, REG_K3RTC_IRQSTATUS_SYS, 0x1);
+
+       /* Sync the write in */
+       ret = k3rtc_fence(priv);
+       if (ret) {
+               dev_err(dev, "Failed to fence irq status clr(%d)!\n", ret);
+               return IRQ_NONE;
+       }
+
+       /*
+        * Force the 32k status to be reloaded back in to ensure status is
+        * reflected back correctly.
+        */
+       k3rtc_field_write(priv, K3RTC_RELOAD_FROM_BBD, 0x1);
+
+       /* Ensure the write sync is through */
+       ret = k3rtc_fence(priv);
+       if (ret) {
+               dev_err(dev, "Failed to fence reload from bbd(%d)!\n", ret);
+               return IRQ_NONE;
+       }
+
+       /* Now we ensure that the status bit is cleared */
+       ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_IRQ_STATUS],
+                                            ret, !ret, 2, priv->sync_timeout_us);
+       if (ret) {
+               dev_err(dev, "Time out waiting for status clear\n");
+               return IRQ_NONE;
+       }
+
+       /* Notify RTC core on event */
+       rtc_update_irq(priv->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops ti_k3_rtc_ops = {
+       .read_time = ti_k3_rtc_read_time,
+       .set_time = ti_k3_rtc_set_time,
+       .read_alarm = ti_k3_rtc_read_alarm,
+       .set_alarm = ti_k3_rtc_set_alarm,
+       .read_offset = ti_k3_rtc_read_offset,
+       .set_offset = ti_k3_rtc_set_offset,
+       .alarm_irq_enable = ti_k3_rtc_alarm_irq_enable,
+};
+
+static int ti_k3_rtc_scratch_read(void *priv_data, unsigned int offset,
+                                 void *val, size_t bytes)
+{
+       struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
+
+       return regmap_bulk_read(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
+}
+
+static int ti_k3_rtc_scratch_write(void *priv_data, unsigned int offset,
+                                  void *val, size_t bytes)
+{
+       struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
+       int ret;
+
+       ret = regmap_bulk_write(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
+       if (ret)
+               return ret;
+
+       return k3rtc_fence(priv);
+}
+
+static struct nvmem_config ti_k3_rtc_nvmem_config = {
+       .name = "ti_k3_rtc_scratch",
+       .word_size = 4,
+       .stride = 4,
+       .size = REG_K3RTC_SCRATCH7 - REG_K3RTC_SCRATCH0 + 4,
+       .reg_read = ti_k3_rtc_scratch_read,
+       .reg_write = ti_k3_rtc_scratch_write,
+};
+
+static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv)
+{
+       int ret;
+       struct clk *clk;
+
+       clk = devm_clk_get(dev, "osc32k");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
+       if (ret)
+               return ret;
+
+       priv->rate_32k = clk_get_rate(clk);
+
+       /* Make sure we are exact 32k clock. Else, try to compensate delay */
+       if (priv->rate_32k != 32768)
+               dev_warn(dev, "Clock rate %ld is not 32768! Could misbehave!\n",
+                        priv->rate_32k);
+
+       /*
+        * Sync timeout should be two 32k clk sync cycles = ~61uS. We double
+        * it to comprehend intermediate bus segment and cpu frequency
+        * deltas
+        */
+       priv->sync_timeout_us = (u32)(DIV_ROUND_UP_ULL(1000000, priv->rate_32k) * 4);
+
+       return ret;
+}
+
+static int k3rtc_get_vbusclk(struct device *dev, struct ti_k3_rtc *priv)
+{
+       int ret;
+       struct clk *clk;
+
+       /* Note: VBUS isn't a context clock, it is needed for hardware operation */
+       clk = devm_clk_get(dev, "vbus");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ret;
+
+       return devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
+}
+
+static int ti_k3_rtc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ti_k3_rtc *priv;
+       void __iomem *rtc_base;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(struct ti_k3_rtc), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       rtc_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(rtc_base))
+               return PTR_ERR(rtc_base);
+
+       priv->regmap = devm_regmap_init_mmio(dev, rtc_base, &ti_k3_rtc_regmap_config);
+       if (IS_ERR(priv->regmap))
+               return PTR_ERR(priv->regmap);
+
+       ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->r_fields,
+                                          ti_rtc_reg_fields, K3_RTC_MAX_FIELDS);
+       if (ret)
+               return ret;
+
+       ret = k3rtc_get_32kclk(dev, priv);
+       if (ret)
+               return ret;
+       ret = k3rtc_get_vbusclk(dev, priv);
+       if (ret)
+               return ret;
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               return ret;
+       priv->irq = (unsigned int)ret;
+
+       priv->rtc_dev = devm_rtc_allocate_device(dev);
+       if (IS_ERR(priv->rtc_dev))
+               return PTR_ERR(priv->rtc_dev);
+
+       priv->soc = of_device_get_match_data(dev);
+
+       priv->rtc_dev->ops = &ti_k3_rtc_ops;
+       priv->rtc_dev->range_max = (1ULL << 48) - 1;    /* 48Bit seconds */
+       ti_k3_rtc_nvmem_config.priv = priv;
+
+       ret = devm_request_threaded_irq(dev, priv->irq, NULL,
+                                       ti_k3_rtc_interrupt,
+                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       dev_name(dev), dev);
+       if (ret) {
+               dev_err(dev, "Could not request IRQ: %d\n", ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, priv);
+
+       ret = k3rtc_configure(dev);
+       if (ret)
+               return ret;
+
+       if (device_property_present(dev, "wakeup-source"))
+               device_init_wakeup(dev, true);
+       else
+               device_set_wakeup_capable(dev, true);
+
+       ret = devm_rtc_register_device(priv->rtc_dev);
+       if (ret)
+               return ret;
+
+       return devm_rtc_nvmem_register(priv->rtc_dev, &ti_k3_rtc_nvmem_config);
+}
+
+static const struct ti_k3_rtc_soc_data ti_k3_am62_data = {
+       .unlock_irq_erratum = true,
+};
+
+static const struct of_device_id ti_k3_rtc_of_match_table[] = {
+       {.compatible = "ti,am62-rtc", .data = &ti_k3_am62_data},
+       {}
+};
+MODULE_DEVICE_TABLE(of, ti_k3_rtc_of_match_table);
+
+static int __maybe_unused ti_k3_rtc_suspend(struct device *dev)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(priv->irq);
+       return 0;
+}
+
+static int __maybe_unused ti_k3_rtc_resume(struct device *dev)
+{
+       struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(priv->irq);
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ti_k3_rtc_pm_ops, ti_k3_rtc_suspend, ti_k3_rtc_resume);
+
+static struct platform_driver ti_k3_rtc_driver = {
+       .probe = ti_k3_rtc_probe,
+       .driver = {
+                  .name = "rtc-ti-k3",
+                  .of_match_table = ti_k3_rtc_of_match_table,
+                  .pm = &ti_k3_rtc_pm_ops,
+       },
+};
+module_platform_driver(ti_k3_rtc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI K3 RTC driver");
+MODULE_AUTHOR("Nishanth Menon");
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
deleted file mode 100644 (file)
index 5a9f9ad..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *  Driver for NEC VR4100 series Real Time Clock unit.
- *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@linux-mips.org>
- */
-#include <linux/compat.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/rtc.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <linux/log2.h>
-
-#include <asm/div64.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
-MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL v2");
-
-/* RTC 1 registers */
-#define ETIMELREG              0x00
-#define ETIMEMREG              0x02
-#define ETIMEHREG              0x04
-/* RFU */
-#define ECMPLREG               0x08
-#define ECMPMREG               0x0a
-#define ECMPHREG               0x0c
-/* RFU */
-#define RTCL1LREG              0x10
-#define RTCL1HREG              0x12
-#define RTCL1CNTLREG           0x14
-#define RTCL1CNTHREG           0x16
-#define RTCL2LREG              0x18
-#define RTCL2HREG              0x1a
-#define RTCL2CNTLREG           0x1c
-#define RTCL2CNTHREG           0x1e
-
-/* RTC 2 registers */
-#define TCLKLREG               0x00
-#define TCLKHREG               0x02
-#define TCLKCNTLREG            0x04
-#define TCLKCNTHREG            0x06
-/* RFU */
-#define RTCINTREG              0x1e
- #define TCLOCK_INT            0x08
- #define RTCLONG2_INT          0x04
- #define RTCLONG1_INT          0x02
- #define ELAPSEDTIME_INT       0x01
-
-#define RTC_FREQUENCY          32768
-#define MAX_PERIODIC_RATE      6553
-
-static void __iomem *rtc1_base;
-static void __iomem *rtc2_base;
-
-#define rtc1_read(offset)              readw(rtc1_base + (offset))
-#define rtc1_write(offset, value)      writew((value), rtc1_base + (offset))
-
-#define rtc2_read(offset)              readw(rtc2_base + (offset))
-#define rtc2_write(offset, value)      writew((value), rtc2_base + (offset))
-
-/* 32-bit compat for ioctls that nobody else uses */
-#define RTC_EPOCH_READ32       _IOR('p', 0x0d, __u32)
-
-static unsigned long epoch = 1970;     /* Jan 1 1970 00:00:00 */
-
-static DEFINE_SPINLOCK(rtc_lock);
-static char rtc_name[] = "RTC";
-static unsigned long periodic_count;
-static unsigned int alarm_enabled;
-static int aie_irq;
-static int pie_irq;
-
-static inline time64_t read_elapsed_second(void)
-{
-
-       unsigned long first_low, first_mid, first_high;
-
-       unsigned long second_low, second_mid, second_high;
-
-       do {
-               first_low = rtc1_read(ETIMELREG);
-               first_mid = rtc1_read(ETIMEMREG);
-               first_high = rtc1_read(ETIMEHREG);
-               second_low = rtc1_read(ETIMELREG);
-               second_mid = rtc1_read(ETIMEMREG);
-               second_high = rtc1_read(ETIMEHREG);
-       } while (first_low != second_low || first_mid != second_mid ||
-                first_high != second_high);
-
-       return ((u64)first_high << 17) | (first_mid << 1) | (first_low >> 15);
-}
-
-static inline void write_elapsed_second(time64_t sec)
-{
-       spin_lock_irq(&rtc_lock);
-
-       rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
-       rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
-       rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
-
-       spin_unlock_irq(&rtc_lock);
-}
-
-static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
-{
-       time64_t epoch_sec, elapsed_sec;
-
-       epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
-       elapsed_sec = read_elapsed_second();
-
-       rtc_time64_to_tm(epoch_sec + elapsed_sec, time);
-
-       return 0;
-}
-
-static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
-{
-       time64_t epoch_sec, current_sec;
-
-       epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
-       current_sec = rtc_tm_to_time64(time);
-
-       write_elapsed_second(current_sec - epoch_sec);
-
-       return 0;
-}
-
-static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
-{
-       unsigned long low, mid, high;
-       struct rtc_time *time = &wkalrm->time;
-
-       spin_lock_irq(&rtc_lock);
-
-       low = rtc1_read(ECMPLREG);
-       mid = rtc1_read(ECMPMREG);
-       high = rtc1_read(ECMPHREG);
-       wkalrm->enabled = alarm_enabled;
-
-       spin_unlock_irq(&rtc_lock);
-
-       rtc_time64_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
-
-       return 0;
-}
-
-static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
-{
-       time64_t alarm_sec;
-
-       alarm_sec = rtc_tm_to_time64(&wkalrm->time);
-
-       spin_lock_irq(&rtc_lock);
-
-       if (alarm_enabled)
-               disable_irq(aie_irq);
-
-       rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
-       rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
-       rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
-
-       if (wkalrm->enabled)
-               enable_irq(aie_irq);
-
-       alarm_enabled = wkalrm->enabled;
-
-       spin_unlock_irq(&rtc_lock);
-
-       return 0;
-}
-
-static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case RTC_EPOCH_READ:
-               return put_user(epoch, (unsigned long __user *)arg);
-#ifdef CONFIG_64BIT
-       case RTC_EPOCH_READ32:
-               return put_user(epoch, (unsigned int __user *)arg);
-#endif
-       case RTC_EPOCH_SET:
-               /* Doesn't support before 1900 */
-               if (arg < 1900)
-                       return -EINVAL;
-               epoch = arg;
-               break;
-       default:
-               return -ENOIOCTLCMD;
-       }
-
-       return 0;
-}
-
-static int vr41xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-{
-       spin_lock_irq(&rtc_lock);
-       if (enabled) {
-               if (!alarm_enabled) {
-                       enable_irq(aie_irq);
-                       alarm_enabled = 1;
-               }
-       } else {
-               if (alarm_enabled) {
-                       disable_irq(aie_irq);
-                       alarm_enabled = 0;
-               }
-       }
-       spin_unlock_irq(&rtc_lock);
-       return 0;
-}
-
-static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id)
-{
-       struct platform_device *pdev = (struct platform_device *)dev_id;
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-       rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
-
-       rtc_update_irq(rtc, 1, RTC_AF);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
-{
-       struct platform_device *pdev = (struct platform_device *)dev_id;
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
-       unsigned long count = periodic_count;
-
-       rtc2_write(RTCINTREG, RTCLONG1_INT);
-
-       rtc1_write(RTCL1LREG, count);
-       rtc1_write(RTCL1HREG, count >> 16);
-
-       rtc_update_irq(rtc, 1, RTC_PF);
-
-       return IRQ_HANDLED;
-}
-
-static const struct rtc_class_ops vr41xx_rtc_ops = {
-       .ioctl                  = vr41xx_rtc_ioctl,
-       .read_time              = vr41xx_rtc_read_time,
-       .set_time               = vr41xx_rtc_set_time,
-       .read_alarm             = vr41xx_rtc_read_alarm,
-       .set_alarm              = vr41xx_rtc_set_alarm,
-       .alarm_irq_enable       = vr41xx_rtc_alarm_irq_enable,
-};
-
-static int rtc_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct rtc_device *rtc;
-       int retval;
-
-       if (pdev->num_resources != 4)
-               return -EBUSY;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EBUSY;
-
-       rtc1_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-       if (!rtc1_base)
-               return -EBUSY;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               retval = -EBUSY;
-               goto err_rtc1_iounmap;
-       }
-
-       rtc2_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-       if (!rtc2_base) {
-               retval = -EBUSY;
-               goto err_rtc1_iounmap;
-       }
-
-       rtc = devm_rtc_allocate_device(&pdev->dev);
-       if (IS_ERR(rtc)) {
-               retval = PTR_ERR(rtc);
-               goto err_iounmap_all;
-       }
-
-       rtc->ops = &vr41xx_rtc_ops;
-
-       /* 48-bit counter at 32.768 kHz */
-       rtc->range_max = (1ULL << 33) - 1;
-       rtc->max_user_freq = MAX_PERIODIC_RATE;
-
-       spin_lock_irq(&rtc_lock);
-
-       rtc1_write(ECMPLREG, 0);
-       rtc1_write(ECMPMREG, 0);
-       rtc1_write(ECMPHREG, 0);
-       rtc1_write(RTCL1LREG, 0);
-       rtc1_write(RTCL1HREG, 0);
-
-       spin_unlock_irq(&rtc_lock);
-
-       aie_irq = platform_get_irq(pdev, 0);
-       if (aie_irq <= 0) {
-               retval = -EBUSY;
-               goto err_iounmap_all;
-       }
-
-       retval = devm_request_irq(&pdev->dev, aie_irq, elapsedtime_interrupt, 0,
-                               "elapsed_time", pdev);
-       if (retval < 0)
-               goto err_iounmap_all;
-
-       pie_irq = platform_get_irq(pdev, 1);
-       if (pie_irq <= 0) {
-               retval = -EBUSY;
-               goto err_iounmap_all;
-       }
-
-       retval = devm_request_irq(&pdev->dev, pie_irq, rtclong1_interrupt, 0,
-                               "rtclong1", pdev);
-       if (retval < 0)
-               goto err_iounmap_all;
-
-       platform_set_drvdata(pdev, rtc);
-
-       disable_irq(aie_irq);
-       disable_irq(pie_irq);
-
-       dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n");
-
-       retval = devm_rtc_register_device(rtc);
-       if (retval)
-               goto err_iounmap_all;
-
-       return 0;
-
-err_iounmap_all:
-       rtc2_base = NULL;
-
-err_rtc1_iounmap:
-       rtc1_base = NULL;
-
-       return retval;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:RTC");
-
-static struct platform_driver rtc_platform_driver = {
-       .probe          = rtc_probe,
-       .driver         = {
-               .name   = rtc_name,
-       },
-};
-
-module_platform_driver(rtc_platform_driver);
index d1d5a44..ba0d22a 100644 (file)
@@ -614,8 +614,7 @@ static void x1205_sysfs_unregister(struct device *dev)
 }
 
 
-static int x1205_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int x1205_probe(struct i2c_client *client)
 {
        int err = 0;
        unsigned char sr;
@@ -681,7 +680,7 @@ static struct i2c_driver x1205_driver = {
                .name   = "rtc-x1205",
                .of_match_table = x1205_dt_ids,
        },
-       .probe          = x1205_probe,
+       .probe_new      = x1205_probe,
        .remove         = x1205_remove,
        .id_table       = x1205_id,
 };
index f440bb5..c9b85c8 100644 (file)
@@ -6,6 +6,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #define RTC_OSC_EN             BIT(24)
 #define RTC_BATT_EN            BIT(31)
 
-#define RTC_CALIB_DEF          0x198233
+#define RTC_CALIB_DEF          0x7FFF
 #define RTC_CALIB_MASK         0x1FFFFF
 #define RTC_ALRM_MASK          BIT(1)
 #define RTC_MSEC               1000
+#define RTC_FR_MASK            0xF0000
+#define RTC_FR_MAX_TICKS       16
+#define RTC_PPB                        1000000000LL
+#define RTC_MIN_OFFSET         -32768000
+#define RTC_MAX_OFFSET         32767000
 
 struct xlnx_rtc_dev {
        struct rtc_device       *rtc;
        void __iomem            *reg_base;
        int                     alarm_irq;
        int                     sec_irq;
-       unsigned int            calibval;
+       struct clk              *rtc_clk;
+       unsigned int            freq;
 };
 
 static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -61,13 +68,6 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
         */
        new_time = rtc_tm_to_time64(tm) + 1;
 
-       /*
-        * Writing into calibration register will clear the Tick Counter and
-        * force the next second to be signaled exactly in 1 second period
-        */
-       xrtcdev->calibval &= RTC_CALIB_MASK;
-       writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
-
        writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);
 
        /*
@@ -173,15 +173,76 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
        rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL);
        rtc_ctrl |= RTC_BATT_EN;
        writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL);
+}
 
-       /*
-        * Based on crystal freq of 33.330 KHz
-        * set the seconds counter and enable, set fractions counter
-        * to default value suggested as per design spec
-        * to correct RTC delay in frequency over period of time.
+static int xlnx_rtc_read_offset(struct device *dev, long *offset)
+{
+       struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+       unsigned long long rtc_ppb = RTC_PPB;
+       unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
+       unsigned int calibval;
+       long offset_val;
+
+       calibval = readl(xrtcdev->reg_base + RTC_CALIB_RD);
+       /* Offset with seconds ticks */
+       offset_val = calibval & RTC_TICK_MASK;
+       offset_val = offset_val - RTC_CALIB_DEF;
+       offset_val = offset_val * tick_mult;
+
+       /* Offset with fractional ticks */
+       if (calibval & RTC_FR_EN)
+               offset_val += ((calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT)
+                       * (tick_mult / RTC_FR_MAX_TICKS);
+       *offset = offset_val;
+
+       return 0;
+}
+
+static int xlnx_rtc_set_offset(struct device *dev, long offset)
+{
+       struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+       unsigned long long rtc_ppb = RTC_PPB;
+       unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
+       unsigned char fract_tick = 0;
+       unsigned int calibval;
+       short int  max_tick;
+       int fract_offset;
+
+       if (offset < RTC_MIN_OFFSET || offset > RTC_MAX_OFFSET)
+               return -ERANGE;
+
+       /* Number ticks for given offset */
+       max_tick = div_s64_rem(offset, tick_mult, &fract_offset);
+
+       /* Number fractional ticks for given offset */
+       if (fract_offset) {
+               if (fract_offset < 0) {
+                       fract_offset = fract_offset + tick_mult;
+                       max_tick--;
+               }
+               if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {
+                       for (fract_tick = 1; fract_tick < 16; fract_tick++) {
+                               if (fract_offset <=
+                                   (fract_tick *
+                                    (tick_mult / RTC_FR_MAX_TICKS)))
+                                       break;
+                       }
+               }
+       }
+
+       /* Zynqmp RTC uses second and fractional tick
+        * counters for compensation
         */
-       xrtcdev->calibval &= RTC_CALIB_MASK;
-       writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
+       calibval = max_tick + RTC_CALIB_DEF;
+
+       if (fract_tick)
+               calibval |= RTC_FR_EN;
+
+       calibval |= (fract_tick << RTC_FR_DATSHIFT);
+
+       writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
+
+       return 0;
 }
 
 static const struct rtc_class_ops xlnx_rtc_ops = {
@@ -190,6 +251,8 @@ static const struct rtc_class_ops xlnx_rtc_ops = {
        .read_alarm       = xlnx_rtc_read_alarm,
        .set_alarm        = xlnx_rtc_set_alarm,
        .alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
+       .read_offset      = xlnx_rtc_read_offset,
+       .set_offset       = xlnx_rtc_set_offset,
 };
 
 static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
@@ -255,10 +318,22 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = of_property_read_u32(pdev->dev.of_node, "calibration",
-                                  &xrtcdev->calibval);
-       if (ret)
-               xrtcdev->calibval = RTC_CALIB_DEF;
+       /* Getting the rtc_clk info */
+       xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc_clk");
+       if (IS_ERR(xrtcdev->rtc_clk)) {
+               if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)
+                       dev_warn(&pdev->dev, "Device clock not found.\n");
+       }
+       xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);
+       if (!xrtcdev->freq) {
+               ret = of_property_read_u32(pdev->dev.of_node, "calibration",
+                                          &xrtcdev->freq);
+               if (ret)
+                       xrtcdev->freq = RTC_CALIB_DEF;
+       }
+       ret = readl(xrtcdev->reg_base + RTC_CALIB_RD);
+       if (!ret)
+               writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR));
 
        xlnx_init_rtc(xrtcdev);