OSDN Git Service

Merge tag 'rtc-v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 26 Jun 2015 01:55:33 +0000 (18:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 26 Jun 2015 01:55:33 +0000 (18:55 -0700)
Pull RTC updates from Alexandre Belloni:
 "Core:
   - Coding style and whitespace fixes (interface, Makefile and Kconfig)
   - New rtc_tm_sub() helper
   - New CONFIG_RTC_SYSTOHC_DEVICE option
   - Removed rtc_set_mmss()

  New drivers:
   - Mediatek MT6397
   - Cortina Gemini

  Drivers:
   - Year 2106 fixes for isl1208, pcf8563 and sunxi
   - update author email for at32ap700x and efi
   - ds1307: alarm fix
   - efi: use correct EFI 'epoch'
   - hym8563: make irq optional
   - imxdi: cleanups and better handling of the security/tamper monitoring
   - snvs: fix wakealarm
   - Compilation fixes or warning removal for gemini, mt6397, palmas, pfc8563
   - Trivial cleanups for ab8500, ds1216, ds1286, ds1672, ep93xx,
     hid-sensor-time, max6900, max8998, max77686, max77802, mc13xxx, mv,
     mxc, s3c, spear, v3020
   - Kconfig fixes for stmp3xxx and xgene"

* tag 'rtc-v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (48 commits)
  rtc: remove useless I2C dependencies
  rtc: whitespace fixes
  rtc: Properly sort Makefile
  MAINTAINERS: Add RTC subsystem repository
  rtc: pfc8563: fix uninitialized variable warning
  rtc: ds1307: Enable the mcp794xx alarm after programming time
  rtc: hym8563: make the irq optional
  rtc: gemini: fix cocci warnings
  rtc: mv: correct 24 hour error message
  rtc: mv: use BIT()
  rtc: efi: use correct EFI 'epoch'
  rtc: interface: Remove rtc_set_mmss()
  sparc: time: Replace update_persistent_clock() with CONFIG_RTC_SYSTOHC
  rtc: NTP: Add CONFIG_RTC_SYSTOHC_DEVICE for NTP synchronization
  rtc: sunxi: Replace deprecated rtc_tm_to_time()
  rtc: isl1208: Replace deprecated rtc_tm_to_time()
  rtc: Introduce rtc_tm_sub() helper function
  rtc: pcf8563: Replace deprecated rtc_time_to_tm() and rtc_tm_to_time()
  rtc: palmas: Initialise bb_charging flag before using it
  rtc: simplify use of devm_ioremap_resource
  ...

39 files changed:
Documentation/devicetree/bindings/rtc/haoyu,hym8563.txt
MAINTAINERS
arch/sparc/Kconfig
arch/sparc/kernel/time_32.c
arch/sparc/kernel/time_64.c
drivers/mfd/mt6397-core.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/interface.c
drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-at32ap700x.c
drivers/rtc/rtc-ds1216.c
drivers/rtc/rtc-ds1286.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-gemini.c [new file with mode: 0644]
drivers/rtc/rtc-hid-sensor-time.c
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-imxdi.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-max6900.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max77802.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-mt6397.c [new file with mode: 0644]
drivers/rtc/rtc-mv.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-palmas.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-sunxi.c
drivers/rtc/rtc-v3020.c
drivers/rtc/systohc.c
include/linux/rtc.h

index 5c199ee..a8934fe 100644 (file)
@@ -6,11 +6,11 @@ as well as a clock output of up to 32kHz.
 Required properties:
 - compatible: should be: "haoyu,hym8563"
 - reg: i2c address
-- interrupts: rtc alarm/event interrupt
 - #clock-cells: the value should be 0
 
 Optional properties:
 - clock-output-names: From common clock binding
+- interrupts: rtc alarm/event interrupt
 
 Example:
 
index d73b656..a01df30 100644 (file)
@@ -984,6 +984,7 @@ L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/ulli-kroll/linux.git
 S:     Maintained
 F:     arch/arm/mach-gemini/
+F:     drivers/rtc/rtc-gemini.c
 
 ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
 M:     Barry Song <baohua@kernel.org>
@@ -1243,6 +1244,13 @@ W:       http://www.digriz.org.uk/ts78xx/kernel
 S:     Maintained
 F:     arch/arm/mach-orion5x/ts78xx-*
 
+ARM/Mediatek RTC DRIVER
+M:     Eddie Huang <eddie.huang@mediatek.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/rtc/rtc-mt6397.c
+
 ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -8380,6 +8388,7 @@ M:        Alessandro Zummo <a.zummo@towertech.it>
 M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
 L:     rtc-linux@googlegroups.com
 Q:     http://patchwork.ozlabs.org/project/rtc-linux/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
 S:     Maintained
 F:     Documentation/rtc.txt
 F:     drivers/rtc/
index e49502a..56442d2 100644 (file)
@@ -25,6 +25,7 @@ config SPARC
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select RTC_CLASS
        select RTC_DRV_M48T59
+       select RTC_SYSTOHC
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
        select HAVE_ARCH_JUMP_LABEL if SPARC64
@@ -35,7 +36,6 @@ config SPARC
        select HAVE_BPF_JIT
        select HAVE_DEBUG_BUGVERBOSE
        select GENERIC_SMP_IDLE_THREAD
-       select GENERIC_CMOS_UPDATE
        select GENERIC_CLOCKEVENTS
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
index 8caf45e..c9692f3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
-#include <linux/rtc.h>
 #include <linux/rtc/m48t59.h>
 #include <linux/timex.h>
 #include <linux/clocksource.h>
