Merge tag 'rtc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Aug 2016 13:48:22 +0000 (09:48 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Aug 2016 13:48:22 +0000 (09:48 -0400)
Pull RTC updates from Alexandre Belloni:
 "RTC for 4.8

  Cleanups:
   - huge cleanup of rtc-generic and char/genrtc this allowed to cleanup
     rtc-cmos, rtc-sh, rtc-m68k, rtc-powerpc and rtc-parisc
   - move mn10300 to rtc-cmos

  Subsystem:
   - fix wakealarms after hibernate
   - multiples fixes for rctest
   - simplify implementations of .read_alarm

  New drivers:
   - Maxim MAX6916

  Drivers:
   - ds1307: fix weekday
   - m41t80: add wakeup support
   - pcf85063: add support for PCF85063A variant
   - rv8803: extend i2c fix and other fixes
   - s35390a: fix alarm reading, this fixes instant reboot after
     shutdown for QNAP TS-41x
   - s3c: clock fixes"

* tag 'rtc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (65 commits)
  rtc: rv8803: Clear V1F when setting the time
  rtc: rv8803: Stop the clock while setting the time
  rtc: rv8803: Always apply the I²C workaround
  rtc: rv8803: Fix read day of week
  rtc: rv8803: Remove the check for valid time
  rtc: rv8803: Kconfig: Indicate rx8900 support
  rtc: asm9260: remove .owner field for driver
  rtc: at91sam9: Fix missing spin_lock_init()
  rtc: m41t80: add suspend handlers for alarm IRQ
  rtc: m41t80: make it a real error message
  rtc: pcf85063: Add support for the PCF85063A device
  rtc: pcf85063: fix year range
  rtc: hym8563: in .read_alarm set .tm_sec to 0 to signal minute accuracy
  rtc: explicitly set tm_sec = 0 for drivers with minute accurancy
  rtc: s3c: Add s3c_rtc_{enable/disable}_clk in s3c_rtc_setfreq()
  rtc: s3c: Remove unnecessary call to disable already disabled clock
  rtc: abx80x: use devm_add_action_or_reset()
  rtc: m41t80: use devm_add_action_or_reset()
  rtc: fix a typo and reduce three empty lines to one
  rtc: s35390a: improve two comments in .set_alarm
  ...

105 files changed:
MAINTAINERS
arch/alpha/include/asm/rtc.h [deleted file]
arch/alpha/kernel/core_marvel.c
arch/alpha/kernel/rtc.c
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-orion5x/ts78xx-setup.c
arch/arm/mach-pxa/cm-x270.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/em-x270.c
arch/frv/include/asm/mc146818rtc.h [deleted file]
arch/h8300/include/asm/mc146818rtc.h [deleted file]
arch/ia64/include/asm/mc146818rtc.h [deleted file]
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/config.c
arch/m68k/include/asm/rtc.h [deleted file]
arch/m68k/kernel/time.c
arch/m68k/mac/config.c
arch/m68k/mac/misc.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/config.c
arch/m68k/sun3/intersil.c
arch/m68k/sun3x/time.c
arch/mips/sgi-ip22/ip22-reset.c
arch/mips/sni/time.c
arch/mn10300/Kconfig
arch/mn10300/include/asm/rtc-regs.h
arch/mn10300/include/asm/rtc.h
arch/mn10300/kernel/rtc.c
arch/mn10300/proc-mn103e010/proc-init.c
arch/mn10300/proc-mn2ws0050/proc-init.c
arch/parisc/include/asm/mc146818rtc.h [deleted file]
arch/parisc/include/asm/rtc.h [deleted file]
arch/parisc/kernel/time.c
arch/powerpc/include/asm/rtc.h [deleted file]
arch/powerpc/kernel/time.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/ps3/time.c
arch/sh/include/asm/mc146818rtc.h [deleted file]
arch/sh/include/asm/rtc.h
arch/sh/kernel/time.c
arch/sparc/include/asm/io_32.h
arch/x86/Kconfig
arch/x86/include/asm/mc146818rtc.h
arch/x86/include/asm/rtc.h [deleted file]
arch/x86/kernel/hpet.c
arch/x86/kernel/nmi.c
arch/x86/kernel/rtc.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/intel-mid/intel_mid_vrtc.c
drivers/acpi/acpi_cmos_rtc.c
drivers/base/power/trace.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/genrtc.c [deleted file]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/interface.c
drivers/rtc/rtc-abx80x.c
drivers/rtc/rtc-asm9260.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-da9052.c
drivers/rtc/rtc-da9055.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1286.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1343.c
drivers/rtc/rtc-ds1685.c
drivers/rtc/rtc-ds2404.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-generic.c
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-isl12057.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6916.c [new file with mode: 0644]
drivers/rtc/rtc-mc146818-lib.c [moved from include/asm-generic/rtc.h with 76% similarity]
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pcf85063.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-rc5t583.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx8010.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-tegra.c
drivers/rtc/rtc-v3020.c
include/linux/ds17287rtc.h [deleted file]
include/linux/mc146818rtc.h
include/linux/platform_data/rtc-ds2404.h [moved from include/linux/rtc-ds2404.h with 100% similarity]
include/linux/platform_data/rtc-m48t86.h [moved from include/linux/m48t86.h with 100% similarity]
include/linux/platform_data/rtc-v3020.h [moved from include/linux/rtc-v3020.h with 100% similarity]
include/linux/rtc/ds1286.h [moved from include/linux/ds1286.h with 100% similarity]
tools/testing/selftests/timers/rtctest.c

index efc2031..e9c7527 100644 (file)
@@ -9828,10 +9828,14 @@ 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/devicetree/bindings/rtc/
 F:     Documentation/rtc.txt
 F:     drivers/rtc/
 F:     include/linux/rtc.h
 F:     include/uapi/linux/rtc.h
+F:     include/linux/rtc/
+F:     include/linux/platform_data/rtc-*
+F:     tools/testing/selftests/timers/rtctest.c
 
 REALTEK AUDIO CODECS
 M:     Bard Liao <bardliao@realtek.com>
diff --git a/arch/alpha/include/asm/rtc.h b/arch/alpha/include/asm/rtc.h
deleted file mode 100644 (file)
index f71c3b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/rtc.h>
index 53dd2f1..d5f0580 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/gct.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
-#include <asm/rtc.h>
 #include <asm/vga.h>
 
 #include "proto.h"
index f535a3f..ceed68c 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
 
-#include <asm/rtc.h>
-
 #include "proto.h"
 
 
@@ -81,7 +79,7 @@ init_rtc_epoch(void)
 static int
 alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       __get_rtc_time(tm);
+       mc146818_get_time(tm);
 
        /* Adjust for non-default epochs.  It's easier to depend on the
           generic __get_rtc_time and adjust the epoch here than create
@@ -112,7 +110,7 @@ alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
                tm = &xtm;
        }
 
-       return __set_rtc_time(tm);
+       return mc146818_set_time(tm);
 }
 
 static int
index 45b81a2..3b39ea3 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
index 3a58a5d..8d59726 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ata_platform.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/timeriomem-rng.h>
index fa5f51d..be4a661 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
 #include <video/mbxfb.h>
 
 #include <linux/spi/spi.h>
index 5f5ac7c..868448d 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/dm9000.h>
 #include <linux/leds.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 
index 6e0268d..03354c2 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/delay.h>
 
 #include <linux/dm9000.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
diff --git a/arch/frv/include/asm/mc146818rtc.h b/arch/frv/include/asm/mc146818rtc.h
deleted file mode 100644 (file)
index 90dfb7a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* mc146818rtc.h: RTC defs
- *
- * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.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.
- */
-
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-
-#endif /* _ASM_MC146818RTC_H */
diff --git a/arch/h8300/include/asm/mc146818rtc.h b/arch/h8300/include/asm/mc146818rtc.h
deleted file mode 100644 (file)
index ab9d964..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _H8300_MC146818RTC_H
-#define _H8300_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
-
-#endif /* _H8300_MC146818RTC_H */
diff --git a/arch/ia64/include/asm/mc146818rtc.h b/arch/ia64/include/asm/mc146818rtc.h
deleted file mode 100644 (file)
index 407787a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_IA64_MC146818RTC_H
-#define _ASM_IA64_MC146818RTC_H
-
-/*
- * Machine dependent access functions for RTC registers.
- */
-
-/* empty include file to satisfy the include in genrtc.c */
-
-#endif /* _ASM_IA64_MC146818RTC_H */
index 01693df..ec9cc1f 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/irq.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 
index 6e62d66..432bc8b 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 
 u_long sio01_physaddr;
index 478623d..611d4d9 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/bvme6000hw.h>
 
index a9befe6..7cfab15 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
+#include <linux/rtc.h>
 
 #include <asm/bootinfo.h>
 #include <asm/bootinfo-hp300.h>
@@ -20,7 +21,6 @@
 #include <asm/blinken.h>
 #include <asm/io.h>                               /* readb() and writeb() */
 #include <asm/hp300hw.h>
-#include <asm/rtc.h>
 
 #include "time.h"
 
diff --git a/arch/m68k/include/asm/rtc.h b/arch/m68k/include/asm/rtc.h
deleted file mode 100644 (file)
index a4d08ea..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/* include/asm-m68k/rtc.h
- *
- * Copyright Richard Zidlicky
- * implementation details for genrtc/q40rtc driver
- */
-/* permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-
-#ifndef _ASM_RTC_H
-#define _ASM_RTC_H
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-#include <asm/errno.h>
-#include <asm/machdep.h>
-
-#define RTC_PIE 0x40           /* periodic interrupt enable */
-#define RTC_AIE 0x20           /* alarm interrupt enable */
-#define RTC_UIE 0x10           /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100     /* battery bad */
-#define RTC_SQWE 0x08          /* enable square-wave output */
-#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
-#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
-       /*
-        * Only the values that we read from the RTC are set. We leave
-        * tm_wday, tm_yday and tm_isdst untouched. Even though the
-        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
-        * by the RTC when initially set to a non-zero value.
-        */
-       if (mach_hwclk)
-               mach_hwclk(0, time);
-       return RTC_24H;
-}
-
-static inline int set_rtc_time(struct rtc_time *time)
-{
-       if (mach_hwclk)
-               return mach_hwclk(1, time);
-       return -EINVAL;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
-       if (mach_get_ss)
-               return mach_get_ss();
-       else{
-               struct rtc_time h;
-
-               get_rtc_time(&h);
-               return h.tm_sec;
-       }
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-       if (mach_get_rtc_pll)
-               return mach_get_rtc_pll(pll);
-       else
-               return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-       if (mach_set_rtc_pll)
-               return mach_set_rtc_pll(pll);
-       else
-               return -EINVAL;
-}
-#endif /* __KERNEL__ */
-
-#endif /* _ASM__RTC_H */
index 3857737..4e5aa2f 100644 (file)
@@ -86,7 +86,49 @@ void read_persistent_clock(struct timespec *ts)
        }
 }
 
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+#if defined(CONFIG_ARCH_USES_GETTIMEOFFSET) && IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+       mach_hwclk(0, tm);
+       return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+       if (mach_hwclk(1, tm) < 0)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+static int rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct rtc_pll_info pll;
+       struct rtc_pll_info __user *argp = (void __user *)arg;
+
+       switch (cmd) {
+       case RTC_PLL_GET:
+               if (!mach_get_rtc_pll || mach_get_rtc_pll(&pll))
+                       return -EINVAL;
+               return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
+
+       case RTC_PLL_SET:
+               if (!mach_set_rtc_pll)
+                       return -EINVAL;
+               if (!capable(CAP_SYS_TIME))
+                       return -EACCES;
+               if (copy_from_user(&pll, argp, sizeof(pll)))
+                       return -EFAULT;
+               return mach_set_rtc_pll(&pll);
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static const struct rtc_class_ops generic_rtc_ops = {
+       .ioctl = rtc_ioctl,
+       .read_time = rtc_generic_get_time,
+       .set_time = rtc_generic_set_time,
+};
 
 static int __init rtc_init(void)
 {
@@ -95,7 +137,9 @@ static int __init rtc_init(void)
        if (!mach_hwclk)
                return -ENODEV;
 
-       pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+       pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+                                            &generic_rtc_ops,
+                                            sizeof(generic_rtc_ops));
        return PTR_ERR_OR_ZERO(pdev);
 }
 
index 689b47d..2f33a33 100644 (file)
@@ -10,6 +10,7 @@
  * Miscellaneous linux stuff
  */
 
+#include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
@@ -25,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
+#include <linux/rtc.h>
 
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
@@ -34,7 +36,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 
 #include <asm/macintosh.h>
index 707b61a..0fb54a9 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/rtc.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
 #include <asm/macintosh.h>
index e6a3b56..c11d38d 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/mvme147hw.h>
 
index a53803c..58e2409 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/mvme16xhw.h>
 
index e90fe90..fcb7f05 100644 (file)
@@ -12,6 +12,7 @@
  * for more details.
  */
 
+#include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -27,7 +28,6 @@
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
-#include <asm/rtc.h>
 #include <asm/bootinfo.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
index 71884bf..3af34fa 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/pgalloc.h>
 #include <asm/sun3-head.h>
 #include <asm/sun3mmu.h>
-#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/machines.h>
 #include <asm/idprom.h>
index 889829e..2cd0bcb 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/rtc.h>
 
 #include <asm/errno.h>
-#include <asm/rtc.h>
 #include <asm/intersil.h>
+#include <asm/machdep.h>
 
 
 /* bits to set for start/run of the intersil */
index c8eb08a..431d3c4 100644 (file)
 
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/machdep.h>
 #include <asm/traps.h>
 #include <asm/sun3x.h>
 #include <asm/sun3ints.h>
-#include <asm/rtc.h>
 
 #include "time.h"
 
index 063c2dd..2f45b03 100644 (file)
@@ -7,7 +7,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <linux/ds1286.h>
+#include <linux/rtc/ds1286.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
index fb4b352..7ee14f4 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
-#include <asm-generic/rtc.h>
 
 #define SNI_CLOCK_TICK_RATE    3686400
 #define SNI_COUNTER2_DIV       64
index 9627e81..38e3494 100644 (file)
@@ -236,7 +236,9 @@ source "kernel/Kconfig.hz"
 config MN10300_RTC
        bool "Using MN10300 RTC"
        depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
-       select GENERIC_CMOS_UPDATE
+       select RTC_CLASS
+       select RTC_DRV_CMOS
+       select RTC_SYSTOHC
        default n
        help
          This option enables support for the RTC, thus enabling time to be