@@ -65,8 +64,6 @@ DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent);
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
-static int set_rtc_mmss(unsigned long);
-
 unsigned long profile_pc(struct pt_regs *regs)
 {
        extern char __copy_user_begin[], __copy_user_end[];
@@ -87,11 +84,6 @@ EXPORT_SYMBOL(profile_pc);
 
 volatile u32 __iomem *master_l10_counter;
 
-int update_persistent_clock(struct timespec now)
-{
-       return set_rtc_mmss(now.tv_sec);
-}
-
 irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
 {
        if (timer_cs_enabled) {
@@ -362,16 +354,3 @@ void __init time_init(void)
                sbus_time_init();
 }
 
-
-static int set_rtc_mmss(unsigned long secs)
-{
-       struct rtc_device *rtc = rtc_class_open("rtc0");
-       int err = -1;
-
-       if (rtc) {
-               err = rtc_set_mmss(rtc, secs);
-               rtc_class_close(rtc);
-       }
-
-       return err;
-}
index edbbeb1..2e6035c 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/cpufreq.h>
 #include <linux/percpu.h>
 #include <linux/miscdevice.h>
-#include <linux/rtc.h>
 #include <linux/rtc/m48t59.h>
 #include <linux/kernel_stat.h>
 #include <linux/clockchips.h>
@@ -394,19 +393,6 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = {
 
 static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
 
-int update_persistent_clock(struct timespec now)
-{
-       struct rtc_device *rtc = rtc_class_open("rtc0");
-       int err = -1;
-
-       if (rtc) {
-               err = rtc_set_mmss(rtc, now.tv_sec);
-               rtc_class_close(rtc);
-       }
-
-       return err;
-}
-
 unsigned long cmos_regs;
 EXPORT_SYMBOL(cmos_regs);
 
index 38a0458..03929a6 100644 (file)
 #include <linux/mfd/mt6397/core.h>
 #include <linux/mfd/mt6397/registers.h>
 
+#define MT6397_RTC_BASE                0xe000
+#define MT6397_RTC_SIZE                0x3e
+
+static const struct resource mt6397_rtc_resources[] = {
+       {
+               .start = MT6397_RTC_BASE,
+               .end   = MT6397_RTC_BASE + MT6397_RTC_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = MT6397_IRQ_RTC,
+               .end   = MT6397_IRQ_RTC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
 static const struct mfd_cell mt6397_devs[] = {
        {
                .name = "mt6397-rtc",
+               .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
+               .resources = mt6397_rtc_resources,
                .of_compatible = "mediatek,mt6397-rtc",
        }, {
                .name = "mt6397-regulator",
index 5e963df..db2fe4a 100644 (file)
@@ -12,7 +12,7 @@ menuconfig RTC_CLASS
        select RTC_LIB
        help
          Generic RTC class support. If you say yes here, you will
-         be allowed to plug one or more RTCs to your system. You will
+         be allowed to plug one or more RTCs to your system. You will
          probably want to enable one or more of the interfaces below.
 
 if RTC_CLASS
@@ -25,17 +25,9 @@ config RTC_HCTOSYS
          the value read from a specified RTC device. This is useful to avoid
          unnecessary fsck runs at boot time, and to network better.
 
-config RTC_SYSTOHC
-       bool "Set the RTC time based on NTP synchronization"
-       default y
-       help
-         If you say yes here, the system time (wall clock) will be stored
-         in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11
-         minutes if userspace reports synchronized NTP status.
-
 config RTC_HCTOSYS_DEVICE
        string "RTC used to set the system time"
-       depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y
+       depends on RTC_HCTOSYS
        default "rtc0"
        help
          The RTC device that will be used to (re)initialize the system
@@ -56,6 +48,25 @@ config RTC_HCTOSYS_DEVICE
          sleep states. Do not specify an RTC here unless it stays powered
          during all this system's supported sleep states.
 
+config RTC_SYSTOHC
+       bool "Set the RTC time based on NTP synchronization"
+       default y
+       help
+         If you say yes here, the system time (wall clock) will be stored
+         in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11
+         minutes if userspace reports synchronized NTP status.
+
+config RTC_SYSTOHC_DEVICE
+       string "RTC used to synchronize NTP adjustment"
+       depends on RTC_SYSTOHC
+       default RTC_HCTOSYS_DEVICE if RTC_HCTOSYS
+       default "rtc0"
+       help
+         The RTC device used for NTP synchronization. The main difference
+         between RTC_HCTOSYS_DEVICE and RTC_SYSTOHC_DEVICE is that this
+         one can sleep when setting time, because it runs in the workqueue
+         context.
+
 config RTC_DEBUG
        bool "RTC debug support"
        help
@@ -135,7 +146,7 @@ if I2C
 
 config RTC_DRV_88PM860X
        tristate "Marvell 88PM860x"
-       depends on I2C && MFD_88PM860X
+       depends on MFD_88PM860X
        help
          If you say yes here you get support for RTC function in Marvell
          88PM860x chips.
@@ -145,7 +156,7 @@ config RTC_DRV_88PM860X
 
 config RTC_DRV_88PM80X
        tristate "Marvell 88PM80x"
-       depends on I2C && MFD_88PM800
+       depends on MFD_88PM800
        help
          If you say yes here you get support for RTC function in Marvell
          88PM80x chips.
@@ -154,10 +165,9 @@ config RTC_DRV_88PM80X
          will be called rtc-88pm80x.
 
 config RTC_DRV_ABB5ZES3
-       depends on I2C
-       select REGMAP_I2C
-       tristate "Abracon AB-RTCMC-32.768kHz-B5ZE-S3"
-       help
+       select REGMAP_I2C
+       tristate "Abracon AB-RTCMC-32.768kHz-B5ZE-S3"
+       help
          If you say yes here you get support for the Abracon
          AB-RTCMC-32.768kHz-B5ZE-S3 I2C RTC chip.
 
@@ -204,7 +214,6 @@ config RTC_DRV_DS1307
 
 config RTC_DRV_DS1374
        tristate "Dallas/Maxim DS1374"
-       depends on I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1374 real-time clock chips. If an interrupt is associated
@@ -232,7 +241,6 @@ config RTC_DRV_DS1672
 
 config RTC_DRV_DS3232
        tristate "Dallas/Maxim DS3232"
-       depends on I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS3232 real-time clock chips. If an interrupt is associated
@@ -243,7 +251,7 @@ config RTC_DRV_DS3232
 
 config RTC_DRV_HYM8563
        tristate "Haoyu Microelectronics HYM8563"
-       depends on I2C && OF
+       depends on OF
        help
          Say Y to enable support for the HYM8563 I2C RTC chip. Apart
          from the usual rtc functions it provides a clock output of
@@ -365,10 +373,9 @@ config RTC_DRV_ISL12022
          will be called rtc-isl12022.
 
 config RTC_DRV_ISL12057
-       depends on I2C
-       select REGMAP_I2C
-       tristate "Intersil ISL12057"
-       help
+       select REGMAP_I2C
+       tristate "Intersil ISL12057"
+       help
          If you say yes here you get support for the Intersil ISL12057
          I2C RTC chip.
 
@@ -603,13 +610,13 @@ comment "SPI RTC drivers"
 if SPI_MASTER
 
 config RTC_DRV_M41T93
-        tristate "ST M41T93"
-        help
-          If you say yes here you will get support for the
-          ST M41T93 SPI RTC chip.
+       tristate "ST M41T93"
+       help
+         If you say yes here you will get support for the
+         ST M41T93 SPI RTC chip.
 
-          This driver can also be built as a module. If so, the module
-          will be called rtc-m41t93.
+         This driver can also be built as a module. If so, the module
+         will be called rtc-m41t93.
 
 config RTC_DRV_M41T94
        tristate "ST M41T94"
@@ -1200,7 +1207,7 @@ config RTC_DRV_SH
          Say Y here to enable support for the on-chip RTC found in
          most SuperH processors.
 
-         To compile this driver as a module, choose M here: the
+         To compile this driver as a module, choose M here: the
          module will be called rtc-sh.
 
 config RTC_DRV_VR41XX
@@ -1299,14 +1306,14 @@ config RTC_DRV_GENERIC
          just say Y.
 
 config RTC_DRV_PXA
-       tristate "PXA27x/PXA3xx"
-       depends on ARCH_PXA
-       help
-         If you say Y here you will get access to the real time clock
-         built into your PXA27x or PXA3xx CPU.
+       tristate "PXA27x/PXA3xx"
+       depends on ARCH_PXA
+       help
+        If you say Y here you will get access to the real time clock
+        built into your PXA27x or PXA3xx CPU.
 
-         This RTC driver uses PXA RTC registers available since pxa27x
-         series (RDxR, RYxR) instead of legacy RCNR, RTAR.
+        This RTC driver uses PXA RTC registers available since pxa27x
+        series (RDxR, RYxR) instead of legacy RCNR, RTAR.
 
 config RTC_DRV_VT8500
        tristate "VIA/WonderMedia 85xx SoC RTC"
@@ -1372,6 +1379,17 @@ config RTC_DRV_ARMADA38X
          This driver can also be built as a module. If so, the module
          will be called armada38x-rtc.
 
+config RTC_DRV_GEMINI
+       tristate "Gemini SoC RTC"
+       depends on ARCH_GEMINI || COMPILE_TEST
+       depends on HAS_IOMEM
+       help
+         If you say Y here you will get support for the
+         RTC found on Gemini SoC's.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-gemini.
+
 config RTC_DRV_PS3
        tristate "PS3 RTC"
        depends on PPC_PS3
@@ -1396,6 +1414,7 @@ config RTC_DRV_COH901331
 config RTC_DRV_STMP
        tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
        depends on ARCH_MXS
+       select STMP_DEVICE
        help
          If you say yes here you will get support for the onboard
          STMP3xxx/i.MX23/i.MX28 RTC.
@@ -1541,9 +1560,20 @@ config RTC_DRV_MOXART
           This driver can also be built as a module. If so, the module
           will be called rtc-moxart
 
+config RTC_DRV_MT6397
+       tristate "Mediatek Real Time Clock driver"
+       depends on MFD_MT6397 || COMPILE_TEST
+       help
+         This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
+         MT6397 PMIC. You should enable MT6397 PMIC MFD before select
+         Mediatek(R) RTC driver.
+
+         If you want to use Mediatek(R) RTC interface, select Y or M here.
+
 config RTC_DRV_XGENE
        tristate "APM X-Gene RTC"
        depends on HAS_IOMEM
+       depends on ARCH_XGENE || COMPILE_TEST
        help
          If you say yes here you get support for the APM X-Gene SoC real time
          clock.
index ebe2c08..1b09a62 100644 (file)
@@ -14,14 +14,14 @@ ifdef CONFIG_RTC_DRV_EFI
 rtc-core-y                     += rtc-efi-platform.o
 endif
 
-rtc-core-$(CONFIG_RTC_INTF_DEV)        += rtc-dev.o
-rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
-rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
+rtc-core-$(CONFIG_RTC_INTF_DEV)                += rtc-dev.o
+rtc-core-$(CONFIG_RTC_INTF_PROC)       += rtc-proc.o
+rtc-core-$(CONFIG_RTC_INTF_SYSFS)      += rtc-sysfs.o
 
 # Keep the list ordered.
 
-obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-88pm860x.o
 obj-$(CONFIG_RTC_DRV_88PM80X)  += rtc-88pm80x.o
+obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o
 obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
@@ -43,7 +43,6 @@ obj-$(CONFIG_RTC_DRV_DA9063)  += rtc-da9063.o
 obj-$(CONFIG_RTC_DRV_DAVINCI)  += rtc-davinci.o
 obj-$(CONFIG_RTC_DRV_DIGICOLOR)        += rtc-digicolor.o
 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
-obj-$(CONFIG_RTC_DRV_VRTC)     += rtc-mrst.o
 obj-$(CONFIG_RTC_DRV_DS1216)   += rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1286)   += rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1302)   += rtc-ds1302.o
@@ -58,20 +57,21 @@ obj-$(CONFIG_RTC_DRV_DS1553)        += rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)   += rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1685_FAMILY)    += rtc-ds1685.o
 obj-$(CONFIG_RTC_DRV_DS1742)   += rtc-ds1742.o
-obj-$(CONFIG_RTC_DRV_DS2404)    += rtc-ds2404.o
+obj-$(CONFIG_RTC_DRV_DS2404)   += rtc-ds2404.o
 obj-$(CONFIG_RTC_DRV_DS3232)   += rtc-ds3232.o
 obj-$(CONFIG_RTC_DRV_DS3234)   += rtc-ds3234.o
 obj-$(CONFIG_RTC_DRV_EFI)      += rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EM3027)   += rtc-em3027.o
 obj-$(CONFIG_RTC_DRV_EP93XX)   += rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)   += rtc-fm3130.o
+obj-$(CONFIG_RTC_DRV_GEMINI)   += rtc-gemini.o
 obj-$(CONFIG_RTC_DRV_GENERIC)  += rtc-generic.o
 obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
 obj-$(CONFIG_RTC_DRV_HYM8563)  += rtc-hym8563.o
 obj-$(CONFIG_RTC_DRV_IMXDI)    += rtc-imxdi.o
-obj-$(CONFIG_RTC_DRV_ISL1208)  += rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
 obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o
+obj-$(CONFIG_RTC_DRV_ISL1208)  += rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_JZ4740)   += rtc-jz4740.o
 obj-$(CONFIG_RTC_DRV_LP8788)   += rtc-lp8788.o
 obj-$(CONFIG_RTC_DRV_LPC32XX)  += rtc-lpc32xx.o
@@ -82,32 +82,35 @@ obj-$(CONFIG_RTC_DRV_M41T94)        += rtc-m41t94.o
 obj-$(CONFIG_RTC_DRV_M48T35)   += rtc-m48t35.o
 obj-$(CONFIG_RTC_DRV_M48T59)   += rtc-m48t59.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
-obj-$(CONFIG_RTC_DRV_MXC)      += rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
+obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
+obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
 obj-$(CONFIG_RTC_DRV_MAX8907)  += rtc-max8907.o
 obj-$(CONFIG_RTC_DRV_MAX8925)  += rtc-max8925.o
-obj-$(CONFIG_RTC_DRV_MAX8998)  += rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MAX8997)  += rtc-max8997.o
-obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
-obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
-obj-$(CONFIG_RTC_DRV_MAX77802)  += rtc-max77802.o
+obj-$(CONFIG_RTC_DRV_MAX8998)  += rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MC13XXX)  += rtc-mc13xxx.o
 obj-$(CONFIG_RTC_DRV_MCP795)   += rtc-mcp795.o
-obj-$(CONFIG_RTC_DRV_MSM6242)  += rtc-msm6242.o
+obj-$(CONFIG_RTC_DRV_MOXART)   += rtc-moxart.o
 obj-$(CONFIG_RTC_DRV_MPC5121)  += rtc-mpc5121.o
+obj-$(CONFIG_RTC_DRV_VRTC)     += rtc-mrst.o
+obj-$(CONFIG_RTC_DRV_MSM6242)  += rtc-msm6242.o
+obj-$(CONFIG_RTC_DRV_MT6397)   += rtc-mt6397.o
 obj-$(CONFIG_RTC_DRV_MV)       += rtc-mv.o
+obj-$(CONFIG_RTC_DRV_MXC)      += rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_NUC900)   += rtc-nuc900.o
-obj-$(CONFIG_RTC_DRV_OPAL)     += rtc-opal.o
 obj-$(CONFIG_RTC_DRV_OMAP)     += rtc-omap.o
+obj-$(CONFIG_RTC_DRV_OPAL)     += rtc-opal.o
 obj-$(CONFIG_RTC_DRV_PALMAS)   += rtc-palmas.o
 obj-$(CONFIG_RTC_DRV_PCAP)     += rtc-pcap.o
+obj-$(CONFIG_RTC_DRV_PCF2123)  += rtc-pcf2123.o
 obj-$(CONFIG_RTC_DRV_PCF2127)  += rtc-pcf2127.o
+obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
+obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
 obj-$(CONFIG_RTC_DRV_PCF8523)  += rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)  += rtc-pcf8563.o
-obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
 obj-$(CONFIG_RTC_DRV_PCF8583)  += rtc-pcf8583.o
-obj-$(CONFIG_RTC_DRV_PCF2123)  += rtc-pcf2123.o
-obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.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
@@ -130,21 +133,23 @@ obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_S5M)      += rtc-s5m.o
 obj-$(CONFIG_RTC_DRV_SA1100)   += rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
+obj-$(CONFIG_RTC_DRV_SIRFSOC)  += rtc-sirfsoc.o
 obj-$(CONFIG_RTC_DRV_SNVS)     += rtc-snvs.o
 obj-$(CONFIG_RTC_DRV_SPEAR)    += rtc-spear.o
 obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
 obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
 obj-$(CONFIG_RTC_DRV_STMP)     += rtc-stmp3xxx.o
+obj-$(CONFIG_RTC_DRV_ST_LPC)   += rtc-st-lpc.o
 obj-$(CONFIG_RTC_DRV_SUN4V)    += rtc-sun4v.o
 obj-$(CONFIG_RTC_DRV_SUN6I)    += rtc-sun6i.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_TILE)     += rtc-tile.o
-obj-$(CONFIG_RTC_DRV_TWL4030)  += rtc-twl.o
 obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
 obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
 obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o
+obj-$(CONFIG_RTC_DRV_TWL4030)  += rtc-twl.o
 obj-$(CONFIG_RTC_DRV_TX4939)   += rtc-tx4939.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_VR41XX)   += rtc-vr41xx.o
@@ -153,6 +158,3 @@ obj-$(CONFIG_RTC_DRV_WM831X)        += rtc-wm831x.o
 obj-$(CONFIG_RTC_DRV_WM8350)   += rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)    += rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_XGENE)    += rtc-xgene.o
-obj-$(CONFIG_RTC_DRV_SIRFSOC)  += rtc-sirfsoc.o
-obj-$(CONFIG_RTC_DRV_ST_LPC)   += rtc-st-lpc.o
-obj-$(CONFIG_RTC_DRV_MOXART)   += rtc-moxart.o
index 166fc60..11b6390 100644 (file)
@@ -91,51 +91,6 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
 }
 EXPORT_SYMBOL_GPL(rtc_set_time);
 