index c42deef..c81cace 100644 (file)
@@ -75,9 +75,9 @@
 #define RTC_PORT(x)            0xd8600000
 #define RTC_ALWAYS_BCD         1       /* RTC operates in binary mode */
 
-#define CMOS_READ(addr)                __SYSREG(0xd8600000 + (addr), u8)
+#define CMOS_READ(addr)                __SYSREG(0xd8600000 + (u32)(addr), u8)
 #define CMOS_WRITE(val, addr)  \
-       do { __SYSREG(0xd8600000 + (addr), u8) = val; } while (0)
+       do { __SYSREG(0xd8600000 + (u32)(addr), u8) = val; } while (0)
 
 #define RTC_IRQ                        RTIRQ
 
index 6c14bb1..07dc876 100644 (file)
@@ -25,6 +25,4 @@ static inline void calibrate_clock(void)
 
 #endif /* !CONFIG_MN10300_RTC */
 
-#include <asm-generic/rtc.h>
-
 #endif /* _ASM_RTC_H */
index 48d7058..f81f370 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
-#include <linux/timex.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
 #include <asm/rtc-regs.h>
 #include <asm/rtc.h>
 
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
-/*
- * Read the current RTC time
- */
-void read_persistent_clock(struct timespec *ts)
-{
-       struct rtc_time tm;
-
-       get_rtc_time(&tm);
-
-       ts->tv_nsec = 0;
-       ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
-                           tm.tm_hour, tm.tm_min, tm.tm_sec);
-
-       /* if rtc is way off in the past, set something reasonable */
-       if (ts->tv_sec < 0)
-               ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0);
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
- * ms after the second nowtime has started, because when nowtime is written
- * into the registers of the CMOS clock, it will jump to the next second
- * precisely 500 ms later.  Check the Motorola MC146818A or Dallas DS12887 data
- * sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you'll only notice that after reboot!
- */
-static int set_rtc_mmss(unsigned long nowtime)
-{
-       unsigned char save_control, save_freq_select;
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-
-       /* gets recalled with irq locally disabled */
-       spin_lock(&rtc_lock);
-       save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
-                                               * set */
-       CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
-
-       save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
-                                                       * prescaler */
-       CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
-
-       cmos_minutes = CMOS_READ(RTC_MINUTES);
-       if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               cmos_minutes = bcd2bin(cmos_minutes);
-
-       /*
-        * since we're only adjusting minutes and seconds,
-        * don't interfere with hour overflow. This avoids
-        * messing with unknown time zones but requires your
-        * RTC not to be off by more than 15 minutes
-        */
-       real_seconds = nowtime % 60;
-       real_minutes = nowtime / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
-               /* correct for half hour time zone */
-               real_minutes += 30;
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       real_seconds = bin2bcd(real_seconds);
-                       real_minutes = bin2bcd(real_minutes);
-               }
-               CMOS_WRITE(real_seconds, RTC_SECONDS);
-               CMOS_WRITE(real_minutes, RTC_MINUTES);
-       } else {
-               printk_once(KERN_NOTICE
-                      "set_rtc_mmss: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       /* The following flags have to be released exactly in this order,
-        * otherwise the DS12887 (popular MC146818A clone with integrated
-        * battery and quartz) will not reset the oscillator and will not
-        * update precisely 500 ms later. You won't find this mentioned in
-        * the Dallas Semiconductor data sheets, but who believes data
-        * sheets anyway ...                           -- Markus Kuhn
-        */
-       CMOS_WRITE(save_control, RTC_CONTROL);
-       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-       spin_unlock(&rtc_lock);
-
-       return retval;
-}
-
-int update_persistent_clock(struct timespec now)
-{
-       return set_rtc_mmss(now.tv_sec);
-}
+static const __initdata struct resource res[] = {
+       DEFINE_RES_IO(RTC_PORT(0), RTC_IO_EXTENT),
+       DEFINE_RES_IRQ(RTC_IRQ),
+};
 
 /*
  * calibrate the TSC clock against the RTC
@@ -129,4 +41,6 @@ void __init calibrate_clock(void)
        RTCRA |= RTCRA_DVR;
        RTCRA &= ~RTCRA_DVR;
        RTCRB &= ~RTCRB_SET;
+
+       platform_device_register_simple("rtc_cmos", -1, res, ARRAY_SIZE(res));
 }
index 27b9798..102d86a 100644 (file)
@@ -9,7 +9,10 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 #include <linux/kernel.h>
+#include <linux/irq.h>
+#include <asm/cacheflush.h>
 #include <asm/fpu.h>
+#include <asm/irq.h>
 #include <asm/rtc.h>
 #include <asm/busctl-regs.h>
 
index ee6d03d..950cc8d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
+#include <asm/cacheflush.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff --git a/arch/parisc/include/asm/mc146818rtc.h b/arch/parisc/include/asm/mc146818rtc.h
deleted file mode 100644 (file)
index adf4163..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c */
-
-#endif /* _ASM_MC146818RTC_H */
diff --git a/arch/parisc/include/asm/rtc.h b/arch/parisc/include/asm/rtc.h
deleted file mode 100644 (file)
index 099d641..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 
- * include/asm-parisc/rtc.h
- *
- * Copyright 2002 Randolph CHung <tausq@debian.org>
- *
- * Based on: include/asm-ppc/rtc.h and the genrtc driver in the
- * 2.4 parisc linux tree
- */
-
-#ifndef __ASM_RTC_H__
-#define __ASM_RTC_H__
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-
-#include <asm/pdc.h>
-
-#define SECS_PER_HOUR   (60 * 60)
-#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
-
-
-#define RTC_PIE 0x40           /* periodic interrupt enable */
-#define RTC_AIE 0x20           /* alarm interrupt enable */
-#define RTC_UIE 0x10           /* update-finished interrupt enable */
-
-#define RTC_BATT_BAD 0x100     /* battery bad */
-
-/* some dummy definitions */
-#define RTC_SQWE 0x08          /* enable square-wave output */
-#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
-#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
-
-# define __isleap(year) \
-  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
-/* How many days come before each month (0-12).  */
-static const unsigned short int __mon_yday[2][13] =
-{
-       /* Normal years.  */
-       { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-       /* Leap years.  */
-       { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
-static inline unsigned int get_rtc_time(struct rtc_time *wtime)
-{
-       struct pdc_tod tod_data;
-       long int days, rem, y;
-       const unsigned short int *ip;
-
-       memset(wtime, 0, sizeof(*wtime));
-       if (pdc_tod_read(&tod_data) < 0)
-               return RTC_24H | RTC_BATT_BAD;
-
-       // most of the remainder of this function is:
-//     Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
-//     This was originally a part of the GNU C Library.
-//      It is distributed under the GPL, and was swiped from offtime.c
-
-
-       days = tod_data.tod_sec / SECS_PER_DAY;
-       rem = tod_data.tod_sec % SECS_PER_DAY;
-
-       wtime->tm_hour = rem / SECS_PER_HOUR;
-       rem %= SECS_PER_HOUR;
-       wtime->tm_min = rem / 60;
-       wtime->tm_sec = rem % 60;
-
-       y = 1970;
-
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
-
-       while (days < 0 || days >= (__isleap (y) ? 366 : 365))
-       {
-               /* Guess a corrected year, assuming 365 days per year.  */
-               long int yg = y + days / 365 - (days % 365 < 0);
-
-               /* Adjust DAYS and Y to match the guessed year.  */
-               days -= ((yg - y) * 365
-                        + LEAPS_THRU_END_OF (yg - 1)
-                        - LEAPS_THRU_END_OF (y - 1));
-               y = yg;
-       }
-       wtime->tm_year = y - 1900;
-
-       ip = __mon_yday[__isleap(y)];
-       for (y = 11; days < (long int) ip[y]; --y)
-               continue;
-       days -= ip[y];
-       wtime->tm_mon = y;
-       wtime->tm_mday = days + 1;
-
-       return RTC_24H;
-}
-
-static int set_rtc_time(struct rtc_time *wtime)
-{
-       u_int32_t secs;
-
-       secs = mktime(wtime->tm_year + 1900, wtime->tm_mon + 1, wtime->tm_mday, 
-                     wtime->tm_hour, wtime->tm_min, wtime->tm_sec);
-
-       if(pdc_tod_set(secs, 0) < 0)
-               return -1;
-       else
-               return 0;
-
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
-       struct rtc_time h;
-
-       get_rtc_time(&h);
-       return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_RTC_H__ */
index 31ec99a..505cf1a 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/rtc.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
@@ -248,14 +249,47 @@ void __init start_cpu_itimer(void)
        per_cpu(cpu_data, cpu).it_value = next_tick;
 }
 
+#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+       struct pdc_tod tod_data;
+
+       memset(tm, 0, sizeof(*tm));
+       if (pdc_tod_read(&tod_data) < 0)
+               return -EOPNOTSUPP;
+
+       /* we treat tod_sec as unsigned, so this can work until year 2106 */
+       rtc_time64_to_tm(tod_data.tod_sec, tm);
+       return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+       time64_t secs = rtc_tm_to_time64(tm);
+
+       if (pdc_tod_set(secs, 0) < 0)
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
+static const struct rtc_class_ops rtc_generic_ops = {
+       .read_time = rtc_generic_get_time,
+       .set_time = rtc_generic_set_time,
+};
+
 static int __init rtc_init(void)
 {
        struct platform_device *pdev;
 
-       pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+       pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+                                            &rtc_generic_ops,
+                                            sizeof(rtc_generic_ops));
+
        return PTR_ERR_OR_ZERO(pdev);
 }
 device_initcall(rtc_init);
+#endif
 
 void read_persistent_clock(struct timespec *ts)
 {
diff --git a/arch/powerpc/include/asm/rtc.h b/arch/powerpc/include/asm/rtc.h
deleted file mode 100644 (file)
index f580292..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Real-time clock definitions and interfaces
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Based on:
- * include/asm-m68k/rtc.h
- *
- * Copyright Richard Zidlicky
- * implementation details for genrtc/q40rtc driver
- *
- * And the old drivers/macintosh/rtc.c which was heavily based on:
- * Linux/SPARC Real Time Clock Driver
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- *
- * With additional work by Paul Mackerras and Franz Sirl.
- */
-
-#ifndef __ASM_POWERPC_RTC_H__
-#define __ASM_POWERPC_RTC_H__
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-
-#include <asm/machdep.h>
-#include <asm/time.h>
-
-#define RTC_PIE 0x40           /* periodic interrupt enable */
-#define RTC_AIE 0x20           /* alarm interrupt enable */
-#define RTC_UIE 0x10           /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100     /* battery bad */
-#define RTC_SQWE 0x08          /* enable square-wave output */
-#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
-#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
-       if (ppc_md.get_rtc_time)
-               ppc_md.get_rtc_time(time);
-       return RTC_24H;
-}
-
-/* Set the current date and time in the real time clock. */
-static inline int set_rtc_time(struct rtc_time *time)
-{
-       if (ppc_md.set_rtc_time)
-               return ppc_md.set_rtc_time(time);
-       return -EINVAL;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
-       struct rtc_time h;
-
-       get_rtc_time(&h);
-       return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_POWERPC_RTC_H__ */
index 4e7759c..3efbede 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/irq_work.h>
 #include <linux/clk-provider.h>
 #include <linux/suspend.h>
+#include <linux/rtc.h>
 #include <asm/trace.h>
 
 #include <asm/io.h>
@@ -1159,6 +1160,29 @@ void calibrate_delay(void)
        loops_per_jiffy = tb_ticks_per_jiffy;
 }
 
+#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+       ppc_md.get_rtc_time(tm);
+       return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+       if (!ppc_md.set_rtc_time)
+               return -EOPNOTSUPP;
+
+       if (ppc_md.set_rtc_time(tm) < 0)
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
+static const struct rtc_class_ops rtc_generic_ops = {
+       .read_time = rtc_generic_get_time,
+       .set_time = rtc_generic_set_time,
+};
+
 static int __init rtc_init(void)
 {
        struct platform_device *pdev;
@@ -1166,9 +1190,12 @@ static int __init rtc_init(void)
        if (!ppc_md.get_rtc_time)
                return -ENODEV;
 
-       pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+       pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+                                            &rtc_generic_ops,
+                                            sizeof(rtc_generic_ops));
 
        return PTR_ERR_OR_ZERO(pdev);
 }
 
 device_initcall(rtc_init);
+#endif
index 3663f71..fbdae83 100644 (file)
@@ -321,6 +321,17 @@ config OF_RTC
          Uses information from the OF or flattened device tree to instantiate
          platform devices for direct mapped RTC chips like the DS1742 or DS1743.
 
+config GEN_RTC
+       bool "Use the platform RTC operations from user space"
+       select RTC_CLASS
+       select RTC_DRV_GENERIC
+       help
+         This option provides backwards compatibility with the old gen_rtc.ko
+         module that was traditionally used for old PowerPC machines.
+         Platforms should migrate to enabling the RTC_DRV_GENERIC by hand
+         replacing their get_rtc_time/set_rtc_time callbacks with
+         a proper RTC device driver.
+
 config SIMPLE_GPIO
        bool "Support for simple, memory-mapped GPIO controllers"
        depends on PPC
index 791c614..11b45b5 100644 (file)
@@ -20,9 +20,9 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/rtc.h>
 
 #include <asm/firmware.h>
-#include <asm/rtc.h>
 #include <asm/lv1call.h>
 #include <asm/ps3.h>
 
diff --git a/arch/sh/include/asm/mc146818rtc.h b/arch/sh/include/asm/mc146818rtc.h
deleted file mode 100644 (file)
index 0aee96a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-#endif /* _ASM_MC146818RTC_H */
index 52b0c2d..f7b010d 100644 (file)
@@ -6,17 +6,6 @@ extern void (*board_time_init)(void);
 extern void (*rtc_sh_get_time)(struct timespec *);
 extern int (*rtc_sh_set_time)(const time_t);
 
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100     /* battery bad */
-#define RTC_SQWE 0x08          /* enable square-wave output */
-#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
-#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
-
-struct rtc_time;
-unsigned int get_rtc_time(struct rtc_time *);
-int set_rtc_time(struct rtc_time *);
-
 #define RTC_CAP_4_DIGIT_YEAR   (1 << 0)
 
 struct sh_rtc_platform_info {
index d6d0a98..a4a7862 100644 (file)
@@ -50,27 +50,31 @@ int update_persistent_clock(struct timespec now)
 }
 #endif
 
-unsigned int get_rtc_time(struct rtc_time *tm)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
 {
-       if (rtc_sh_get_time != null_rtc_get_time) {
-               struct timespec tv;
+       struct timespec tv;
 
-               rtc_sh_get_time(&tv);
-               rtc_time_to_tm(tv.tv_sec, tm);
-       }
-
-       return RTC_24H;
+       rtc_sh_get_time(&tv);
+       rtc_time_to_tm(tv.tv_sec, tm);
+       return 0;
 }
-EXPORT_SYMBOL(get_rtc_time);
 
-int set_rtc_time(struct rtc_time *tm)
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
 {
        unsigned long secs;
 
        rtc_tm_to_time(tm, &secs);
-       return rtc_sh_set_time(secs);
+       if ((rtc_sh_set_time == null_rtc_set_time) ||
+           (rtc_sh_set_time(secs) < 0))
+               return -EOPNOTSUPP;
+
+       return 0;
 }
-EXPORT_SYMBOL(set_rtc_time);
+
+static const struct rtc_class_ops rtc_generic_ops = {
+       .read_time = rtc_generic_get_time,
+       .set_time = rtc_generic_set_time,
+};
 
 static int __init rtc_generic_init(void)
 {
@@ -79,7 +83,10 @@ static int __init rtc_generic_init(void)
        if (rtc_sh_get_time == null_rtc_get_time)
                return -ENODEV;
 
-       pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+       pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+                                            &rtc_generic_ops,
+                                            sizeof(rtc_generic_ops));
+
 
        return PTR_ERR_OR_ZERO(pdev);
 }
index 57f26c3..4dd268a 100644 (file)
@@ -140,16 +140,6 @@ void ioport_unmap(void __iomem *);
 struct pci_dev;
 void pci_iounmap(struct pci_dev *dev, void __iomem *);
 
-
-
-/*
- * At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
- * so rtc_port is static in it. This should not change unless a new
- * hardware pops up.
- */
-#define RTC_PORT(x)   (rtc_port + (x))
-#define RTC_ALWAYS_BCD  0
-
 static inline int sbus_can_dma_64bit(void)
 {
        return 0; /* actually, sparc_cpu_model==sun4d */
index 3a9add5..5c6e747 100644 (file)
@@ -152,6 +152,7 @@ config X86
        select OLD_SIGSUSPEND3                  if X86_32 || IA32_EMULATION
        select PERF_EVENTS
        select RTC_LIB
+       select RTC_MC146818_LIB
        select SPARSE_IRQ
        select SRCU
        select SYSCTL_EXCEPTION_TRACE
index 0f555cc..24acd9b 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <asm/io.h>
 #include <asm/processor.h>
-#include <linux/mc146818rtc.h>
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)    (0x70 + (x))
diff --git a/arch/x86/include/asm/rtc.h b/arch/x86/include/asm/rtc.h
deleted file mode 100644 (file)
index f71c3b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/rtc.h>
index 3d74707..ed16e58 100644 (file)
@@ -1019,7 +1019,6 @@ void hpet_disable(void)
  */
 #include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
-#include <asm/rtc.h>
 
 #define DEFAULT_RTC_INT_FREQ   64
 #define DEFAULT_RTC_SHIFT      6
@@ -1243,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
        memset(&curr_time, 0, sizeof(struct rtc_time));
 
        if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
-               get_rtc_time(&curr_time);
+               mc146818_set_time(&curr_time);
 
        if (hpet_rtc_flags & RTC_UIE &&
            curr_time.tm_sec != hpet_prev_update_sec) {
index 04b132a..bfe4d6c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/hardirq.h>
+#include <linux/ratelimit.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 
index eceaa08..79c6311 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/x86_init.h>
 #include <asm/time.h>
 #include <asm/intel-mid.h>
-#include <asm/rtc.h>
 #include <asm/setup.h>
 
 #ifdef CONFIG_X86_32
@@ -47,7 +46,7 @@ int mach_set_rtc_mmss(const struct timespec *now)
 
        rtc_time_to_tm(nowtime, &tm);
        if (!rtc_valid_tm(&tm)) {
-               retval = set_rtc_time(&tm);
+               retval = mc146818_set_time(&tm);
                if (retval)
                        printk(KERN_ERR "%s: RTC write failed with error %d\n",
                               __func__, retval);
index 17c8bbd..1fbb408 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
-#include <asm/rtc.h>
 #include <asm/uv/uv.h>
 
 static struct efi efi_phys __initdata;
index 04db6fb..677e29e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/mc146818rtc.h>
 #include <linux/efi.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
index ee40fcb..5802486 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
+#include <linux/mc146818rtc.h>
 
 #include <asm/intel-mid.h>
 #include <asm/intel_mid_vrtc.h>
index 81dc750..0980a13 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <asm-generic/rtc.h>
+#include <linux/mc146818rtc.h>
 
 #include "internal.h"
 
index a697579..efec10b 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/export.h>
 #include <linux/rtc.h>
 
-#include <asm/rtc.h>
+#include <linux/mc146818rtc.h>
 
 #include "power.h"
 
@@ -103,7 +103,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev
        n /= 24;
        time.tm_min = (n % 20) * 3;
        n /= 20;
-       set_rtc_time(&time);
+       mc146818_set_time(&time);
        return n ? -1 : 0;
 }
 
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
        struct rtc_time time;
        unsigned int val;
 
-       get_rtc_time(&time);
+       mc146818_get_time(&time);
        pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
                time.tm_hour, time.tm_min, time.tm_sec,
                time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
index fdb8f3e..dcc0973 100644 (file)
@@ -293,7 +293,7 @@ if RTC_LIB=n
 
 config RTC
        tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
-       depends on ALPHA || (MIPS && MACH_LOONGSON64) || MN10300
+       depends on ALPHA || (MIPS && MACH_LOONGSON64)
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -339,32 +339,6 @@ config JS_RTC
          To compile this driver as a module, choose M here: the
          module will be called js-rtc.
 
-config GEN_RTC
-       tristate "Generic /dev/rtc emulation"
-       depends on RTC!=y
-       depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86
-       ---help---
-         If you say Y here and create a character special file /dev/rtc with
-         major number 10 and minor number 135 using mknod ("man mknod"), you
-         will get access to the real time clock (or hardware clock) built
-         into your computer.
-
-         It reports status information via the file /proc/driver/rtc and its
-         behaviour is set by various ioctls on /dev/rtc. If you enable the
-         "extended RTC operation" below it will also provide an emulation
-         for RTC_UIE which is required by some programs and may improve
-         precision in some cases.
-
-         To compile this driver as a module, choose M here: the
-         module will be called genrtc.
-
-config GEN_RTC_X
-       bool "Extended RTC operation"
-       depends on GEN_RTC
-       help
-         Provides an emulation for RTC_UIE which is required by some programs
-         and may improve precision of the generic RTC support in some cases.
-
 config EFI_RTC
        bool "EFI Real Time Clock Services"
        depends on IA64
index 55d16bf..6e6c244 100644 (file)
@@ -25,7 +25,6 @@ obj-$(CONFIG_APPLICOM)                += applicom.o
 obj-$(CONFIG_SONYPI)           += sonypi.o
 obj-$(CONFIG_RTC)              += rtc.o
 obj-$(CONFIG_HPET)             += hpet.o
-obj-$(CONFIG_GEN_RTC)          += genrtc.o
 obj-$(CONFIG_EFI_RTC)          += efirtc.o
 obj-$(CONFIG_DS1302)           += ds1302.o
 obj-$(CONFIG_XILINX_HWICAP)    += xilinx_hwicap/
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
deleted file mode 100644 (file)
index 4f94375..0000000
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- *     Real Time Clock interface for
- *             - q40 and other m68k machines,
- *             - HP PARISC machines
- *             - PowerPC machines
- *      emulate some RTC irq capabilities in software
- *
- *      Copyright (C) 1999 Richard Zidlicky
- *
- *     based on Paul Gortmaker's rtc.c device and
- *           Sam Creasey Generic rtc driver
- *
- *     This driver allows use of the real time clock (built into
- *     nearly all computers) from user space. It exports the /dev/rtc
- *     interface supporting various ioctl() and also the /proc/driver/rtc
- *     pseudo-file for status information.
- *
- *     The ioctls can be used to set the interrupt behaviour where
- *     supported.
- *
- *     The /dev/rtc interface will block on reads until an interrupt
- *     has been received. If a RTC interrupt has already happened,
- *     it will output an unsigned long and then block. The output value
- *     contains the interrupt status in the low byte and the number of
- *     interrupts since the last read in the remaining high bytes. The
- *     /dev/rtc interface can also be used with the select(2) call.
- *
- *     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.
- *
-
- *      1.01 fix for 2.3.X                    rz@linux-m68k.org
- *      1.02 merged with code from genrtc.c   rz@linux-m68k.org
- *      1.03 make it more portable            zippel@linux-m68k.org
- *      1.04 removed useless timer code       rz@linux-m68k.org
- *      1.05 portable RTC_UIE emulation       rz@linux-m68k.org
- *      1.06 set_rtc_time can return an error trini@kernel.crashing.org
- *      1.07 ported to HP PARISC (hppa)              Helge Deller <deller@gmx.de>
- */
-
-#define RTC_VERSION    "1.07"
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-
-#include <linux/rtc.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/rtc.h>
-
-/*
- *     We sponge a minor off of the misc major. No need slurping
- *     up another valuable major dev number for this. If you add
- *     an ioctl, make sure you don't conflict with SPARC's RTC
- *     ioctls.
- */
-
-static DEFINE_MUTEX(gen_rtc_mutex);
-static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
-
-/*
- *     Bits in gen_rtc_status.
- */
-
-#define RTC_IS_OPEN            0x01    /* means /dev/rtc is in use     */
-
-static unsigned char gen_rtc_status;   /* bitmapped status byte.       */
-static unsigned long gen_rtc_irq_data; /* our output to the world      */
-
-/* months start at 0 now */
-static unsigned char days_in_mo[] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static int irq_active;
-
-#ifdef CONFIG_GEN_RTC_X
-static struct work_struct genrtc_task;
-static struct timer_list timer_task;
-
-static unsigned int oldsecs;
-static int lostint;
-static unsigned long tt_exp;
-
-static void gen_rtc_timer(unsigned long data);
-
-static volatile int stask_active;              /* schedule_work */
-static volatile int ttask_active;              /* timer_task */
-static int stop_rtc_timers;                    /* don't requeue tasks */
-static DEFINE_SPINLOCK(gen_rtc_lock);
-
-static void gen_rtc_interrupt(unsigned long arg);
-
-/*
- * Routine to poll RTC seconds field for change as often as possible,
- * after first RTC_UIE use timer to reduce polling
- */
-static void genrtc_troutine(struct work_struct *work)
-{
-       unsigned int tmp = get_rtc_ss();
-       
-       if (stop_rtc_timers) {
-               stask_active = 0;
-               return;
-       }
-
-       if (oldsecs != tmp){
-               oldsecs = tmp;
-
-               timer_task.function = gen_rtc_timer;
-               timer_task.expires = jiffies + HZ - (HZ/10);
-               tt_exp=timer_task.expires;
-               ttask_active=1;
-               stask_active=0;
-               add_timer(&timer_task);
-
-               gen_rtc_interrupt(0);
-       } else if (schedule_work(&genrtc_task) == 0)
-               stask_active = 0;
-}
-
-static void gen_rtc_timer(unsigned long data)
-{
-       lostint = get_rtc_ss() - oldsecs ;
-       if (lostint<0) 
-               lostint = 60 - lostint;
-       if (time_after(jiffies, tt_exp))
-               printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n",
-                      jiffies-tt_exp);
-       ttask_active=0;
-       stask_active=1;
-       if ((schedule_work(&genrtc_task) == 0))
-               stask_active = 0;
-}
-
-/* 
- * call gen_rtc_interrupt function to signal an RTC_UIE,
- * arg is unused.
- * Could be invoked either from a real interrupt handler or
- * from some routine that periodically (eg 100HZ) monitors
- * whether RTC_SECS changed
- */
-static void gen_rtc_interrupt(unsigned long arg)
-{
-       /*  We store the status in the low byte and the number of
-        *      interrupts received since the last read in the remainder
-        *      of rtc_irq_data.  */
-
-       gen_rtc_irq_data += 0x100;
-       gen_rtc_irq_data &= ~0xff;
-       gen_rtc_irq_data |= RTC_UIE;
-
-       if (lostint){
-               printk("genrtc: system delaying clock ticks?\n");
-               /* increment count so that userspace knows something is wrong */
-               gen_rtc_irq_data += ((lostint-1)<<8);
-               lostint = 0;
-       }
-
-       wake_up_interruptible(&gen_rtc_wait);
-}
-
-/*
- *     Now all the various file operations that we export.
- */
-static ssize_t gen_rtc_read(struct file *file, char __user *buf,
-                       size_t count, loff_t *ppos)
-{
-       unsigned long data;
-       ssize_t retval;
-
-       if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
-               return -EINVAL;
-
-       if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
-               return -EAGAIN;
-
-       retval = wait_event_interruptible(gen_rtc_wait,
-                       (data = xchg(&gen_rtc_irq_data, 0)));
-       if (retval)
-               goto out;
-
-       /* first test allows optimizer to nuke this case for 32-bit machines */
-       if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
-               unsigned int uidata = data;
-               retval = put_user(uidata, (unsigned int __user *)buf) ?:
-                       sizeof(unsigned int);
-       }
-       else {
-               retval = put_user(data, (unsigned long __user *)buf) ?:
-                       sizeof(unsigned long);
-       }
-out:
-       return retval;
-}
-
-static unsigned int gen_rtc_poll(struct file *file,
-                                struct poll_table_struct *wait)
-{
-       poll_wait(file, &gen_rtc_wait, wait);
-       if (gen_rtc_irq_data != 0)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-#endif
-
-/*
- * Used to disable/enable interrupts, only RTC_UIE supported
- * We also clear out any old irq data after an ioctl() that
- * meddles with the interrupt enable/disable bits.
- */
-
-static inline void gen_clear_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
-       stop_rtc_timers = 1;
-       if (ttask_active){
-               del_timer_sync(&timer_task);
-               ttask_active = 0;
-       }
-       while (stask_active)
-               schedule();
-
-       spin_lock(&gen_rtc_lock);
-       irq_active = 0;
-       spin_unlock(&gen_rtc_lock);
-#endif
-}
-
-static inline int gen_set_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
-       spin_lock(&gen_rtc_lock);
-       if ( !irq_active ) {
-               irq_active = 1;
-               stop_rtc_timers = 0;
-               lostint = 0;
-               INIT_WORK(&genrtc_task, genrtc_troutine);
-               oldsecs = get_rtc_ss();
-               init_timer(&timer_task);
-
-               stask_active = 1;
-               if (schedule_work(&genrtc_task) == 0){
-                       stask_active = 0;
-               }
-       }
-       spin_unlock(&gen_rtc_lock);
-       gen_rtc_irq_data = 0;
-       return 0;
-#else
-       return -EINVAL;
-#endif
-}
-
-static int gen_rtc_ioctl(struct file *file,
-                        unsigned int cmd, unsigned long arg)
-{
-       struct rtc_time wtime;
-       struct rtc_pll_info pll;
-       void __user *argp = (void __user *)arg;
-
-       switch (cmd) {
-
-       case RTC_PLL_GET:
-           if (get_rtc_pll(&pll))
-                   return -EINVAL;
-           else
-                   return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
-
-       case RTC_PLL_SET:
-               if (!capable(CAP_SYS_TIME))
-                       return -EACCES;
-               if (copy_from_user(&pll, argp, sizeof(pll)))
-                       return -EFAULT;
-           return set_rtc_pll(&pll);
-
-       case RTC_UIE_OFF:       /* disable ints from RTC updates.       */
-               gen_clear_rtc_irq_bit(RTC_UIE);
-               return 0;
-
-       case RTC_UIE_ON:        /* enable ints for RTC updates. */
-               return gen_set_rtc_irq_bit(RTC_UIE);
-
-       case RTC_RD_TIME:       /* Read the time/date from RTC  */
-               /* this doesn't get week-day, who cares */
-               memset(&wtime, 0, sizeof(wtime));
-               get_rtc_time(&wtime);
-
-               return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
-
-       case RTC_SET_TIME:      /* Set the RTC */
-           {
-               int year;
-               unsigned char leap_yr;
-
-               if (!capable(CAP_SYS_TIME))
-                       return -EACCES;
-
-               if (copy_from_user(&wtime, argp, sizeof(wtime)))
-                       return -EFAULT;
-
-               year = wtime.tm_year + 1900;
-               leap_yr = ((!(year % 4) && (year % 100)) ||
-                          !(year % 400));
-
-               if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
-                       return -EINVAL;
-
-               if (wtime.tm_mday < 0 || wtime.tm_mday >
-                   (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
-                       return -EINVAL;
-
-               if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
-                   wtime.tm_min < 0 || wtime.tm_min >= 60 ||
-                   wtime.tm_sec < 0 || wtime.tm_sec >= 60)
-                       return -EINVAL;
-
-               return set_rtc_time(&wtime);
-           }
-       }
-
-       return -EINVAL;
-}
-
-static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-{
-       int ret;
-
-       mutex_lock(&gen_rtc_mutex);
-       ret = gen_rtc_ioctl(file, cmd, arg);
-       mutex_unlock(&gen_rtc_mutex);
-
-       return ret;
-}
-
-/*
- *     We enforce only one user at a time here with the open/close.
- *     Also clear the previous interrupt data on an open, and clean
- *     up things on a close.
- */
-
-static int gen_rtc_open(struct inode *inode, struct file *file)
-{
-       mutex_lock(&gen_rtc_mutex);
-       if (gen_rtc_status & RTC_IS_OPEN) {
-               mutex_unlock(&gen_rtc_mutex);
-               return -EBUSY;
-       }
-
-       gen_rtc_status |= RTC_IS_OPEN;
-       gen_rtc_irq_data = 0;
-       irq_active = 0;
-       mutex_unlock(&gen_rtc_mutex);
-
-       return 0;
-}
-
-static int gen_rtc_release(struct inode *inode, struct file *file)
-{
-       /*
-        * Turn off all interrupts once the device is no longer
-        * in use and clear the data.
-        */
-
-       gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
-
-       gen_rtc_status &= ~RTC_IS_OPEN;
-       return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-/*
- *     Info exported via "/proc/driver/rtc".
- */
-
-static int gen_rtc_proc_show(struct seq_file *m, void *v)
-{
-       struct rtc_time tm;
-       unsigned int flags;
-       struct rtc_pll_info pll;
-
-       flags = get_rtc_time(&tm);
-
-       seq_printf(m,
-                    "rtc_time\t: %02d:%02d:%02d\n"
-                    "rtc_date\t: %04d-%02d-%02d\n"
-                    "rtc_epoch\t: %04u\n",
-                    tm.tm_hour, tm.tm_min, tm.tm_sec,
-                    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900);
-
-       tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-
-       seq_puts(m, "alarm\t\t: ");
-       if (tm.tm_hour <= 24)
-               seq_printf(m, "%02d:", tm.tm_hour);
-       else
-               seq_puts(m, "**:");
-
-       if (tm.tm_min <= 59)
-               seq_printf(m, "%02d:", tm.tm_min);
-       else
-               seq_puts(m, "**:");
-
-       if (tm.tm_sec <= 59)
-               seq_printf(m, "%02d\n", tm.tm_sec);
-       else
-               seq_puts(m, "**\n");
-
-       seq_printf(m,
-                    "DST_enable\t: %s\n"
-                    "BCD\t\t: %s\n"
-                    "24hr\t\t: %s\n"
-                    "square_wave\t: %s\n"
-                    "alarm_IRQ\t: %s\n"
-                    "update_IRQ\t: %s\n"
-                    "periodic_IRQ\t: %s\n"
-                    "periodic_freq\t: %ld\n"
-                    "batt_status\t: %s\n",
-                    (flags & RTC_DST_EN) ? "yes" : "no",
-                    (flags & RTC_DM_BINARY) ? "no" : "yes",
-                    (flags & RTC_24H) ? "yes" : "no",
-                    (flags & RTC_SQWE) ? "yes" : "no",
-                    (flags & RTC_AIE) ? "yes" : "no",
-                    irq_active ? "yes" : "no",
-                    (flags & RTC_PIE) ? "yes" : "no",
-                    0L /* freq */,
-                    (flags & RTC_BATT_BAD) ? "bad" : "okay");
-       if (!get_rtc_pll(&pll))
-           seq_printf(m,
-                        "PLL adjustment\t: %d\n"
-                        "PLL max +ve adjustment\t: %d\n"
-                        "PLL max -ve adjustment\t: %d\n"
-                        "PLL +ve adjustment factor\t: %d\n"
-                        "PLL -ve adjustment factor\t: %d\n"
-                        "PLL frequency\t: %ld\n",
-                        pll.pll_value,
-                        pll.pll_max,
-                        pll.pll_min,
-                        pll.pll_posmult,
-                        pll.pll_negmult,
-                        pll.pll_clock);
-       return 0;
-}
-
-static int gen_rtc_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, gen_rtc_proc_show, NULL);
-}
-
-static const struct file_operations gen_rtc_proc_fops = {
-       .open           = gen_rtc_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init gen_rtc_proc_init(void)
-{
-       struct proc_dir_entry *r;
-
-       r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops);
-       if (!r)
-               return -ENOMEM;
-       return 0;
-}
-#else
-static inline int gen_rtc_proc_init(void) { return 0; }
-#endif /* CONFIG_PROC_FS */
-
-
-/*
- *     The various file operations we support.
- */
-
-static const struct file_operations gen_rtc_fops = {
-       .owner          = THIS_MODULE,
-#ifdef CONFIG_GEN_RTC_X
-       .read           = gen_rtc_read,
-       .poll           = gen_rtc_poll,
-#endif
-       .unlocked_ioctl = gen_rtc_unlocked_ioctl,
-       .open           = gen_rtc_open,
-       .release        = gen_rtc_release,
-       .llseek         = noop_llseek,
-};
-
-static struct miscdevice rtc_gen_dev =
-{
-       .minor          = RTC_MINOR,
-       .name           = "rtc",
-       .fops           = &gen_rtc_fops,
-};
-
-static int __init rtc_generic_init(void)
-{
-       int retval;
-
-       printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
-
-       retval = misc_register(&rtc_gen_dev);
-       if (retval < 0)
-               return retval;
-
-       retval = gen_rtc_proc_init();
-       if (retval) {
-               misc_deregister(&rtc_gen_dev);
-               return retval;
-       }
-
-       return 0;
-}
-
-static void __exit rtc_generic_exit(void)
-{
-       remove_proc_entry ("driver/rtc", NULL);
-       misc_deregister(&rtc_gen_dev);
-}
-
-
-module_init(rtc_generic_init);
-module_exit(rtc_generic_exit);
-
-MODULE_AUTHOR("Richard Zidlicky");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(RTC_MINOR);
index 18639e0..e215f50 100644 (file)
@@ -5,6 +5,10 @@
 config RTC_LIB
        bool
 
+config RTC_MC146818_LIB
+       bool
+       select RTC_LIB
+
 menuconfig RTC_CLASS
        bool "Real Time Clock"
        default n
@@ -574,10 +578,10 @@ config RTC_DRV_EM3027
          will be called rtc-em3027.
 
 config RTC_DRV_RV8803
-       tristate "Micro Crystal RV8803"
+       tristate "Micro Crystal RV8803, Epson RX8900"
        help
-         If you say yes here you get support for the Micro Crystal
-         RV8803 RTC chips.
+         If you say yes here you get support for the Micro Crystal RV8803 and
+         Epson RX8900 RTC chips.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-rv8803.
@@ -670,6 +674,18 @@ config RTC_DRV_DS1390
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1390.
 
+config RTC_DRV_MAX6916
+       tristate "Maxim MAX6916"
+       help
+         If you say yes here you will get support for the
+         Maxim MAX6916 SPI RTC chip.
+
+         This driver only supports the RTC feature, and not other chip
+         features such as alarms.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-max6916.
+
 config RTC_DRV_R9701
        tristate "Epson RTC-9701JE"
        help
@@ -795,8 +811,9 @@ comment "Platform RTC drivers"
 
 config RTC_DRV_CMOS
        tristate "PC-style 'CMOS'"