-int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
-{
-       int err;
-
-       err = mutex_lock_interruptible(&rtc->ops_lock);
-       if (err)
-               return err;
-
-       if (!rtc->ops)
-               err = -ENODEV;
-       else if (rtc->ops->set_mmss64)
-               err = rtc->ops->set_mmss64(rtc->dev.parent, secs);
-       else if (rtc->ops->set_mmss)
-               err = rtc->ops->set_mmss(rtc->dev.parent, secs);
-       else if (rtc->ops->read_time && rtc->ops->set_time) {
-               struct rtc_time new, old;
-
-               err = rtc->ops->read_time(rtc->dev.parent, &old);
-               if (err == 0) {
-                       rtc_time64_to_tm(secs, &new);
-
-                       /*
-                        * avoid writing when we're going to change the day of
-                        * the month. We will retry in the next minute. This
-                        * basically means that if the RTC must not drift
-                        * by more than 1 minute in 11 minutes.
-                        */
-                       if (!((old.tm_hour == 23 && old.tm_min == 59) ||
-                               (new.tm_hour == 23 && new.tm_min == 59)))
-                               err = rtc->ops->set_time(rtc->dev.parent,
-                                               &new);
-               }
-       } else {
-               err = -EINVAL;
-       }
-
-       pm_stay_awake(rtc->dev.parent);
-       mutex_unlock(&rtc->ops_lock);
-       /* A timer might have just expired */
-       schedule_work(&rtc->irqwork);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(rtc_set_mmss);
-
 static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 {
        int err;
@@ -976,14 +931,12 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
  *
  * Kernel interface to cancel an rtc_timer
  */
-int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
+void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
 {
-       int ret = 0;
        mutex_lock(&rtc->ops_lock);
        if (timer->enabled)
                rtc_timer_remove(rtc, timer);
        mutex_unlock(&rtc->ops_lock);
-       return ret;
 }
 
 
index 6856f0a..133d2e2 100644 (file)
@@ -442,7 +442,7 @@ static const struct rtc_class_ops ab8540_rtc_ops = {
        .alarm_irq_enable       = ab8500_rtc_irq_enable,
 };
 
-static struct platform_device_id ab85xx_rtc_ids[] = {
+static const struct platform_device_id ab85xx_rtc_ids[] = {
        { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
        { "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, },
 };
index d618d6c..83ac233 100644 (file)
@@ -282,6 +282,6 @@ static struct platform_driver at32_rtc_driver = {
 
 module_platform_driver_probe(at32_rtc_driver, at32_rtc_probe);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
 MODULE_LICENSE("GPL");
index d16f550..12dbd70 100644 (file)
@@ -144,15 +144,13 @@ static int __init ds1216_rtc_probe(struct platform_device *pdev)
        struct ds1216_priv *priv;
        u8 dummy[8];
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        platform_set_drvdata(pdev, priv);
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->ioaddr = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->ioaddr))
                return PTR_ERR(priv->ioaddr);
index 2fe537f..8247a29 100644 (file)
@@ -332,13 +332,11 @@ static int ds1286_probe(struct platform_device *pdev)
        struct resource *res;
        struct ds1286_priv *priv;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
        priv = devm_kzalloc(&pdev->dev, sizeof(struct ds1286_priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->rtcregs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->rtcregs))
                return PTR_ERR(priv->rtcregs);
index 4ffabb3..6e76de1 100644 (file)
@@ -742,17 +742,17 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        regs[6] &= ~MCP794XX_BIT_ALMX_IF;
        /* Set alarm match: second, minute, hour, day, date, month. */
        regs[6] |= MCP794XX_MSK_ALMX_MATCH;
-
-       if (t->enabled)
-               regs[0] |= MCP794XX_BIT_ALM0_EN;
-       else
-               regs[0] &= ~MCP794XX_BIT_ALM0_EN;
+       /* Disable interrupt. We will not enable until completely programmed */
+       regs[0] &= ~MCP794XX_BIT_ALM0_EN;
 
        ret = ds1307->write_block_data(client, MCP794XX_REG_CONTROL, 10, regs);
        if (ret < 0)
                return ret;
 
-       return 0;
+       if (!t->enabled)
+               return 0;
+       regs[0] |= MCP794XX_BIT_ALM0_EN;
+       return i2c_smbus_write_byte_data(client, MCP794XX_REG_CONTROL, regs[0]);
 }
 
 static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
index a4888db..92b1cbf 100644 (file)
@@ -198,6 +198,7 @@ static struct i2c_device_id ds1672_id[] = {
        { "ds1672", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c, ds1672_id);
 
 static struct i2c_driver ds1672_driver = {
        .driver = {
index cb989cd..3806961 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  *
- * Author: dann frazier <dannf@hp.com>
+ * Author: dann frazier <dannf@dannf.org>
  * Based on efirtc.c by Stephane Eranian
  *
  *  This program is free software; you can redistribute  it and/or modify it
 #include <linux/efi.h>
 
 #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT)
-/*
- * EFI Epoch is 1/1/1998
- */
-#define EFI_RTC_EPOCH          1998
 
 /*
  * returns day of the year [0-365]
@@ -38,31 +34,24 @@ compute_yday(efi_time_t *eft)
        /* efi_time_t.month is in the [1-12] so, we need -1 */
        return rtc_year_days(eft->day, eft->month - 1, eft->year);
 }
+
 /*
  * returns day of the week [0-6] 0=Sunday
- *
- * Don't try to provide a year that's before 1998, please !
  */
 static int
-compute_wday(efi_time_t *eft)
+compute_wday(efi_time_t *eft, int yday)
 {
-       int y;
-       int ndays = 0;
-
-       if (eft->year < EFI_RTC_EPOCH) {
-               pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", invalid date\n");
-               return -1;
-       }
-
-       for (y = EFI_RTC_EPOCH; y < eft->year; y++)
-               ndays += 365 + (is_leap_year(y) ? 1 : 0);
-
-       ndays += compute_yday(eft);
+       int ndays = eft->year * (365 % 7)
+                   + (eft->year - 1) / 4
+                   - (eft->year - 1) / 100
+                   + (eft->year - 1) / 400
+                   + yday;
 
        /*
-        * 4=1/1/1998 was a Thursday
+        * 1/1/0000 may or may not have been a Sunday (if it ever existed at
+        * all) but assuming it was makes this calculation work correctly.
         */
-       return (ndays + 4) % 7;
+       return ndays % 7;
 }
 
 static void
@@ -103,16 +92,16 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
        if (!eft->month || eft->month > 12)
                return false;
        wtime->tm_mon  = eft->month - 1;
-       wtime->tm_year = eft->year - 1900;
 
-       /* day of the week [0-6], Sunday=0 */
-       wtime->tm_wday = compute_wday(eft);
-       if (wtime->tm_wday < 0)
+       if (eft->year < 1900 || eft->year > 9999)
                return false;
+       wtime->tm_year = eft->year - 1900;
 
        /* day in the year [1-365]*/
        wtime->tm_yday = compute_yday(eft);
 
+       /* day of the week [0-6], Sunday=0 */
+       wtime->tm_wday = compute_wday(eft, wtime->tm_yday);
 
        switch (eft->daylight & EFI_ISDST) {
        case EFI_ISDST:
@@ -233,7 +222,7 @@ static struct platform_driver efi_rtc_driver = {
 module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
 
 MODULE_ALIAS("platform:rtc-efi");
-MODULE_AUTHOR("dann frazier <dannf@hp.com>");
+MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("EFI RTC driver");
 MODULE_ALIAS("platform:rtc-efi");
index de325d6..a1628ad 100644 (file)
@@ -45,7 +45,7 @@ static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
        struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
        unsigned long comp;
 
-       comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
+       comp = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
 
        if (preload)
                *preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK)
@@ -63,7 +63,7 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
        struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
        unsigned long time;
 
-        time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
+        time = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
 
        rtc_time_to_tm(time, tm);
        return 0;
@@ -73,7 +73,7 @@ static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
 {
        struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
 
-       __raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
+       writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
        return 0;
 }
 
diff --git a/drivers/rtc/rtc-gemini.c b/drivers/rtc/rtc-gemini.c
new file mode 100644 (file)
index 0000000..35f4486
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  Gemini OnChip RTC
+ *
+ *  Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Original code for older kernel 2.6.15 are from Stormlinksemi
+ * first update from Janos Laube for > 2.6.29 kernels
+ *
+ * checkpatch fixes and usage of rtc-lib code
+ * Hans Ulli Kroll <ulli.kroll@googlemail.com>
+ */
+
+#include <linux/rtc.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define DRV_NAME        "rtc-gemini"
+#define DRV_VERSION     "0.2"
+
+MODULE_AUTHOR("Hans Ulli Kroll <ulli.kroll@googlemail.com>");
+MODULE_DESCRIPTION("RTC driver for Gemini SoC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+
+struct gemini_rtc {
+       struct rtc_device       *rtc_dev;
+       void __iomem            *rtc_base;
+       int                     rtc_irq;
+};
+
+enum gemini_rtc_offsets {
+       GEMINI_RTC_SECOND       = 0x00,
+       GEMINI_RTC_MINUTE       = 0x04,
+       GEMINI_RTC_HOUR         = 0x08,
+       GEMINI_RTC_DAYS         = 0x0C,
+       GEMINI_RTC_ALARM_SECOND = 0x10,
+       GEMINI_RTC_ALARM_MINUTE = 0x14,
+       GEMINI_RTC_ALARM_HOUR   = 0x18,
+       GEMINI_RTC_RECORD       = 0x1C,
+       GEMINI_RTC_CR           = 0x20
+};
+
+static irqreturn_t gemini_rtc_interrupt(int irq, void *dev)
+{
+       return IRQ_HANDLED;
+}
+
+/*
+ * Looks like the RTC in the Gemini SoC is (totaly) broken
+ * We can't read/write directly the time from RTC registers.
+ * We must do some "offset" calculation to get the real time
+ *
+ * This FIX works pretty fine and Stormlinksemi aka Cortina-Networks does
+ * the same thing, without the rtc-lib.c calls.
+ */
+
+static int gemini_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct gemini_rtc *rtc = dev_get_drvdata(dev);
+
+       unsigned int  days, hour, min, sec;
+       unsigned long offset, time;
+
+       sec  = readl(rtc->rtc_base + GEMINI_RTC_SECOND);
+       min  = readl(rtc->rtc_base + GEMINI_RTC_MINUTE);
+       hour = readl(rtc->rtc_base + GEMINI_RTC_HOUR);
+       days = readl(rtc->rtc_base + GEMINI_RTC_DAYS);
+       offset = readl(rtc->rtc_base + GEMINI_RTC_RECORD);
+
+       time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
+
+       rtc_time_to_tm(time, tm);
+
+       return 0;
+}
+
+static int gemini_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct gemini_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int sec, min, hour, day;
+       unsigned long offset, time;
+
+       if (tm->tm_year >= 2148)        /* EPOCH Year + 179 */
+               return -EINVAL;
+
+       rtc_tm_to_time(tm, &time);
+
+       sec = readl(rtc->rtc_base + GEMINI_RTC_SECOND);
+       min = readl(rtc->rtc_base + GEMINI_RTC_MINUTE);
+       hour = readl(rtc->rtc_base + GEMINI_RTC_HOUR);
+       day = readl(rtc->rtc_base + GEMINI_RTC_DAYS);
+
+       offset = time - (day * 86400 + hour * 3600 + min * 60 + sec);
+
+       writel(offset, rtc->rtc_base + GEMINI_RTC_RECORD);
+       writel(0x01, rtc->rtc_base + GEMINI_RTC_CR);
+
+       return 0;
+}
+
+static struct rtc_class_ops gemini_rtc_ops = {
+       .read_time     = gemini_rtc_read_time,
+       .set_time      = gemini_rtc_set_time,
+};
+
+static int gemini_rtc_probe(struct platform_device *pdev)
+{
+       struct gemini_rtc *rtc;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int ret;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+       if (unlikely(!rtc))
+               return -ENOMEM;
+       platform_set_drvdata(pdev, rtc);
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res)
+               return -ENODEV;
+
+       rtc->rtc_irq = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       rtc->rtc_base = devm_ioremap(dev, res->start,
+                                    resource_size(res));
+
+       ret = devm_request_irq(dev, rtc->rtc_irq, gemini_rtc_interrupt,
+                              IRQF_SHARED, pdev->name, dev);
+       if (unlikely(ret))
+               return ret;
+
+       rtc->rtc_dev = rtc_device_register(pdev->name, dev,
+                                          &gemini_rtc_ops, THIS_MODULE);
+       if (likely(IS_ERR(rtc->rtc_dev)))
+               return PTR_ERR(rtc->rtc_dev);
+
+       return 0;
+}
+
+static int gemini_rtc_remove(struct platform_device *pdev)
+{
+       struct gemini_rtc *rtc = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(rtc->rtc_dev);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver gemini_rtc_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+       .probe          = gemini_rtc_probe,
+       .remove         = gemini_rtc_remove,
+};
+
+module_platform_driver_probe(gemini_rtc_driver, gemini_rtc_probe);
index af4f85a..c398f74 100644 (file)
@@ -318,7 +318,7 @@ static int hid_time_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_device_id hid_time_ids[] = {
+static const struct platform_device_id hid_time_ids[] = {
        {
                /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
                .name = "HID-SENSOR-2000a0",
index 0f710e9..e9da795 100644 (file)
@@ -548,14 +548,16 @@ static int hym8563_probe(struct i2c_client *client,
                return ret;
        }
 
-       ret = devm_request_threaded_irq(&client->dev, client->irq,
-                                       NULL, hym8563_irq,
-                                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                                       client->name, hym8563);
-       if (ret < 0) {
-               dev_err(&client->dev, "irq %d request failed, %d\n",
-                       client->irq, ret);
-               return ret;
+       if (client->irq > 0) {
+               ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                               NULL, hym8563_irq,
+                                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                                               client->name, hym8563);
+               if (ret < 0) {
+                       dev_err(&client->dev, "irq %d request failed, %d\n",
+                               client->irq, ret);
+                       return ret;
+               }
        }
 
        /* check state of calendar information */
index c666eab..7bffd7f 100644 (file)
@@ -129,6 +129,324 @@ struct imxdi_dev {
        struct work_struct work;
 };
 
+/* Some background:
+ *
+ * The DryIce unit is a complex security/tamper monitor device. To be able do
+ * its job in a useful manner it runs a bigger statemachine to bring it into
+ * security/tamper failure state and once again to bring it out of this state.
+ *
+ * This unit can be in one of three states:
+ *
+ * - "NON-VALID STATE"
+ *   always after the battery power was removed
+ * - "FAILURE STATE"
+ *   if one of the enabled security events has happened
+ * - "VALID STATE"
+ *   if the unit works as expected
+ *
+ * Everything stops when the unit enters the failure state including the RTC
+ * counter (to be able to detect the time the security event happened).
+ *
+ * The following events (when enabled) let the DryIce unit enter the failure
+ * state:
+ *
+ * - wire-mesh-tamper detect
+ * - external tamper B detect
+ * - external tamper A detect
+ * - temperature tamper detect
+ * - clock tamper detect
+ * - voltage tamper detect
+ * - RTC counter overflow
+ * - monotonic counter overflow
+ * - external boot
+ *
+ * If we find the DryIce unit in "FAILURE STATE" and the TDCHL cleared, we
+ * can only detect this state. In this case the unit is completely locked and
+ * must force a second "SYSTEM POR" to bring the DryIce into the
+ * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
+ * If the TDCHL is set in the "FAILURE STATE" we are out of luck. In this case
+ * a battery power cycle is required.
+ *
+ * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
+ * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
+ * task, we bring back this unit into life.
+ */
+
+/*
+ * Do a write into the unit without interrupt support.
+ * We do not need to check the WEF here, because the only reason this kind of
+ * write error can happen is if we write to the unit twice within the 122 us
+ * interval. This cannot happen, since we are using this function only while
+ * setting up the unit.
+ */
+static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
+                              unsigned reg)
+{
+       /* do the register write */
+       writel(val, imxdi->ioaddr + reg);
+
+       /*
+        * now it takes four 32,768 kHz clock cycles to take
+        * the change into effect = 122 us
+        */
+       usleep_range(130, 200);
+}
+
+static void di_report_tamper_info(struct imxdi_dev *imxdi,  u32 dsr)
+{
+       u32 dtcr;
+
+       dtcr = readl(imxdi->ioaddr + DTCR);
+
+       dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
+       /* the following flags force a transition into the "FAILURE STATE" */
+       if (dsr & DSR_VTD)
+               dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
+                         dtcr & DTCR_VTE ? "" : "Spurious ");
+
+       if (dsr & DSR_CTD)
+               dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
+                         dtcr & DTCR_CTE ? "" : "Spurious ");
+
+       if (dsr & DSR_TTD)
+               dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n",
+                         dtcr & DTCR_TTE ? "" : "Spurious ");
+
+       if (dsr & DSR_SAD)
+               dev_emerg(&imxdi->pdev->dev,
+                         "%sSecure Controller Alarm Event\n",
+                         dtcr & DTCR_SAIE ? "" : "Spurious ");
+
+       if (dsr & DSR_EBD)
+               dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n",
+                         dtcr & DTCR_EBE ? "" : "Spurious ");
+
+       if (dsr & DSR_ETAD)
+               dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n",
+                         dtcr & DTCR_ETAE ? "" : "Spurious ");
+
+       if (dsr & DSR_ETBD)
+               dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n",
+                         dtcr & DTCR_ETBE ? "" : "Spurious ");
+
+       if (dsr & DSR_WTD)
+               dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n",
+                         dtcr & DTCR_WTE ? "" : "Spurious ");
+
+       if (dsr & DSR_MCO)
+               dev_emerg(&imxdi->pdev->dev,
+                         "%sMonotonic-counter Overflow Event\n",
+                         dtcr & DTCR_MOE ? "" : "Spurious ");
+
+       if (dsr & DSR_TCO)
+               dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n",
+                         dtcr & DTCR_TOE ? "" : "Spurious ");
+}
+
+static void di_what_is_to_be_done(struct imxdi_dev *imxdi,
+                                 const char *power_supply)
+{
+       dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit working again\n",
+                 power_supply);
+}
+
+static int di_handle_failure_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+       u32 dcr;
+
+       dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr);
+
+       /* report the cause */
+       di_report_tamper_info(imxdi, dsr);
+
+       dcr = readl(imxdi->ioaddr + DCR);
+
+       if (dcr & DCR_FSHL) {
+               /* we are out of luck */
+               di_what_is_to_be_done(imxdi, "battery");
+               return -ENODEV;
+       }
+       /*
+        * with the next SYSTEM POR we will transit from the "FAILURE STATE"
+        * into the "NON-VALID STATE" + "FAILURE STATE"
+        */
+       di_what_is_to_be_done(imxdi, "main");
+
+       return -ENODEV;
+}
+
+static int di_handle_valid_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+       /* initialize alarm */
+       di_write_busy_wait(imxdi, DCAMR_UNSET, DCAMR);
+       di_write_busy_wait(imxdi, 0, DCALR);
+
+       /* clear alarm flag */
+       if (dsr & DSR_CAF)
+               di_write_busy_wait(imxdi, DSR_CAF, DSR);
+
+       return 0;
+}
+
+static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+       u32 dcr, sec;
+
+       /*
+        * lets disable all sources which can force the DryIce unit into
+        * the "FAILURE STATE" for now
+        */
+       di_write_busy_wait(imxdi, 0x00000000, DTCR);
+       /* and lets protect them at runtime from any change */
+       di_write_busy_wait(imxdi, DCR_TDCSL, DCR);
+
+       sec = readl(imxdi->ioaddr + DTCMR);
+       if (sec != 0)
+               dev_warn(&imxdi->pdev->dev,
+                        "The security violation has happend at %u seconds\n",
+                        sec);
+       /*
+        * the timer cannot be set/modified if
+        * - the TCHL or TCSL bit is set in DCR
+        */
+       dcr = readl(imxdi->ioaddr + DCR);
+       if (!(dcr & DCR_TCE)) {
+               if (dcr & DCR_TCHL) {
+                       /* we are out of luck */
+                       di_what_is_to_be_done(imxdi, "battery");
+                       return -ENODEV;
+               }
+               if (dcr & DCR_TCSL) {
+                       di_what_is_to_be_done(imxdi, "main");
+                       return -ENODEV;
+               }
+       }
+       /*
+        * - the timer counter stops/is stopped if
+        *   - its overflow flag is set (TCO in DSR)
+        *      -> clear overflow bit to make it count again
+        *   - NVF is set in DSR
+        *      -> clear non-valid bit to make it count again
+        *   - its TCE (DCR) is cleared
+        *      -> set TCE to make it count
+        *   - it was never set before
+        *      -> write a time into it (required again if the NVF was set)
+        */
+       /* state handled */
+       di_write_busy_wait(imxdi, DSR_NVF, DSR);
+       /* clear overflow flag */
+       di_write_busy_wait(imxdi, DSR_TCO, DSR);
+       /* enable the counter */
+       di_write_busy_wait(imxdi, dcr | DCR_TCE, DCR);
+       /* set and trigger it to make it count */
+       di_write_busy_wait(imxdi, sec, DTCMR);
+
+       /* now prepare for the valid state */
+       return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR));
+}
+
+static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+       u32 dcr;
+
+       /*
+        * now we must first remove the tamper sources in order to get the
+        * device out of the "FAILURE STATE"
+        * To disable any of the following sources we need to modify the DTCR
+        */
+       if (dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD | DSR_EBD | DSR_SAD |
+                       DSR_TTD | DSR_CTD | DSR_VTD | DSR_MCO | DSR_TCO)) {
+               dcr = __raw_readl(imxdi->ioaddr + DCR);
+               if (dcr & DCR_TDCHL) {
+                       /*
+                        * the tamper register is locked. We cannot disable the
+                        * tamper detection. The TDCHL can only be reset by a
+                        * DRYICE POR, but we cannot force a DRYICE POR in
+                        * softwere because we are still in "FAILURE STATE".
+                        * We need a DRYICE POR via battery power cycling....
+                        */
+                       /*
+                        * out of luck!
+                        * we cannot disable them without a DRYICE POR
+                        */
+                       di_what_is_to_be_done(imxdi, "battery");
+                       return -ENODEV;
+               }
+               if (dcr & DCR_TDCSL) {
+                       /* a soft lock can be removed by a SYSTEM POR */
+                       di_what_is_to_be_done(imxdi, "main");
+                       return -ENODEV;
+               }
+       }
+
+       /* disable all sources */
+       di_write_busy_wait(imxdi, 0x00000000, DTCR);
+
+       /* clear the status bits now */
+       di_write_busy_wait(imxdi, dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD |
+                       DSR_EBD | DSR_SAD | DSR_TTD | DSR_CTD | DSR_VTD |
+                       DSR_MCO | DSR_TCO), DSR);
+
+       dsr = readl(imxdi->ioaddr + DSR);
+       if ((dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
+                       DSR_WCF | DSR_WEF)) != 0)
+               dev_warn(&imxdi->pdev->dev,
+                        "There are still some sources of pain in DSR: %08x!\n",
+                        dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
+                                DSR_WCF | DSR_WEF));
+
+       /*
+        * now we are trying to clear the "Security-violation flag" to
+        * get the DryIce out of this state
+        */
+       di_write_busy_wait(imxdi, DSR_SVF, DSR);
+
+       /* success? */
+       dsr = readl(imxdi->ioaddr + DSR);
+       if (dsr & DSR_SVF) {
+               dev_crit(&imxdi->pdev->dev,
+                        "Cannot clear the security violation flag. We are ending up in an endless loop!\n");
+               /* last resort */
+               di_what_is_to_be_done(imxdi, "battery");
+               return -ENODEV;
+       }
+
+       /*
+        * now we have left the "FAILURE STATE" and ending up in the
+        * "NON-VALID STATE" time to recover everything
+        */
+       return di_handle_invalid_state(imxdi, dsr);
+}
+
+static int di_handle_state(struct imxdi_dev *imxdi)
+{
+       int rc;
+       u32 dsr;
+
+       dsr = readl(imxdi->ioaddr + DSR);
+
+       switch (dsr & (DSR_NVF | DSR_SVF)) {
+       case DSR_NVF:
+               dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n");
+               rc = di_handle_invalid_state(imxdi, dsr);
+               break;
+       case DSR_SVF:
+               dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n");
+               rc = di_handle_failure_state(imxdi, dsr);
+               break;
+       case DSR_NVF | DSR_SVF:
+               dev_warn(&imxdi->pdev->dev,
+                        "Failure+Invalid stated unit detected\n");
+               rc = di_handle_invalid_and_failure_state(imxdi, dsr);
+               break;
+       default:
+               dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n");
+               rc = di_handle_valid_state(imxdi, dsr);
+       }
+
+       return rc;
+}
+
 /*
  * enable a dryice interrupt
  */