-       depends on X86 || ARM || M32R || PPC || MIPS || SPARC64
+       depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300
        default y if X86
+       select RTC_MC146818_LIB
        help
          Say "yes" here to get direct support for the real time clock
          found in every PC or ACPI-based system, and some other boards.
@@ -815,6 +832,7 @@ config RTC_DRV_CMOS
 config RTC_DRV_ALPHA
        bool "Alpha PC-style CMOS"
        depends on ALPHA
+       select RTC_MC146818_LIB
        default y
        help
          Direct support for the real-time clock found on every Alpha
index ea28337..7cf7ad5 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB)           += rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)      += hctosys.o
 obj-$(CONFIG_RTC_SYSTOHC)      += systohc.o
 obj-$(CONFIG_RTC_CLASS)                += rtc-core.o
+obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o
 rtc-core-y                     := class.o interface.o
 
 ifdef CONFIG_RTC_DRV_EFI
@@ -85,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_M48T59)  += rtc-m48t59.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MAX6916)  += rtc-max6916.o
 obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
 obj-$(CONFIG_RTC_DRV_MAX8907)  += rtc-max8907.o
 obj-$(CONFIG_RTC_DRV_MAX8925)  += rtc-max8925.o
index 9ef5f6f..84a52db 100644 (file)
@@ -104,7 +104,17 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
        else if (!rtc->ops->read_alarm)
                err = -EINVAL;
        else {
-               memset(alarm, 0, sizeof(struct rtc_wkalrm));
+               alarm->enabled = 0;
+               alarm->pending = 0;
+               alarm->time.tm_sec = -1;
+               alarm->time.tm_min = -1;
+               alarm->time.tm_hour = -1;
+               alarm->time.tm_mday = -1;
+               alarm->time.tm_mon = -1;
+               alarm->time.tm_year = -1;
+               alarm->time.tm_wday = -1;
+               alarm->time.tm_yday = -1;
+               alarm->time.tm_isdst = -1;
                err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
        }
 
@@ -383,7 +393,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
        rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
        rtc->aie_timer.period = ktime_set(0, 0);
 
-       /* Alarm has to be enabled & in the futrure for us to enqueue it */
+       /* Alarm has to be enabled & in the future for us to enqueue it */
        if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
                         rtc->aie_timer.node.expires.tv64)) {
 
@@ -395,8 +405,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 }
 EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
 
-
-
 int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
 {
        int err = mutex_lock_interruptible(&rtc->ops_lock);
@@ -748,9 +756,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
  */
 static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
 {
+       struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
+       struct rtc_time tm;
+       ktime_t now;
+
        timer->enabled = 1;
+       __rtc_read_time(rtc, &tm);
+       now = rtc_tm_to_ktime(tm);
+
+       /* Skip over expired timers */
+       while (next) {
+               if (next->expires.tv64 >= now.tv64)
+                       break;
+               next = timerqueue_iterate_next(next);
+       }
+
        timerqueue_add(&rtc->timerqueue, &timer->node);
-       if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
+       if (!next) {
                struct rtc_wkalrm alarm;
                int err;
                alarm.time = rtc_ktime_to_tm(timer->node.expires);
index ba0d619..fea9a60 100644 (file)
@@ -643,17 +643,15 @@ static int abx80x_probe(struct i2c_client *client,
                return err;
        }
 
-       err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group,
-                             &client->dev);
-       if (err) {
-               rtc_calib_remove_sysfs_group(&client->dev);
+       err = devm_add_action_or_reset(&client->dev,
+                                      rtc_calib_remove_sysfs_group,
+                                      &client->dev);
+       if (err)
                dev_err(&client->dev,
                        "Failed to add sysfs cleanup action: %d\n",
                        err);
-               return err;
-       }
 
-       return 0;
+       return err;
 }
 
 static int abx80x_remove(struct i2c_client *client)
index 355fdb9..5219916 100644 (file)
@@ -343,7 +343,6 @@ static struct platform_driver asm9260_rtc_driver = {
        .remove         = asm9260_rtc_remove,
        .driver         = {
                .name   = "asm9260-rtc",
-               .owner  = THIS_MODULE,
                .of_match_table = asm9260_dt_ids,
        },
 };
index 99732e6..7418a76 100644 (file)
@@ -375,6 +375,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
        if (!rtc)
                return -ENOMEM;
 
+       spin_lock_init(&rtc->lock);
        rtc->irq = irq;
 
        /* platform setup code should have handled this; sigh */
index fbe9c72..43745ca 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/of_platform.h>
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
-#include <asm-generic/rtc.h>
+#include <linux/mc146818rtc.h>
 
 struct cmos_rtc {
        struct rtc_device       *rtc;
@@ -190,10 +190,10 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
 static int cmos_read_time(struct device *dev, struct rtc_time *t)
 {
        /* REVISIT:  if the clock has a "century" register, use
-        * that instead of the heuristic in get_rtc_time().
+        * that instead of the heuristic in mc146818_get_time().
         * That'll make Y3K compatility (year > 2070) easy!
         */
-       get_rtc_time(t);
+       mc146818_get_time(t);
        return 0;
 }
 
@@ -205,7 +205,7 @@ static int cmos_set_time(struct device *dev, struct rtc_time *t)
         * takes effect exactly 500ms after we write the register.
         * (Also queueing and other delays before we get this far.)
         */
-       return set_rtc_time(t);
+       return mc146818_set_time(t);
 }
 
 static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
@@ -220,8 +220,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
         * Some also support day and month, for alarms up to a year in
         * the future.
         */
-       t->time.tm_mday = -1;
-       t->time.tm_mon = -1;
 
        spin_lock_irq(&rtc_lock);
        t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
@@ -272,7 +270,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
                        }
                }
        }
-       t->time.tm_year = -1;
 
        t->enabled = !!(rtc_control & RTC_AIE);
        t->pending = 0;
@@ -630,7 +627,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
        address_space = 64;
 #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \
                        || defined(__sparc__) || defined(__mips__) \
-                       || defined(__powerpc__)
+                       || defined(__powerpc__) || defined(CONFIG_MN10300)
        address_space = 128;
 #else
 #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@@ -1142,14 +1139,14 @@ static __init void cmos_of_init(struct platform_device *pdev)
        if (val)
                CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
 
-       get_rtc_time(&time);
+       cmos_read_time(&pdev->dev, &time);
        ret = rtc_valid_tm(&time);
        if (ret) {
                struct rtc_time def_time = {
                        .tm_year = 1,
                        .tm_mday = 1,
                };
-               set_rtc_time(&def_time);
+               cmos_set_time(&pdev->dev, &def_time);
        }
 }
 #else
index a20bcf0..4273377 100644 (file)
@@ -85,6 +85,7 @@ static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
                        rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
                        rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
                        rtc_tm->tm_min  = v[0][0] & DA9052_RTC_MIN;
+                       rtc_tm->tm_sec = 0;
 
                        ret = rtc_valid_tm(rtc_tm);
                        return ret;
index 7ec0872..678af86 100644 (file)
@@ -74,6 +74,7 @@ static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
        rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY;
        rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR;
        rtc_tm->tm_min  = v[0] & DA9055_RTC_ALM_MIN;
+       rtc_tm->tm_sec = 0;
 
        return rtc_valid_tm(rtc_tm);
 }
index c5432bf..dba60c1 100644 (file)
@@ -388,6 +388,8 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        u8 day0, day1;
        unsigned long flags;
 
+       alm->time.tm_sec = 0;
+
        spin_lock_irqsave(&davinci_rtc_lock, flags);
 
        davinci_rtcss_calendar_wait(davinci_rtc);
index 756e509..ef75c34 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
 #include <linux/bcd.h>
-#include <linux/ds1286.h>
+#include <linux/rtc/ds1286.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 
index 8e41c46..72b2293 100644 (file)
@@ -313,13 +313,6 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
        alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]);
        alm->time.tm_min = bcd2bin(buf[DS1305_MIN]);
        alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
-       alm->time.tm_mday = -1;
-       alm->time.tm_mon = -1;
-       alm->time.tm_year = -1;
-       /* next three fields are unused by Linux */
-       alm->time.tm_wday = -1;
-       alm->time.tm_mday = -1;
-       alm->time.tm_isdst = -1;
 
        return 0;
 }
index 821d9c0..8e1c5cb 100644 (file)
@@ -482,11 +482,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
        t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
        t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
-       t->time.tm_mon = -1;
-       t->time.tm_year = -1;
-       t->time.tm_wday = -1;
-       t->time.tm_yday = -1;
-       t->time.tm_isdst = -1;
 
        /* ... and status */
        t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
@@ -602,6 +597,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
  * Alarm support for mcp794xx devices.
  */
 
+#define MCP794XX_REG_WEEKDAY           0x3
+#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7
 #define MCP794XX_REG_CONTROL           0x07
 #      define MCP794XX_BIT_ALM0_EN     0x10
 #      define MCP794XX_BIT_ALM1_EN     0x20
@@ -1231,13 +1228,16 @@ static int ds1307_probe(struct i2c_client *client,
 {
        struct ds1307           *ds1307;
        int                     err = -ENODEV;
-       int                     tmp;
+       int                     tmp, wday;
        struct chip_desc        *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
        bool                    want_irq = false;
        bool                    ds1307_can_wakeup_device = false;
        unsigned char           *buf;
        struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct rtc_time         tm;
+       unsigned long           timestamp;
+
        irq_handler_t   irq_handler = ds1307_irq;
 
        static const int        bbsqi_bitpos[] = {
@@ -1526,6 +1526,27 @@ read_rtc:
                                bin2bcd(tmp));
        }
 
+       /*
+        * Some IPs have weekday reset value = 0x1 which might not correct
+        * hence compute the wday using the current date/month/year values
+        */
+       ds1307_get_time(&client->dev, &tm);
+       wday = tm.tm_wday;
+       timestamp = rtc_tm_to_time64(&tm);
+       rtc_time64_to_tm(timestamp, &tm);
+
+       /*
+        * Check if reset wday is different from the computed wday
+        * If different then set the wday which we computed using
+        * timestamp
+        */
+       if (wday != tm.tm_wday) {
+               wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY);
+               wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK;
+               wday = wday | (tm.tm_wday + 1);
+               i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday);
+       }
+
        if (want_irq) {
                device_set_wakeup_capable(&client->dev, true);
                set_bit(HAS_ALARM, &ds1307->flags);
index 23fa9f0..895fbee 100644 (file)
@@ -504,12 +504,6 @@ static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour;
        alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday;
 
-       alarm->time.tm_mon = -1;
-       alarm->time.tm_year = -1;
-       alarm->time.tm_wday = -1;
-       alarm->time.tm_yday = -1;
-       alarm->time.tm_isdst = -1;
-
 out:
        mutex_unlock(&priv->mutex);
        return res;
index b3ce3c6..ed43b43 100644 (file)
@@ -103,6 +103,26 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask)
 }
 
 /**
+ * s1685_rtc_check_mday - check validity of the day of month.
+ * @rtc: pointer to the ds1685 rtc structure.
+ * @mday: day of month.
+ *
+ * Returns -EDOM if the day of month is not within 1..31 range.
+ */
+static inline int
+ds1685_rtc_check_mday(struct ds1685_priv *rtc, u8 mday)
+{
+       if (rtc->bcd_mode) {
+               if (mday < 0x01 || mday > 0x31 || (mday & 0x0f) > 0x09)
+                       return -EDOM;
+       } else {
+               if (mday < 1 || mday > 31)
+                       return -EDOM;
+       }
+       return 0;
+}
+
+/**
  * ds1685_rtc_switch_to_bank0 - switch the rtc to bank 0.
  * @rtc: pointer to the ds1685 rtc structure.
  */
@@ -377,6 +397,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct platform_device *pdev = to_platform_device(dev);
        struct ds1685_priv *rtc = platform_get_drvdata(pdev);
        u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
+       int ret;
 
        /* Fetch the alarm info from the RTC alarm registers. */
        ds1685_rtc_begin_data_access(rtc);
@@ -388,34 +409,29 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        ctrlc   = rtc->read(rtc, RTC_CTRL_C);
        ds1685_rtc_end_data_access(rtc);
 
-       /* Check month date. */
-       if (!(mday >= 1) && (mday <= 31))
-               return -EDOM;
+       /* Check the month date for validity. */
+       ret = ds1685_rtc_check_mday(rtc, mday);
+       if (ret)
+               return ret;
 
        /*
         * Check the three alarm bytes.
         *
         * The Linux RTC system doesn't support the "don't care" capability
         * of this RTC chip.  We check for it anyways in case support is
-        * added in the future.
+        * added in the future and only assign when we care.
         */
-       if (unlikely(seconds >= 0xc0))
-               alrm->time.tm_sec = -1;
-       else
+       if (likely(seconds < 0xc0))
                alrm->time.tm_sec = ds1685_rtc_bcd2bin(rtc, seconds,
                                                       RTC_SECS_BCD_MASK,
                                                       RTC_SECS_BIN_MASK);
 
-       if (unlikely(minutes >= 0xc0))
-               alrm->time.tm_min = -1;
-       else
+       if (likely(minutes < 0xc0))
                alrm->time.tm_min = ds1685_rtc_bcd2bin(rtc, minutes,
                                                       RTC_MINS_BCD_MASK,
                                                       RTC_MINS_BIN_MASK);
 
-       if (unlikely(hours >= 0xc0))
-               alrm->time.tm_hour = -1;
-       else
+       if (likely(hours < 0xc0))
                alrm->time.tm_hour = ds1685_rtc_bcd2bin(rtc, hours,
                                                        RTC_HRS_24_BCD_MASK,
                                                        RTC_HRS_24_BIN_MASK);
@@ -423,11 +439,6 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        /* Write the data to rtc_wkalrm. */
        alrm->time.tm_mday = ds1685_rtc_bcd2bin(rtc, mday, RTC_MDAY_BCD_MASK,
                                                RTC_MDAY_BIN_MASK);
-       alrm->time.tm_mon = -1;
-       alrm->time.tm_year = -1;
-       alrm->time.tm_wday = -1;
-       alrm->time.tm_yday = -1;
-       alrm->time.tm_isdst = -1;
        alrm->enabled = !!(ctrlb & RTC_CTRL_B_AIE);
        alrm->pending = !!(ctrlc & RTC_CTRL_C_AF);
 
@@ -445,6 +456,7 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct platform_device *pdev = to_platform_device(dev);
        struct ds1685_priv *rtc = platform_get_drvdata(pdev);
        u8 ctrlb, seconds, minutes, hours, mday;
+       int ret;
 
        /* Fetch the alarm info and convert to BCD. */
        seconds = ds1685_rtc_bin2bcd(rtc, alrm->time.tm_sec,
@@ -461,8 +473,9 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                                     RTC_MDAY_BCD_MASK);
 
        /* Check the month date for validity. */
-       if (!(mday >= 1) && (mday <= 31))
-               return -EDOM;
+       ret = ds1685_rtc_check_mday(rtc, mday);
+       if (ret)
+               return ret;
 
        /*
         * Check the three alarm bytes.
index 16310fe..9a1582e 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/rtc.h>
 #include <linux/types.h>
 #include <linux/bcd.h>
-#include <linux/rtc-ds2404.h>
+#include <linux/platform_data/rtc-ds2404.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
index 04fbd7f..b1f20d8 100644 (file)
@@ -197,12 +197,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
        alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
 
-       alarm->time.tm_mon = -1;
-       alarm->time.tm_year = -1;
-       alarm->time.tm_wday = -1;
-       alarm->time.tm_yday = -1;
-       alarm->time.tm_isdst = -1;
-
        alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
        alarm->pending = !!(stat & DS3232_REG_SR_A1F);
 
index 96d3860..0130afd 100644 (file)
@@ -259,6 +259,12 @@ static const struct rtc_class_ops efi_rtc_ops = {
 static int __init efi_rtc_probe(struct platform_device *dev)
 {
        struct rtc_device *rtc;
+       efi_time_t eft;
+       efi_time_cap_t cap;
+
+       /* First check if the RTC is usable */
+       if (efi.get_time(&eft, &cap) != EFI_SUCCESS)
+               return -ENODEV;
 
        rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops,
                                        THIS_MODULE);
index d726c6a..1bf5d23 100644 (file)
@@ -9,44 +9,10 @@
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 
-#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
-    defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
-#include <asm/rtc.h>
-
-static int generic_get_time(struct device *dev, struct rtc_time *tm)
-{
-       unsigned int ret = get_rtc_time(tm);
-
-       if (ret & RTC_BATT_BAD)
-               return -EOPNOTSUPP;
-
-       return rtc_valid_tm(tm);
-}
-
-static int generic_set_time(struct device *dev, struct rtc_time *tm)
-{
-       if (set_rtc_time(tm) < 0)
-               return -EOPNOTSUPP;
-
-       return 0;
-}
-
-static const struct rtc_class_ops generic_rtc_ops = {
-       .read_time = generic_get_time,
-       .set_time = generic_set_time,
-};
-#else
-#define generic_rtc_ops *(struct rtc_class_ops*)NULL
-#endif
-
 static int __init generic_rtc_probe(struct platform_device *dev)
 {
        struct rtc_device *rtc;
-       const struct rtc_class_ops *ops;
-
-       ops = dev_get_platdata(&dev->dev);
-       if (!ops)
-               ops = &generic_rtc_ops;
+       const struct rtc_class_ops *ops = dev_get_platdata(&dev->dev);
 
        rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
                                        ops, THIS_MODULE);
index 2072703..e5ad527 100644 (file)
@@ -198,7 +198,7 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
                return ret;
 
        /* The alarm only has a minute accuracy */
-       alm_tm->tm_sec = -1;
+       alm_tm->tm_sec = 0;
 
        alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?
                                        -1 :
@@ -213,9 +213,6 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
                                        -1 :
                                        bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);
 
-       alm_tm->tm_mon = -1;
-       alm_tm->tm_year = -1;
-
        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
        if (ret < 0)
                return ret;
index 54328d4..0e7f0f5 100644 (file)
@@ -245,8 +245,7 @@ static int isl12057_rtc_update_alarm(struct device *dev, int enable)
 static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        struct isl12057_rtc_data *data = dev_get_drvdata(dev);
-       struct rtc_time rtc_tm, *alarm_tm = &alarm->time;
-       unsigned long rtc_secs, alarm_secs;
+       struct rtc_time *alarm_tm = &alarm->time;
        u8 regs[ISL12057_A1_SEC_LEN];
        unsigned int ir;
        int ret;
@@ -264,36 +263,6 @@ static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        alarm_tm->tm_min  = bcd2bin(regs[1] & 0x7f);
        alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f);
        alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f);