@@ -137,8 +455,8 @@ static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
        unsigned long flags;
 
        spin_lock_irqsave(&imxdi->irq_lock, flags);
-       __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr,
-                       imxdi->ioaddr + DIER);
+       writel(readl(imxdi->ioaddr + DIER) | intr,
+              imxdi->ioaddr + DIER);
        spin_unlock_irqrestore(&imxdi->irq_lock, flags);
 }
 
@@ -150,8 +468,8 @@ static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
        unsigned long flags;
 
        spin_lock_irqsave(&imxdi->irq_lock, flags);
-       __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr,
-                       imxdi->ioaddr + DIER);
+       writel(readl(imxdi->ioaddr + DIER) & ~intr,
+              imxdi->ioaddr + DIER);
        spin_unlock_irqrestore(&imxdi->irq_lock, flags);
 }
 
@@ -169,11 +487,11 @@ static void clear_write_error(struct imxdi_dev *imxdi)
        dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
 
        /* clear the write error flag */
-       __raw_writel(DSR_WEF, imxdi->ioaddr + DSR);
+       writel(DSR_WEF, imxdi->ioaddr + DSR);
 
        /* wait for it to take effect */
        for (cnt = 0; cnt < 1000; cnt++) {
-               if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
+               if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
                        return;
                udelay(10);
        }
@@ -201,7 +519,7 @@ static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
        imxdi->dsr = 0;
 
        /* do the register write */
-       __raw_writel(val, imxdi->ioaddr + reg);
+       writel(val, imxdi->ioaddr + reg);
 
        /* wait for the write to finish */
        ret = wait_event_interruptible_timeout(imxdi->write_wait,
@@ -235,7 +553,7 @@ static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
        struct imxdi_dev *imxdi = dev_get_drvdata(dev);
        unsigned long now;
 
-       now = __raw_readl(imxdi->ioaddr + DTCMR);
+       now = readl(imxdi->ioaddr + DTCMR);
        rtc_time_to_tm(now, tm);
 
        return 0;
@@ -248,14 +566,35 @@ static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs)
 {
        struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+       u32 dcr, dsr;
        int rc;
 
+       dcr = readl(imxdi->ioaddr + DCR);
+       dsr = readl(imxdi->ioaddr + DSR);
+
+       if (!(dcr & DCR_TCE) || (dsr & DSR_SVF)) {
+               if (dcr & DCR_TCHL) {
+                       /* we are even more out of luck */
+                       di_what_is_to_be_done(imxdi, "battery");
+                       return -EPERM;
+               }
+               if ((dcr & DCR_TCSL) || (dsr & DSR_SVF)) {
+                       /* we are out of luck for now */
+                       di_what_is_to_be_done(imxdi, "main");
+                       return -EPERM;
+               }
+       }
+
        /* zero the fractional part first */
        rc = di_write_wait(imxdi, 0, DTCLR);
-       if (rc == 0)
-               rc = di_write_wait(imxdi, secs, DTCMR);
+       if (rc != 0)
+               return rc;
 
-       return rc;
+       rc = di_write_wait(imxdi, secs, DTCMR);
+       if (rc != 0)
+               return rc;
+
+       return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR);
 }
 
 static int dryice_rtc_alarm_irq_enable(struct device *dev,
@@ -280,17 +619,17 @@ static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        struct imxdi_dev *imxdi = dev_get_drvdata(dev);
        u32 dcamr;
 
-       dcamr = __raw_readl(imxdi->ioaddr + DCAMR);
+       dcamr = readl(imxdi->ioaddr + DCAMR);
        rtc_time_to_tm(dcamr, &alarm->time);
 
        /* alarm is enabled if the interrupt is enabled */
-       alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
+       alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
 
        /* don't allow the DSR read to mess up DSR_WCF */
        mutex_lock(&imxdi->write_mutex);
 
        /* alarm is pending if the alarm flag is set */
-       alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
+       alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
 
        mutex_unlock(&imxdi->write_mutex);
 
@@ -312,7 +651,7 @@ static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
                return rc;
 
        /* don't allow setting alarm in the past */
-       now = __raw_readl(imxdi->ioaddr + DTCMR);
+       now = readl(imxdi->ioaddr + DTCMR);
        if (alarm_time < now)
                return -EINVAL;
 
@@ -346,7 +685,26 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
        u32 dsr, dier;
        irqreturn_t rc = IRQ_NONE;
 
-       dier = __raw_readl(imxdi->ioaddr + DIER);
+       dier = readl(imxdi->ioaddr + DIER);
+       dsr = readl(imxdi->ioaddr + DSR);
+
+       /* handle the security violation event */
+       if (dier & DIER_SVIE) {
+               if (dsr & DSR_SVF) {
+                       /*
+                        * Disable the interrupt when this kind of event has
+                        * happened.
+                        * There cannot be more than one event of this type,
+                        * because it needs a complex state change
+                        * including a main power cycle to get again out of
+                        * this state.
+                        */
+                       di_int_disable(imxdi, DIER_SVIE);
+                       /* report the violation */
+                       di_report_tamper_info(imxdi, dsr);
+                       rc = IRQ_HANDLED;
+               }
+       }
 
        /* handle write complete and write error cases */
        if (dier & DIER_WCIE) {
@@ -357,7 +715,6 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
                        return rc;
 
                /* DSR_WCF clears itself on DSR read */
-               dsr = __raw_readl(imxdi->ioaddr + DSR);
                if (dsr & (DSR_WCF | DSR_WEF)) {
                        /* mask the interrupt */
                        di_int_disable(imxdi, DIER_WCIE);
@@ -373,7 +730,6 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
        /* handle the alarm case */
        if (dier & DIER_CAIE) {
                /* DSR_WCF clears itself on DSR read */
-               dsr = __raw_readl(imxdi->ioaddr + DSR);
                if (dsr & DSR_CAF) {
                        /* mask the interrupt */
                        di_int_disable(imxdi, DIER_CAIE);
@@ -446,7 +802,11 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
         */
 
        /* mask all interrupts */
-       __raw_writel(0, imxdi->ioaddr + DIER);
+       writel(0, imxdi->ioaddr + DIER);
+
+       rc = di_handle_state(imxdi);
+       if (rc != 0)
+               goto err;
 
        rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq,
                        IRQF_SHARED, pdev->name, imxdi);
@@ -455,44 +815,6 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       /* put dryice into valid state */
-       if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) {
-               rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR);
-               if (rc)
-                       goto err;
-       }
-
-       /* initialize alarm */
-       rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR);
-       if (rc)
-               goto err;
-       rc = di_write_wait(imxdi, 0, DCALR);
-       if (rc)
-               goto err;
-
-       /* clear alarm flag */
-       if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) {
-               rc = di_write_wait(imxdi, DSR_CAF, DSR);
-               if (rc)
-                       goto err;
-       }
-
-       /* the timer won't count if it has never been written to */
-       if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) {
-               rc = di_write_wait(imxdi, 0, DTCMR);
-               if (rc)
-                       goto err;
-       }
-
-       /* start keeping time */
-       if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) {
-               rc = di_write_wait(imxdi,
-                               __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE,
-                               DCR);
-               if (rc)
-                       goto err;
-       }
-
        platform_set_drvdata(pdev, imxdi);
        imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                                  &dryice_rtc_ops, THIS_MODULE);