-       alarm_tm->tm_wday = -1;
-
-       /*
-        * The alarm section does not store year/month. We use the ones in rtc
-        * section as a basis and increment month and then year if needed to get
-        * alarm after current time.
-        */
-       ret = _isl12057_rtc_read_time(dev, &rtc_tm);
-       if (ret)
-               goto err_unlock;
-
-       alarm_tm->tm_year = rtc_tm.tm_year;
-       alarm_tm->tm_mon = rtc_tm.tm_mon;
-
-       ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
-       if (ret)
-               goto err_unlock;
-
-       ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
-       if (ret)
-               goto err_unlock;
-
-       if (alarm_secs < rtc_secs) {
-               if (alarm_tm->tm_mon == 11) {
-                       alarm_tm->tm_mon = 0;
-                       alarm_tm->tm_year += 1;
-               } else {
-                       alarm_tm->tm_mon += 1;
-               }
-       }
 
        ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir);
        if (ret) {
index d1bf93a..58698d2 100644 (file)
@@ -244,7 +244,7 @@ static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
        retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags);
        if (retval < 0) {
-               dev_info(dev, "Unable to enable alarm IRQ %d\n", retval);
+               dev_err(dev, "Unable to enable alarm IRQ %d\n", retval);
                return retval;
        }
        return 0;
@@ -320,10 +320,8 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        alrm->time.tm_sec  = bcd2bin(alarmvals[4] & 0x7f);
        alrm->time.tm_min  = bcd2bin(alarmvals[3] & 0x7f);
        alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
-       alrm->time.tm_wday = -1;
        alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
        alrm->time.tm_mon  = bcd2bin(alarmvals[0] & 0x3f);
-       alrm->time.tm_year = -1;
 
        alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
        alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
@@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = {
        .proc = m41t80_rtc_proc,
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int m41t80_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       if (client->irq >= 0 && device_may_wakeup(dev))
+               enable_irq_wake(client->irq);
+
+       return 0;
+}
+
+static int m41t80_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       if (client->irq >= 0 && device_may_wakeup(dev))
+               disable_irq_wake(client->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume);
+
 static ssize_t flags_show(struct device *dev,
                          struct device_attribute *attr, char *buf)
 {
@@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client,
                return rc;
        }
 
-       rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group,
-                            &client->dev);
+       rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group,
+                                     &client->dev);
        if (rc) {
-               m41t80_remove_sysfs_group(&client->dev);
                dev_err(&client->dev,
                        "Failed to add sysfs cleanup action: %d\n", rc);
                return rc;
@@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client)
 static struct i2c_driver m41t80_driver = {
        .driver = {
                .name = "rtc-m41t80",
+               .pm = &m41t80_pm,
        },
        .probe = m41t80_probe,
        .remove = m41t80_remove,
index f72b91f..0eeb571 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
 #include <linux/bcd.h>
 
 #define M48T86_REG_SEC         0x00
diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c
new file mode 100644 (file)
index 0000000..623ab27
--- /dev/null
@@ -0,0 +1,164 @@
+/* rtc-max6916.c
+ *
+ * Driver for MAXIM  max6916 Low Current, SPI Compatible
+ * Real Time Clock
+ *
+ * Author : Venkat Prashanth B U <venkat.prashanth2498@gmail.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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+/* Registers in max6916 rtc */
+
+#define MAX6916_SECONDS_REG    0x01
+#define MAX6916_MINUTES_REG    0x02
+#define MAX6916_HOURS_REG      0x03
+#define MAX6916_DATE_REG       0x04
+#define MAX6916_MONTH_REG      0x05
+#define MAX6916_DAY_REG        0x06
+#define MAX6916_YEAR_REG       0x07
+#define MAX6916_CONTROL_REG    0x08
+#define MAX6916_STATUS_REG     0x0C
+#define MAX6916_CLOCK_BURST    0x3F
+
+static int max6916_read_reg(struct device *dev, unsigned char address,
+                           unsigned char *data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+
+       *data = address | 0x80;
+
+       return spi_write_then_read(spi, data, 1, data, 1);
+}
+
+static int max6916_write_reg(struct device *dev, unsigned char address,
+                            unsigned char data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       unsigned char buf[2];
+
+       buf[0] = address & 0x7F;
+       buf[1] = data;
+
+       return spi_write_then_read(spi, buf, 2, NULL, 0);
+}
+
+static int max6916_read_time(struct device *dev, struct rtc_time *dt)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       int err;
+       unsigned char buf[8];
+
+       buf[0] = MAX6916_CLOCK_BURST | 0x80;
+
+       err = spi_write_then_read(spi, buf, 1, buf, 8);
+
+       if (err)
+               return err;
+
+       dt->tm_sec = bcd2bin(buf[0]);
+       dt->tm_min = bcd2bin(buf[1]);
+       dt->tm_hour = bcd2bin(buf[2] & 0x3F);
+       dt->tm_mday = bcd2bin(buf[3]);
+       dt->tm_mon = bcd2bin(buf[4]) - 1;
+       dt->tm_wday = bcd2bin(buf[5]) - 1;
+       dt->tm_year = bcd2bin(buf[6]) + 100;
+
+       return rtc_valid_tm(dt);
+}
+
+static int max6916_set_time(struct device *dev, struct rtc_time *dt)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       unsigned char buf[9];
+
+       if (dt->tm_year < 100 || dt->tm_year > 199) {
+               dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n",
+                       dt->tm_year + 1900);
+       return -EINVAL;
+       }
+
+       buf[0] = MAX6916_CLOCK_BURST & 0x7F;
+       buf[1] = bin2bcd(dt->tm_sec);
+       buf[2] = bin2bcd(dt->tm_min);
+       buf[3] = (bin2bcd(dt->tm_hour) & 0X3F);
+       buf[4] = bin2bcd(dt->tm_mday);
+       buf[5] = bin2bcd(dt->tm_mon + 1);
+       buf[6] = bin2bcd(dt->tm_wday + 1);
+       buf[7] = bin2bcd(dt->tm_year % 100);
+       buf[8] = bin2bcd(0x00);
+
+       /* write the rtc settings */
+       return spi_write_then_read(spi, buf, 9, NULL, 0);
+}
+
+static const struct rtc_class_ops max6916_rtc_ops = {
+       .read_time = max6916_read_time,
+       .set_time = max6916_set_time,
+};
+
+static int max6916_probe(struct spi_device *spi)
+{
+       struct rtc_device *rtc;
+       unsigned char data;
+       int res;
+
+       /* spi setup with max6916 in mode 3 and bits per word as 8 */
+       spi->mode = SPI_MODE_3;
+       spi->bits_per_word = 8;
+       spi_setup(spi);
+
+       /* RTC Settings */
+       res = max6916_read_reg(&spi->dev, MAX6916_SECONDS_REG, &data);
+       if (res)
+               return res;
+
+       /* Disable the write protect of rtc */
+       max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
+       data = data & ~(1 << 7);
+       max6916_write_reg(&spi->dev, MAX6916_CONTROL_REG, data);
+
+       /*Enable oscillator,disable oscillator stop flag, glitch filter*/
+       max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
+       data = data & 0x1B;
+       max6916_write_reg(&spi->dev, MAX6916_STATUS_REG, data);
+
+       /* display the settings */
+       max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
+       dev_info(&spi->dev, "MAX6916 RTC CTRL Reg = 0x%02x\n", data);
+
+       max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
+       dev_info(&spi->dev, "MAX6916 RTC Status Reg = 0x%02x\n", data);
+
+       rtc = devm_rtc_device_register(&spi->dev, "max6916",
+                                      &max6916_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       spi_set_drvdata(spi, rtc);
+
+       return 0;
+}
+
+static struct spi_driver max6916_driver = {
+       .driver = {
+               .name = "max6916",
+       },
+       .probe = max6916_probe,
+};
+module_spi_driver(max6916_driver);
+
+MODULE_DESCRIPTION("MAX6916 SPI RTC DRIVER");
+MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@gmail.com>");
+MODULE_LICENSE("GPL v2");
similarity index 76%
rename from include/asm-generic/rtc.h
rename to drivers/rtc/rtc-mc146818-lib.c
index 4e3b655..2f1772a 100644 (file)
@@ -1,40 +1,16 @@
-/* 
- * include/asm-generic/rtc.h
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * Based on:
- * drivers/char/rtc.c
- *
- * Please read the COPYING file for all license details.
- */
-
-#ifndef __ASM_RTC_H__
-#define __ASM_RTC_H__
-
-#include <linux/mc146818rtc.h>
-#include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/mc146818rtc.h>
+
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
 #endif
 
-#define RTC_PIE 0x40           /* periodic interrupt enable */
-#define RTC_AIE 0x20           /* alarm interrupt enable */
-#define RTC_UIE 0x10           /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100     /* battery bad */
-#define RTC_SQWE 0x08          /* enable square-wave output */
-#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
-#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
-
 /*
  * Returns true if a clock update is in progress
  */
-static inline unsigned char rtc_is_updating(void)
+static inline unsigned char mc146818_is_updating(void)
 {
        unsigned char uip;
        unsigned long flags;
@@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void)
        return uip;
 }
 
-static inline unsigned int __get_rtc_time(struct rtc_time *time)
+unsigned int mc146818_get_time(struct rtc_time *time)
 {
        unsigned char ctrl;
        unsigned long flags;
@@ -60,11 +36,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
         * can take just over 2ms. We wait 20ms. There is no need to
         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
         * If you need to know *exactly* when a second has started, enable
-        * periodic update complete interrupts, (via ioctl) and then 
+        * periodic update complete interrupts, (via ioctl) and then
         * immediately read /dev/rtc which will block until you get the IRQ.
         * Once the read clears, read the RTC time (again via ioctl). Easy.
         */
-       if (rtc_is_updating())
+       if (mc146818_is_updating())
                mdelay(20);
 
        /*
@@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
 
        return RTC_24H;
 }
-
-#ifndef get_rtc_time
-#define get_rtc_time   __get_rtc_time
-#endif
+EXPORT_SYMBOL_GPL(mc146818_get_time);
 
 /* Set the current date and time in the real time clock. */
-static inline int __set_rtc_time(struct rtc_time *time)
+int mc146818_set_time(struct rtc_time *time)
 {
        unsigned long flags;
        unsigned char mon, day, hrs, min, sec;
@@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time)
 
        return 0;
 }
-
-#ifndef set_rtc_time
-#define set_rtc_time   __set_rtc_time
-#endif
-
-static inline unsigned int get_rtc_ss(void)
-{
-       struct rtc_time h;
-
-       get_rtc_time(&h);
-       return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-
-#endif /* __ASM_RTC_H__ */
+EXPORT_SYMBOL_GPL(mc146818_set_time);
index 0094d9b..7334c44 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sfi.h>
 
-#include <asm-generic/rtc.h>
 #include <asm/intel_scu_ipc.h>
 #include <asm/intel-mid.h>
 #include <asm/intel_mid_vrtc.h>
@@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        if (mrst->irq <= 0)
                return -EIO;
 
-       /* Basic alarms only support hour, minute, and seconds fields.
-        * Some also support day and month, for alarms up to a year in
-        * the future.
-        */
-       t->time.tm_mday = -1;
-       t->time.tm_mon = -1;
-       t->time.tm_year = -1;
-
        /* vRTC only supports binary mode */
        spin_lock_irq(&rtc_lock);
        t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
index f22e060..b4478cc 100644 (file)
@@ -96,7 +96,7 @@
 #define CD_TMR_TE              BIT(3)  /* Countdown timer enable */
 
 /* PCF2123_REG_OFFSET BITS */
-#define OFFSET_SIGN_BIT                BIT(6)  /* 2's complement sign bit */
+#define OFFSET_SIGN_BIT                6       /* 2's complement sign bit */
 #define OFFSET_COARSE          BIT(7)  /* Coarse mode offset */
 #define OFFSET_STEP            (2170)  /* Offset step in parts per billion */
 
@@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)
        if (reg & OFFSET_COARSE)
                reg <<= 1; /* multiply by 2 and sign extend */
        else
-               reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
+               reg = sign_extend32(reg, OFFSET_SIGN_BIT);
 
        *offset = ((long)reg) * OFFSET_STEP;
 
index e8ddbb3..efb0a08 100644 (file)
 #include <linux/rtc.h>
 #include <linux/module.h>
 
+/*
+ * Information for this driver was pulled from the following datasheets.
+ *
+ *  http://www.nxp.com/documents/data_sheet/PCF85063A.pdf
+ *  http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
+ *
+ *  PCF85063A -- Rev. 6 — 18 November 2015
+ *  PCF85063TP -- Rev. 4 — 6 May 2015
+*/
+
 #define PCF85063_REG_CTRL1             0x00 /* status */
 #define PCF85063_REG_CTRL1_STOP                BIT(5)
 #define PCF85063_REG_CTRL2             0x01
@@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
        return 0;
 }
 
-/*
- * In the routines that deal directly with the pcf85063 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- */
+static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
+{
+       s32 ret;
+
+       /* start the clock */
+       ctrl1 &= PCF85063_REG_CTRL1_STOP;
+
+       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failing to start the clock\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
        int rc;
@@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        tm->tm_wday = regs[4] & 0x07;
        tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
        tm->tm_year = bcd2bin(regs[6]);
-       if (tm->tm_year < 70)
-               tm->tm_year += 100;     /* assume we are in 1970...2069 */
+       tm->tm_year += 100;
 
        return rtc_valid_tm(tm);
 }
@@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
        int rc;
-       u8 regs[8];
+       u8 regs[7];
+       u8 ctrl1;
+
+       if ((tm->tm_year < 100) || (tm->tm_year > 199))
+               return -EINVAL;
 
        /*
         * to accurately set the time, reset the divider chain and keep it in
         * reset state until all time/date registers are written
         */
-       rc = pcf85063_stop_clock(client, &regs[7]);
+       rc = pcf85063_stop_clock(client, &ctrl1);
        if (rc != 0)
                return rc;
 
@@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
        regs[5] = bin2bcd(tm->tm_mon + 1);
 
        /* year and century */
-       regs[6] = bin2bcd(tm->tm_year % 100);
-
-       /*
-        * after all time/date registers are written, let the 'address auto
-        * increment' feature wrap around and write register CTRL1 to re-enable
-        * the clock divider chain again
-        */
-       regs[7] &= ~PCF85063_REG_CTRL1_STOP;
+       regs[6] = bin2bcd(tm->tm_year - 100);
 
        /* write all registers at once */
        rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
@@ -142,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                return rc;
        }
 
+       /*
+        * Write the control register as a separate action since the size of
+        * the register space is different between the PCF85063TP and
+        * PCF85063A devices.  The rollover point can not be used.
+        */
+       rc = pcf85063_start_clock(client, ctrl1);
+       if (rc != 0)
+               return rc;
+
        return 0;
 }
 
index b9ddbb0..1227cea 100644 (file)
@@ -341,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
                "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
                __func__, buf[0], buf[1], buf[2], buf[3]);
 