@@ -516,7 +838,7 @@ static int __exit dryice_rtc_remove(struct platform_device *pdev)
        flush_work(&imxdi->work);
 
        /* mask all interrupts */
-       __raw_writel(0, imxdi->ioaddr + DIER);
+       writel(0, imxdi->ioaddr + DIER);
 
        clk_disable_unprepare(imxdi->clk);
 
index c3c549d..aa3b8f1 100644 (file)
@@ -370,22 +370,15 @@ isl1208_i2c_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
        struct rtc_time *alarm_tm = &alarm->time;
        u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
        const int offs = ISL1208_REG_SCA;
-       unsigned long rtc_secs, alarm_secs;
        struct rtc_time rtc_tm;
        int err, enable;
 
        err = isl1208_i2c_read_time(client, &rtc_tm);
        if (err)
                return err;
-       err = rtc_tm_to_time(&rtc_tm, &rtc_secs);
-       if (err)
-               return err;
-       err = rtc_tm_to_time(alarm_tm, &alarm_secs);
-       if (err)
-               return err;
 
        /* If the alarm time is before the current time disable the alarm */
-       if (!alarm->enabled || alarm_secs <= rtc_secs)
+       if (!alarm->enabled || rtc_tm_sub(alarm_tm, &rtc_tm) <= 0)
                enable = 0x00;
        else
                enable = 0x80;
index 4804985..b2a7607 100644 (file)
@@ -234,6 +234,7 @@ static struct i2c_device_id max6900_id[] = {
        { "max6900", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c, max6900_id);
 
 static struct i2c_driver max6900_driver = {
        .driver = {
index 7632a87..7184a0e 100644 (file)
@@ -511,6 +511,7 @@ static const struct platform_device_id rtc_id[] = {
        { "max77686-rtc", 0 },
        {},
 };
+MODULE_DEVICE_TABLE(platform, rtc_id);
 
 static struct platform_driver max77686_rtc_driver = {
        .driver         = {
index 7f8adf8..82ffcc5 100644 (file)
@@ -484,6 +484,7 @@ static const struct platform_device_id rtc_id[] = {
        { "max77802-rtc", 0 },
        {},
 };
+MODULE_DEVICE_TABLE(platform, rtc_id);
 
 static struct platform_driver max77802_rtc_driver = {
        .driver         = {
index 5726ef7..30804b0 100644 (file)
@@ -309,6 +309,7 @@ static const struct platform_device_id max8998_rtc_id[] = {
        { "lp3974-rtc", TYPE_LP3974 },
        { }
 };
+MODULE_DEVICE_TABLE(platform, max8998_rtc_id);
 
 static struct platform_driver max8998_rtc_driver = {
        .driver         = {
index 32df1d8..a658680 100644 (file)
@@ -216,7 +216,7 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
        s1970 = rtc_tm_to_time64(&alarm->time);
 
-       dev_dbg(dev, "%s: o%2.s %lld\n", __func__, alarm->enabled ? "n" : "ff",
+       dev_dbg(dev, "%s: %s %lld\n", __func__, alarm->enabled ? "on" : "off",
                        (long long)s1970);
 
        ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
new file mode 100644 (file)
index 0000000..c0090b6
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2014-2015 MediaTek Inc.
+* Author: Tianping.Fang <tianping.fang@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/mfd/mt6397/core.h>
+
+#define RTC_BBPU               0x0000
+#define RTC_BBPU_CBUSY         BIT(6)
+
+#define RTC_WRTGR              0x003c
+
+#define RTC_IRQ_STA            0x0002
+#define RTC_IRQ_STA_AL         BIT(0)
+#define RTC_IRQ_STA_LP         BIT(3)
+
+#define RTC_IRQ_EN             0x0004
+#define RTC_IRQ_EN_AL          BIT(0)
+#define RTC_IRQ_EN_ONESHOT     BIT(2)
+#define RTC_IRQ_EN_LP          BIT(3)
+#define RTC_IRQ_EN_ONESHOT_AL  (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
+
+#define RTC_AL_MASK            0x0008
+#define RTC_AL_MASK_DOW                BIT(4)
+
+#define RTC_TC_SEC             0x000a
+/* Min, Hour, Dom... register offset to RTC_TC_SEC */
+#define RTC_OFFSET_SEC         0
+#define RTC_OFFSET_MIN         1
+#define RTC_OFFSET_HOUR                2
+#define RTC_OFFSET_DOM         3
+#define RTC_OFFSET_DOW         4
+#define RTC_OFFSET_MTH         5
+#define RTC_OFFSET_YEAR                6
+#define RTC_OFFSET_COUNT       7
+
+#define RTC_AL_SEC             0x0018
+
+#define RTC_PDN2               0x002e
+#define RTC_PDN2_PWRON_ALARM   BIT(4)
+
+#define RTC_MIN_YEAR           1968
+#define RTC_BASE_YEAR          1900
+#define RTC_NUM_YEARS          128
+#define RTC_MIN_YEAR_OFFSET    (RTC_MIN_YEAR - RTC_BASE_YEAR)
+
+struct mt6397_rtc {
+       struct device           *dev;
+       struct rtc_device       *rtc_dev;
+       struct mutex            lock;
+       struct regmap           *regmap;
+       int                     irq;
+       u32                     addr_base;
+};
+
+static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
+{
+       unsigned long timeout = jiffies + HZ;
+       int ret;
+       u32 data;
+
+       ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1);
+       if (ret < 0)
+               return ret;
+
+       while (1) {
+               ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU,
+                                 &data);
+               if (ret < 0)
+                       break;
+               if (!(data & RTC_BBPU_CBUSY))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+               cpu_relax();
+       }
+
+       return ret;
+}
+
+static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data)
+{
+       struct mt6397_rtc *rtc = data;
+       u32 irqsta, irqen;
+       int ret;
+
+       ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_STA, &irqsta);
+       if ((ret >= 0) && (irqsta & RTC_IRQ_STA_AL)) {
+               rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+               irqen = irqsta & ~RTC_IRQ_EN_AL;
+               mutex_lock(&rtc->lock);
+               if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
+                                irqen) < 0)
+                       mtk_rtc_write_trigger(rtc);
+               mutex_unlock(&rtc->lock);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+static int __mtk_rtc_read_time(struct mt6397_rtc *rtc,
+                              struct rtc_time *tm, int *sec)
+{
+       int ret;
+       u16 data[RTC_OFFSET_COUNT];
+
+       mutex_lock(&rtc->lock);
+       ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+                              data, RTC_OFFSET_COUNT);
+       if (ret < 0)
+               goto exit;
+
+       tm->tm_sec = data[RTC_OFFSET_SEC];
+       tm->tm_min = data[RTC_OFFSET_MIN];
+       tm->tm_hour = data[RTC_OFFSET_HOUR];
+       tm->tm_mday = data[RTC_OFFSET_DOM];
+       tm->tm_mon = data[RTC_OFFSET_MTH];
+       tm->tm_year = data[RTC_OFFSET_YEAR];
+
+       ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, sec);
+exit:
+       mutex_unlock(&rtc->lock);
+       return ret;
+}
+
+static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       time64_t time;
+       struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+       int days, sec, ret;
+
+       do {
+               ret = __mtk_rtc_read_time(rtc, tm, &sec);
+               if (ret < 0)
+                       goto exit;
+       } while (sec < tm->tm_sec);
+
+       /* HW register use 7 bits to store year data, minus
+        * RTC_MIN_YEAR_OFFSET before write year data to register, and plus
+        * RTC_MIN_YEAR_OFFSET back after read year from register
+        */
+       tm->tm_year += RTC_MIN_YEAR_OFFSET;
+
+       /* HW register start mon from one, but tm_mon start from zero. */
+       tm->tm_mon--;
+       time = rtc_tm_to_time64(tm);
+
+       /* rtc_tm_to_time64 covert Gregorian date to seconds since
+        * 01-01-1970 00:00:00, and this date is Thursday.
+        */
+       days = div_s64(time, 86400);
+       tm->tm_wday = (days + 4) % 7;
+
+exit:
+       return ret;
+}
+
+static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+       int ret;
+       u16 data[RTC_OFFSET_COUNT];
+
+       tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+       tm->tm_mon++;
+
+       data[RTC_OFFSET_SEC] = tm->tm_sec;
+       data[RTC_OFFSET_MIN] = tm->tm_min;
+       data[RTC_OFFSET_HOUR] = tm->tm_hour;
+       data[RTC_OFFSET_DOM] = tm->tm_mday;
+       data[RTC_OFFSET_MTH] = tm->tm_mon;
+       data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+       mutex_lock(&rtc->lock);
+       ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+                               data, RTC_OFFSET_COUNT);
+       if (ret < 0)
+               goto exit;
+
+       /* Time register write to hardware after call trigger function */
+       ret = mtk_rtc_write_trigger(rtc);
+
+exit:
+       mutex_unlock(&rtc->lock);
+       return ret;
+}
+
+static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct rtc_time *tm = &alm->time;
+       struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+       u32 irqen, pdn2;
+       int ret;
+       u16 data[RTC_OFFSET_COUNT];
+
+       mutex_lock(&rtc->lock);
+       ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, &irqen);
+       if (ret < 0)
+               goto err_exit;
+       ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_PDN2, &pdn2);
+       if (ret < 0)
+               goto err_exit;
+
+       ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+                              data, RTC_OFFSET_COUNT);
+       if (ret < 0)
+               goto err_exit;
+
+       alm->enabled = !!(irqen & RTC_IRQ_EN_AL);
+       alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
+       mutex_unlock(&rtc->lock);
+
+       tm->tm_sec = data[RTC_OFFSET_SEC];
+       tm->tm_min = data[RTC_OFFSET_MIN];
+       tm->tm_hour = data[RTC_OFFSET_HOUR];
+       tm->tm_mday = data[RTC_OFFSET_DOM];
+       tm->tm_mon = data[RTC_OFFSET_MTH];
+       tm->tm_year = data[RTC_OFFSET_YEAR];
+
+       tm->tm_year += RTC_MIN_YEAR_OFFSET;
+       tm->tm_mon--;
+
+       return 0;
+err_exit:
+       mutex_unlock(&rtc->lock);
+       return ret;
+}
+
+static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct rtc_time *tm = &alm->time;
+       struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+       int ret;
+       u16 data[RTC_OFFSET_COUNT];
+
+       tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+       tm->tm_mon++;
+
+       data[RTC_OFFSET_SEC] = tm->tm_sec;
+       data[RTC_OFFSET_MIN] = tm->tm_min;
+       data[RTC_OFFSET_HOUR] = tm->tm_hour;
+       data[RTC_OFFSET_DOM] = tm->tm_mday;
+       data[RTC_OFFSET_MTH] = tm->tm_mon;
+       data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+       mutex_lock(&rtc->lock);
+       if (alm->enabled) {
+               ret = regmap_bulk_write(rtc->regmap,
+                                       rtc->addr_base + RTC_AL_SEC,
+                                       data, RTC_OFFSET_COUNT);
+               if (ret < 0)
+                       goto exit;
+               ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_AL_MASK,
+                                  RTC_AL_MASK_DOW);
+               if (ret < 0)
+                       goto exit;
+               ret = regmap_update_bits(rtc->regmap,
+                                        rtc->addr_base + RTC_IRQ_EN,
+                                        RTC_IRQ_EN_ONESHOT_AL,
+                                        RTC_IRQ_EN_ONESHOT_AL);
+               if (ret < 0)
+                       goto exit;
+       } else {
+               ret = regmap_update_bits(rtc->regmap,
+                                        rtc->addr_base + RTC_IRQ_EN,
+                                        RTC_IRQ_EN_ONESHOT_AL, 0);
+               if (ret < 0)
+                       goto exit;
+       }
+
+       /* All alarm time register write to hardware after calling
+        * mtk_rtc_write_trigger. This can avoid race condition if alarm
+        * occur happen during writing alarm time register.
+        */
+       ret = mtk_rtc_write_trigger(rtc);
+exit:
+       mutex_unlock(&rtc->lock);
+       return ret;
+}
+
+static struct rtc_class_ops mtk_rtc_ops = {
+       .read_time  = mtk_rtc_read_time,
+       .set_time   = mtk_rtc_set_time,
+       .read_alarm = mtk_rtc_read_alarm,
+       .set_alarm  = mtk_rtc_set_alarm,
+};
+
+static int mtk_rtc_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
+       struct mt6397_rtc *rtc;
+       int ret;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rtc->addr_base = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start);
+       if (rtc->irq <= 0)
+               return -EINVAL;
+
+       rtc->regmap = mt6397_chip->regmap;
+       rtc->dev = &pdev->dev;
+       mutex_init(&rtc->lock);
+
+       platform_set_drvdata(pdev, rtc);
+
+       ret = request_threaded_irq(rtc->irq, NULL,
+                                  mtk_rtc_irq_handler_thread,
+                                  IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+                                  "mt6397-rtc", rtc);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+                       rtc->irq, ret);
+               goto out_dispose_irq;
+       }
+
+       rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev,
+                                          &mtk_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc_dev)) {
+               dev_err(&pdev->dev, "register rtc device failed\n");
+               ret = PTR_ERR(rtc->rtc_dev);
+               goto out_free_irq;
+       }
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       return 0;
+
+out_free_irq:
+       free_irq(rtc->irq, rtc->rtc_dev);
+out_dispose_irq:
+       irq_dispose_mapping(rtc->irq);
+       return ret;
+}
+
+static int mtk_rtc_remove(struct platform_device *pdev)
+{
+       struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(rtc->rtc_dev);
+       free_irq(rtc->irq, rtc->rtc_dev);
+       irq_dispose_mapping(rtc->irq);
+
+       return 0;
+}
+
+static const struct of_device_id mt6397_rtc_of_match[] = {
+       { .compatible = "mediatek,mt6397-rtc", },
+       { }
+};
+
+static struct platform_driver mtk_rtc_driver = {
+       .driver = {
+               .name = "mt6397-rtc",
+               .of_match_table = mt6397_rtc_of_match,
+       },
+       .probe  = mtk_rtc_probe,
+       .remove = mtk_rtc_remove,
+};
+
+module_platform_driver(mtk_rtc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
+MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
+MODULE_ALIAS("platform:mt6397-rtc");
index 4237622..7f50d2e 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
+#include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
@@ -24,7 +25,7 @@
 #define RTC_MINUTES_OFFS       8
 #define RTC_HOURS_OFFS         16
 #define RTC_WDAY_OFFS          24
-#define RTC_HOURS_12H_MODE             (1 << 22) /* 12 hours mode */
+#define RTC_HOURS_12H_MODE     BIT(22) /* 12 hour mode */
 
 #define RTC_DATE_REG_OFFS      4
 #define RTC_MDAY_OFFS          0
@@ -33,7 +34,7 @@
 
 #define RTC_ALARM_TIME_REG_OFFS        8
 #define RTC_ALARM_DATE_REG_OFFS        0xc
-#define RTC_ALARM_VALID                (1 << 7)
+#define RTC_ALARM_VALID                BIT(7)
 
 #define RTC_ALARM_INTERRUPT_MASK_REG_OFFS      0x10
 #define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS     0x14
@@ -77,7 +78,7 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
        second = rtc_time & 0x7f;
        minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
-       hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
+       hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hour mode */
        wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
 
        day = rtc_date & 0x3f;
@@ -108,7 +109,7 @@ static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
        second = rtc_time & 0x7f;
        minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
-       hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
+       hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hour mode */
        wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
 
        day = rtc_date & 0x3f;
@@ -239,10 +240,10 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
        if (!IS_ERR(pdata->clk))
                clk_prepare_enable(pdata->clk);
 
-       /* make sure the 24 hours mode is enabled */
+       /* make sure the 24 hour mode is enabled */
        rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
        if (rtc_time & RTC_HOURS_12H_MODE) {
-               dev_err(&pdev->dev, "24 Hours mode not supported.\n");
+               dev_err(&pdev->dev, "12 Hour mode is enabled but not supported.\n");
                ret = -EINVAL;
                goto out;
        }
index 09d422b..5fc292c 100644 (file)
@@ -84,7 +84,7 @@ struct rtc_plat_data {
        enum imx_rtc_type devtype;
 };
 
-static struct platform_device_id imx_rtc_devtype[] = {
+static const struct platform_device_id imx_rtc_devtype[] = {
        {
                .name = "imx1-rtc",
                .driver_data = IMX1_RTC,
index 3b01d56..7ea2c47 100644 (file)
@@ -239,7 +239,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
        struct palmas_rtc *palmas_rtc = NULL;
        int ret;
        bool enable_bb_charging = false;
-       bool high_bb_charging;
+       bool high_bb_charging = false;
 
        if (pdev->dev.of_node) {
                enable_bb_charging = of_property_read_bool(pdev->dev.of_node,
index 0ba7e59..8bba022 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/of.h>
 #include <linux/err.h>
 
-#define DRV_VERSION "0.4.3"
+#define DRV_VERSION "0.4.4"
 
 #define PCF8563_REG_ST1                0x00 /* status */
 #define PCF8563_REG_ST2                0x01
@@ -202,8 +202,9 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
                pcf8563->voltage_low = 1;
-               dev_info(&client->dev,
+               dev_err(&client->dev,
                        "low voltage detected, date/time is not reliable.\n");
+               return -EINVAL;
        }
 
        dev_dbg(&client->dev,
@@ -234,12 +235,6 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
                tm->tm_sec, tm->tm_min, tm->tm_hour,
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
-       /* the clock can give out invalid datetime, but we cannot return
-        * -EINVAL otherwise hwclock will refuse to set the time on bootup.
-        */
-       if (rtc_valid_tm(tm) < 0)
-               dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
        return 0;
 }
 
@@ -363,13 +358,13 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
        struct i2c_client *client = to_i2c_client(dev);
        unsigned char buf[4];
        int err;
-       unsigned long alarm_time;
 
        /* The alarm has no seconds, round up to nearest minute */
        if (tm->time.tm_sec) {
-               rtc_tm_to_time(&tm->time, &alarm_time);
-               alarm_time += 60-tm->time.tm_sec;
-               rtc_time_to_tm(alarm_time, &tm->time);
+               time64_t alarm_time = rtc_tm_to_time64(&tm->time);
+
+               alarm_time += 60 - tm->time.tm_sec;
+               rtc_time64_to_tm(alarm_time, &tm->time);
        }
 
        dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d "
@@ -437,7 +432,7 @@ static int pcf8563_probe(struct i2c_client *client,
        }
 
        err = pcf8563_get_alarm_mode(client, NULL, &alm_pending);
-       if (err < 0) {
+       if (err) {
                dev_err(&client->dev, "%s: read error\n", __func__);
                return err;
        }
index 76cbad7..a0f8323 100644 (file)
@@ -772,18 +772,6 @@ static struct s3c_rtc_data const s3c6410_rtc_data = {
        .disable                = s3c6410_rtc_disable,
 };
 
-static struct s3c_rtc_data const exynos3250_rtc_data = {
-       .max_user_freq          = 32768,
-       .needs_src_clk          = true,
-       .irq_handler            = s3c6410_rtc_irq,
-       .set_freq               = s3c6410_rtc_setfreq,
-       .enable_tick            = s3c6410_rtc_enable_tick,
-       .save_tick_cnt          = s3c6410_rtc_save_tick_cnt,
-       .restore_tick_cnt       = s3c6410_rtc_restore_tick_cnt,
-       .enable                 = s3c24xx_rtc_enable,
-       .disable                = s3c6410_rtc_disable,
-};
-
 static const struct of_device_id s3c_rtc_dt_match[] = {
        {
                .compatible = "samsung,s3c2410-rtc",
@@ -799,7 +787,7 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
                .data = (void *)&s3c6410_rtc_data,
        }, {
                .compatible = "samsung,exynos3250-rtc",
-               .data = (void *)&exynos3250_rtc_data,
+               .data = (void *)&s3c6410_rtc_data,
        },
        { /* sentinel */ },
 };
index 0479e80..d87a85c 100644 (file)
@@ -322,6 +322,13 @@ static int snvs_rtc_suspend(struct device *dev)
        if (device_may_wakeup(dev))
                enable_irq_wake(data->irq);
 
+       return 0;
+}
+
+static int snvs_rtc_suspend_noirq(struct device *dev)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+
        if (data->clk)
                clk_disable_unprepare(data->clk);
 
@@ -331,23 +338,28 @@ static int snvs_rtc_suspend(struct device *dev)
 static int snvs_rtc_resume(struct device *dev)
 {
        struct snvs_rtc_data *data = dev_get_drvdata(dev);
-       int ret;
 
        if (device_may_wakeup(dev))
-               disable_irq_wake(data->irq);
+               return disable_irq_wake(data->irq);
 
-       if (data->clk) {
-               ret = clk_prepare_enable(data->clk);
-               if (ret)
-                       return ret;
-       }
+       return 0;
+}
+
+static int snvs_rtc_resume_noirq(struct device *dev)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+
+       if (data->clk)
+               return clk_prepare_enable(data->clk);
 
        return 0;
 }
 
 static const struct dev_pm_ops snvs_rtc_pm_ops = {
-       .suspend_noirq = snvs_rtc_suspend,
-       .resume_noirq = snvs_rtc_resume,
+       .suspend = snvs_rtc_suspend,
+       .suspend_noirq = snvs_rtc_suspend_noirq,
+       .resume = snvs_rtc_resume,
+       .resume_noirq = snvs_rtc_resume_noirq,
 };
 
 #define SNVS_RTC_PM_OPS        (&snvs_rtc_pm_ops)
index d2cdb98..f05ef85 100644 (file)
@@ -358,12 +358,6 @@ static int spear_rtc_probe(struct platform_device *pdev)
        int status = 0;
        int irq;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no resource defined\n");
-               return -EBUSY;
-       }
-
        config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
        if (!config)
                return -ENOMEM;
@@ -383,6 +377,7 @@ static int spear_rtc_probe(struct platform_device *pdev)
                return status;
        }
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        config->ioaddr = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(config->ioaddr))
                return PTR_ERR(config->ioaddr);
index 6e678fa..52543ae 100644 (file)
@@ -269,14 +269,13 @@ static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
        struct rtc_time *alrm_tm = &wkalrm->time;
        struct rtc_time tm_now;
-       u32 alrm = 0;
-       unsigned long time_now = 0;
-       unsigned long time_set = 0;
-       unsigned long time_gap = 0;
-       unsigned long time_gap_day = 0;
-       unsigned long time_gap_hour = 0;
-       unsigned long time_gap_min = 0;
-       int ret = 0;
+       u32 alrm;
+       time64_t diff;
+       unsigned long time_gap;
+       unsigned long time_gap_day;
+       unsigned long time_gap_hour;
+       unsigned long time_gap_min;
+       int ret;
 
        ret = sunxi_rtc_gettime(dev, &tm_now);
        if (ret < 0) {
@@ -284,14 +283,18 @@ static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
                return -EINVAL;
        }
 
-       rtc_tm_to_time(alrm_tm, &time_set);
-       rtc_tm_to_time(&tm_now, &time_now);
-       if (time_set <= time_now) {
+       diff = rtc_tm_sub(alrm_tm, &tm_now);
+       if (diff <= 0) {
                dev_err(dev, "Date to set in the past\n");
                return -EINVAL;
        }
 
-       time_gap = time_set - time_now;
+       if (diff > 255 * SEC_IN_DAY) {
+               dev_err(dev, "Day must be in the range 0 - 255\n");
+               return -EINVAL;
+       }
+
+       time_gap = diff;
        time_gap_day = time_gap / SEC_IN_DAY;
        time_gap -= time_gap_day * SEC_IN_DAY;
        time_gap_hour = time_gap / SEC_IN_HOUR;
@@ -299,11 +302,6 @@ static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        time_gap_min = time_gap / SEC_IN_MIN;
        time_gap -= time_gap_min * SEC_IN_MIN;
 
-       if (time_gap_day > 255) {
-               dev_err(dev, "Day must be in the range 0 - 255\n");
-               return -EINVAL;
-       }
-
        sunxi_rtc_setaie(0, chip);
        writel(0, chip->base + SUNXI_ALRM_DHMS);
        usleep_range(100, 300);
index bfbfa7e..f9f9709 100644 (file)
@@ -49,18 +49,13 @@ struct v3020_chip_ops {
 #define V3020_RD       2
 #define V3020_IO       3
 
-struct v3020_gpio {
-       const char *name;
-       unsigned int gpio;
-};
-
 struct v3020 {
        /* MMIO access */
        void __iomem *ioaddress;
        int leftshift;
 
        /* GPIO access */
-       struct v3020_gpio *gpio;
+       struct gpio *gpio;
 
        struct v3020_chip_ops *ops;
 
@@ -107,48 +102,34 @@ static struct v3020_chip_ops v3020_mmio_ops = {
        .write_bit      = v3020_mmio_write_bit,
 };
 
-static struct v3020_gpio v3020_gpio[] = {
-       { "RTC CS", 0 },
-       { "RTC WR", 0 },
-       { "RTC RD", 0 },
-       { "RTC IO", 0 },
+static struct gpio v3020_gpio[] = {
+       { 0, GPIOF_OUT_INIT_HIGH, "RTC CS"},
+       { 0, GPIOF_OUT_INIT_HIGH, "RTC WR"},
+       { 0, GPIOF_OUT_INIT_HIGH, "RTC RD"},
+       { 0, GPIOF_OUT_INIT_HIGH, "RTC IO"},
 };
 
 static int v3020_gpio_map(struct v3020 *chip, struct platform_device *pdev,
                          struct v3020_platform_data *pdata)
 {
-       int i, err;
+       int err;
 
        v3020_gpio[V3020_CS].gpio = pdata->gpio_cs;
        v3020_gpio[V3020_WR].gpio = pdata->gpio_wr;
        v3020_gpio[V3020_RD].gpio = pdata->gpio_rd;
        v3020_gpio[V3020_IO].gpio = pdata->gpio_io;
 
-       for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) {
-               err = gpio_request(v3020_gpio[i].gpio, v3020_gpio[i].name);
-               if (err)
-                       goto err_request;
+       err = gpio_request_array(v3020_gpio, ARRAY_SIZE(v3020_gpio));
 
-               gpio_direction_output(v3020_gpio[i].gpio, 1);
-       }
-
-       chip->gpio = v3020_gpio;
-
-       return 0;
-
-err_request:
-       while (--i >= 0)
-               gpio_free(v3020_gpio[i].gpio);
+       if (!err)
+               chip->gpio = v3020_gpio;
 
        return err;
 }
 
 static void v3020_gpio_unmap(struct v3020 *chip)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++)
-               gpio_free(v3020_gpio[i].gpio);
+       gpio_free_array(v3020_gpio, ARRAY_SIZE(v3020_gpio));
 }
 
 static void v3020_gpio_write_bit(struct v3020 *chip, unsigned char bit)
index 7728d5e..b4a68ff 100644 (file)
@@ -31,7 +31,7 @@ int rtc_set_ntp_time(struct timespec64 now)
        else
                rtc_time64_to_tm(now.tv_sec + 1, &tm);
 
-       rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+       rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
        if (rtc) {
                /* rtc_hctosys exclusively uses UTC, so we call set_time here,
                 * not set_mmss. */
index 8dcf682..3359f04 100644 (file)
@@ -24,6 +24,14 @@ extern void rtc_time64_to_tm(time64_t time, struct rtc_time *tm);
 ktime_t rtc_tm_to_ktime(struct rtc_time tm);
 struct rtc_time rtc_ktime_to_tm(ktime_t kt);
 
+/*
+ * rtc_tm_sub - Return the difference in seconds.
+ */
+static inline time64_t rtc_tm_sub(struct rtc_time *lhs, struct rtc_time *rhs)
+{
+       return rtc_tm_to_time64(lhs) - rtc_tm_to_time64(rhs);
+}
+
 /**
  * Deprecated. Use rtc_time64_to_tm().
  */
@@ -101,8 +109,7 @@ struct rtc_timer {
 /* flags */
 #define RTC_DEV_BUSY 0
 
-struct rtc_device
-{
+struct rtc_device {
        struct device dev;
        struct module *owner;
 
@@ -161,7 +168,6 @@ extern void devm_rtc_device_unregister(struct device *dev,
 
 extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
 extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
-extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
 extern int rtc_set_ntp_time(struct timespec64 now);
 int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
 extern int rtc_read_alarm(struct rtc_device *rtc,
@@ -198,10 +204,10 @@ int rtc_register(rtc_task_t *task);
 int rtc_unregister(rtc_task_t *task);
 int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
 
-void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data);
-int rtc_timer_start(struct rtc_device *rtc, struct rtc_timertimer,
-                       ktime_t expires, ktime_t period);
-int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer);
+void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data);
+int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
+                   ktime_t expires, ktime_t period);
+void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer);
 void rtc_timer_do_work(struct work_struct *work);
 
 static inline bool is_leap_year(unsigned int year)