+       tm->time.tm_sec = 0;
        tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
        tm->time.tm_hour = bcd2bin(buf[1] & 0x3F);
        tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
        tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
-       tm->time.tm_mon = -1;
-       tm->time.tm_year = -1;
-       tm->time.tm_yday = -1;
-       tm->time.tm_isdst = -1;
 
        err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
        if (err < 0)
index f28d577..68ce774 100644 (file)
@@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
                return ret;
        }
 
+       alm->time.tm_sec = 0;
        alm->time.tm_min = bcd2bin(alarm_data[0]);
        alm->time.tm_hour = bcd2bin(alarm_data[1]);
        alm->time.tm_mday = bcd2bin(alarm_data[2]);
index ef86229..c8c7574 100644 (file)
@@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        t->time.tm_sec = 0;
        t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
        t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
-       t->time.tm_mday = -1;
-       t->time.tm_mon = -1;
-       t->time.tm_year = -1;
-       t->time.tm_wday = -1;
-       t->time.tm_yday = -1;
-       t->time.tm_isdst = -1;
 
        /* ... and status */
        t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
index f623038..9a2f6a9 100644 (file)
 
 #include <linux/bcd.h>
 #include <linux/bitops.h>
+#include <linux/log2.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/rtc.h>
 
+#define RV8803_I2C_TRY_COUNT           4
+
 #define RV8803_SEC                     0x00
 #define RV8803_MIN                     0x01
 #define RV8803_HOUR                    0x02
@@ -56,19 +59,85 @@ struct rv8803_data {
        u8 ctrl;
 };
 
+static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
+{
+       int try = RV8803_I2C_TRY_COUNT;
+       s32 ret;
+
+       /*
+        * There is a 61µs window during which the RTC does not acknowledge I2C
+        * transfers. In that case, ensure that there are multiple attempts.
+        */
+       do
+               ret = i2c_smbus_read_byte_data(client, reg);
+       while ((ret == -ENXIO || ret == -EIO) && --try);
+       if (ret < 0)
+               dev_err(&client->dev, "Unable to read register 0x%02x\n", reg);
+
+       return ret;
+}
+
+static int rv8803_read_regs(const struct i2c_client *client,
+                           u8 reg, u8 count, u8 *values)
+{
+       int try = RV8803_I2C_TRY_COUNT;
+       s32 ret;
+
+       do
+               ret = i2c_smbus_read_i2c_block_data(client, reg, count, values);
+       while ((ret == -ENXIO || ret == -EIO) && --try);
+       if (ret != count) {
+               dev_err(&client->dev,
+                       "Unable to read registers 0x%02x..0x%02x\n",
+                       reg, reg + count - 1);
+               return ret < 0 ? ret : -EIO;
+       }
+
+       return 0;
+}
+
+static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value)
+{
+       int try = RV8803_I2C_TRY_COUNT;
+       s32 ret;
+
+       do
+               ret = i2c_smbus_write_byte_data(client, reg, value);
+       while ((ret == -ENXIO || ret == -EIO) && --try);
+       if (ret)
+               dev_err(&client->dev, "Unable to write register 0x%02x\n", reg);
+
+       return ret;
+}
+
+static int rv8803_write_regs(const struct i2c_client *client,
+                            u8 reg, u8 count, const u8 *values)
+{
+       int try = RV8803_I2C_TRY_COUNT;
+       s32 ret;
+
+       do
+               ret = i2c_smbus_write_i2c_block_data(client, reg, count,
+                                                    values);
+       while ((ret == -ENXIO || ret == -EIO) && --try);
+       if (ret)
+               dev_err(&client->dev,
+                       "Unable to write registers 0x%02x..0x%02x\n",
+                       reg, reg + count - 1);
+
+       return ret;
+}
+
 static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
 {
        struct i2c_client *client = dev_id;
        struct rv8803_data *rv8803 = i2c_get_clientdata(client);
        unsigned long events = 0;
-       int flags, try = 0;
+       int flags;
 
        mutex_lock(&rv8803->flags_lock);
 
-       do {
-               flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
-               try++;
-       } while ((flags == -ENXIO) && (try < 3));
+       flags = rv8803_read_reg(client, RV8803_FLAG);
        if (flags <= 0) {
                mutex_unlock(&rv8803->flags_lock);
                return IRQ_NONE;
@@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
 
        if (events) {
                rtc_update_irq(rv8803->rtc, 1, events);
-               i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
-               i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
-                                         rv8803->ctrl);
+               rv8803_write_reg(client, RV8803_FLAG, flags);
+               rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl);
        }
 
        mutex_unlock(&rv8803->flags_lock);
@@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
        u8 *date = date1;
        int ret, flags;
 
-       flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+       flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
        if (flags < 0)
                return flags;
 
@@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
-                                           7, date);
-       if (ret != 7)
-               return ret < 0 ? ret : -EIO;
+       ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date);
+       if (ret)
+               return ret;
 
        if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
-               ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
-                                                   7, date2);
-               if (ret != 7)
-                       return ret < 0 ? ret : -EIO;
+               ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2);
+               if (ret)
+                       return ret;
 
                if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
                        date = date2;
@@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
        tm->tm_sec  = bcd2bin(date[RV8803_SEC] & 0x7f);
        tm->tm_min  = bcd2bin(date[RV8803_MIN] & 0x7f);
        tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f);
-       tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f);
+       tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f);
        tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
        tm->tm_mon  = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
        tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100;
 
-       return rtc_valid_tm(tm);
+       return 0;
 }
 
 static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct rv8803_data *rv8803 = dev_get_drvdata(dev);
        u8 date[7];
-       int flags, ret;
+       int ctrl, flags, ret;
 
        if ((tm->tm_year < 100) || (tm->tm_year > 199))
                return -EINVAL;
 
+       ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL);
+       if (ctrl < 0)
+               return ctrl;
+
+       /* Stop the clock */
+       ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+                              ctrl | RV8803_CTRL_RESET);
+       if (ret)
+               return ret;
+
        date[RV8803_SEC]   = bin2bcd(tm->tm_sec);
        date[RV8803_MIN]   = bin2bcd(tm->tm_min);
        date[RV8803_HOUR]  = bin2bcd(tm->tm_hour);
@@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
        date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1);
        date[RV8803_YEAR]  = bin2bcd(tm->tm_year - 100);
 
-       ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC,
-                                            7, date);
-       if (ret < 0)
+       ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date);
+       if (ret)
+               return ret;
+
+       /* Restart the clock */
+       ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+                              ctrl & ~RV8803_CTRL_RESET);
+       if (ret)
                return ret;
 
        mutex_lock(&rv8803->flags_lock);
 
-       flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+       flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
        if (flags < 0) {
                mutex_unlock(&rv8803->flags_lock);
                return flags;
        }
 
-       ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
-                                       flags & ~RV8803_FLAG_V2F);
+       ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
+                              flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
 
        mutex_unlock(&rv8803->flags_lock);
 
@@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        u8 alarmvals[3];
        int flags, ret;
 
-       ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN,
-                                           3, alarmvals);
-       if (ret != 3)
-               return ret < 0 ? ret : -EIO;
+       ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals);
+       if (ret)
+               return ret;
 
-       flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+       flags = rv8803_read_reg(client, RV8803_FLAG);
        if (flags < 0)
                return flags;
 
        alrm->time.tm_sec  = 0;
        alrm->time.tm_min  = bcd2bin(alarmvals[0] & 0x7f);
        alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
-       alrm->time.tm_wday = -1;
        alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
-       alrm->time.tm_mon  = -1;
-       alrm->time.tm_year = -1;
 
        alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
        alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
@@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        mutex_lock(&rv8803->flags_lock);
 
-       ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
-       if (ret != 2) {
+       ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl);
+       if (ret) {
                mutex_unlock(&rv8803->flags_lock);
-               return ret < 0 ? ret : -EIO;
+               return ret;
        }
 
        alarmvals[0] = bin2bcd(alrm->time.tm_min);
@@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
                rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE);
-               err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
-                                               rv8803->ctrl);
+               err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+                                      rv8803->ctrl);
                if (err) {
                        mutex_unlock(&rv8803->flags_lock);
                        return err;
@@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        }
 
        ctrl[1] &= ~RV8803_FLAG_AF;
-       err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
+       err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]);
        mutex_unlock(&rv8803->flags_lock);
        if (err)
                return err;
 
-       err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN,
-                                            3, alarmvals);
+       err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals);
        if (err)
                return err;
 
@@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                if (rv8803->rtc->aie_timer.enabled)
                        rv8803->ctrl |= RV8803_CTRL_AIE;
 
-               err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
-                                               rv8803->ctrl);
+               err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+                                      rv8803->ctrl);
                if (err)
                        return err;
        }
@@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
        }
 
        mutex_lock(&rv8803->flags_lock);
-       flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+       flags = rv8803_read_reg(client, RV8803_FLAG);
        if (flags < 0) {
                mutex_unlock(&rv8803->flags_lock);
                return flags;
        }
        flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
-       err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+       err = rv8803_write_reg(client, RV8803_FLAG, flags);
        mutex_unlock(&rv8803->flags_lock);
        if (err)
                return err;
 
        if (ctrl != rv8803->ctrl) {
                rv8803->ctrl = ctrl;
-               err = i2c_smbus_write_byte_data(client, RV8803_CTRL,
-                                               rv8803->ctrl);
+               err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl);
                if (err)
                        return err;
        }
@@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case RTC_VL_READ:
-               flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+               flags = rv8803_read_reg(client, RV8803_FLAG);
                if (flags < 0)
                        return flags;
 
@@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 
        case RTC_VL_CLR:
                mutex_lock(&rv8803->flags_lock);
-               flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+               flags = rv8803_read_reg(client, RV8803_FLAG);
                if (flags < 0) {
                        mutex_unlock(&rv8803->flags_lock);
                        return flags;
                }
 
                flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
-               ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+               ret = rv8803_write_reg(client, RV8803_FLAG, flags);
                mutex_unlock(&rv8803->flags_lock);
-               if (ret < 0)
+               if (ret)
                        return ret;
 
                return 0;
@@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
        struct i2c_client *client = to_i2c_client(dev);
        int ret;
 
-       ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]);
-       if (ret < 0)
+       ret = rv8803_write_reg(client, RV8803_RAM, buf[0]);
+       if (ret)
                return ret;
 
        return 1;
@@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
        struct i2c_client *client = to_i2c_client(dev);
        int ret;
 
-       ret = i2c_smbus_read_byte_data(client, RV8803_RAM);
+       ret = rv8803_read_reg(client, RV8803_RAM);
        if (ret < 0)
                return ret;
 
@@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client,
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct rv8803_data *rv8803;
-       int err, flags, try = 0;
+       int err, flags;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_I2C_BLOCK)) {
@@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client,
        rv8803->client = client;
        i2c_set_clientdata(client, rv8803);
 
-       /*
-        * There is a 60µs window where the RTC may not reply on the i2c bus in
-        * that case, the transfer is not ACKed. In that case, ensure there are
-        * multiple attempts.
-        */
-       do {
-               flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
-               try++;
-       } while ((flags == -ENXIO) && (try < 3));
-
+       flags = rv8803_read_reg(client, RV8803_FLAG);
        if (flags < 0)
                return flags;
 
@@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client,
                return PTR_ERR(rv8803->rtc);
        }
 
-       try = 0;
-       do {
-               err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
-                                               RV8803_EXT_WADA);
-               try++;
-       } while ((err == -ENXIO) && (try < 3));
+       err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
        if (err)
                return err;
 
index 772d221..7163b91 100644 (file)
@@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
        t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
 
-       if (alarmvals[2] & RX8010_ALARM_AE)
-               t->time.tm_mday = -1;
-       else
+       if (!(alarmvals[2] & RX8010_ALARM_AE))
                t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f);
 
-       t->time.tm_wday = -1;
-       t->time.tm_mon = -1;
-       t->time.tm_year = -1;
-
        t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
        t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;
 
index 9f105ef..2b85cc7 100644 (file)
@@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
                t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
                        + (ald[1] & 0x20 ? 12 : 0);
 
-       t->time.tm_wday = -1;
-       t->time.tm_mday = -1;
-       t->time.tm_mon = -1;
-       t->time.tm_year = -1;
-
        dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n",
                __func__,
                t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
index f40afdd..5dab466 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/bitrev.h>
 #include <linux/bcd.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #define S35390A_CMD_STATUS1    0
 #define S35390A_CMD_STATUS2    1
 #define S35390A_ALRM_BYTE_HOURS        1
 #define S35390A_ALRM_BYTE_MINS 2
 
+/* flags for STATUS1 */
 #define S35390A_FLAG_POC       0x01
 #define S35390A_FLAG_BLD       0x02
+#define S35390A_FLAG_INT2      0x04
 #define S35390A_FLAG_24H       0x40
 #define S35390A_FLAG_RESET     0x80
+
+/* flag for STATUS2 */
 #define S35390A_FLAG_TEST      0x01
 
 #define S35390A_INT2_MODE_MASK         0xF0
@@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
        return 0;
 }
 
-static int s35390a_reset(struct s35390a *s35390a)
+/*
+ * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
+ * To keep the information if an irq is pending, pass the value read from
+ * STATUS1 to the caller.
+ */
+static int s35390a_reset(struct s35390a *s35390a, char *status1)
 {
-       char buf[1];
-
-       if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
-               return -EIO;
-
-       if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
+       char buf;
+       int ret;
+       unsigned initcount = 0;
+
+       ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
+       if (ret < 0)
+               return ret;
+
+       if (*status1 & S35390A_FLAG_POC)
+               /*
+                * Do not communicate for 0.5 seconds since the power-on
+                * detection circuit is in operation.
+                */
+               msleep(500);
+       else if (!(*status1 & S35390A_FLAG_BLD))
+               /*
+                * If both POC and BLD are unset everything is fine.
+                */
                return 0;
 
-       buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
-       buf[0] &= 0xf0;
-       return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
+       /*
+        * At least one of POC and BLD are set, so reinitialise chip. Keeping
+        * this information in the hardware to know later that the time isn't
+        * valid is unfortunately not possible because POC and BLD are cleared
+        * on read. So the reset is best done now.
+        *
+        * The 24H bit is kept over reset, so set it already here.
+        */
+initialize:
+       *status1 = S35390A_FLAG_24H;
+       buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
+       ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+
+       if (ret < 0)
+               return ret;
+
+       ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+       if (ret < 0)
+               return ret;
+
+       if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
+               /* Try up to five times to reset the chip */
+               if (initcount < 5) {
+                       ++initcount;
+                       goto initialize;
+               } else
+                       return -EIO;
+       }
+
+       return 1;
 }
 
 static int s35390a_disable_test_mode(struct s35390a *s35390a)
@@ -217,12 +266,12 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
                alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
                alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
 
-       /* disable interrupt */
+       /* disable interrupt (which deasserts the irq line) */
        err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
        if (err < 0)
                return err;
 
-       /* clear pending interrupt, if any */
+       /* clear pending interrupt (in STATUS1 only), if any */
        err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
        if (err < 0)
                return err;
@@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
 
        if (alm->time.tm_wday != -1)
                buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
+       else
+               buf[S35390A_ALRM_BYTE_WDAY] = 0;
 
        buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
                        alm->time.tm_hour) | 0x80;
@@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
        if (err < 0)
                return err;
 
-       if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
-               return -EINVAL;
+       if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
+               /*
+                * When the alarm isn't enabled, the register to configure
+                * the alarm time isn't accessible.
+                */
+               alm->enabled = 0;
+               return 0;
+       } else {
+               alm->enabled = 1;
+       }
 
        err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
        if (err < 0)
                return err;
 
        /* This chip returns the bits of each byte in reverse order */
-       for (i = 0; i < 3; ++i) {
+       for (i = 0; i < 3; ++i)
                buf[i] = bitrev8(buf[i]);
-               buf[i] &= ~0x80;
-       }
 
-       alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
-       alm->time.tm_hour = s35390a_reg2hr(s35390a,
-                                               buf[S35390A_ALRM_BYTE_HOURS]);
-       alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
+       /*
+        * B0 of the three matching registers is an enable flag. Iff it is set
+        * the configured value is used for matching.
+        */
+       if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
+               alm->time.tm_wday =
+                       bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
+
+       if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
+               alm->time.tm_hour =
+                       s35390a_reg2hr(s35390a,
+                                      buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
+
+       if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
+               alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
+
+       /* alarm triggers always at s=0 */
+       alm->time.tm_sec = 0;
 
        dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
                        __func__, alm->time.tm_min, alm->time.tm_hour,
@@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver;
 static int s35390a_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
-       int err;
+       int err, err_reset;
        unsigned int i;
        struct s35390a *s35390a;
        struct rtc_time tm;
-       char buf[1];
+       char buf, status1;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
@@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client,
                }
        }
 
-       err = s35390a_reset(s35390a);
-       if (err < 0) {
+       err_reset = s35390a_reset(s35390a, &status1);
+       if (err_reset < 0) {
+               err = err_reset;
                dev_err(&client->dev, "error resetting chip\n");
                goto exit_dummy;
        }
 
-       err = s35390a_disable_test_mode(s35390a);
-       if (err < 0) {
-               dev_err(&client->dev, "error disabling test mode\n");
-               goto exit_dummy;
-       }
-
-       err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
-       if (err < 0) {
-               dev_err(&client->dev, "error checking 12/24 hour mode\n");
-               goto exit_dummy;
-       }
-       if (buf[0] & S35390A_FLAG_24H)
+       if (status1 & S35390A_FLAG_24H)
                s35390a->twentyfourhour = 1;
        else
                s35390a->twentyfourhour = 0;
 
-       if (s35390a_get_datetime(client, &tm) < 0)
+       if (status1 & S35390A_FLAG_INT2) {
+               /* disable alarm (and maybe test mode) */
+               buf = 0;
+               err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
+               if (err < 0) {
+                       dev_err(&client->dev, "error disabling alarm");
+                       goto exit_dummy;
+               }
+       } else {
+               err = s35390a_disable_test_mode(s35390a);
+               if (err < 0) {
+                       dev_err(&client->dev, "error disabling test mode\n");
+                       goto exit_dummy;
+               }
+       }
+
+       if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
                dev_warn(&client->dev, "clock needs to be set\n");
 
        device_set_wakeup_capable(&client->dev, 1);
@@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client,
                err = PTR_ERR(s35390a->rtc);
                goto exit_dummy;
        }
+
+       if (status1 & S35390A_FLAG_INT2)
+               rtc_update_irq(s35390a->rtc, 1, RTC_AF);
+
        return 0;
 
 exit_dummy:
index d01ad7e..d44fb34 100644 (file)
@@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
        if (!is_power_of_2(freq))
                return -EINVAL;
 
+       s3c_rtc_enable_clk(info);
        spin_lock_irq(&info->pie_lock);
 
        if (info->data->set_freq)
                info->data->set_freq(info, freq);
 
        spin_unlock_irq(&info->pie_lock);
+       s3c_rtc_disable_clk(info);
 
        return 0;
 }
@@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
        /* decode the alarm enable field */
        if (alm_en & S3C2410_RTCALM_SECEN)
                alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
-       else
-               alm_tm->tm_sec = -1;
 
        if (alm_en & S3C2410_RTCALM_MINEN)
                alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
-       else
-               alm_tm->tm_min = -1;
 
        if (alm_en & S3C2410_RTCALM_HOUREN)
                alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
-       else
-               alm_tm->tm_hour = -1;
 
        if (alm_en & S3C2410_RTCALM_DAYEN)
                alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
-       else
-               alm_tm->tm_mday = -1;
 
        if (alm_en & S3C2410_RTCALM_MONEN) {
                alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
                alm_tm->tm_mon -= 1;
-       } else {
-               alm_tm->tm_mon = -1;
        }
 
        if (alm_en & S3C2410_RTCALM_YEAREN)
                alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
-       else
-               alm_tm->tm_year = -1;
 
        return 0;
 }
@@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
 
        s3c_rtc_setfreq(info, 1);
 
-       s3c_rtc_disable_clk(info);
-
        return 0;
 
  err_nortc:
index a45845a..17b6235 100644 (file)
@@ -481,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        tm->tm_mon      = sh_rtc_read_alarm_value(rtc, RMONAR);
        if (tm->tm_mon > 0)
                tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
-       tm->tm_year     = 0xffff;
 
        wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
 
@@ -500,52 +499,13 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
                writeb(bin2bcd(value) | AR_ENB,  rtc->regbase + reg_off);
 }
 
-static int sh_rtc_check_alarm(struct rtc_time *tm)
-{
-       /*
-        * The original rtc says anything > 0xc0 is "don't care" or "match
-        * all" - most users use 0xff but rtc-dev uses -1 for the same thing.
-        * The original rtc doesn't support years - some things use -1 and
-        * some 0xffff. We use -1 to make out tests easier.
-        */
-       if (tm->tm_year == 0xffff)
-               tm->tm_year = -1;
-       if (tm->tm_mon >= 0xff)
-               tm->tm_mon = -1;
-       if (tm->tm_mday >= 0xff)
-               tm->tm_mday = -1;
-       if (tm->tm_wday >= 0xff)
-               tm->tm_wday = -1;
-       if (tm->tm_hour >= 0xff)
-               tm->tm_hour = -1;
-       if (tm->tm_min >= 0xff)
-               tm->tm_min = -1;
-       if (tm->tm_sec >= 0xff)
-               tm->tm_sec = -1;
-
-       if (tm->tm_year > 9999 ||
-               tm->tm_mon >= 12 ||
-               tm->tm_mday == 0 || tm->tm_mday >= 32 ||
-               tm->tm_wday >= 7 ||
-               tm->tm_hour >= 24 ||
-               tm->tm_min >= 60 ||
-               tm->tm_sec >= 60)
-               return -EINVAL;
-
-       return 0;
-}
-
 static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct sh_rtc *rtc = platform_get_drvdata(pdev);
        unsigned int rcr1;
        struct rtc_time *tm = &wkalrm->time;
-       int mon, err;
-
-       err = sh_rtc_check_alarm(tm);
-       if (unlikely(err < 0))
-               return err;
+       int mon;
 
        spin_lock_irq(&rtc->lock);
 
index 60232bd..15ac597 100644 (file)
@@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        if (sec == 0) {
                /* alarm is disabled. */
                alarm->enabled = 0;
-               alarm->time.tm_mon = -1;
-               alarm->time.tm_mday = -1;
-               alarm->time.tm_year = -1;
-               alarm->time.tm_hour = -1;
-               alarm->time.tm_min = -1;
-               alarm->time.tm_sec = -1;
        } else {
                /* alarm is enabled. */
                alarm->enabled = 1;
index 7a04363..1f3117b 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/rtc.h>
 #include <linux/types.h>
 #include <linux/bcd.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
diff --git a/include/linux/ds17287rtc.h b/include/linux/ds17287rtc.h
deleted file mode 100644 (file)
index d85d3f4..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ds17287rtc.h - register definitions for the ds1728[57] RTC / CMOS RAM
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * (C) 2003 Guido Guenther <agx@sigxcpu.org>
- */
-#ifndef __LINUX_DS17287RTC_H
-#define __LINUX_DS17287RTC_H
-
-#include <linux/rtc.h>                 /* get the user-level API */
-#include <linux/mc146818rtc.h>
-
-/* Register A */
-#define DS_REGA_DV2    0x40            /* countdown chain */
-#define DS_REGA_DV1    0x20            /* oscillator enable */
-#define DS_REGA_DV0    0x10            /* bank select */
-
-/* bank 1 registers */
-#define DS_B1_MODEL    0x40            /* model number byte */
-#define DS_B1_SN1      0x41            /* serial number byte 1 */
-#define DS_B1_SN2      0x42            /* serial number byte 2 */
-#define DS_B1_SN3      0x43            /* serial number byte 3 */
-#define DS_B1_SN4      0x44            /* serial number byte 4 */
-#define DS_B1_SN5      0x45            /* serial number byte 5 */
-#define DS_B1_SN6      0x46            /* serial number byte 6 */
-#define DS_B1_CRC      0x47            /* CRC byte */
-#define DS_B1_CENTURY  0x48            /* Century byte */
-#define DS_B1_DALARM   0x49            /* date alarm */
-#define DS_B1_XCTRL4A  0x4a            /* extendec control register 4a */
-#define DS_B1_XCTRL4B  0x4b            /* extendec control register 4b */
-#define DS_B1_RTCADDR2         0x4e            /* rtc address 2 */
-#define DS_B1_RTCADDR3         0x4f            /* rtc address 3 */
-#define DS_B1_RAMLSB   0x50            /* extended ram LSB */
-#define DS_B1_RAMMSB   0x51            /* extended ram MSB */
-#define DS_B1_RAMDPORT 0x53            /* extended ram data port */
-
-/* register details */
-/* extended control register 4a */
-#define DS_XCTRL4A_VRT2        0x80            /* valid ram and time */
-#define DS_XCTRL4A_INCR        0x40            /* increment progress status */
-#define DS_XCTRL4A_BME 0x20            /* burst mode enable */
-#define DS_XCTRL4A_PAB 0x08            /* power active bar ctrl */
-#define DS_XCTRL4A_RF  0x04            /* ram clear flag */
-#define DS_XCTRL4A_WF  0x02            /* wake up alarm flag */
-#define DS_XCTRL4A_KF  0x01            /* kickstart flag */
-
-/* interrupt causes */
-#define DS_XCTRL4A_IFS (DS_XCTRL4A_RF|DS_XCTRL4A_WF|DS_XCTRL4A_KF)
-
-/* extended control register 4b */
-#define DS_XCTRL4B_ABE 0x80            /* auxiliary battery enable */
-#define DS_XCTRL4B_E32K        0x40            /* enable 32.768 kHz Output */
-#define DS_XCTRL4B_CS  0x20            /* crystal select */
-#define DS_XCTRL4B_RCE 0x10            /* ram clear enable */
-#define DS_XCTRL4B_PRS 0x08            /* PAB resec select */
-#define DS_XCTRL4B_RIE 0x04            /* ram clear interrupt enable */
-#define DS_XCTRL4B_WFE 0x02            /* wake up alarm interrupt enable */
-#define DS_XCTRL4B_KFE 0x01            /* kickstart interrupt enable */
-
-/* interrupt enable bits */
-#define DS_XCTRL4B_IFES        (DS_XCTRL4B_RIE|DS_XCTRL4B_WFE|DS_XCTRL4B_KFE)
-
-#endif /* __LINUX_DS17287RTC_H */
index 433e0c7..a585b4b 100644 (file)
@@ -14,6 +14,8 @@
 #include <asm/io.h>
 #include <linux/rtc.h>                 /* get the user-level API */
 #include <asm/mc146818rtc.h>           /* register access macros */
+#include <linux/bcd.h>
+#include <linux/delay.h>
 
 #ifdef __KERNEL__
 #include <linux/spinlock.h>            /* spinlock_t */
@@ -120,4 +122,7 @@ struct cmos_rtc_board_info {
 #define RTC_IO_EXTENT_USED      RTC_IO_EXTENT
 #endif /* ARCH_RTC_LOCATION */
 
+unsigned int mc146818_get_time(struct rtc_time *time);
+int mc146818_set_time(struct rtc_time *time);
+
 #endif /* _MC146818RTC_H */
index 624bce5..4230d30 100644 (file)
@@ -144,11 +144,12 @@ test_READ:
 
        retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
        if (retval == -1) {
-               if (errno == ENOTTY) {
+               if (errno == EINVAL) {
                        fprintf(stderr,
                                "\n...Alarm IRQs not supported.\n");
                        goto test_PIE;
                }
+
                perror("RTC_ALM_SET ioctl");
                exit(errno);
        }
@@ -166,6 +167,12 @@ test_READ:
        /* Enable alarm interrupts */
        retval = ioctl(fd, RTC_AIE_ON, 0);
        if (retval == -1) {
+               if (errno == EINVAL) {
+                       fprintf(stderr,
+                               "\n...Alarm IRQs not supported.\n");
+                       goto test_PIE;
+               }
+
                perror("RTC_AIE_ON ioctl");
                exit(errno);
        }
@@ -193,7 +200,7 @@ test_PIE:
        retval = ioctl(fd, RTC_IRQP_READ, &tmp);
        if (retval == -1) {
                /* not all RTCs support periodic IRQs */
-               if (errno == ENOTTY) {
+               if (errno == EINVAL) {
                        fprintf(stderr, "\nNo periodic IRQ support\n");
                        goto done;
                }
@@ -211,7 +218,7 @@ test_PIE:
                retval = ioctl(fd, RTC_IRQP_SET, tmp);
                if (retval == -1) {
                        /* not all RTCs can change their periodic IRQ rate */
-                       if (errno == ENOTTY) {
+                       if (errno == EINVAL) {
                                fprintf(stderr,
                                        "\n...Periodic IRQ rate is fixed\n");
                                goto done;