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 ...
Unified · Split
| @@ -9828,10 +9828,14 @@ L: rtc-linux@googlegroups.com · 9827 unmodified lines | ||
| 9828 | 9828 | Q: http://patchwork.ozlabs.org/project/rtc-linux/list/ |
| 9829 | 9829 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git |
| 9830 | 9830 | S: Maintained |
| 9831 | +F: Documentation/devicetree/bindings/rtc/ | |
| 9831 | 9832 | F: Documentation/rtc.txt |
| 9832 | 9833 | F: drivers/rtc/ |
| 9833 | 9834 | F: include/linux/rtc.h |
| 9834 | 9835 | F: include/uapi/linux/rtc.h |
| 9836 | +F: include/linux/rtc/ | |
| 9837 | +F: include/linux/platform_data/rtc-* | |
| 9838 | +F: tools/testing/selftests/timers/rtctest.c | |
| 9835 | 9839 | |
| 9836 | 9840 | REALTEK AUDIO CODECS |
| 9837 | 9841 | M: Bard Liao <bardliao@realtek.com> |
| @@ -1 +0,0 @@ | ||
| 1 | −#include <asm-generic/rtc.h> | |
| @@ -24,7 +24,6 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <asm/gct.h> |
| 25 | 25 | #include <asm/pgalloc.h> |
| 26 | 26 | #include <asm/tlbflush.h> |
| 27 | −#include <asm/rtc.h> | |
| 28 | 27 | #include <asm/vga.h> |
| 29 | 28 | |
| 30 | 29 | #include "proto.h" |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/rtc.h> |
| 16 | 16 | #include <linux/platform_device.h> |
| 17 | 17 | |
| 18 | −#include <asm/rtc.h> | |
| 19 | − | |
| 20 | 18 | #include "proto.h" |
| 21 | 19 | |
| 22 | 20 | |
| @@ -81,7 +79,7 @@ init_rtc_epoch(void) · 58 unmodified lines | ||
| 81 | 79 | static int |
| 82 | 80 | alpha_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 83 | 81 | { |
| 84 | − __get_rtc_time(tm); | |
| 82 | + mc146818_get_time(tm); | |
| 85 | 83 | |
| 86 | 84 | /* Adjust for non-default epochs. It's easier to depend on the |
| 87 | 85 | 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) · 24 unmodified lines | ||
| 112 | 110 | tm = &xtm; |
| 113 | 111 | } |
| 114 | 112 | |
| 115 | − return __set_rtc_time(tm); | |
| 113 | + return mc146818_set_time(tm); | |
| 116 | 114 | } |
| 117 | 115 | |
| 118 | 116 | static int |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/init.h> |
| 17 | 17 | #include <linux/platform_device.h> |
| 18 | 18 | #include <linux/io.h> |
| 19 | −#include <linux/m48t86.h> | |
| 19 | +#include <linux/platform_data/rtc-m48t86.h> | |
| 20 | 20 | #include <linux/mtd/nand.h> |
| 21 | 21 | #include <linux/mtd/partitions.h> |
| 22 | 22 | |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/platform_device.h> |
| 17 | 17 | #include <linux/mv643xx_eth.h> |
| 18 | 18 | #include <linux/ata_platform.h> |
| 19 | −#include <linux/m48t86.h> | |
| 19 | +#include <linux/platform_data/rtc-m48t86.h> | |
| 20 | 20 | #include <linux/mtd/nand.h> |
| 21 | 21 | #include <linux/mtd/partitions.h> |
| 22 | 22 | #include <linux/timeriomem-rng.h> |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/gpio.h> |
| 15 | 15 | #include <linux/delay.h> |
| 16 | 16 | |
| 17 | −#include <linux/rtc-v3020.h> | |
| 17 | +#include <linux/platform_data/rtc-v3020.h> | |
| 18 | 18 | #include <video/mbxfb.h> |
| 19 | 19 | |
| 20 | 20 | #include <linux/spi/spi.h> |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/gpio.h> |
| 26 | 26 | #include <linux/dm9000.h> |
| 27 | 27 | #include <linux/leds.h> |
| 28 | −#include <linux/rtc-v3020.h> | |
| 28 | +#include <linux/platform_data/rtc-v3020.h> | |
| 29 | 29 | #include <linux/pwm.h> |
| 30 | 30 | #include <linux/pwm_backlight.h> |
| 31 | 31 | |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/delay.h> |
| 15 | 15 | |
| 16 | 16 | #include <linux/dm9000.h> |
| 17 | −#include <linux/rtc-v3020.h> | |
| 17 | +#include <linux/platform_data/rtc-v3020.h> | |
| 18 | 18 | #include <linux/mtd/nand.h> |
| 19 | 19 | #include <linux/mtd/partitions.h> |
| 20 | 20 | #include <linux/mtd/physmap.h> |
| @@ -1,16 +0,0 @@ | ||
| 1 | −/* mc146818rtc.h: RTC defs | |
| 2 | − * | |
| 3 | − * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | |
| 4 | − * Written by David Howells (dhowells@redhat.com) | |
| 5 | − * | |
| 6 | − * This program is free software; you can redistribute it and/or | |
| 7 | − * modify it under the terms of the GNU General Public License | |
| 8 | − * as published by the Free Software Foundation; either version | |
| 9 | − * 2 of the License, or (at your option) any later version. | |
| 10 | − */ | |
| 11 | − | |
| 12 | −#ifndef _ASM_MC146818RTC_H | |
| 13 | −#define _ASM_MC146818RTC_H | |
| 14 | − | |
| 15 | − | |
| 16 | −#endif /* _ASM_MC146818RTC_H */ | |
| @@ -1,9 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Machine dependent access functions for RTC registers. | |
| 3 | − */ | |
| 4 | −#ifndef _H8300_MC146818RTC_H | |
| 5 | −#define _H8300_MC146818RTC_H | |
| 6 | − | |
| 7 | −/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */ | |
| 8 | − | |
| 9 | −#endif /* _H8300_MC146818RTC_H */ | |
| @@ -1,10 +0,0 @@ | ||
| 1 | −#ifndef _ASM_IA64_MC146818RTC_H | |
| 2 | −#define _ASM_IA64_MC146818RTC_H | |
| 3 | − | |
| 4 | −/* | |
| 5 | − * Machine dependent access functions for RTC registers. | |
| 6 | − */ | |
| 7 | − | |
| 8 | −/* empty include file to satisfy the include in genrtc.c */ | |
| 9 | − | |
| 10 | −#endif /* _ASM_IA64_MC146818RTC_H */ | |
| @@ -35,7 +35,6 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <asm/amigahw.h> |
| 36 | 36 | #include <asm/amigaints.h> |
| 37 | 37 | #include <asm/irq.h> |
| 38 | −#include <asm/rtc.h> | |
| 39 | 38 | #include <asm/machdep.h> |
| 40 | 39 | #include <asm/io.h> |
| 41 | 40 | |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <asm/pgtable.h> |
| 16 | 16 | #include <asm/apollohw.h> |
| 17 | 17 | #include <asm/irq.h> |
| 18 | −#include <asm/rtc.h> | |
| 19 | 18 | #include <asm/machdep.h> |
| 20 | 19 | |
| 21 | 20 | u_long sio01_physaddr; |
| @@ -34,7 +34,6 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <asm/setup.h> |
| 35 | 35 | #include <asm/irq.h> |
| 36 | 36 | #include <asm/traps.h> |
| 37 | −#include <asm/rtc.h> | |
| 38 | 37 | #include <asm/machdep.h> |
| 39 | 38 | #include <asm/bvme6000hw.h> |
| 40 | 39 | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/string.h> |
| 13 | 13 | #include <linux/kernel.h> |
| 14 | 14 | #include <linux/console.h> |
| 15 | +#include <linux/rtc.h> | |
| 15 | 16 | |
| 16 | 17 | #include <asm/bootinfo.h> |
| 17 | 18 | #include <asm/bootinfo-hp300.h> |
| @@ -20,7 +21,6 @@ · 2 unmodified lines | ||
| 20 | 21 | #include <asm/blinken.h> |
| 21 | 22 | #include <asm/io.h> /* readb() and writeb() */ |
| 22 | 23 | #include <asm/hp300hw.h> |
| 23 | −#include <asm/rtc.h> | |
| 24 | 24 | |
| 25 | 25 | #include "time.h" |
| 26 | 26 | |
| @@ -1,79 +0,0 @@ | ||
| 1 | −/* include/asm-m68k/rtc.h | |
| 2 | − * | |
| 3 | − * Copyright Richard Zidlicky | |
| 4 | − * implementation details for genrtc/q40rtc driver | |
| 5 | − */ | |
| 6 | −/* permission is hereby granted to copy, modify and redistribute this code | |
| 7 | − * in terms of the GNU Library General Public License, Version 2 or later, | |
| 8 | − * at your option. | |
| 9 | − */ | |
| 10 | − | |
| 11 | −#ifndef _ASM_RTC_H | |
| 12 | −#define _ASM_RTC_H | |
| 13 | − | |
| 14 | −#ifdef __KERNEL__ | |
| 15 | − | |
| 16 | −#include <linux/rtc.h> | |
| 17 | −#include <asm/errno.h> | |
| 18 | −#include <asm/machdep.h> | |
| 19 | − | |
| 20 | −#define RTC_PIE 0x40 /* periodic interrupt enable */ | |
| 21 | −#define RTC_AIE 0x20 /* alarm interrupt enable */ | |
| 22 | −#define RTC_UIE 0x10 /* update-finished interrupt enable */ | |
| 23 | − | |
| 24 | −/* some dummy definitions */ | |
| 25 | −#define RTC_BATT_BAD 0x100 /* battery bad */ | |
| 26 | −#define RTC_SQWE 0x08 /* enable square-wave output */ | |
| 27 | −#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | |
| 28 | −#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | |
| 29 | −#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | |
| 30 | − | |
| 31 | −static inline unsigned int get_rtc_time(struct rtc_time *time) | |
| 32 | −{ | |
| 33 | − /* | |
| 34 | − * Only the values that we read from the RTC are set. We leave | |
| 35 | − * tm_wday, tm_yday and tm_isdst untouched. Even though the | |
| 36 | − * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated | |
| 37 | − * by the RTC when initially set to a non-zero value. | |
| 38 | − */ | |
| 39 | − if (mach_hwclk) | |
| 40 | − mach_hwclk(0, time); | |
| 41 | − return RTC_24H; | |
| 42 | −} | |
| 43 | − | |
| 44 | −static inline int set_rtc_time(struct rtc_time *time) | |
| 45 | −{ | |
| 46 | − if (mach_hwclk) | |
| 47 | − return mach_hwclk(1, time); | |
| 48 | − return -EINVAL; | |
| 49 | −} | |
| 50 | − | |
| 51 | −static inline unsigned int get_rtc_ss(void) | |
| 52 | −{ | |
| 53 | − if (mach_get_ss) | |
| 54 | − return mach_get_ss(); | |
| 55 | − else{ | |
| 56 | − struct rtc_time h; | |
| 57 | − | |
| 58 | − get_rtc_time(&h); | |
| 59 | − return h.tm_sec; | |
| 60 | − } | |
| 61 | −} | |
| 62 | − | |
| 63 | −static inline int get_rtc_pll(struct rtc_pll_info *pll) | |
| 64 | −{ | |
| 65 | − if (mach_get_rtc_pll) | |
| 66 | − return mach_get_rtc_pll(pll); | |
| 67 | − else | |
| 68 | − return -EINVAL; | |
| 69 | −} | |
| 70 | −static inline int set_rtc_pll(struct rtc_pll_info *pll) | |
| 71 | −{ | |
| 72 | − if (mach_set_rtc_pll) | |
| 73 | − return mach_set_rtc_pll(pll); | |
| 74 | − else | |
| 75 | − return -EINVAL; | |
| 76 | −} | |
| 77 | −#endif /* __KERNEL__ */ | |
| 78 | − | |
| 79 | −#endif /* _ASM__RTC_H */ | |
| @@ -86,7 +86,49 @@ void read_persistent_clock(struct timespec *ts) · 85 unmodified lines | ||
| 86 | 86 | } |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | −#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET | |
| 89 | +#if defined(CONFIG_ARCH_USES_GETTIMEOFFSET) && IS_ENABLED(CONFIG_RTC_DRV_GENERIC) | |
| 90 | +static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) | |
| 91 | +{ | |
| 92 | + mach_hwclk(0, tm); | |
| 93 | + return rtc_valid_tm(tm); | |
| 94 | +} | |
| 95 | + | |
| 96 | +static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) | |
| 97 | +{ | |
| 98 | + if (mach_hwclk(1, tm) < 0) | |
| 99 | + return -EOPNOTSUPP; | |
| 100 | + return 0; | |
| 101 | +} | |
| 102 | + | |
| 103 | +static int rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |
| 104 | +{ | |
| 105 | + struct rtc_pll_info pll; | |
| 106 | + struct rtc_pll_info __user *argp = (void __user *)arg; | |
| 107 | + | |
| 108 | + switch (cmd) { | |
| 109 | + case RTC_PLL_GET: | |
| 110 | + if (!mach_get_rtc_pll || mach_get_rtc_pll(&pll)) | |
| 111 | + return -EINVAL; | |
| 112 | + return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0; | |
| 113 | + | |
| 114 | + case RTC_PLL_SET: | |
| 115 | + if (!mach_set_rtc_pll) | |
| 116 | + return -EINVAL; | |
| 117 | + if (!capable(CAP_SYS_TIME)) | |
| 118 | + return -EACCES; | |
| 119 | + if (copy_from_user(&pll, argp, sizeof(pll))) | |
| 120 | + return -EFAULT; | |
| 121 | + return mach_set_rtc_pll(&pll); | |
| 122 | + } | |
| 123 | + | |
| 124 | + return -ENOIOCTLCMD; | |
| 125 | +} | |
| 126 | + | |
| 127 | +static const struct rtc_class_ops generic_rtc_ops = { | |
| 128 | + .ioctl = rtc_ioctl, | |
| 129 | + .read_time = rtc_generic_get_time, | |
| 130 | + .set_time = rtc_generic_set_time, | |
| 131 | +}; | |
| 90 | 132 | |
| 91 | 133 | static int __init rtc_init(void) |
| 92 | 134 | { |
| @@ -95,7 +137,9 @@ static int __init rtc_init(void) · 2 unmodified lines | ||
| 95 | 137 | if (!mach_hwclk) |
| 96 | 138 | return -ENODEV; |
| 97 | 139 | |
| 98 | − pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | |
| 140 | + pdev = platform_device_register_data(NULL, "rtc-generic", -1, | |
| 141 | + &generic_rtc_ops, | |
| 142 | + sizeof(generic_rtc_ops)); | |
| 99 | 143 | return PTR_ERR_OR_ZERO(pdev); |
| 100 | 144 | } |
| 101 | 145 | |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | * Miscellaneous linux stuff |
| 11 | 11 | */ |
| 12 | 12 | |
| 13 | +#include <linux/errno.h> | |
| 13 | 14 | #include <linux/module.h> |
| 14 | 15 | #include <linux/types.h> |
| 15 | 16 | #include <linux/mm.h> |
| @@ -25,6 +26,7 @@ · 9 unmodified lines | ||
| 25 | 26 | #include <linux/platform_device.h> |
| 26 | 27 | #include <linux/adb.h> |
| 27 | 28 | #include <linux/cuda.h> |
| 29 | +#include <linux/rtc.h> | |
| 28 | 30 | |
| 29 | 31 | #include <asm/setup.h> |
| 30 | 32 | #include <asm/bootinfo.h> |
| @@ -34,7 +36,6 @@ · 3 unmodified lines | ||
| 34 | 36 | #include <asm/io.h> |
| 35 | 37 | #include <asm/irq.h> |
| 36 | 38 | #include <asm/pgtable.h> |
| 37 | −#include <asm/rtc.h> | |
| 38 | 39 | #include <asm/machdep.h> |
| 39 | 40 | |
| 40 | 41 | #include <asm/macintosh.h> |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include <asm/uaccess.h> |
| 20 | 20 | #include <asm/io.h> |
| 21 | −#include <asm/rtc.h> | |
| 22 | 21 | #include <asm/segment.h> |
| 23 | 22 | #include <asm/setup.h> |
| 24 | 23 | #include <asm/macintosh.h> |
| @@ -32,7 +32,6 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <asm/setup.h> |
| 33 | 33 | #include <asm/irq.h> |
| 34 | 34 | #include <asm/traps.h> |
| 35 | −#include <asm/rtc.h> | |
| 36 | 35 | #include <asm/machdep.h> |
| 37 | 36 | #include <asm/mvme147hw.h> |
| 38 | 37 | |
| @@ -35,7 +35,6 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <asm/setup.h> |
| 36 | 36 | #include <asm/irq.h> |
| 37 | 37 | #include <asm/traps.h> |
| 38 | −#include <asm/rtc.h> | |
| 39 | 38 | #include <asm/machdep.h> |
| 40 | 39 | #include <asm/mvme16xhw.h> |
| 41 | 40 | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | * for more details. |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | +#include <linux/errno.h> | |
| 15 | 16 | #include <linux/types.h> |
| 16 | 17 | #include <linux/kernel.h> |
| 17 | 18 | #include <linux/mm.h> |
| @@ -27,7 +28,6 @@ · 9 unmodified lines | ||
| 27 | 28 | #include <linux/platform_device.h> |
| 28 | 29 | |
| 29 | 30 | #include <asm/io.h> |
| 30 | −#include <asm/rtc.h> | |
| 31 | 31 | #include <asm/bootinfo.h> |
| 32 | 32 | #include <asm/pgtable.h> |
| 33 | 33 | #include <asm/setup.h> |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <asm/pgalloc.h> |
| 27 | 27 | #include <asm/sun3-head.h> |
| 28 | 28 | #include <asm/sun3mmu.h> |
| 29 | −#include <asm/rtc.h> | |
| 30 | 29 | #include <asm/machdep.h> |
| 31 | 30 | #include <asm/machines.h> |
| 32 | 31 | #include <asm/idprom.h> |
| @@ -14,8 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/rtc.h> |
| 15 | 15 | |
| 16 | 16 | #include <asm/errno.h> |
| 17 | −#include <asm/rtc.h> | |
| 18 | 17 | #include <asm/intersil.h> |
| 18 | +#include <asm/machdep.h> | |
| 19 | 19 | |
| 20 | 20 | |
| 21 | 21 | /* bits to set for start/run of the intersil */ |
| @@ -15,10 +15,10 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include <asm/irq.h> |
| 17 | 17 | #include <asm/io.h> |
| 18 | +#include <asm/machdep.h> | |
| 18 | 19 | #include <asm/traps.h> |
| 19 | 20 | #include <asm/sun3x.h> |
| 20 | 21 | #include <asm/sun3ints.h> |
| 21 | −#include <asm/rtc.h> | |
| 22 | 22 | |
| 23 | 23 | #include "time.h" |
| 24 | 24 | |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | */ |
| 8 | 8 | #include <linux/linkage.h> |
| 9 | 9 | #include <linux/init.h> |
| 10 | −#include <linux/ds1286.h> | |
| 10 | +#include <linux/rtc/ds1286.h> | |
| 11 | 11 | #include <linux/module.h> |
| 12 | 12 | #include <linux/interrupt.h> |
| 13 | 13 | #include <linux/kernel.h> |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #include <asm/sni.h> |
| 10 | 10 | #include <asm/time.h> |
| 11 | −#include <asm-generic/rtc.h> | |
| 12 | 11 | |
| 13 | 12 | #define SNI_CLOCK_TICK_RATE 3686400 |
| 14 | 13 | #define SNI_COUNTER2_DIV 64 |
| @@ -236,7 +236,9 @@ source "kernel/Kconfig.hz" · 235 unmodified lines | ||
| 236 | 236 | config MN10300_RTC |
| 237 | 237 | bool "Using MN10300 RTC" |
| 238 | 238 | depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050 |
| 239 | − select GENERIC_CMOS_UPDATE | |
| 239 | + select RTC_CLASS | |
| 240 | + select RTC_DRV_CMOS | |
| 241 | + select RTC_SYSTOHC | |
| 240 | 242 | default n |
| 241 | 243 | help |
| 242 | 244 | This option enables support for the RTC, thus enabling time to be |
| @@ -75,9 +75,9 @@ · 74 unmodified lines | ||
| 75 | 75 | #define RTC_PORT(x) 0xd8600000 |
| 76 | 76 | #define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ |
| 77 | 77 | |
| 78 | −#define CMOS_READ(addr) __SYSREG(0xd8600000 + (addr), u8) | |
| 78 | +#define CMOS_READ(addr) __SYSREG(0xd8600000 + (u32)(addr), u8) | |
| 79 | 79 | #define CMOS_WRITE(val, addr) \ |
| 80 | − do { __SYSREG(0xd8600000 + (addr), u8) = val; } while (0) | |
| 80 | + do { __SYSREG(0xd8600000 + (u32)(addr), u8) = val; } while (0) | |
| 81 | 81 | |
| 82 | 82 | #define RTC_IRQ RTIRQ |
| 83 | 83 | |
| @@ -25,6 +25,4 @@ static inline void calibrate_clock(void) · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #endif /* !CONFIG_MN10300_RTC */ |
| 27 | 27 | |
| 28 | −#include <asm-generic/rtc.h> | |
| 29 | − | |
| 30 | 28 | #endif /* _ASM_RTC_H */ |
| @@ -12,107 +12,19 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/module.h> |
| 13 | 13 | #include <linux/init.h> |
| 14 | 14 | #include <linux/mc146818rtc.h> |
| 15 | −#include <linux/bcd.h> | |
| 16 | −#include <linux/timex.h> | |
| 15 | +#include <linux/ioport.h> | |
| 16 | +#include <linux/platform_device.h> | |
| 17 | + | |
| 17 | 18 | #include <asm/rtc-regs.h> |
| 18 | 19 | #include <asm/rtc.h> |
| 19 | 20 | |
| 20 | 21 | DEFINE_SPINLOCK(rtc_lock); |
| 21 | 22 | EXPORT_SYMBOL(rtc_lock); |
| 22 | 23 | |
| 23 | −/* | |
| 24 | − * Read the current RTC time | |
| 25 | − */ | |
| 26 | −void read_persistent_clock(struct timespec *ts) | |
| 27 | −{ | |
| 28 | − struct rtc_time tm; | |
| 29 | − | |
| 30 | − get_rtc_time(&tm); | |
| 31 | − | |
| 32 | − ts->tv_nsec = 0; | |
| 33 | − ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, | |
| 34 | − tm.tm_hour, tm.tm_min, tm.tm_sec); | |
| 35 | − | |
| 36 | − /* if rtc is way off in the past, set something reasonable */ | |
| 37 | − if (ts->tv_sec < 0) | |
| 38 | − ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0); | |
| 39 | −} | |
| 40 | − | |
| 41 | −/* | |
| 42 | − * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500 | |
| 43 | − * ms after the second nowtime has started, because when nowtime is written | |
| 44 | − * into the registers of the CMOS clock, it will jump to the next second | |
| 45 | − * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data | |
| 46 | − * sheet for details. | |
| 47 | − * | |
| 48 | − * BUG: This routine does not handle hour overflow properly; it just | |
| 49 | − * sets the minutes. Usually you'll only notice that after reboot! | |
| 50 | − */ | |
| 51 | −static int set_rtc_mmss(unsigned long nowtime) | |
| 52 | −{ | |
| 53 | − unsigned char save_control, save_freq_select; | |
| 54 | − int retval = 0; | |
| 55 | − int real_seconds, real_minutes, cmos_minutes; | |
| 56 | − | |
| 57 | − /* gets recalled with irq locally disabled */ | |
| 58 | − spin_lock(&rtc_lock); | |
| 59 | − save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being | |
| 60 | − * set */ | |
| 61 | − CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL); | |
| 62 | − | |
| 63 | − save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset | |
| 64 | − * prescaler */ | |
| 65 | − CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT); | |
| 66 | − | |
| 67 | − cmos_minutes = CMOS_READ(RTC_MINUTES); | |
| 68 | − if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | |
| 69 | − cmos_minutes = bcd2bin(cmos_minutes); | |
| 70 | − | |
| 71 | − /* | |
| 72 | − * since we're only adjusting minutes and seconds, | |
| 73 | − * don't interfere with hour overflow. This avoids | |
| 74 | − * messing with unknown time zones but requires your | |
| 75 | − * RTC not to be off by more than 15 minutes | |
| 76 | − */ | |
| 77 | − real_seconds = nowtime % 60; | |
| 78 | − real_minutes = nowtime / 60; | |
| 79 | − if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) | |
| 80 | − /* correct for half hour time zone */ | |
| 81 | − real_minutes += 30; | |
| 82 | − real_minutes %= 60; | |
| 83 | − | |
| 84 | − if (abs(real_minutes - cmos_minutes) < 30) { | |
| 85 | − if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | |
| 86 | − real_seconds = bin2bcd(real_seconds); | |
| 87 | − real_minutes = bin2bcd(real_minutes); | |
| 88 | − } | |
| 89 | − CMOS_WRITE(real_seconds, RTC_SECONDS); | |
| 90 | − CMOS_WRITE(real_minutes, RTC_MINUTES); | |
| 91 | − } else { | |
| 92 | − printk_once(KERN_NOTICE | |
| 93 | − "set_rtc_mmss: can't update from %d to %d\n", | |
| 94 | − cmos_minutes, real_minutes); | |
| 95 | − retval = -1; | |
| 96 | − } | |
| 97 | − | |
| 98 | − /* The following flags have to be released exactly in this order, | |
| 99 | − * otherwise the DS12887 (popular MC146818A clone with integrated | |
| 100 | − * battery and quartz) will not reset the oscillator and will not | |
| 101 | − * update precisely 500 ms later. You won't find this mentioned in | |
| 102 | − * the Dallas Semiconductor data sheets, but who believes data | |
| 103 | − * sheets anyway ... -- Markus Kuhn | |
| 104 | − */ | |
| 105 | − CMOS_WRITE(save_control, RTC_CONTROL); | |
| 106 | − CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | |
| 107 | − spin_unlock(&rtc_lock); | |
| 108 | − | |
| 109 | − return retval; | |
| 110 | −} | |
| 111 | − | |
| 112 | −int update_persistent_clock(struct timespec now) | |
| 113 | −{ | |
| 114 | − return set_rtc_mmss(now.tv_sec); | |
| 115 | −} | |
| 24 | +static const __initdata struct resource res[] = { | |
| 25 | + DEFINE_RES_IO(RTC_PORT(0), RTC_IO_EXTENT), | |
| 26 | + DEFINE_RES_IRQ(RTC_IRQ), | |
| 27 | +}; | |
| 116 | 28 | |
| 117 | 29 | /* |
| 118 | 30 | * calibrate the TSC clock against the RTC |
| @@ -129,4 +41,6 @@ void __init calibrate_clock(void) · 10 unmodified lines | ||
| 129 | 41 | RTCRA |= RTCRA_DVR; |
| 130 | 42 | RTCRA &= ~RTCRA_DVR; |
| 131 | 43 | RTCRB &= ~RTCRB_SET; |
| 44 | + | |
| 45 | + platform_device_register_simple("rtc_cmos", -1, res, ARRAY_SIZE(res)); | |
| 132 | 46 | } |
| @@ -9,7 +9,10 @@ · 8 unmodified lines | ||
| 9 | 9 | * 2 of the Licence, or (at your option) any later version. |
| 10 | 10 | */ |
| 11 | 11 | #include <linux/kernel.h> |
| 12 | +#include <linux/irq.h> | |
| 13 | +#include <asm/cacheflush.h> | |
| 12 | 14 | #include <asm/fpu.h> |
| 15 | +#include <asm/irq.h> | |
| 13 | 16 | #include <asm/rtc.h> |
| 14 | 17 | #include <asm/busctl-regs.h> |
| 15 | 18 | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/delay.h> |
| 15 | 15 | #include <linux/interrupt.h> |
| 16 | 16 | |
| 17 | +#include <asm/cacheflush.h> | |
| 17 | 18 | #include <asm/processor.h> |
| 18 | 19 | #include <asm/uaccess.h> |
| 19 | 20 | #include <asm/io.h> |
| @@ -1,9 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Machine dependent access functions for RTC registers. | |
| 3 | − */ | |
| 4 | −#ifndef _ASM_MC146818RTC_H | |
| 5 | −#define _ASM_MC146818RTC_H | |
| 6 | − | |
| 7 | −/* empty include file to satisfy the include in genrtc.c */ | |
| 8 | − | |
| 9 | −#endif /* _ASM_MC146818RTC_H */ | |
| @@ -1,131 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * include/asm-parisc/rtc.h | |
| 3 | − * | |
| 4 | − * Copyright 2002 Randolph CHung <tausq@debian.org> | |
| 5 | − * | |
| 6 | − * Based on: include/asm-ppc/rtc.h and the genrtc driver in the | |
| 7 | − * 2.4 parisc linux tree | |
| 8 | − */ | |
| 9 | − | |
| 10 | −#ifndef __ASM_RTC_H__ | |
| 11 | −#define __ASM_RTC_H__ | |
| 12 | − | |
| 13 | −#ifdef __KERNEL__ | |
| 14 | − | |
| 15 | −#include <linux/rtc.h> | |
| 16 | − | |
| 17 | −#include <asm/pdc.h> | |
| 18 | − | |
| 19 | −#define SECS_PER_HOUR (60 * 60) | |
| 20 | −#define SECS_PER_DAY (SECS_PER_HOUR * 24) | |
| 21 | − | |
| 22 | − | |
| 23 | −#define RTC_PIE 0x40 /* periodic interrupt enable */ | |
| 24 | −#define RTC_AIE 0x20 /* alarm interrupt enable */ | |
| 25 | −#define RTC_UIE 0x10 /* update-finished interrupt enable */ | |
| 26 | − | |
| 27 | −#define RTC_BATT_BAD 0x100 /* battery bad */ | |
| 28 | − | |
| 29 | −/* some dummy definitions */ | |
| 30 | −#define RTC_SQWE 0x08 /* enable square-wave output */ | |
| 31 | −#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | |
| 32 | −#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | |
| 33 | −#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | |
| 34 | − | |
| 35 | −# define __isleap(year) \ | |
| 36 | − ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | |
| 37 | − | |
| 38 | −/* How many days come before each month (0-12). */ | |
| 39 | −static const unsigned short int __mon_yday[2][13] = | |
| 40 | −{ | |
| 41 | − /* Normal years. */ | |
| 42 | − { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | |
| 43 | − /* Leap years. */ | |
| 44 | − { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | |
| 45 | −}; | |
| 46 | − | |
| 47 | −static inline unsigned int get_rtc_time(struct rtc_time *wtime) | |
| 48 | −{ | |
| 49 | − struct pdc_tod tod_data; | |
| 50 | − long int days, rem, y; | |
| 51 | − const unsigned short int *ip; | |
| 52 | − | |
| 53 | − memset(wtime, 0, sizeof(*wtime)); | |
| 54 | − if (pdc_tod_read(&tod_data) < 0) | |
| 55 | − return RTC_24H | RTC_BATT_BAD; | |
| 56 | − | |
| 57 | − // most of the remainder of this function is: | |
| 58 | −// Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc. | |
| 59 | −// This was originally a part of the GNU C Library. | |
| 60 | −// It is distributed under the GPL, and was swiped from offtime.c | |
| 61 | − | |
| 62 | − | |
| 63 | − days = tod_data.tod_sec / SECS_PER_DAY; | |
| 64 | − rem = tod_data.tod_sec % SECS_PER_DAY; | |
| 65 | − | |
| 66 | − wtime->tm_hour = rem / SECS_PER_HOUR; | |
| 67 | − rem %= SECS_PER_HOUR; | |
| 68 | − wtime->tm_min = rem / 60; | |
| 69 | − wtime->tm_sec = rem % 60; | |
| 70 | − | |
| 71 | − y = 1970; | |
| 72 | − | |
| 73 | −#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) | |
| 74 | −#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) | |
| 75 | − | |
| 76 | − while (days < 0 || days >= (__isleap (y) ? 366 : 365)) | |
| 77 | − { | |
| 78 | − /* Guess a corrected year, assuming 365 days per year. */ | |
| 79 | − long int yg = y + days / 365 - (days % 365 < 0); | |
| 80 | − | |
| 81 | − /* Adjust DAYS and Y to match the guessed year. */ | |
| 82 | − days -= ((yg - y) * 365 | |
| 83 | − + LEAPS_THRU_END_OF (yg - 1) | |
| 84 | − - LEAPS_THRU_END_OF (y - 1)); | |
| 85 | − y = yg; | |
| 86 | − } | |
| 87 | − wtime->tm_year = y - 1900; | |
| 88 | − | |
| 89 | − ip = __mon_yday[__isleap(y)]; | |
| 90 | − for (y = 11; days < (long int) ip[y]; --y) | |
| 91 | − continue; | |
| 92 | − days -= ip[y]; | |
| 93 | − wtime->tm_mon = y; | |
| 94 | − wtime->tm_mday = days + 1; | |
| 95 | − | |
| 96 | − return RTC_24H; | |
| 97 | −} | |
| 98 | − | |
| 99 | −static int set_rtc_time(struct rtc_time *wtime) | |
| 100 | −{ | |
| 101 | − u_int32_t secs; | |
| 102 | − | |
| 103 | − secs = mktime(wtime->tm_year + 1900, wtime->tm_mon + 1, wtime->tm_mday, | |
| 104 | − wtime->tm_hour, wtime->tm_min, wtime->tm_sec); | |
| 105 | − | |
| 106 | − if(pdc_tod_set(secs, 0) < 0) | |
| 107 | − return -1; | |
| 108 | − else | |
| 109 | − return 0; | |
| 110 | − | |
| 111 | −} | |
| 112 | − | |
| 113 | −static inline unsigned int get_rtc_ss(void) | |
| 114 | −{ | |
| 115 | − struct rtc_time h; | |
| 116 | − | |
| 117 | − get_rtc_time(&h); | |
| 118 | − return h.tm_sec; | |
| 119 | −} | |
| 120 | − | |
| 121 | −static inline int get_rtc_pll(struct rtc_pll_info *pll) | |
| 122 | −{ | |
| 123 | − return -EINVAL; | |
| 124 | −} | |
| 125 | −static inline int set_rtc_pll(struct rtc_pll_info *pll) | |
| 126 | −{ | |
| 127 | − return -EINVAL; | |
| 128 | −} | |
| 129 | − | |
| 130 | −#endif /* __KERNEL__ */ | |
| 131 | −#endif /* __ASM_RTC_H__ */ | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | */ |
| 13 | 13 | #include <linux/errno.h> |
| 14 | 14 | #include <linux/module.h> |
| 15 | +#include <linux/rtc.h> | |
| 15 | 16 | #include <linux/sched.h> |
| 16 | 17 | #include <linux/kernel.h> |
| 17 | 18 | #include <linux/param.h> |
| @@ -248,14 +249,47 @@ void __init start_cpu_itimer(void) · 230 unmodified lines | ||
| 248 | 249 | per_cpu(cpu_data, cpu).it_value = next_tick; |
| 249 | 250 | } |
| 250 | 251 | |
| 252 | +#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC) | |
| 253 | +static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) | |
| 254 | +{ | |
| 255 | + struct pdc_tod tod_data; | |
| 256 | + | |
| 257 | + memset(tm, 0, sizeof(*tm)); | |
| 258 | + if (pdc_tod_read(&tod_data) < 0) | |
| 259 | + return -EOPNOTSUPP; | |
| 260 | + | |
| 261 | + /* we treat tod_sec as unsigned, so this can work until year 2106 */ | |
| 262 | + rtc_time64_to_tm(tod_data.tod_sec, tm); | |
| 263 | + return rtc_valid_tm(tm); | |
| 264 | +} | |
| 265 | + | |
| 266 | +static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) | |
| 267 | +{ | |
| 268 | + time64_t secs = rtc_tm_to_time64(tm); | |
| 269 | + | |
| 270 | + if (pdc_tod_set(secs, 0) < 0) | |
| 271 | + return -EOPNOTSUPP; | |
| 272 | + | |
| 273 | + return 0; | |
| 274 | +} | |
| 275 | + | |
| 276 | +static const struct rtc_class_ops rtc_generic_ops = { | |
| 277 | + .read_time = rtc_generic_get_time, | |
| 278 | + .set_time = rtc_generic_set_time, | |
| 279 | +}; | |
| 280 | + | |
| 251 | 281 | static int __init rtc_init(void) |
| 252 | 282 | { |
| 253 | 283 | struct platform_device *pdev; |
| 254 | 284 | |
| 255 | − pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | |
| 285 | + pdev = platform_device_register_data(NULL, "rtc-generic", -1, | |
| 286 | + &rtc_generic_ops, | |
| 287 | + sizeof(rtc_generic_ops)); | |
| 288 | + | |
| 256 | 289 | return PTR_ERR_OR_ZERO(pdev); |
| 257 | 290 | } |
| 258 | 291 | device_initcall(rtc_init); |
| 292 | +#endif | |
| 259 | 293 | |
| 260 | 294 | void read_persistent_clock(struct timespec *ts) |
| 261 | 295 | { |
| @@ -1,78 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Real-time clock definitions and interfaces | |
| 3 | − * | |
| 4 | − * Author: Tom Rini <trini@mvista.com> | |
| 5 | − * | |
| 6 | − * 2002 (c) MontaVista, Software, Inc. This file is licensed under | |
| 7 | − * the terms of the GNU General Public License version 2. This program | |
| 8 | − * is licensed "as is" without any warranty of any kind, whether express | |
| 9 | − * or implied. | |
| 10 | − * | |
| 11 | − * Based on: | |
| 12 | − * include/asm-m68k/rtc.h | |
| 13 | − * | |
| 14 | − * Copyright Richard Zidlicky | |
| 15 | − * implementation details for genrtc/q40rtc driver | |
| 16 | − * | |
| 17 | − * And the old drivers/macintosh/rtc.c which was heavily based on: | |
| 18 | − * Linux/SPARC Real Time Clock Driver | |
| 19 | − * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | |
| 20 | − * | |
| 21 | − * With additional work by Paul Mackerras and Franz Sirl. | |
| 22 | − */ | |
| 23 | − | |
| 24 | −#ifndef __ASM_POWERPC_RTC_H__ | |
| 25 | −#define __ASM_POWERPC_RTC_H__ | |
| 26 | − | |
| 27 | −#ifdef __KERNEL__ | |
| 28 | − | |
| 29 | −#include <linux/rtc.h> | |
| 30 | − | |
| 31 | −#include <asm/machdep.h> | |
| 32 | −#include <asm/time.h> | |
| 33 | − | |
| 34 | −#define RTC_PIE 0x40 /* periodic interrupt enable */ | |
| 35 | −#define RTC_AIE 0x20 /* alarm interrupt enable */ | |
| 36 | −#define RTC_UIE 0x10 /* update-finished interrupt enable */ | |
| 37 | − | |
| 38 | −/* some dummy definitions */ | |
| 39 | −#define RTC_BATT_BAD 0x100 /* battery bad */ | |
| 40 | −#define RTC_SQWE 0x08 /* enable square-wave output */ | |
| 41 | −#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | |
| 42 | −#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | |
| 43 | −#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | |
| 44 | − | |
| 45 | −static inline unsigned int get_rtc_time(struct rtc_time *time) | |
| 46 | −{ | |
| 47 | − if (ppc_md.get_rtc_time) | |
| 48 | − ppc_md.get_rtc_time(time); | |
| 49 | − return RTC_24H; | |
| 50 | −} | |
| 51 | − | |
| 52 | −/* Set the current date and time in the real time clock. */ | |
| 53 | −static inline int set_rtc_time(struct rtc_time *time) | |
| 54 | −{ | |
| 55 | − if (ppc_md.set_rtc_time) | |
| 56 | − return ppc_md.set_rtc_time(time); | |
| 57 | − return -EINVAL; | |
| 58 | −} | |
| 59 | − | |
| 60 | −static inline unsigned int get_rtc_ss(void) | |
| 61 | −{ | |
| 62 | − struct rtc_time h; | |
| 63 | − | |
| 64 | − get_rtc_time(&h); | |
| 65 | − return h.tm_sec; | |
| 66 | −} | |
| 67 | − | |
| 68 | −static inline int get_rtc_pll(struct rtc_pll_info *pll) | |
| 69 | −{ | |
| 70 | − return -EINVAL; | |
| 71 | −} | |
| 72 | −static inline int set_rtc_pll(struct rtc_pll_info *pll) | |
| 73 | −{ | |
| 74 | − return -EINVAL; | |
| 75 | −} | |
| 76 | − | |
| 77 | −#endif /* __KERNEL__ */ | |
| 78 | −#endif /* __ASM_POWERPC_RTC_H__ */ | |
| @@ -56,6 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #include <linux/irq_work.h> |
| 57 | 57 | #include <linux/clk-provider.h> |
| 58 | 58 | #include <linux/suspend.h> |
| 59 | +#include <linux/rtc.h> | |
| 59 | 60 | #include <asm/trace.h> |
| 60 | 61 | |
| 61 | 62 | #include <asm/io.h> |
| @@ -1159,6 +1160,29 @@ void calibrate_delay(void) · 1097 unmodified lines | ||
| 1159 | 1160 | loops_per_jiffy = tb_ticks_per_jiffy; |
| 1160 | 1161 | } |
| 1161 | 1162 | |
| 1163 | +#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC) | |
| 1164 | +static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) | |
| 1165 | +{ | |
| 1166 | + ppc_md.get_rtc_time(tm); | |
| 1167 | + return rtc_valid_tm(tm); | |
| 1168 | +} | |
| 1169 | + | |
| 1170 | +static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) | |
| 1171 | +{ | |
| 1172 | + if (!ppc_md.set_rtc_time) | |
| 1173 | + return -EOPNOTSUPP; | |
| 1174 | + | |
| 1175 | + if (ppc_md.set_rtc_time(tm) < 0) | |
| 1176 | + return -EOPNOTSUPP; | |
| 1177 | + | |
| 1178 | + return 0; | |
| 1179 | +} | |
| 1180 | + | |
| 1181 | +static const struct rtc_class_ops rtc_generic_ops = { | |
| 1182 | + .read_time = rtc_generic_get_time, | |
| 1183 | + .set_time = rtc_generic_set_time, | |
| 1184 | +}; | |
| 1185 | + | |
| 1162 | 1186 | static int __init rtc_init(void) |
| 1163 | 1187 | { |
| 1164 | 1188 | struct platform_device *pdev; |
| @@ -1166,9 +1190,12 @@ static int __init rtc_init(void) · 1 unmodified line | ||
| 1166 | 1190 | if (!ppc_md.get_rtc_time) |
| 1167 | 1191 | return -ENODEV; |
| 1168 | 1192 | |
| 1169 | − pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | |
| 1193 | + pdev = platform_device_register_data(NULL, "rtc-generic", -1, | |
| 1194 | + &rtc_generic_ops, | |
| 1195 | + sizeof(rtc_generic_ops)); | |
| 1170 | 1196 | |
| 1171 | 1197 | return PTR_ERR_OR_ZERO(pdev); |
| 1172 | 1198 | } |
| 1173 | 1199 | |
| 1174 | 1200 | device_initcall(rtc_init); |
| 1201 | +#endif | |
| @@ -321,6 +321,17 @@ config OF_RTC · 320 unmodified lines | ||
| 321 | 321 | Uses information from the OF or flattened device tree to instantiate |
| 322 | 322 | platform devices for direct mapped RTC chips like the DS1742 or DS1743. |
| 323 | 323 | |
| 324 | +config GEN_RTC | |
| 325 | + bool "Use the platform RTC operations from user space" | |
| 326 | + select RTC_CLASS | |
| 327 | + select RTC_DRV_GENERIC | |
| 328 | + help | |
| 329 | + This option provides backwards compatibility with the old gen_rtc.ko | |
| 330 | + module that was traditionally used for old PowerPC machines. | |
| 331 | + Platforms should migrate to enabling the RTC_DRV_GENERIC by hand | |
| 332 | + replacing their get_rtc_time/set_rtc_time callbacks with | |
| 333 | + a proper RTC device driver. | |
| 334 | + | |
| 324 | 335 | config SIMPLE_GPIO |
| 325 | 336 | bool "Support for simple, memory-mapped GPIO controllers" |
| 326 | 337 | depends on PPC |
| @@ -20,9 +20,9 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #include <linux/kernel.h> |
| 22 | 22 | #include <linux/platform_device.h> |
| 23 | +#include <linux/rtc.h> | |
| 23 | 24 | |
| 24 | 25 | #include <asm/firmware.h> |
| 25 | −#include <asm/rtc.h> | |
| 26 | 26 | #include <asm/lv1call.h> |
| 27 | 27 | #include <asm/ps3.h> |
| 28 | 28 | |
| @@ -1,7 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Machine dependent access functions for RTC registers. | |
| 3 | − */ | |
| 4 | −#ifndef _ASM_MC146818RTC_H | |
| 5 | −#define _ASM_MC146818RTC_H | |
| 6 | − | |
| 7 | −#endif /* _ASM_MC146818RTC_H */ | |
| @@ -6,17 +6,6 @@ extern void (*board_time_init)(void); · 5 unmodified lines | ||
| 6 | 6 | extern void (*rtc_sh_get_time)(struct timespec *); |
| 7 | 7 | extern int (*rtc_sh_set_time)(const time_t); |
| 8 | 8 | |
| 9 | −/* some dummy definitions */ | |
| 10 | −#define RTC_BATT_BAD 0x100 /* battery bad */ | |
| 11 | −#define RTC_SQWE 0x08 /* enable square-wave output */ | |
| 12 | −#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | |
| 13 | −#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | |
| 14 | −#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | |
| 15 | − | |
| 16 | −struct rtc_time; | |
| 17 | −unsigned int get_rtc_time(struct rtc_time *); | |
| 18 | −int set_rtc_time(struct rtc_time *); | |
| 19 | − | |
| 20 | 9 | #define RTC_CAP_4_DIGIT_YEAR (1 << 0) |
| 21 | 10 | |
| 22 | 11 | struct sh_rtc_platform_info { |
| @@ -50,27 +50,31 @@ int update_persistent_clock(struct timespec now) · 49 unmodified lines | ||
| 50 | 50 | } |
| 51 | 51 | #endif |
| 52 | 52 | |
| 53 | −unsigned int get_rtc_time(struct rtc_time *tm) | |
| 53 | +static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) | |
| 54 | 54 | { |
| 55 | − if (rtc_sh_get_time != null_rtc_get_time) { | |
| 56 | − struct timespec tv; | |
| 55 | + struct timespec tv; | |
| 57 | 56 | |
| 58 | − rtc_sh_get_time(&tv); | |
| 59 | − rtc_time_to_tm(tv.tv_sec, tm); | |
| 60 | − } | |
| 61 | − | |
| 62 | − return RTC_24H; | |
| 57 | + rtc_sh_get_time(&tv); | |
| 58 | + rtc_time_to_tm(tv.tv_sec, tm); | |
| 59 | + return 0; | |
| 63 | 60 | } |
| 64 | −EXPORT_SYMBOL(get_rtc_time); | |
| 65 | 61 | |
| 66 | −int set_rtc_time(struct rtc_time *tm) | |
| 62 | +static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) | |
| 67 | 63 | { |
| 68 | 64 | unsigned long secs; |
| 69 | 65 | |
| 70 | 66 | rtc_tm_to_time(tm, &secs); |
| 71 | − return rtc_sh_set_time(secs); | |
| 67 | + if ((rtc_sh_set_time == null_rtc_set_time) || | |
| 68 | + (rtc_sh_set_time(secs) < 0)) | |
| 69 | + return -EOPNOTSUPP; | |
| 70 | + | |
| 71 | + return 0; | |
| 72 | 72 | } |
| 73 | −EXPORT_SYMBOL(set_rtc_time); | |
| 73 | + | |
| 74 | +static const struct rtc_class_ops rtc_generic_ops = { | |
| 75 | + .read_time = rtc_generic_get_time, | |
| 76 | + .set_time = rtc_generic_set_time, | |
| 77 | +}; | |
| 74 | 78 | |
| 75 | 79 | static int __init rtc_generic_init(void) |
| 76 | 80 | { |
| @@ -79,7 +83,10 @@ static int __init rtc_generic_init(void) · 2 unmodified lines | ||
| 79 | 83 | if (rtc_sh_get_time == null_rtc_get_time) |
| 80 | 84 | return -ENODEV; |
| 81 | 85 | |
| 82 | − pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | |
| 86 | + pdev = platform_device_register_data(NULL, "rtc-generic", -1, | |
| 87 | + &rtc_generic_ops, | |
| 88 | + sizeof(rtc_generic_ops)); | |
| 89 | + | |
| 83 | 90 | |
| 84 | 91 | return PTR_ERR_OR_ZERO(pdev); |
| 85 | 92 | } |
| @@ -140,16 +140,6 @@ void ioport_unmap(void __iomem *); · 139 unmodified lines | ||
| 140 | 140 | struct pci_dev; |
| 141 | 141 | void pci_iounmap(struct pci_dev *dev, void __iomem *); |
| 142 | 142 | |
| 143 | − | |
| 144 | − | |
| 145 | −/* | |
| 146 | − * At the moment, we do not use CMOS_READ anywhere outside of rtc.c, | |
| 147 | − * so rtc_port is static in it. This should not change unless a new | |
| 148 | − * hardware pops up. | |
| 149 | − */ | |
| 150 | −#define RTC_PORT(x) (rtc_port + (x)) | |
| 151 | −#define RTC_ALWAYS_BCD 0 | |
| 152 | − | |
| 153 | 143 | static inline int sbus_can_dma_64bit(void) |
| 154 | 144 | { |
| 155 | 145 | return 0; /* actually, sparc_cpu_model==sun4d */ |
| @@ -152,6 +152,7 @@ config X86 · 151 unmodified lines | ||
| 152 | 152 | select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION |
| 153 | 153 | select PERF_EVENTS |
| 154 | 154 | select RTC_LIB |
| 155 | + select RTC_MC146818_LIB | |
| 155 | 156 | select SPARSE_IRQ |
| 156 | 157 | select SRCU |
| 157 | 158 | select SYSCTL_EXCEPTION_TRACE |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | #include <asm/io.h> |
| 8 | 8 | #include <asm/processor.h> |
| 9 | −#include <linux/mc146818rtc.h> | |
| 10 | 9 | |
| 11 | 10 | #ifndef RTC_PORT |
| 12 | 11 | #define RTC_PORT(x) (0x70 + (x)) |
| @@ -1 +0,0 @@ | ||
| 1 | −#include <asm-generic/rtc.h> | |
| @@ -1019,7 +1019,6 @@ void hpet_disable(void) · 1018 unmodified lines | ||
| 1019 | 1019 | */ |
| 1020 | 1020 | #include <linux/mc146818rtc.h> |
| 1021 | 1021 | #include <linux/rtc.h> |
| 1022 | −#include <asm/rtc.h> | |
| 1023 | 1022 | |
| 1024 | 1023 | #define DEFAULT_RTC_INT_FREQ 64 |
| 1025 | 1024 | #define DEFAULT_RTC_SHIFT 6 |
| @@ -1243,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) · 217 unmodified lines | ||
| 1243 | 1242 | memset(&curr_time, 0, sizeof(struct rtc_time)); |
| 1244 | 1243 | |
| 1245 | 1244 | if (hpet_rtc_flags & (RTC_UIE | RTC_AIE)) |
| 1246 | − get_rtc_time(&curr_time); | |
| 1245 | + mc146818_set_time(&curr_time); | |
| 1247 | 1246 | |
| 1248 | 1247 | if (hpet_rtc_flags & RTC_UIE && |
| 1249 | 1248 | curr_time.tm_sec != hpet_prev_update_sec) { |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/debugfs.h> |
| 18 | 18 | #include <linux/delay.h> |
| 19 | 19 | #include <linux/hardirq.h> |
| 20 | +#include <linux/ratelimit.h> | |
| 20 | 21 | #include <linux/slab.h> |
| 21 | 22 | #include <linux/export.h> |
| 22 | 23 | |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <asm/x86_init.h> |
| 14 | 14 | #include <asm/time.h> |
| 15 | 15 | #include <asm/intel-mid.h> |
| 16 | −#include <asm/rtc.h> | |
| 17 | 16 | #include <asm/setup.h> |
| 18 | 17 | |
| 19 | 18 | #ifdef CONFIG_X86_32 |
| @@ -47,7 +46,7 @@ int mach_set_rtc_mmss(const struct timespec *now) · 27 unmodified lines | ||
| 47 | 46 | |
| 48 | 47 | rtc_time_to_tm(nowtime, &tm); |
| 49 | 48 | if (!rtc_valid_tm(&tm)) { |
| 50 | − retval = set_rtc_time(&tm); | |
| 49 | + retval = mc146818_set_time(&tm); | |
| 51 | 50 | if (retval) |
| 52 | 51 | printk(KERN_ERR "%s: RTC write failed with error %d\n", |
| 53 | 52 | __func__, retval); |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | ||
| 51 | 51 | #include <asm/cacheflush.h> |
| 52 | 52 | #include <asm/tlbflush.h> |
| 53 | 53 | #include <asm/x86_init.h> |
| 54 | −#include <asm/rtc.h> | |
| 55 | 54 | #include <asm/uv/uv.h> |
| 56 | 55 | |
| 57 | 56 | static struct efi efi_phys __initdata; |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/bootmem.h> |
| 26 | 26 | #include <linux/ioport.h> |
| 27 | 27 | #include <linux/init.h> |
| 28 | +#include <linux/mc146818rtc.h> | |
| 28 | 29 | #include <linux/efi.h> |
| 29 | 30 | #include <linux/uaccess.h> |
| 30 | 31 | #include <linux/io.h> |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/init.h> |
| 23 | 23 | #include <linux/sfi.h> |
| 24 | 24 | #include <linux/platform_device.h> |
| 25 | +#include <linux/mc146818rtc.h> | |
| 25 | 26 | |
| 26 | 27 | #include <asm/intel-mid.h> |
| 27 | 28 | #include <asm/intel_mid_vrtc.h> |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/err.h> |
| 15 | 15 | #include <linux/kernel.h> |
| 16 | 16 | #include <linux/module.h> |
| 17 | −#include <asm-generic/rtc.h> | |
| 17 | +#include <linux/mc146818rtc.h> | |
| 18 | 18 | |
| 19 | 19 | #include "internal.h" |
| 20 | 20 | |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/export.h> |
| 12 | 12 | #include <linux/rtc.h> |
| 13 | 13 | |
| 14 | −#include <asm/rtc.h> | |
| 14 | +#include <linux/mc146818rtc.h> | |
| 15 | 15 | |
| 16 | 16 | #include "power.h" |
| 17 | 17 | |
| @@ -103,7 +103,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev · 85 unmodified lines | ||
| 103 | 103 | n /= 24; |
| 104 | 104 | time.tm_min = (n % 20) * 3; |
| 105 | 105 | n /= 20; |
| 106 | − set_rtc_time(&time); | |
| 106 | + mc146818_set_time(&time); | |
| 107 | 107 | return n ? -1 : 0; |
| 108 | 108 | } |
| 109 | 109 | |
| @@ -112,7 +112,7 @@ static unsigned int read_magic_time(void) · 2 unmodified lines | ||
| 112 | 112 | struct rtc_time time; |
| 113 | 113 | unsigned int val; |
| 114 | 114 | |
| 115 | − get_rtc_time(&time); | |
| 115 | + mc146818_get_time(&time); | |
| 116 | 116 | pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n", |
| 117 | 117 | time.tm_hour, time.tm_min, time.tm_sec, |
| 118 | 118 | time.tm_mon + 1, time.tm_mday, time.tm_year % 100); |
| @@ -293,7 +293,7 @@ if RTC_LIB=n · 292 unmodified lines | ||
| 293 | 293 | |
| 294 | 294 | config RTC |
| 295 | 295 | tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" |
| 296 | − depends on ALPHA || (MIPS && MACH_LOONGSON64) || MN10300 | |
| 296 | + depends on ALPHA || (MIPS && MACH_LOONGSON64) | |
| 297 | 297 | ---help--- |
| 298 | 298 | If you say Y here and create a character special file /dev/rtc with |
| 299 | 299 | major number 10 and minor number 135 using mknod ("man mknod"), you |
| @@ -339,32 +339,6 @@ config JS_RTC · 39 unmodified lines | ||
| 339 | 339 | To compile this driver as a module, choose M here: the |
| 340 | 340 | module will be called js-rtc. |
| 341 | 341 | |
| 342 | −config GEN_RTC | |
| 343 | − tristate "Generic /dev/rtc emulation" | |
| 344 | − depends on RTC!=y | |
| 345 | − depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86 | |
| 346 | − ---help--- | |
| 347 | − If you say Y here and create a character special file /dev/rtc with | |
| 348 | − major number 10 and minor number 135 using mknod ("man mknod"), you | |
| 349 | − will get access to the real time clock (or hardware clock) built | |
| 350 | − into your computer. | |
| 351 | − | |
| 352 | − It reports status information via the file /proc/driver/rtc and its | |
| 353 | − behaviour is set by various ioctls on /dev/rtc. If you enable the | |
| 354 | − "extended RTC operation" below it will also provide an emulation | |
| 355 | − for RTC_UIE which is required by some programs and may improve | |
| 356 | − precision in some cases. | |
| 357 | − | |
| 358 | − To compile this driver as a module, choose M here: the | |
| 359 | − module will be called genrtc. | |
| 360 | − | |
| 361 | −config GEN_RTC_X | |
| 362 | − bool "Extended RTC operation" | |
| 363 | − depends on GEN_RTC | |
| 364 | − help | |
| 365 | − Provides an emulation for RTC_UIE which is required by some programs | |
| 366 | − and may improve precision of the generic RTC support in some cases. | |
| 367 | − | |
| 368 | 342 | config EFI_RTC |
| 369 | 343 | bool "EFI Real Time Clock Services" |
| 370 | 344 | depends on IA64 |
| @@ -25,7 +25,6 @@ obj-$(CONFIG_APPLICOM) += applicom.o · 24 unmodified lines | ||
| 25 | 25 | obj-$(CONFIG_SONYPI) += sonypi.o |
| 26 | 26 | obj-$(CONFIG_RTC) += rtc.o |
| 27 | 27 | obj-$(CONFIG_HPET) += hpet.o |
| 28 | −obj-$(CONFIG_GEN_RTC) += genrtc.o | |
| 29 | 28 | obj-$(CONFIG_EFI_RTC) += efirtc.o |
| 30 | 29 | obj-$(CONFIG_DS1302) += ds1302.o |
| 31 | 30 | obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ |
| @@ -1,539 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Real Time Clock interface for | |
| 3 | − * - q40 and other m68k machines, | |
| 4 | − * - HP PARISC machines | |
| 5 | − * - PowerPC machines | |
| 6 | − * emulate some RTC irq capabilities in software | |
| 7 | − * | |
| 8 | − * Copyright (C) 1999 Richard Zidlicky | |
| 9 | − * | |
| 10 | − * based on Paul Gortmaker's rtc.c device and | |
| 11 | − * Sam Creasey Generic rtc driver | |
| 12 | − * | |
| 13 | − * This driver allows use of the real time clock (built into | |
| 14 | − * nearly all computers) from user space. It exports the /dev/rtc | |
| 15 | − * interface supporting various ioctl() and also the /proc/driver/rtc | |
| 16 | − * pseudo-file for status information. | |
| 17 | − * | |
| 18 | − * The ioctls can be used to set the interrupt behaviour where | |
| 19 | − * supported. | |
| 20 | − * | |
| 21 | − * The /dev/rtc interface will block on reads until an interrupt | |
| 22 | − * has been received. If a RTC interrupt has already happened, | |
| 23 | − * it will output an unsigned long and then block. The output value | |
| 24 | − * contains the interrupt status in the low byte and the number of | |
| 25 | − * interrupts since the last read in the remaining high bytes. The | |
| 26 | − * /dev/rtc interface can also be used with the select(2) call. | |
| 27 | − * | |
| 28 | − * This program is free software; you can redistribute it and/or | |
| 29 | − * modify it under the terms of the GNU General Public License | |
| 30 | − * as published by the Free Software Foundation; either version | |
| 31 | − * 2 of the License, or (at your option) any later version. | |
| 32 | − * | |
| 33 | − | |
| 34 | − * 1.01 fix for 2.3.X rz@linux-m68k.org | |
| 35 | − * 1.02 merged with code from genrtc.c rz@linux-m68k.org | |
| 36 | − * 1.03 make it more portable zippel@linux-m68k.org | |
| 37 | − * 1.04 removed useless timer code rz@linux-m68k.org | |
| 38 | − * 1.05 portable RTC_UIE emulation rz@linux-m68k.org | |
| 39 | − * 1.06 set_rtc_time can return an error trini@kernel.crashing.org | |
| 40 | − * 1.07 ported to HP PARISC (hppa) Helge Deller <deller@gmx.de> | |
| 41 | − */ | |
| 42 | − | |
| 43 | −#define RTC_VERSION "1.07" | |
| 44 | − | |
| 45 | −#include <linux/module.h> | |
| 46 | −#include <linux/sched.h> | |
| 47 | −#include <linux/errno.h> | |
| 48 | −#include <linux/miscdevice.h> | |
| 49 | −#include <linux/fcntl.h> | |
| 50 | − | |
| 51 | −#include <linux/rtc.h> | |
| 52 | −#include <linux/init.h> | |
| 53 | −#include <linux/poll.h> | |
| 54 | −#include <linux/proc_fs.h> | |
| 55 | −#include <linux/seq_file.h> | |
| 56 | −#include <linux/mutex.h> | |
| 57 | −#include <linux/workqueue.h> | |
| 58 | − | |
| 59 | −#include <asm/uaccess.h> | |
| 60 | −#include <asm/rtc.h> | |
| 61 | − | |
| 62 | −/* | |
| 63 | − * We sponge a minor off of the misc major. No need slurping | |
| 64 | − * up another valuable major dev number for this. If you add | |
| 65 | − * an ioctl, make sure you don't conflict with SPARC's RTC | |
| 66 | − * ioctls. | |
| 67 | − */ | |
| 68 | − | |
| 69 | −static DEFINE_MUTEX(gen_rtc_mutex); | |
| 70 | −static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait); | |
| 71 | − | |
| 72 | −/* | |
| 73 | − * Bits in gen_rtc_status. | |
| 74 | − */ | |
| 75 | − | |
| 76 | −#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ | |
| 77 | − | |
| 78 | −static unsigned char gen_rtc_status; /* bitmapped status byte. */ | |
| 79 | −static unsigned long gen_rtc_irq_data; /* our output to the world */ | |
| 80 | − | |
| 81 | −/* months start at 0 now */ | |
| 82 | −static unsigned char days_in_mo[] = | |
| 83 | −{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | |
| 84 | − | |
| 85 | −static int irq_active; | |
| 86 | − | |
| 87 | −#ifdef CONFIG_GEN_RTC_X | |
| 88 | −static struct work_struct genrtc_task; | |
| 89 | −static struct timer_list timer_task; | |
| 90 | − | |
| 91 | −static unsigned int oldsecs; | |
| 92 | −static int lostint; | |
| 93 | −static unsigned long tt_exp; | |
| 94 | − | |
| 95 | −static void gen_rtc_timer(unsigned long data); | |
| 96 | − | |
| 97 | −static volatile int stask_active; /* schedule_work */ | |
| 98 | −static volatile int ttask_active; /* timer_task */ | |
| 99 | −static int stop_rtc_timers; /* don't requeue tasks */ | |
| 100 | −static DEFINE_SPINLOCK(gen_rtc_lock); | |
| 101 | − | |
| 102 | −static void gen_rtc_interrupt(unsigned long arg); | |
| 103 | − | |
| 104 | −/* | |
| 105 | − * Routine to poll RTC seconds field for change as often as possible, | |
| 106 | − * after first RTC_UIE use timer to reduce polling | |
| 107 | − */ | |
| 108 | −static void genrtc_troutine(struct work_struct *work) | |
| 109 | −{ | |
| 110 | − unsigned int tmp = get_rtc_ss(); | |
| 111 | − | |
| 112 | − if (stop_rtc_timers) { | |
| 113 | − stask_active = 0; | |
| 114 | − return; | |
| 115 | − } | |
| 116 | − | |
| 117 | − if (oldsecs != tmp){ | |
| 118 | − oldsecs = tmp; | |
| 119 | − | |
| 120 | − timer_task.function = gen_rtc_timer; | |
| 121 | − timer_task.expires = jiffies + HZ - (HZ/10); | |
| 122 | − tt_exp=timer_task.expires; | |
| 123 | − ttask_active=1; | |
| 124 | − stask_active=0; | |
| 125 | − add_timer(&timer_task); | |
| 126 | − | |
| 127 | − gen_rtc_interrupt(0); | |
| 128 | − } else if (schedule_work(&genrtc_task) == 0) | |
| 129 | − stask_active = 0; | |
| 130 | −} | |
| 131 | − | |
| 132 | −static void gen_rtc_timer(unsigned long data) | |
| 133 | −{ | |
| 134 | − lostint = get_rtc_ss() - oldsecs ; | |
| 135 | − if (lostint<0) | |
| 136 | − lostint = 60 - lostint; | |
| 137 | − if (time_after(jiffies, tt_exp)) | |
| 138 | − printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n", | |
| 139 | − jiffies-tt_exp); | |
| 140 | − ttask_active=0; | |
| 141 | − stask_active=1; | |
| 142 | − if ((schedule_work(&genrtc_task) == 0)) | |
| 143 | − stask_active = 0; | |
| 144 | −} | |
| 145 | − | |
| 146 | −/* | |
| 147 | − * call gen_rtc_interrupt function to signal an RTC_UIE, | |
| 148 | − * arg is unused. | |
| 149 | − * Could be invoked either from a real interrupt handler or | |
| 150 | − * from some routine that periodically (eg 100HZ) monitors | |
| 151 | − * whether RTC_SECS changed | |
| 152 | − */ | |
| 153 | −static void gen_rtc_interrupt(unsigned long arg) | |
| 154 | −{ | |
| 155 | − /* We store the status in the low byte and the number of | |
| 156 | − * interrupts received since the last read in the remainder | |
| 157 | − * of rtc_irq_data. */ | |
| 158 | − | |
| 159 | − gen_rtc_irq_data += 0x100; | |
| 160 | − gen_rtc_irq_data &= ~0xff; | |
| 161 | − gen_rtc_irq_data |= RTC_UIE; | |
| 162 | − | |
| 163 | − if (lostint){ | |
| 164 | − printk("genrtc: system delaying clock ticks?\n"); | |
| 165 | − /* increment count so that userspace knows something is wrong */ | |
| 166 | − gen_rtc_irq_data += ((lostint-1)<<8); | |
| 167 | − lostint = 0; | |
| 168 | − } | |
| 169 | − | |
| 170 | − wake_up_interruptible(&gen_rtc_wait); | |
| 171 | −} | |
| 172 | − | |
| 173 | −/* | |
| 174 | − * Now all the various file operations that we export. | |
| 175 | − */ | |
| 176 | −static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |
| 177 | − size_t count, loff_t *ppos) | |
| 178 | −{ | |
| 179 | − unsigned long data; | |
| 180 | − ssize_t retval; | |
| 181 | − | |
| 182 | − if (count != sizeof (unsigned int) && count != sizeof (unsigned long)) | |
| 183 | − return -EINVAL; | |
| 184 | − | |
| 185 | − if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data) | |
| 186 | − return -EAGAIN; | |
| 187 | − | |
| 188 | − retval = wait_event_interruptible(gen_rtc_wait, | |
| 189 | − (data = xchg(&gen_rtc_irq_data, 0))); | |
| 190 | − if (retval) | |
| 191 | − goto out; | |
| 192 | − | |
| 193 | − /* first test allows optimizer to nuke this case for 32-bit machines */ | |
| 194 | − if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { | |
| 195 | − unsigned int uidata = data; | |
| 196 | − retval = put_user(uidata, (unsigned int __user *)buf) ?: | |
| 197 | − sizeof(unsigned int); | |
| 198 | − } | |
| 199 | − else { | |
| 200 | − retval = put_user(data, (unsigned long __user *)buf) ?: | |
| 201 | − sizeof(unsigned long); | |
| 202 | − } | |
| 203 | −out: | |
| 204 | − return retval; | |
| 205 | −} | |
| 206 | − | |
| 207 | −static unsigned int gen_rtc_poll(struct file *file, | |
| 208 | − struct poll_table_struct *wait) | |
| 209 | −{ | |
| 210 | − poll_wait(file, &gen_rtc_wait, wait); | |
| 211 | − if (gen_rtc_irq_data != 0) | |
| 212 | − return POLLIN | POLLRDNORM; | |
| 213 | − return 0; | |
| 214 | −} | |
| 215 | − | |
| 216 | −#endif | |
| 217 | − | |
| 218 | −/* | |
| 219 | − * Used to disable/enable interrupts, only RTC_UIE supported | |
| 220 | − * We also clear out any old irq data after an ioctl() that | |
| 221 | − * meddles with the interrupt enable/disable bits. | |
| 222 | − */ | |
| 223 | − | |
| 224 | −static inline void gen_clear_rtc_irq_bit(unsigned char bit) | |
| 225 | −{ | |
| 226 | −#ifdef CONFIG_GEN_RTC_X | |
| 227 | − stop_rtc_timers = 1; | |
| 228 | − if (ttask_active){ | |
| 229 | − del_timer_sync(&timer_task); | |
| 230 | − ttask_active = 0; | |
| 231 | − } | |
| 232 | − while (stask_active) | |
| 233 | − schedule(); | |
| 234 | − | |
| 235 | − spin_lock(&gen_rtc_lock); | |
| 236 | − irq_active = 0; | |
| 237 | − spin_unlock(&gen_rtc_lock); | |
| 238 | −#endif | |
| 239 | −} | |
| 240 | − | |
| 241 | −static inline int gen_set_rtc_irq_bit(unsigned char bit) | |
| 242 | −{ | |
| 243 | −#ifdef CONFIG_GEN_RTC_X | |
| 244 | − spin_lock(&gen_rtc_lock); | |
| 245 | − if ( !irq_active ) { | |
| 246 | − irq_active = 1; | |
| 247 | − stop_rtc_timers = 0; | |
| 248 | − lostint = 0; | |
| 249 | − INIT_WORK(&genrtc_task, genrtc_troutine); | |
| 250 | − oldsecs = get_rtc_ss(); | |
| 251 | − init_timer(&timer_task); | |
| 252 | − | |
| 253 | − stask_active = 1; | |
| 254 | − if (schedule_work(&genrtc_task) == 0){ | |
| 255 | − stask_active = 0; | |
| 256 | − } | |
| 257 | − } | |
| 258 | − spin_unlock(&gen_rtc_lock); | |
| 259 | − gen_rtc_irq_data = 0; | |
| 260 | − return 0; | |
| 261 | −#else | |
| 262 | − return -EINVAL; | |
| 263 | −#endif | |
| 264 | −} | |
| 265 | − | |
| 266 | −static int gen_rtc_ioctl(struct file *file, | |
| 267 | − unsigned int cmd, unsigned long arg) | |
| 268 | −{ | |
| 269 | − struct rtc_time wtime; | |
| 270 | − struct rtc_pll_info pll; | |
| 271 | − void __user *argp = (void __user *)arg; | |
| 272 | − | |
| 273 | − switch (cmd) { | |
| 274 | − | |
| 275 | − case RTC_PLL_GET: | |
| 276 | − if (get_rtc_pll(&pll)) | |
| 277 | − return -EINVAL; | |
| 278 | − else | |
| 279 | − return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0; | |
| 280 | − | |
| 281 | − case RTC_PLL_SET: | |
| 282 | − if (!capable(CAP_SYS_TIME)) | |
| 283 | − return -EACCES; | |
| 284 | − if (copy_from_user(&pll, argp, sizeof(pll))) | |
| 285 | − return -EFAULT; | |
| 286 | − return set_rtc_pll(&pll); | |
| 287 | − | |
| 288 | − case RTC_UIE_OFF: /* disable ints from RTC updates. */ | |
| 289 | − gen_clear_rtc_irq_bit(RTC_UIE); | |
| 290 | − return 0; | |
| 291 | − | |
| 292 | − case RTC_UIE_ON: /* enable ints for RTC updates. */ | |
| 293 | − return gen_set_rtc_irq_bit(RTC_UIE); | |
| 294 | − | |
| 295 | − case RTC_RD_TIME: /* Read the time/date from RTC */ | |
| 296 | − /* this doesn't get week-day, who cares */ | |
| 297 | − memset(&wtime, 0, sizeof(wtime)); | |
| 298 | − get_rtc_time(&wtime); | |
| 299 | − | |
| 300 | − return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; | |
| 301 | − | |
| 302 | − case RTC_SET_TIME: /* Set the RTC */ | |
| 303 | − { | |
| 304 | − int year; | |
| 305 | − unsigned char leap_yr; | |
| 306 | − | |
| 307 | − if (!capable(CAP_SYS_TIME)) | |
| 308 | − return -EACCES; | |
| 309 | − | |
| 310 | − if (copy_from_user(&wtime, argp, sizeof(wtime))) | |
| 311 | − return -EFAULT; | |
| 312 | − | |
| 313 | − year = wtime.tm_year + 1900; | |
| 314 | − leap_yr = ((!(year % 4) && (year % 100)) || | |
| 315 | − !(year % 400)); | |
| 316 | − | |
| 317 | − if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1)) | |
| 318 | − return -EINVAL; | |
| 319 | − | |
| 320 | − if (wtime.tm_mday < 0 || wtime.tm_mday > | |
| 321 | − (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr))) | |
| 322 | − return -EINVAL; | |
| 323 | − | |
| 324 | − if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || | |
| 325 | − wtime.tm_min < 0 || wtime.tm_min >= 60 || | |
| 326 | − wtime.tm_sec < 0 || wtime.tm_sec >= 60) | |
| 327 | − return -EINVAL; | |
| 328 | − | |
| 329 | − return set_rtc_time(&wtime); | |
| 330 | − } | |
| 331 | − } | |
| 332 | − | |
| 333 | − return -EINVAL; | |
| 334 | −} | |
| 335 | − | |
| 336 | −static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd, | |
| 337 | − unsigned long arg) | |
| 338 | −{ | |
| 339 | − int ret; | |
| 340 | − | |
| 341 | − mutex_lock(&gen_rtc_mutex); | |
| 342 | − ret = gen_rtc_ioctl(file, cmd, arg); | |
| 343 | − mutex_unlock(&gen_rtc_mutex); | |
| 344 | − | |
| 345 | − return ret; | |
| 346 | −} | |
| 347 | − | |
| 348 | −/* | |
| 349 | − * We enforce only one user at a time here with the open/close. | |
| 350 | − * Also clear the previous interrupt data on an open, and clean | |
| 351 | − * up things on a close. | |
| 352 | − */ | |
| 353 | − | |
| 354 | −static int gen_rtc_open(struct inode *inode, struct file *file) | |
| 355 | −{ | |
| 356 | − mutex_lock(&gen_rtc_mutex); | |
| 357 | − if (gen_rtc_status & RTC_IS_OPEN) { | |
| 358 | − mutex_unlock(&gen_rtc_mutex); | |
| 359 | − return -EBUSY; | |
| 360 | − } | |
| 361 | − | |
| 362 | − gen_rtc_status |= RTC_IS_OPEN; | |
| 363 | − gen_rtc_irq_data = 0; | |
| 364 | − irq_active = 0; | |
| 365 | − mutex_unlock(&gen_rtc_mutex); | |
| 366 | − | |
| 367 | − return 0; | |
| 368 | −} | |
| 369 | − | |
| 370 | −static int gen_rtc_release(struct inode *inode, struct file *file) | |
| 371 | −{ | |
| 372 | − /* | |
| 373 | − * Turn off all interrupts once the device is no longer | |
| 374 | − * in use and clear the data. | |
| 375 | − */ | |
| 376 | − | |
| 377 | − gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE); | |
| 378 | − | |
| 379 | − gen_rtc_status &= ~RTC_IS_OPEN; | |
| 380 | − return 0; | |
| 381 | −} | |
| 382 | − | |
| 383 | − | |
| 384 | −#ifdef CONFIG_PROC_FS | |
| 385 | − | |
| 386 | −/* | |
| 387 | − * Info exported via "/proc/driver/rtc". | |
| 388 | − */ | |
| 389 | − | |
| 390 | −static int gen_rtc_proc_show(struct seq_file *m, void *v) | |
| 391 | −{ | |
| 392 | − struct rtc_time tm; | |
| 393 | − unsigned int flags; | |
| 394 | − struct rtc_pll_info pll; | |
| 395 | − | |
| 396 | − flags = get_rtc_time(&tm); | |
| 397 | − | |
| 398 | − seq_printf(m, | |
| 399 | − "rtc_time\t: %02d:%02d:%02d\n" | |
| 400 | − "rtc_date\t: %04d-%02d-%02d\n" | |
| 401 | − "rtc_epoch\t: %04u\n", | |
| 402 | − tm.tm_hour, tm.tm_min, tm.tm_sec, | |
| 403 | − tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900); | |
| 404 | − | |
| 405 | − tm.tm_hour = tm.tm_min = tm.tm_sec = 0; | |
| 406 | − | |
| 407 | − seq_puts(m, "alarm\t\t: "); | |
| 408 | − if (tm.tm_hour <= 24) | |
| 409 | − seq_printf(m, "%02d:", tm.tm_hour); | |
| 410 | − else | |
| 411 | − seq_puts(m, "**:"); | |
| 412 | − | |
| 413 | − if (tm.tm_min <= 59) | |
| 414 | − seq_printf(m, "%02d:", tm.tm_min); | |
| 415 | − else | |
| 416 | − seq_puts(m, "**:"); | |
| 417 | − | |
| 418 | − if (tm.tm_sec <= 59) | |
| 419 | − seq_printf(m, "%02d\n", tm.tm_sec); | |
| 420 | − else | |
| 421 | − seq_puts(m, "**\n"); | |
| 422 | − | |
| 423 | − seq_printf(m, | |
| 424 | − "DST_enable\t: %s\n" | |
| 425 | − "BCD\t\t: %s\n" | |
| 426 | − "24hr\t\t: %s\n" | |
| 427 | − "square_wave\t: %s\n" | |
| 428 | − "alarm_IRQ\t: %s\n" | |
| 429 | − "update_IRQ\t: %s\n" | |
| 430 | − "periodic_IRQ\t: %s\n" | |
| 431 | − "periodic_freq\t: %ld\n" | |
| 432 | − "batt_status\t: %s\n", | |
| 433 | − (flags & RTC_DST_EN) ? "yes" : "no", | |
| 434 | − (flags & RTC_DM_BINARY) ? "no" : "yes", | |
| 435 | − (flags & RTC_24H) ? "yes" : "no", | |
| 436 | − (flags & RTC_SQWE) ? "yes" : "no", | |
| 437 | − (flags & RTC_AIE) ? "yes" : "no", | |
| 438 | − irq_active ? "yes" : "no", | |
| 439 | − (flags & RTC_PIE) ? "yes" : "no", | |
| 440 | − 0L /* freq */, | |
| 441 | − (flags & RTC_BATT_BAD) ? "bad" : "okay"); | |
| 442 | − if (!get_rtc_pll(&pll)) | |
| 443 | − seq_printf(m, | |
| 444 | − "PLL adjustment\t: %d\n" | |
| 445 | − "PLL max +ve adjustment\t: %d\n" | |
| 446 | − "PLL max -ve adjustment\t: %d\n" | |
| 447 | − "PLL +ve adjustment factor\t: %d\n" | |
| 448 | − "PLL -ve adjustment factor\t: %d\n" | |
| 449 | − "PLL frequency\t: %ld\n", | |
| 450 | − pll.pll_value, | |
| 451 | − pll.pll_max, | |
| 452 | − pll.pll_min, | |
| 453 | − pll.pll_posmult, | |
| 454 | − pll.pll_negmult, | |
| 455 | − pll.pll_clock); | |
| 456 | − return 0; | |
| 457 | −} | |
| 458 | − | |
| 459 | −static int gen_rtc_proc_open(struct inode *inode, struct file *file) | |
| 460 | −{ | |
| 461 | − return single_open(file, gen_rtc_proc_show, NULL); | |
| 462 | −} | |
| 463 | − | |
| 464 | −static const struct file_operations gen_rtc_proc_fops = { | |
| 465 | − .open = gen_rtc_proc_open, | |
| 466 | − .read = seq_read, | |
| 467 | − .llseek = seq_lseek, | |
| 468 | − .release = single_release, | |
| 469 | −}; | |
| 470 | − | |
| 471 | −static int __init gen_rtc_proc_init(void) | |
| 472 | −{ | |
| 473 | − struct proc_dir_entry *r; | |
| 474 | − | |
| 475 | − r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops); | |
| 476 | − if (!r) | |
| 477 | − return -ENOMEM; | |
| 478 | − return 0; | |
| 479 | −} | |
| 480 | −#else | |
| 481 | −static inline int gen_rtc_proc_init(void) { return 0; } | |
| 482 | −#endif /* CONFIG_PROC_FS */ | |
| 483 | − | |
| 484 | − | |
| 485 | −/* | |
| 486 | − * The various file operations we support. | |
| 487 | − */ | |
| 488 | − | |
| 489 | −static const struct file_operations gen_rtc_fops = { | |
| 490 | − .owner = THIS_MODULE, | |
| 491 | −#ifdef CONFIG_GEN_RTC_X | |
| 492 | − .read = gen_rtc_read, | |
| 493 | − .poll = gen_rtc_poll, | |
| 494 | −#endif | |
| 495 | − .unlocked_ioctl = gen_rtc_unlocked_ioctl, | |
| 496 | − .open = gen_rtc_open, | |
| 497 | − .release = gen_rtc_release, | |
| 498 | − .llseek = noop_llseek, | |
| 499 | −}; | |
| 500 | − | |
| 501 | −static struct miscdevice rtc_gen_dev = | |
| 502 | −{ | |
| 503 | − .minor = RTC_MINOR, | |
| 504 | − .name = "rtc", | |
| 505 | − .fops = &gen_rtc_fops, | |
| 506 | −}; | |
| 507 | − | |
| 508 | −static int __init rtc_generic_init(void) | |
| 509 | −{ | |
| 510 | − int retval; | |
| 511 | − | |
| 512 | − printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION); | |
| 513 | − | |
| 514 | − retval = misc_register(&rtc_gen_dev); | |
| 515 | − if (retval < 0) | |
| 516 | − return retval; | |
| 517 | − | |
| 518 | − retval = gen_rtc_proc_init(); | |
| 519 | − if (retval) { | |
| 520 | − misc_deregister(&rtc_gen_dev); | |
| 521 | − return retval; | |
| 522 | − } | |
| 523 | − | |
| 524 | − return 0; | |
| 525 | −} | |
| 526 | − | |
| 527 | −static void __exit rtc_generic_exit(void) | |
| 528 | −{ | |
| 529 | − remove_proc_entry ("driver/rtc", NULL); | |
| 530 | − misc_deregister(&rtc_gen_dev); | |
| 531 | −} | |
| 532 | − | |
| 533 | − | |
| 534 | −module_init(rtc_generic_init); | |
| 535 | −module_exit(rtc_generic_exit); | |
| 536 | − | |
| 537 | −MODULE_AUTHOR("Richard Zidlicky"); | |
| 538 | −MODULE_LICENSE("GPL"); | |
| 539 | −MODULE_ALIAS_MISCDEV(RTC_MINOR); | |
| @@ -5,6 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | config RTC_LIB |
| 6 | 6 | bool |
| 7 | 7 | |
| 8 | +config RTC_MC146818_LIB | |
| 9 | + bool | |
| 10 | + select RTC_LIB | |
| 11 | + | |
| 8 | 12 | menuconfig RTC_CLASS |
| 9 | 13 | bool "Real Time Clock" |
| 10 | 14 | default n |
| @@ -574,10 +578,10 @@ config RTC_DRV_EM3027 · 563 unmodified lines | ||
| 574 | 578 | will be called rtc-em3027. |
| 575 | 579 | |
| 576 | 580 | config RTC_DRV_RV8803 |
| 577 | − tristate "Micro Crystal RV8803" | |
| 581 | + tristate "Micro Crystal RV8803, Epson RX8900" | |
| 578 | 582 | help |
| 579 | − If you say yes here you get support for the Micro Crystal | |
| 580 | − RV8803 RTC chips. | |
| 583 | + If you say yes here you get support for the Micro Crystal RV8803 and | |
| 584 | + Epson RX8900 RTC chips. | |
| 581 | 585 | |
| 582 | 586 | This driver can also be built as a module. If so, the module |
| 583 | 587 | will be called rtc-rv8803. |
| @@ -670,6 +674,18 @@ config RTC_DRV_DS1390 · 86 unmodified lines | ||
| 670 | 674 | This driver can also be built as a module. If so, the module |
| 671 | 675 | will be called rtc-ds1390. |
| 672 | 676 | |
| 677 | +config RTC_DRV_MAX6916 | |
| 678 | + tristate "Maxim MAX6916" | |
| 679 | + help | |
| 680 | + If you say yes here you will get support for the | |
| 681 | + Maxim MAX6916 SPI RTC chip. | |
| 682 | + | |
| 683 | + This driver only supports the RTC feature, and not other chip | |
| 684 | + features such as alarms. | |
| 685 | + | |
| 686 | + This driver can also be built as a module. If so, the module | |
| 687 | + will be called rtc-max6916. | |
| 688 | + | |
| 673 | 689 | config RTC_DRV_R9701 |
| 674 | 690 | tristate "Epson RTC-9701JE" |
| 675 | 691 | help |
| @@ -795,8 +811,9 @@ comment "Platform RTC drivers" · 119 unmodified lines | ||
| 795 | 811 | |
| 796 | 812 | config RTC_DRV_CMOS |
| 797 | 813 | tristate "PC-style 'CMOS'" |
| 798 | − depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 | |
| 814 | + depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 | |
| 799 | 815 | default y if X86 |
| 816 | + select RTC_MC146818_LIB | |
| 800 | 817 | help |
| 801 | 818 | Say "yes" here to get direct support for the real time clock |
| 802 | 819 | found in every PC or ACPI-based system, and some other boards. |
| @@ -815,6 +832,7 @@ config RTC_DRV_CMOS · 12 unmodified lines | ||
| 815 | 832 | config RTC_DRV_ALPHA |
| 816 | 833 | bool "Alpha PC-style CMOS" |
| 817 | 834 | depends on ALPHA |
| 835 | + select RTC_MC146818_LIB | |
| 818 | 836 | default y |
| 819 | 837 | help |
| 820 | 838 | Direct support for the real-time clock found on every Alpha |
| @@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o · 7 unmodified lines | ||
| 8 | 8 | obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o |
| 9 | 9 | obj-$(CONFIG_RTC_SYSTOHC) += systohc.o |
| 10 | 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
| 11 | +obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o | |
| 11 | 12 | rtc-core-y := class.o interface.o |
| 12 | 13 | |
| 13 | 14 | ifdef CONFIG_RTC_DRV_EFI |
| @@ -85,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o · 71 unmodified lines | ||
| 85 | 86 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 86 | 87 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
| 87 | 88 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 89 | +obj-$(CONFIG_RTC_DRV_MAX6916) += rtc-max6916.o | |
| 88 | 90 | obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o |
| 89 | 91 | obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o |
| 90 | 92 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
| @@ -104,7 +104,17 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al · 103 unmodified lines | ||
| 104 | 104 | else if (!rtc->ops->read_alarm) |
| 105 | 105 | err = -EINVAL; |
| 106 | 106 | else { |
| 107 | − memset(alarm, 0, sizeof(struct rtc_wkalrm)); | |
| 107 | + alarm->enabled = 0; | |
| 108 | + alarm->pending = 0; | |
| 109 | + alarm->time.tm_sec = -1; | |
| 110 | + alarm->time.tm_min = -1; | |
| 111 | + alarm->time.tm_hour = -1; | |
| 112 | + alarm->time.tm_mday = -1; | |
| 113 | + alarm->time.tm_mon = -1; | |
| 114 | + alarm->time.tm_year = -1; | |
| 115 | + alarm->time.tm_wday = -1; | |
| 116 | + alarm->time.tm_yday = -1; | |
| 117 | + alarm->time.tm_isdst = -1; | |
| 108 | 118 | err = rtc->ops->read_alarm(rtc->dev.parent, alarm); |
| 109 | 119 | } |
| 110 | 120 | |
| @@ -383,7 +393,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) · 272 unmodified lines | ||
| 383 | 393 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
| 384 | 394 | rtc->aie_timer.period = ktime_set(0, 0); |
| 385 | 395 | |
| 386 | − /* Alarm has to be enabled & in the futrure for us to enqueue it */ | |
| 396 | + /* Alarm has to be enabled & in the future for us to enqueue it */ | |
| 387 | 397 | if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 < |
| 388 | 398 | rtc->aie_timer.node.expires.tv64)) { |
| 389 | 399 | |
| @@ -395,8 +405,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) · 5 unmodified lines | ||
| 395 | 405 | } |
| 396 | 406 | EXPORT_SYMBOL_GPL(rtc_initialize_alarm); |
| 397 | 407 | |
| 398 | − | |
| 399 | − | |
| 400 | 408 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) |
| 401 | 409 | { |
| 402 | 410 | int err = mutex_lock_interruptible(&rtc->ops_lock); |
| @@ -748,9 +756,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); · 345 unmodified lines | ||
| 748 | 756 | */ |
| 749 | 757 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) |
| 750 | 758 | { |
| 759 | + struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | |
| 760 | + struct rtc_time tm; | |
| 761 | + ktime_t now; | |
| 762 | + | |
| 751 | 763 | timer->enabled = 1; |
| 764 | + __rtc_read_time(rtc, &tm); | |
| 765 | + now = rtc_tm_to_ktime(tm); | |
| 766 | + | |
| 767 | + /* Skip over expired timers */ | |
| 768 | + while (next) { | |
| 769 | + if (next->expires.tv64 >= now.tv64) | |
| 770 | + break; | |
| 771 | + next = timerqueue_iterate_next(next); | |
| 772 | + } | |
| 773 | + | |
| 752 | 774 | timerqueue_add(&rtc->timerqueue, &timer->node); |
| 753 | − if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { | |
| 775 | + if (!next) { | |
| 754 | 776 | struct rtc_wkalrm alarm; |
| 755 | 777 | int err; |
| 756 | 778 | alarm.time = rtc_ktime_to_tm(timer->node.expires); |
| @@ -643,17 +643,15 @@ static int abx80x_probe(struct i2c_client *client, · 642 unmodified lines | ||
| 643 | 643 | return err; |
| 644 | 644 | } |
| 645 | 645 | |
| 646 | − err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group, | |
| 647 | − &client->dev); | |
| 648 | − if (err) { | |
| 649 | − rtc_calib_remove_sysfs_group(&client->dev); | |
| 646 | + err = devm_add_action_or_reset(&client->dev, | |
| 647 | + rtc_calib_remove_sysfs_group, | |
| 648 | + &client->dev); | |
| 649 | + if (err) | |
| 650 | 650 | dev_err(&client->dev, |
| 651 | 651 | "Failed to add sysfs cleanup action: %d\n", |
| 652 | 652 | err); |
| 653 | − return err; | |
| 654 | − } | |
| 655 | 653 | |
| 656 | − return 0; | |
| 654 | + return err; | |
| 657 | 655 | } |
| 658 | 656 | |
| 659 | 657 | static int abx80x_remove(struct i2c_client *client) |
| @@ -343,7 +343,6 @@ static struct platform_driver asm9260_rtc_driver = { · 342 unmodified lines | ||
| 343 | 343 | .remove = asm9260_rtc_remove, |
| 344 | 344 | .driver = { |
| 345 | 345 | .name = "asm9260-rtc", |
| 346 | − .owner = THIS_MODULE, | |
| 347 | 346 | .of_match_table = asm9260_dt_ids, |
| 348 | 347 | }, |
| 349 | 348 | }; |
| @@ -375,6 +375,7 @@ static int at91_rtc_probe(struct platform_device *pdev) · 374 unmodified lines | ||
| 375 | 375 | if (!rtc) |
| 376 | 376 | return -ENOMEM; |
| 377 | 377 | |
| 378 | + spin_lock_init(&rtc->lock); | |
| 378 | 379 | rtc->irq = irq; |
| 379 | 380 | |
| 380 | 381 | /* platform setup code should have handled this; sigh */ |
| @@ -43,7 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/of_platform.h> |
| 44 | 44 | |
| 45 | 45 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
| 46 | −#include <asm-generic/rtc.h> | |
| 46 | +#include <linux/mc146818rtc.h> | |
| 47 | 47 | |
| 48 | 48 | struct cmos_rtc { |
| 49 | 49 | struct rtc_device *rtc; |
| @@ -190,10 +190,10 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr) · 140 unmodified lines | ||
| 190 | 190 | static int cmos_read_time(struct device *dev, struct rtc_time *t) |
| 191 | 191 | { |
| 192 | 192 | /* REVISIT: if the clock has a "century" register, use |
| 193 | − * that instead of the heuristic in get_rtc_time(). | |
| 193 | + * that instead of the heuristic in mc146818_get_time(). | |
| 194 | 194 | * That'll make Y3K compatility (year > 2070) easy! |
| 195 | 195 | */ |
| 196 | − get_rtc_time(t); | |
| 196 | + mc146818_get_time(t); | |
| 197 | 197 | return 0; |
| 198 | 198 | } |
| 199 | 199 | |
| @@ -205,7 +205,7 @@ static int cmos_set_time(struct device *dev, struct rtc_time *t) · 5 unmodified lines | ||
| 205 | 205 | * takes effect exactly 500ms after we write the register. |
| 206 | 206 | * (Also queueing and other delays before we get this far.) |
| 207 | 207 | */ |
| 208 | − return set_rtc_time(t); | |
| 208 | + return mc146818_set_time(t); | |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | 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) · 8 unmodified lines | ||
| 220 | 220 | * Some also support day and month, for alarms up to a year in |
| 221 | 221 | * the future. |
| 222 | 222 | */ |
| 223 | − t->time.tm_mday = -1; | |
| 224 | − t->time.tm_mon = -1; | |
| 225 | 223 | |
| 226 | 224 | spin_lock_irq(&rtc_lock); |
| 227 | 225 | 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) · 44 unmodified lines | ||
| 272 | 270 | } |
| 273 | 271 | } |
| 274 | 272 | } |
| 275 | − t->time.tm_year = -1; | |
| 276 | 273 | |
| 277 | 274 | t->enabled = !!(rtc_control & RTC_AIE); |
| 278 | 275 | t->pending = 0; |
| @@ -630,7 +627,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) · 351 unmodified lines | ||
| 630 | 627 | address_space = 64; |
| 631 | 628 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
| 632 | 629 | || defined(__sparc__) || defined(__mips__) \ |
| 633 | − || defined(__powerpc__) | |
| 630 | + || defined(__powerpc__) || defined(CONFIG_MN10300) | |
| 634 | 631 | address_space = 128; |
| 635 | 632 | #else |
| 636 | 633 | #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) · 505 unmodified lines | ||
| 1142 | 1139 | if (val) |
| 1143 | 1140 | CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); |
| 1144 | 1141 | |
| 1145 | − get_rtc_time(&time); | |
| 1142 | + cmos_read_time(&pdev->dev, &time); | |
| 1146 | 1143 | ret = rtc_valid_tm(&time); |
| 1147 | 1144 | if (ret) { |
| 1148 | 1145 | struct rtc_time def_time = { |
| 1149 | 1146 | .tm_year = 1, |
| 1150 | 1147 | .tm_mday = 1, |
| 1151 | 1148 | }; |
| 1152 | − set_rtc_time(&def_time); | |
| 1149 | + cmos_set_time(&pdev->dev, &def_time); | |
| 1153 | 1150 | } |
| 1154 | 1151 | } |
| 1155 | 1152 | #else |
| @@ -85,6 +85,7 @@ static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) · 84 unmodified lines | ||
| 85 | 85 | rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY; |
| 86 | 86 | rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR; |
| 87 | 87 | rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN; |
| 88 | + rtc_tm->tm_sec = 0; | |
| 88 | 89 | |
| 89 | 90 | ret = rtc_valid_tm(rtc_tm); |
| 90 | 91 | return ret; |
| @@ -74,6 +74,7 @@ static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) · 73 unmodified lines | ||
| 74 | 74 | rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY; |
| 75 | 75 | rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR; |
| 76 | 76 | rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN; |
| 77 | + rtc_tm->tm_sec = 0; | |
| 77 | 78 | |
| 78 | 79 | return rtc_valid_tm(rtc_tm); |
| 79 | 80 | } |
| @@ -388,6 +388,8 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) · 387 unmodified lines | ||
| 388 | 388 | u8 day0, day1; |
| 389 | 389 | unsigned long flags; |
| 390 | 390 | |
| 391 | + alm->time.tm_sec = 0; | |
| 392 | + | |
| 391 | 393 | spin_lock_irqsave(&davinci_rtc_lock, flags); |
| 392 | 394 | |
| 393 | 395 | davinci_rtcss_calendar_wait(davinci_rtc); |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/rtc.h> |
| 17 | 17 | #include <linux/platform_device.h> |
| 18 | 18 | #include <linux/bcd.h> |
| 19 | −#include <linux/ds1286.h> | |
| 19 | +#include <linux/rtc/ds1286.h> | |
| 20 | 20 | #include <linux/io.h> |
| 21 | 21 | #include <linux/slab.h> |
| 22 | 22 | |
| @@ -313,13 +313,6 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm) · 312 unmodified lines | ||
| 313 | 313 | alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]); |
| 314 | 314 | alm->time.tm_min = bcd2bin(buf[DS1305_MIN]); |
| 315 | 315 | alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]); |
| 316 | − alm->time.tm_mday = -1; | |
| 317 | − alm->time.tm_mon = -1; | |
| 318 | − alm->time.tm_year = -1; | |
| 319 | − /* next three fields are unused by Linux */ | |
| 320 | − alm->time.tm_wday = -1; | |
| 321 | − alm->time.tm_mday = -1; | |
| 322 | − alm->time.tm_isdst = -1; | |
| 323 | 316 | |
| 324 | 317 | return 0; |
| 325 | 318 | } |
| @@ -482,11 +482,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) · 481 unmodified lines | ||
| 482 | 482 | t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); |
| 483 | 483 | t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); |
| 484 | 484 | t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); |
| 485 | − t->time.tm_mon = -1; | |
| 486 | − t->time.tm_year = -1; | |
| 487 | − t->time.tm_wday = -1; | |
| 488 | − t->time.tm_yday = -1; | |
| 489 | − t->time.tm_isdst = -1; | |
| 490 | 485 | |
| 491 | 486 | /* ... and status */ |
| 492 | 487 | t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); |
| @@ -602,6 +597,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { · 109 unmodified lines | ||
| 602 | 597 | * Alarm support for mcp794xx devices. |
| 603 | 598 | */ |
| 604 | 599 | |
| 600 | +#define MCP794XX_REG_WEEKDAY 0x3 | |
| 601 | +#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7 | |
| 605 | 602 | #define MCP794XX_REG_CONTROL 0x07 |
| 606 | 603 | # define MCP794XX_BIT_ALM0_EN 0x10 |
| 607 | 604 | # define MCP794XX_BIT_ALM1_EN 0x20 |
| @@ -1231,13 +1228,16 @@ static int ds1307_probe(struct i2c_client *client, · 623 unmodified lines | ||
| 1231 | 1228 | { |
| 1232 | 1229 | struct ds1307 *ds1307; |
| 1233 | 1230 | int err = -ENODEV; |
| 1234 | − int tmp; | |
| 1231 | + int tmp, wday; | |
| 1235 | 1232 | struct chip_desc *chip = &chips[id->driver_data]; |
| 1236 | 1233 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
| 1237 | 1234 | bool want_irq = false; |
| 1238 | 1235 | bool ds1307_can_wakeup_device = false; |
| 1239 | 1236 | unsigned char *buf; |
| 1240 | 1237 | struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); |
| 1238 | + struct rtc_time tm; | |
| 1239 | + unsigned long timestamp; | |
| 1240 | + | |
| 1241 | 1241 | irq_handler_t irq_handler = ds1307_irq; |
| 1242 | 1242 | |
| 1243 | 1243 | static const int bbsqi_bitpos[] = { |
| @@ -1526,6 +1526,27 @@ read_rtc: · 282 unmodified lines | ||
| 1526 | 1526 | bin2bcd(tmp)); |
| 1527 | 1527 | } |
| 1528 | 1528 | |
| 1529 | + /* | |
| 1530 | + * Some IPs have weekday reset value = 0x1 which might not correct | |
| 1531 | + * hence compute the wday using the current date/month/year values | |
| 1532 | + */ | |
| 1533 | + ds1307_get_time(&client->dev, &tm); | |
| 1534 | + wday = tm.tm_wday; | |
| 1535 | + timestamp = rtc_tm_to_time64(&tm); | |
| 1536 | + rtc_time64_to_tm(timestamp, &tm); | |
| 1537 | + | |
| 1538 | + /* | |
| 1539 | + * Check if reset wday is different from the computed wday | |
| 1540 | + * If different then set the wday which we computed using | |
| 1541 | + * timestamp | |
| 1542 | + */ | |
| 1543 | + if (wday != tm.tm_wday) { | |
| 1544 | + wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY); | |
| 1545 | + wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK; | |
| 1546 | + wday = wday | (tm.tm_wday + 1); | |
| 1547 | + i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday); | |
| 1548 | + } | |
| 1549 | + | |
| 1529 | 1550 | if (want_irq) { |
| 1530 | 1551 | device_set_wakeup_capable(&client->dev, true); |
| 1531 | 1552 | set_bit(HAS_ALARM, &ds1307->flags); |
| @@ -504,12 +504,6 @@ static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) · 503 unmodified lines | ||
| 504 | 504 | alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour; |
| 505 | 505 | alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday; |
| 506 | 506 | |
| 507 | − alarm->time.tm_mon = -1; | |
| 508 | − alarm->time.tm_year = -1; | |
| 509 | − alarm->time.tm_wday = -1; | |
| 510 | − alarm->time.tm_yday = -1; | |
| 511 | − alarm->time.tm_isdst = -1; | |
| 512 | − | |
| 513 | 507 | out: |
| 514 | 508 | mutex_unlock(&priv->mutex); |
| 515 | 509 | return res; |
| @@ -102,6 +102,26 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask) · 101 unmodified lines | ||
| 102 | 102 | return (val & bin_mask); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | +/** | |
| 106 | + * s1685_rtc_check_mday - check validity of the day of month. | |
| 107 | + * @rtc: pointer to the ds1685 rtc structure. | |
| 108 | + * @mday: day of month. | |
| 109 | + * | |
| 110 | + * Returns -EDOM if the day of month is not within 1..31 range. | |
| 111 | + */ | |
| 112 | +static inline int | |
| 113 | +ds1685_rtc_check_mday(struct ds1685_priv *rtc, u8 mday) | |
| 114 | +{ | |
| 115 | + if (rtc->bcd_mode) { | |
| 116 | + if (mday < 0x01 || mday > 0x31 || (mday & 0x0f) > 0x09) | |
| 117 | + return -EDOM; | |
| 118 | + } else { | |
| 119 | + if (mday < 1 || mday > 31) | |
| 120 | + return -EDOM; | |
| 121 | + } | |
| 122 | + return 0; | |
| 123 | +} | |
| 124 | + | |
| 105 | 125 | /** |
| 106 | 126 | * ds1685_rtc_switch_to_bank0 - switch the rtc to bank 0. |
| 107 | 127 | * @rtc: pointer to the ds1685 rtc structure. |
| @@ -377,6 +397,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 269 unmodified lines | ||
| 377 | 397 | struct platform_device *pdev = to_platform_device(dev); |
| 378 | 398 | struct ds1685_priv *rtc = platform_get_drvdata(pdev); |
| 379 | 399 | u8 seconds, minutes, hours, mday, ctrlb, ctrlc; |
| 400 | + int ret; | |
| 380 | 401 | |
| 381 | 402 | /* Fetch the alarm info from the RTC alarm registers. */ |
| 382 | 403 | ds1685_rtc_begin_data_access(rtc); |
| @@ -388,34 +409,29 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 5 unmodified lines | ||
| 388 | 409 | ctrlc = rtc->read(rtc, RTC_CTRL_C); |
| 389 | 410 | ds1685_rtc_end_data_access(rtc); |
| 390 | 411 | |
| 391 | − /* Check month date. */ | |
| 392 | − if (!(mday >= 1) && (mday <= 31)) | |
| 393 | − return -EDOM; | |
| 412 | + /* Check the month date for validity. */ | |
| 413 | + ret = ds1685_rtc_check_mday(rtc, mday); | |
| 414 | + if (ret) | |
| 415 | + return ret; | |
| 394 | 416 | |
| 395 | 417 | /* |
| 396 | 418 | * Check the three alarm bytes. |
| 397 | 419 | * |
| 398 | 420 | * The Linux RTC system doesn't support the "don't care" capability |
| 399 | 421 | * of this RTC chip. We check for it anyways in case support is |
| 400 | − * added in the future. | |
| 422 | + * added in the future and only assign when we care. | |
| 401 | 423 | */ |
| 402 | − if (unlikely(seconds >= 0xc0)) | |
| 403 | − alrm->time.tm_sec = -1; | |
| 404 | − else | |
| 424 | + if (likely(seconds < 0xc0)) | |
| 405 | 425 | alrm->time.tm_sec = ds1685_rtc_bcd2bin(rtc, seconds, |
| 406 | 426 | RTC_SECS_BCD_MASK, |
| 407 | 427 | RTC_SECS_BIN_MASK); |
| 408 | 428 | |
| 409 | − if (unlikely(minutes >= 0xc0)) | |
| 410 | − alrm->time.tm_min = -1; | |
| 411 | − else | |
| 429 | + if (likely(minutes < 0xc0)) | |
| 412 | 430 | alrm->time.tm_min = ds1685_rtc_bcd2bin(rtc, minutes, |
| 413 | 431 | RTC_MINS_BCD_MASK, |
| 414 | 432 | RTC_MINS_BIN_MASK); |
| 415 | 433 | |
| 416 | − if (unlikely(hours >= 0xc0)) | |
| 417 | − alrm->time.tm_hour = -1; | |
| 418 | − else | |
| 434 | + if (likely(hours < 0xc0)) | |
| 419 | 435 | alrm->time.tm_hour = ds1685_rtc_bcd2bin(rtc, hours, |
| 420 | 436 | RTC_HRS_24_BCD_MASK, |
| 421 | 437 | RTC_HRS_24_BIN_MASK); |
| @@ -423,11 +439,6 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 1 unmodified line | ||
| 423 | 439 | /* Write the data to rtc_wkalrm. */ |
| 424 | 440 | alrm->time.tm_mday = ds1685_rtc_bcd2bin(rtc, mday, RTC_MDAY_BCD_MASK, |
| 425 | 441 | RTC_MDAY_BIN_MASK); |
| 426 | − alrm->time.tm_mon = -1; | |
| 427 | − alrm->time.tm_year = -1; | |
| 428 | − alrm->time.tm_wday = -1; | |
| 429 | − alrm->time.tm_yday = -1; | |
| 430 | − alrm->time.tm_isdst = -1; | |
| 431 | 442 | alrm->enabled = !!(ctrlb & RTC_CTRL_B_AIE); |
| 432 | 443 | alrm->pending = !!(ctrlc & RTC_CTRL_C_AF); |
| 433 | 444 | |
| @@ -445,6 +456,7 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 11 unmodified lines | ||
| 445 | 456 | struct platform_device *pdev = to_platform_device(dev); |
| 446 | 457 | struct ds1685_priv *rtc = platform_get_drvdata(pdev); |
| 447 | 458 | u8 ctrlb, seconds, minutes, hours, mday; |
| 459 | + int ret; | |
| 448 | 460 | |
| 449 | 461 | /* Fetch the alarm info and convert to BCD. */ |
| 450 | 462 | seconds = ds1685_rtc_bin2bcd(rtc, alrm->time.tm_sec, |
| @@ -461,8 +473,9 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 10 unmodified lines | ||
| 461 | 473 | RTC_MDAY_BCD_MASK); |
| 462 | 474 | |
| 463 | 475 | /* Check the month date for validity. */ |
| 464 | − if (!(mday >= 1) && (mday <= 31)) | |
| 465 | − return -EDOM; | |
| 476 | + ret = ds1685_rtc_check_mday(rtc, mday); | |
| 477 | + if (ret) | |
| 478 | + return ret; | |
| 466 | 479 | |
| 467 | 480 | /* |
| 468 | 481 | * Check the three alarm bytes. |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/rtc.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | 15 | #include <linux/bcd.h> |
| 16 | −#include <linux/rtc-ds2404.h> | |
| 16 | +#include <linux/platform_data/rtc-ds2404.h> | |
| 17 | 17 | #include <linux/delay.h> |
| 18 | 18 | #include <linux/gpio.h> |
| 19 | 19 | #include <linux/slab.h> |
| @@ -197,12 +197,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) · 196 unmodified lines | ||
| 197 | 197 | alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); |
| 198 | 198 | alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); |
| 199 | 199 | |
| 200 | − alarm->time.tm_mon = -1; | |
| 201 | − alarm->time.tm_year = -1; | |
| 202 | − alarm->time.tm_wday = -1; | |
| 203 | − alarm->time.tm_yday = -1; | |
| 204 | − alarm->time.tm_isdst = -1; | |
| 205 | − | |
| 206 | 200 | alarm->enabled = !!(control & DS3232_REG_CR_A1IE); |
| 207 | 201 | alarm->pending = !!(stat & DS3232_REG_SR_A1F); |
| 208 | 202 | |
| @@ -259,6 +259,12 @@ static const struct rtc_class_ops efi_rtc_ops = { · 258 unmodified lines | ||
| 259 | 259 | static int __init efi_rtc_probe(struct platform_device *dev) |
| 260 | 260 | { |
| 261 | 261 | struct rtc_device *rtc; |
| 262 | + efi_time_t eft; | |
| 263 | + efi_time_cap_t cap; | |
| 264 | + | |
| 265 | + /* First check if the RTC is usable */ | |
| 266 | + if (efi.get_time(&eft, &cap) != EFI_SUCCESS) | |
| 267 | + return -ENODEV; | |
| 262 | 268 | |
| 263 | 269 | rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops, |
| 264 | 270 | THIS_MODULE); |
| @@ -9,44 +9,10 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/platform_device.h> |
| 10 | 10 | #include <linux/rtc.h> |
| 11 | 11 | |
| 12 | −#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \ | |
| 13 | − defined(CONFIG_PPC) || defined(CONFIG_SUPERH32) | |
| 14 | −#include <asm/rtc.h> | |
| 15 | − | |
| 16 | −static int generic_get_time(struct device *dev, struct rtc_time *tm) | |
| 17 | −{ | |
| 18 | − unsigned int ret = get_rtc_time(tm); | |
| 19 | − | |
| 20 | − if (ret & RTC_BATT_BAD) | |
| 21 | − return -EOPNOTSUPP; | |
| 22 | − | |
| 23 | − return rtc_valid_tm(tm); | |
| 24 | −} | |
| 25 | − | |
| 26 | −static int generic_set_time(struct device *dev, struct rtc_time *tm) | |
| 27 | −{ | |
| 28 | − if (set_rtc_time(tm) < 0) | |
| 29 | − return -EOPNOTSUPP; | |
| 30 | − | |
| 31 | − return 0; | |
| 32 | −} | |
| 33 | − | |
| 34 | −static const struct rtc_class_ops generic_rtc_ops = { | |
| 35 | − .read_time = generic_get_time, | |
| 36 | − .set_time = generic_set_time, | |
| 37 | −}; | |
| 38 | −#else | |
| 39 | −#define generic_rtc_ops *(struct rtc_class_ops*)NULL | |
| 40 | −#endif | |
| 41 | − | |
| 42 | 12 | static int __init generic_rtc_probe(struct platform_device *dev) |
| 43 | 13 | { |
| 44 | 14 | struct rtc_device *rtc; |
| 45 | − const struct rtc_class_ops *ops; | |
| 46 | − | |
| 47 | − ops = dev_get_platdata(&dev->dev); | |
| 48 | − if (!ops) | |
| 49 | − ops = &generic_rtc_ops; | |
| 15 | + const struct rtc_class_ops *ops = dev_get_platdata(&dev->dev); | |
| 50 | 16 | |
| 51 | 17 | rtc = devm_rtc_device_register(&dev->dev, "rtc-generic", |
| 52 | 18 | ops, THIS_MODULE); |
| @@ -198,7 +198,7 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) · 197 unmodified lines | ||
| 198 | 198 | return ret; |
| 199 | 199 | |
| 200 | 200 | /* The alarm only has a minute accuracy */ |
| 201 | − alm_tm->tm_sec = -1; | |
| 201 | + alm_tm->tm_sec = 0; | |
| 202 | 202 | |
| 203 | 203 | alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ? |
| 204 | 204 | -1 : |
| @@ -213,9 +213,6 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) · 8 unmodified lines | ||
| 213 | 213 | -1 : |
| 214 | 214 | bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK); |
| 215 | 215 | |
| 216 | − alm_tm->tm_mon = -1; | |
| 217 | − alm_tm->tm_year = -1; | |
| 218 | − | |
| 219 | 216 | ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); |
| 220 | 217 | if (ret < 0) |
| 221 | 218 | return ret; |
| @@ -245,8 +245,7 @@ static int isl12057_rtc_update_alarm(struct device *dev, int enable) · 244 unmodified lines | ||
| 245 | 245 | static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 246 | 246 | { |
| 247 | 247 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); |
| 248 | − struct rtc_time rtc_tm, *alarm_tm = &alarm->time; | |
| 249 | − unsigned long rtc_secs, alarm_secs; | |
| 248 | + struct rtc_time *alarm_tm = &alarm->time; | |
| 250 | 249 | u8 regs[ISL12057_A1_SEC_LEN]; |
| 251 | 250 | unsigned int ir; |
| 252 | 251 | int ret; |
| @@ -264,36 +263,6 @@ static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) · 11 unmodified lines | ||
| 264 | 263 | alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f); |
| 265 | 264 | alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f); |
| 266 | 265 | alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f); |
| 267 | − alarm_tm->tm_wday = -1; | |
| 268 | − | |
| 269 | − /* | |
| 270 | − * The alarm section does not store year/month. We use the ones in rtc | |
| 271 | − * section as a basis and increment month and then year if needed to get | |
| 272 | − * alarm after current time. | |
| 273 | − */ | |
| 274 | − ret = _isl12057_rtc_read_time(dev, &rtc_tm); | |
| 275 | − if (ret) | |
| 276 | − goto err_unlock; | |
| 277 | − | |
| 278 | − alarm_tm->tm_year = rtc_tm.tm_year; | |
| 279 | − alarm_tm->tm_mon = rtc_tm.tm_mon; | |
| 280 | − | |
| 281 | − ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); | |
| 282 | − if (ret) | |
| 283 | − goto err_unlock; | |
| 284 | − | |
| 285 | − ret = rtc_tm_to_time(alarm_tm, &alarm_secs); | |
| 286 | − if (ret) | |
| 287 | − goto err_unlock; | |
| 288 | − | |
| 289 | − if (alarm_secs < rtc_secs) { | |
| 290 | − if (alarm_tm->tm_mon == 11) { | |
| 291 | − alarm_tm->tm_mon = 0; | |
| 292 | − alarm_tm->tm_year += 1; | |
| 293 | − } else { | |
| 294 | − alarm_tm->tm_mon += 1; | |
| 295 | − } | |
| 296 | − } | |
| 297 | 266 | |
| 298 | 267 | ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir); |
| 299 | 268 | if (ret) { |
| @@ -244,7 +244,7 @@ static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled) · 243 unmodified lines | ||
| 244 | 244 | |
| 245 | 245 | retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags); |
| 246 | 246 | if (retval < 0) { |
| 247 | − dev_info(dev, "Unable to enable alarm IRQ %d\n", retval); | |
| 247 | + dev_err(dev, "Unable to enable alarm IRQ %d\n", retval); | |
| 248 | 248 | return retval; |
| 249 | 249 | } |
| 250 | 250 | return 0; |
| @@ -320,10 +320,8 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 69 unmodified lines | ||
| 320 | 320 | alrm->time.tm_sec = bcd2bin(alarmvals[4] & 0x7f); |
| 321 | 321 | alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f); |
| 322 | 322 | alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f); |
| 323 | − alrm->time.tm_wday = -1; | |
| 324 | 323 | alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f); |
| 325 | 324 | alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f); |
| 326 | − alrm->time.tm_year = -1; | |
| 327 | 325 | |
| 328 | 326 | alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE); |
| 329 | 327 | alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled; |
| @@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = { · 7 unmodified lines | ||
| 337 | 335 | .proc = m41t80_rtc_proc, |
| 338 | 336 | }; |
| 339 | 337 | |
| 338 | +#ifdef CONFIG_PM_SLEEP | |
| 339 | +static int m41t80_suspend(struct device *dev) | |
| 340 | +{ | |
| 341 | + struct i2c_client *client = to_i2c_client(dev); | |
| 342 | + | |
| 343 | + if (client->irq >= 0 && device_may_wakeup(dev)) | |
| 344 | + enable_irq_wake(client->irq); | |
| 345 | + | |
| 346 | + return 0; | |
| 347 | +} | |
| 348 | + | |
| 349 | +static int m41t80_resume(struct device *dev) | |
| 350 | +{ | |
| 351 | + struct i2c_client *client = to_i2c_client(dev); | |
| 352 | + | |
| 353 | + if (client->irq >= 0 && device_may_wakeup(dev)) | |
| 354 | + disable_irq_wake(client->irq); | |
| 355 | + | |
| 356 | + return 0; | |
| 357 | +} | |
| 358 | +#endif | |
| 359 | + | |
| 360 | +static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); | |
| 361 | + | |
| 340 | 362 | static ssize_t flags_show(struct device *dev, |
| 341 | 363 | struct device_attribute *attr, char *buf) |
| 342 | 364 | { |
| @@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client, · 488 unmodified lines | ||
| 831 | 853 | return rc; |
| 832 | 854 | } |
| 833 | 855 | |
| 834 | − rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group, | |
| 835 | − &client->dev); | |
| 856 | + rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group, | |
| 857 | + &client->dev); | |
| 836 | 858 | if (rc) { |
| 837 | − m41t80_remove_sysfs_group(&client->dev); | |
| 838 | 859 | dev_err(&client->dev, |
| 839 | 860 | "Failed to add sysfs cleanup action: %d\n", rc); |
| 840 | 861 | return rc; |
| @@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client) · 32 unmodified lines | ||
| 873 | 894 | static struct i2c_driver m41t80_driver = { |
| 874 | 895 | .driver = { |
| 875 | 896 | .name = "rtc-m41t80", |
| 897 | + .pm = &m41t80_pm, | |
| 876 | 898 | }, |
| 877 | 899 | .probe = m41t80_probe, |
| 878 | 900 | .remove = m41t80_remove, |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/module.h> |
| 17 | 17 | #include <linux/rtc.h> |
| 18 | 18 | #include <linux/platform_device.h> |
| 19 | −#include <linux/m48t86.h> | |
| 19 | +#include <linux/platform_data/rtc-m48t86.h> | |
| 20 | 20 | #include <linux/bcd.h> |
| 21 | 21 | |
| 22 | 22 | #define M48T86_REG_SEC 0x00 |
| @@ -0,0 +1,164 @@ | ||
| 1 | +/* rtc-max6916.c | |
| 2 | + * | |
| 3 | + * Driver for MAXIM max6916 Low Current, SPI Compatible | |
| 4 | + * Real Time Clock | |
| 5 | + * | |
| 6 | + * Author : Venkat Prashanth B U <venkat.prashanth2498@gmail.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + * | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/init.h> | |
| 15 | +#include <linux/module.h> | |
| 16 | +#include <linux/device.h> | |
| 17 | +#include <linux/platform_device.h> | |
| 18 | +#include <linux/rtc.h> | |
| 19 | +#include <linux/spi/spi.h> | |
| 20 | +#include <linux/bcd.h> | |
| 21 | + | |
| 22 | +/* Registers in max6916 rtc */ | |
| 23 | + | |
| 24 | +#define MAX6916_SECONDS_REG 0x01 | |
| 25 | +#define MAX6916_MINUTES_REG 0x02 | |
| 26 | +#define MAX6916_HOURS_REG 0x03 | |
| 27 | +#define MAX6916_DATE_REG 0x04 | |
| 28 | +#define MAX6916_MONTH_REG 0x05 | |
| 29 | +#define MAX6916_DAY_REG 0x06 | |
| 30 | +#define MAX6916_YEAR_REG 0x07 | |
| 31 | +#define MAX6916_CONTROL_REG 0x08 | |
| 32 | +#define MAX6916_STATUS_REG 0x0C | |
| 33 | +#define MAX6916_CLOCK_BURST 0x3F | |
| 34 | + | |
| 35 | +static int max6916_read_reg(struct device *dev, unsigned char address, | |
| 36 | + unsigned char *data) | |
| 37 | +{ | |
| 38 | + struct spi_device *spi = to_spi_device(dev); | |
| 39 | + | |
| 40 | + *data = address | 0x80; | |
| 41 | + | |
| 42 | + return spi_write_then_read(spi, data, 1, data, 1); | |
| 43 | +} | |
| 44 | + | |
| 45 | +static int max6916_write_reg(struct device *dev, unsigned char address, | |
| 46 | + unsigned char data) | |
| 47 | +{ | |
| 48 | + struct spi_device *spi = to_spi_device(dev); | |
| 49 | + unsigned char buf[2]; | |
| 50 | + | |
| 51 | + buf[0] = address & 0x7F; | |
| 52 | + buf[1] = data; | |
| 53 | + | |
| 54 | + return spi_write_then_read(spi, buf, 2, NULL, 0); | |
| 55 | +} | |
| 56 | + | |
| 57 | +static int max6916_read_time(struct device *dev, struct rtc_time *dt) | |
| 58 | +{ | |
| 59 | + struct spi_device *spi = to_spi_device(dev); | |
| 60 | + int err; | |
| 61 | + unsigned char buf[8]; | |
| 62 | + | |
| 63 | + buf[0] = MAX6916_CLOCK_BURST | 0x80; | |
| 64 | + | |
| 65 | + err = spi_write_then_read(spi, buf, 1, buf, 8); | |
| 66 | + | |
| 67 | + if (err) | |
| 68 | + return err; | |
| 69 | + | |
| 70 | + dt->tm_sec = bcd2bin(buf[0]); | |
| 71 | + dt->tm_min = bcd2bin(buf[1]); | |
| 72 | + dt->tm_hour = bcd2bin(buf[2] & 0x3F); | |
| 73 | + dt->tm_mday = bcd2bin(buf[3]); | |
| 74 | + dt->tm_mon = bcd2bin(buf[4]) - 1; | |
| 75 | + dt->tm_wday = bcd2bin(buf[5]) - 1; | |
| 76 | + dt->tm_year = bcd2bin(buf[6]) + 100; | |
| 77 | + | |
| 78 | + return rtc_valid_tm(dt); | |
| 79 | +} | |
| 80 | + | |
| 81 | +static int max6916_set_time(struct device *dev, struct rtc_time *dt) | |
| 82 | +{ | |
| 83 | + struct spi_device *spi = to_spi_device(dev); | |
| 84 | + unsigned char buf[9]; | |
| 85 | + | |
| 86 | + if (dt->tm_year < 100 || dt->tm_year > 199) { | |
| 87 | + dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n", | |
| 88 | + dt->tm_year + 1900); | |
| 89 | + return -EINVAL; | |
| 90 | + } | |
| 91 | + | |
| 92 | + buf[0] = MAX6916_CLOCK_BURST & 0x7F; | |
| 93 | + buf[1] = bin2bcd(dt->tm_sec); | |
| 94 | + buf[2] = bin2bcd(dt->tm_min); | |
| 95 | + buf[3] = (bin2bcd(dt->tm_hour) & 0X3F); | |
| 96 | + buf[4] = bin2bcd(dt->tm_mday); | |
| 97 | + buf[5] = bin2bcd(dt->tm_mon + 1); | |
| 98 | + buf[6] = bin2bcd(dt->tm_wday + 1); | |
| 99 | + buf[7] = bin2bcd(dt->tm_year % 100); | |
| 100 | + buf[8] = bin2bcd(0x00); | |
| 101 | + | |
| 102 | + /* write the rtc settings */ | |
| 103 | + return spi_write_then_read(spi, buf, 9, NULL, 0); | |
| 104 | +} | |
| 105 | + | |
| 106 | +static const struct rtc_class_ops max6916_rtc_ops = { | |
| 107 | + .read_time = max6916_read_time, | |
| 108 | + .set_time = max6916_set_time, | |
| 109 | +}; | |
| 110 | + | |
| 111 | +static int max6916_probe(struct spi_device *spi) | |
| 112 | +{ | |
| 113 | + struct rtc_device *rtc; | |
| 114 | + unsigned char data; | |
| 115 | + int res; | |
| 116 | + | |
| 117 | + /* spi setup with max6916 in mode 3 and bits per word as 8 */ | |
| 118 | + spi->mode = SPI_MODE_3; | |
| 119 | + spi->bits_per_word = 8; | |
| 120 | + spi_setup(spi); | |
| 121 | + | |
| 122 | + /* RTC Settings */ | |
| 123 | + res = max6916_read_reg(&spi->dev, MAX6916_SECONDS_REG, &data); | |
| 124 | + if (res) | |
| 125 | + return res; | |
| 126 | + | |
| 127 | + /* Disable the write protect of rtc */ | |
| 128 | + max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data); | |
| 129 | + data = data & ~(1 << 7); | |
| 130 | + max6916_write_reg(&spi->dev, MAX6916_CONTROL_REG, data); | |
| 131 | + | |
| 132 | + /*Enable oscillator,disable oscillator stop flag, glitch filter*/ | |
| 133 | + max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data); | |
| 134 | + data = data & 0x1B; | |
| 135 | + max6916_write_reg(&spi->dev, MAX6916_STATUS_REG, data); | |
| 136 | + | |
| 137 | + /* display the settings */ | |
| 138 | + max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data); | |
| 139 | + dev_info(&spi->dev, "MAX6916 RTC CTRL Reg = 0x%02x\n", data); | |
| 140 | + | |
| 141 | + max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data); | |
| 142 | + dev_info(&spi->dev, "MAX6916 RTC Status Reg = 0x%02x\n", data); | |
| 143 | + | |
| 144 | + rtc = devm_rtc_device_register(&spi->dev, "max6916", | |
| 145 | + &max6916_rtc_ops, THIS_MODULE); | |
| 146 | + if (IS_ERR(rtc)) | |
| 147 | + return PTR_ERR(rtc); | |
| 148 | + | |
| 149 | + spi_set_drvdata(spi, rtc); | |
| 150 | + | |
| 151 | + return 0; | |
| 152 | +} | |
| 153 | + | |
| 154 | +static struct spi_driver max6916_driver = { | |
| 155 | + .driver = { | |
| 156 | + .name = "max6916", | |
| 157 | + }, | |
| 158 | + .probe = max6916_probe, | |
| 159 | +}; | |
| 160 | +module_spi_driver(max6916_driver); | |
| 161 | + | |
| 162 | +MODULE_DESCRIPTION("MAX6916 SPI RTC DRIVER"); | |
| 163 | +MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@gmail.com>"); | |
| 164 | +MODULE_LICENSE("GPL v2"); | |
| @@ -1,40 +1,16 @@ | ||
| 1 | −/* | |
| 2 | − * include/asm-generic/rtc.h | |
| 3 | − * | |
| 4 | − * Author: Tom Rini <trini@mvista.com> | |
| 5 | − * | |
| 6 | − * Based on: | |
| 7 | − * drivers/char/rtc.c | |
| 8 | − * | |
| 9 | − * Please read the COPYING file for all license details. | |
| 10 | − */ | |
| 11 | − | |
| 12 | −#ifndef __ASM_RTC_H__ | |
| 13 | −#define __ASM_RTC_H__ | |
| 14 | − | |
| 15 | −#include <linux/mc146818rtc.h> | |
| 16 | −#include <linux/rtc.h> | |
| 17 | 1 | #include <linux/bcd.h> |
| 18 | 2 | #include <linux/delay.h> |
| 3 | +#include <linux/export.h> | |
| 4 | +#include <linux/mc146818rtc.h> | |
| 5 | + | |
| 19 | 6 | #ifdef CONFIG_ACPI |
| 20 | 7 | #include <linux/acpi.h> |
| 21 | 8 | #endif |
| 22 | 9 | |
| 23 | −#define RTC_PIE 0x40 /* periodic interrupt enable */ | |
| 24 | −#define RTC_AIE 0x20 /* alarm interrupt enable */ | |
| 25 | −#define RTC_UIE 0x10 /* update-finished interrupt enable */ | |
| 26 | − | |
| 27 | −/* some dummy definitions */ | |
| 28 | −#define RTC_BATT_BAD 0x100 /* battery bad */ | |
| 29 | −#define RTC_SQWE 0x08 /* enable square-wave output */ | |
| 30 | −#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ | |
| 31 | −#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | |
| 32 | −#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | |
| 33 | − | |
| 34 | 10 | /* |
| 35 | 11 | * Returns true if a clock update is in progress |
| 36 | 12 | */ |
| 37 | −static inline unsigned char rtc_is_updating(void) | |
| 13 | +static inline unsigned char mc146818_is_updating(void) | |
| 38 | 14 | { |
| 39 | 15 | unsigned char uip; |
| 40 | 16 | unsigned long flags; |
| @@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void) · 4 unmodified lines | ||
| 45 | 21 | return uip; |
| 46 | 22 | } |
| 47 | 23 | |
| 48 | −static inline unsigned int __get_rtc_time(struct rtc_time *time) | |
| 24 | +unsigned int mc146818_get_time(struct rtc_time *time) | |
| 49 | 25 | { |
| 50 | 26 | unsigned char ctrl; |
| 51 | 27 | unsigned long flags; |
| @@ -60,11 +36,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) · 8 unmodified lines | ||
| 60 | 36 | * can take just over 2ms. We wait 20ms. There is no need to |
| 61 | 37 | * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. |
| 62 | 38 | * If you need to know *exactly* when a second has started, enable |
| 63 | − * periodic update complete interrupts, (via ioctl) and then | |
| 39 | + * periodic update complete interrupts, (via ioctl) and then | |
| 64 | 40 | * immediately read /dev/rtc which will block until you get the IRQ. |
| 65 | 41 | * Once the read clears, read the RTC time (again via ioctl). Easy. |
| 66 | 42 | */ |
| 67 | − if (rtc_is_updating()) | |
| 43 | + if (mc146818_is_updating()) | |
| 68 | 44 | mdelay(20); |
| 69 | 45 | |
| 70 | 46 | /* |
| @@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) · 49 unmodified lines | ||
| 120 | 96 | |
| 121 | 97 | return RTC_24H; |
| 122 | 98 | } |
| 123 | − | |
| 124 | −#ifndef get_rtc_time | |
| 125 | −#define get_rtc_time __get_rtc_time | |
| 126 | −#endif | |
| 99 | +EXPORT_SYMBOL_GPL(mc146818_get_time); | |
| 127 | 100 | |
| 128 | 101 | /* Set the current date and time in the real time clock. */ |
| 129 | −static inline int __set_rtc_time(struct rtc_time *time) | |
| 102 | +int mc146818_set_time(struct rtc_time *time) | |
| 130 | 103 | { |
| 131 | 104 | unsigned long flags; |
| 132 | 105 | unsigned char mon, day, hrs, min, sec; |
| @@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time) · 89 unmodified lines | ||
| 222 | 195 | |
| 223 | 196 | return 0; |
| 224 | 197 | } |
| 225 | − | |
| 226 | −#ifndef set_rtc_time | |
| 227 | −#define set_rtc_time __set_rtc_time | |
| 228 | −#endif | |
| 229 | − | |
| 230 | −static inline unsigned int get_rtc_ss(void) | |
| 231 | −{ | |
| 232 | − struct rtc_time h; | |
| 233 | − | |
| 234 | − get_rtc_time(&h); | |
| 235 | − return h.tm_sec; | |
| 236 | −} | |
| 237 | − | |
| 238 | −static inline int get_rtc_pll(struct rtc_pll_info *pll) | |
| 239 | −{ | |
| 240 | − return -EINVAL; | |
| 241 | −} | |
| 242 | −static inline int set_rtc_pll(struct rtc_pll_info *pll) | |
| 243 | −{ | |
| 244 | − return -EINVAL; | |
| 245 | −} | |
| 246 | − | |
| 247 | −#endif /* __ASM_RTC_H__ */ | |
| 198 | +EXPORT_SYMBOL_GPL(mc146818_set_time); | |
| @@ -32,11 +32,11 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <linux/interrupt.h> |
| 33 | 33 | #include <linux/spinlock.h> |
| 34 | 34 | #include <linux/kernel.h> |
| 35 | +#include <linux/mc146818rtc.h> | |
| 35 | 36 | #include <linux/module.h> |
| 36 | 37 | #include <linux/init.h> |
| 37 | 38 | #include <linux/sfi.h> |
| 38 | 39 | |
| 39 | −#include <asm-generic/rtc.h> | |
| 40 | 40 | #include <asm/intel_scu_ipc.h> |
| 41 | 41 | #include <asm/intel-mid.h> |
| 42 | 42 | #include <asm/intel_mid_vrtc.h> |
| @@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) · 106 unmodified lines | ||
| 149 | 149 | if (mrst->irq <= 0) |
| 150 | 150 | return -EIO; |
| 151 | 151 | |
| 152 | − /* Basic alarms only support hour, minute, and seconds fields. | |
| 153 | − * Some also support day and month, for alarms up to a year in | |
| 154 | − * the future. | |
| 155 | − */ | |
| 156 | − t->time.tm_mday = -1; | |
| 157 | − t->time.tm_mon = -1; | |
| 158 | − t->time.tm_year = -1; | |
| 159 | − | |
| 160 | 152 | /* vRTC only supports binary mode */ |
| 161 | 153 | spin_lock_irq(&rtc_lock); |
| 162 | 154 | t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); |
| @@ -96,7 +96,7 @@ · 95 unmodified lines | ||
| 96 | 96 | #define CD_TMR_TE BIT(3) /* Countdown timer enable */ |
| 97 | 97 | |
| 98 | 98 | /* PCF2123_REG_OFFSET BITS */ |
| 99 | −#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */ | |
| 99 | +#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ | |
| 100 | 100 | #define OFFSET_COARSE BIT(7) /* Coarse mode offset */ |
| 101 | 101 | #define OFFSET_STEP (2170) /* Offset step in parts per billion */ |
| 102 | 102 | |
| @@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset) · 114 unmodified lines | ||
| 217 | 217 | if (reg & OFFSET_COARSE) |
| 218 | 218 | reg <<= 1; /* multiply by 2 and sign extend */ |
| 219 | 219 | else |
| 220 | − reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */ | |
| 220 | + reg = sign_extend32(reg, OFFSET_SIGN_BIT); | |
| 221 | 221 | |
| 222 | 222 | *offset = ((long)reg) * OFFSET_STEP; |
| 223 | 223 | |
| @@ -16,6 +16,16 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/rtc.h> |
| 17 | 17 | #include <linux/module.h> |
| 18 | 18 | |
| 19 | +/* | |
| 20 | + * Information for this driver was pulled from the following datasheets. | |
| 21 | + * | |
| 22 | + * http://www.nxp.com/documents/data_sheet/PCF85063A.pdf | |
| 23 | + * http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf | |
| 24 | + * | |
| 25 | + * PCF85063A -- Rev. 6 — 18 November 2015 | |
| 26 | + * PCF85063TP -- Rev. 4 — 6 May 2015 | |
| 27 | +*/ | |
| 28 | + | |
| 19 | 29 | #define PCF85063_REG_CTRL1 0x00 /* status */ |
| 20 | 30 | #define PCF85063_REG_CTRL1_STOP BIT(5) |
| 21 | 31 | #define PCF85063_REG_CTRL2 0x01 |
| @@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) · 33 unmodified lines | ||
| 55 | 65 | return 0; |
| 56 | 66 | } |
| 57 | 67 | |
| 58 | −/* | |
| 59 | − * In the routines that deal directly with the pcf85063 hardware, we use | |
| 60 | − * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | |
| 61 | − */ | |
| 68 | +static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) | |
| 69 | +{ | |
| 70 | + s32 ret; | |
| 71 | + | |
| 72 | + /* start the clock */ | |
| 73 | + ctrl1 &= PCF85063_REG_CTRL1_STOP; | |
| 74 | + | |
| 75 | + ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); | |
| 76 | + if (ret < 0) { | |
| 77 | + dev_err(&client->dev, "Failing to start the clock\n"); | |
| 78 | + return -EIO; | |
| 79 | + } | |
| 80 | + | |
| 81 | + return 0; | |
| 82 | +} | |
| 83 | + | |
| 62 | 84 | static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) |
| 63 | 85 | { |
| 64 | 86 | int rc; |
| @@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) · 25 unmodified lines | ||
| 90 | 112 | tm->tm_wday = regs[4] & 0x07; |
| 91 | 113 | tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */ |
| 92 | 114 | tm->tm_year = bcd2bin(regs[6]); |
| 93 | − if (tm->tm_year < 70) | |
| 94 | − tm->tm_year += 100; /* assume we are in 1970...2069 */ | |
| 115 | + tm->tm_year += 100; | |
| 95 | 116 | |
| 96 | 117 | return rtc_valid_tm(tm); |
| 97 | 118 | } |
| @@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) · 1 unmodified line | ||
| 99 | 120 | static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) |
| 100 | 121 | { |
| 101 | 122 | int rc; |
| 102 | − u8 regs[8]; | |
| 123 | + u8 regs[7]; | |
| 124 | + u8 ctrl1; | |
| 125 | + | |
| 126 | + if ((tm->tm_year < 100) || (tm->tm_year > 199)) | |
| 127 | + return -EINVAL; | |
| 103 | 128 | |
| 104 | 129 | /* |
| 105 | 130 | * to accurately set the time, reset the divider chain and keep it in |
| 106 | 131 | * reset state until all time/date registers are written |
| 107 | 132 | */ |
| 108 | − rc = pcf85063_stop_clock(client, ®s[7]); | |
| 133 | + rc = pcf85063_stop_clock(client, &ctrl1); | |
| 109 | 134 | if (rc != 0) |
| 110 | 135 | return rc; |
| 111 | 136 | |
| @@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) · 13 unmodified lines | ||
| 125 | 150 | regs[5] = bin2bcd(tm->tm_mon + 1); |
| 126 | 151 | |
| 127 | 152 | /* year and century */ |
| 128 | − regs[6] = bin2bcd(tm->tm_year % 100); | |
| 129 | − | |
| 130 | − /* | |
| 131 | − * after all time/date registers are written, let the 'address auto | |
| 132 | − * increment' feature wrap around and write register CTRL1 to re-enable | |
| 133 | − * the clock divider chain again | |
| 134 | − */ | |
| 135 | − regs[7] &= ~PCF85063_REG_CTRL1_STOP; | |
| 153 | + regs[6] = bin2bcd(tm->tm_year - 100); | |
| 136 | 154 | |
| 137 | 155 | /* write all registers at once */ |
| 138 | 156 | 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) · 3 unmodified lines | ||
| 142 | 160 | return rc; |
| 143 | 161 | } |
| 144 | 162 | |
| 163 | + /* | |
| 164 | + * Write the control register as a separate action since the size of | |
| 165 | + * the register space is different between the PCF85063TP and | |
| 166 | + * PCF85063A devices. The rollover point can not be used. | |
| 167 | + */ | |
| 168 | + rc = pcf85063_start_clock(client, ctrl1); | |
| 169 | + if (rc != 0) | |
| 170 | + return rc; | |
| 171 | + | |
| 145 | 172 | return 0; |
| 146 | 173 | } |
| 147 | 174 | |
| @@ -341,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) · 340 unmodified lines | ||
| 341 | 341 | "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n", |
| 342 | 342 | __func__, buf[0], buf[1], buf[2], buf[3]); |
| 343 | 343 | |
| 344 | + tm->time.tm_sec = 0; | |
| 344 | 345 | tm->time.tm_min = bcd2bin(buf[0] & 0x7F); |
| 345 | 346 | tm->time.tm_hour = bcd2bin(buf[1] & 0x3F); |
| 346 | 347 | tm->time.tm_mday = bcd2bin(buf[2] & 0x3F); |
| 347 | 348 | tm->time.tm_wday = bcd2bin(buf[3] & 0x7); |
| 348 | − tm->time.tm_mon = -1; | |
| 349 | − tm->time.tm_year = -1; | |
| 350 | − tm->time.tm_yday = -1; | |
| 351 | − tm->time.tm_isdst = -1; | |
| 352 | 349 | |
| 353 | 350 | err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending); |
| 354 | 351 | if (err < 0) |
| @@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) · 127 unmodified lines | ||
| 128 | 128 | return ret; |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | + alm->time.tm_sec = 0; | |
| 131 | 132 | alm->time.tm_min = bcd2bin(alarm_data[0]); |
| 132 | 133 | alm->time.tm_hour = bcd2bin(alarm_data[1]); |
| 133 | 134 | alm->time.tm_mday = bcd2bin(alarm_data[2]); |
| @@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t) · 340 unmodified lines | ||
| 341 | 341 | t->time.tm_sec = 0; |
| 342 | 342 | t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); |
| 343 | 343 | t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); |
| 344 | − t->time.tm_mday = -1; | |
| 345 | − t->time.tm_mon = -1; | |
| 346 | − t->time.tm_year = -1; | |
| 347 | − t->time.tm_wday = -1; | |
| 348 | − t->time.tm_yday = -1; | |
| 349 | − t->time.tm_isdst = -1; | |
| 350 | 344 | |
| 351 | 345 | /* ... and status */ |
| 352 | 346 | t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE); |
| @@ -13,12 +13,15 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include <linux/bcd.h> |
| 15 | 15 | #include <linux/bitops.h> |
| 16 | +#include <linux/log2.h> | |
| 16 | 17 | #include <linux/i2c.h> |
| 17 | 18 | #include <linux/interrupt.h> |
| 18 | 19 | #include <linux/kernel.h> |
| 19 | 20 | #include <linux/module.h> |
| 20 | 21 | #include <linux/rtc.h> |
| 21 | 22 | |
| 23 | +#define RV8803_I2C_TRY_COUNT 4 | |
| 24 | + | |
| 22 | 25 | #define RV8803_SEC 0x00 |
| 23 | 26 | #define RV8803_MIN 0x01 |
| 24 | 27 | #define RV8803_HOUR 0x02 |
| @@ -56,19 +59,85 @@ struct rv8803_data { · 31 unmodified lines | ||
| 56 | 59 | u8 ctrl; |
| 57 | 60 | }; |
| 58 | 61 | |
| 62 | +static int rv8803_read_reg(const struct i2c_client *client, u8 reg) | |
| 63 | +{ | |
| 64 | + int try = RV8803_I2C_TRY_COUNT; | |
| 65 | + s32 ret; | |
| 66 | + | |
| 67 | + /* | |
| 68 | + * There is a 61µs window during which the RTC does not acknowledge I2C | |
| 69 | + * transfers. In that case, ensure that there are multiple attempts. | |
| 70 | + */ | |
| 71 | + do | |
| 72 | + ret = i2c_smbus_read_byte_data(client, reg); | |
| 73 | + while ((ret == -ENXIO || ret == -EIO) && --try); | |
| 74 | + if (ret < 0) | |
| 75 | + dev_err(&client->dev, "Unable to read register 0x%02x\n", reg); | |
| 76 | + | |
| 77 | + return ret; | |
| 78 | +} | |
| 79 | + | |
| 80 | +static int rv8803_read_regs(const struct i2c_client *client, | |
| 81 | + u8 reg, u8 count, u8 *values) | |
| 82 | +{ | |
| 83 | + int try = RV8803_I2C_TRY_COUNT; | |
| 84 | + s32 ret; | |
| 85 | + | |
| 86 | + do | |
| 87 | + ret = i2c_smbus_read_i2c_block_data(client, reg, count, values); | |
| 88 | + while ((ret == -ENXIO || ret == -EIO) && --try); | |
| 89 | + if (ret != count) { | |
| 90 | + dev_err(&client->dev, | |
| 91 | + "Unable to read registers 0x%02x..0x%02x\n", | |
| 92 | + reg, reg + count - 1); | |
| 93 | + return ret < 0 ? ret : -EIO; | |
| 94 | + } | |
| 95 | + | |
| 96 | + return 0; | |
| 97 | +} | |
| 98 | + | |
| 99 | +static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value) | |
| 100 | +{ | |
| 101 | + int try = RV8803_I2C_TRY_COUNT; | |
| 102 | + s32 ret; | |
| 103 | + | |
| 104 | + do | |
| 105 | + ret = i2c_smbus_write_byte_data(client, reg, value); | |
| 106 | + while ((ret == -ENXIO || ret == -EIO) && --try); | |
| 107 | + if (ret) | |
| 108 | + dev_err(&client->dev, "Unable to write register 0x%02x\n", reg); | |
| 109 | + | |
| 110 | + return ret; | |
| 111 | +} | |
| 112 | + | |
| 113 | +static int rv8803_write_regs(const struct i2c_client *client, | |
| 114 | + u8 reg, u8 count, const u8 *values) | |
| 115 | +{ | |
| 116 | + int try = RV8803_I2C_TRY_COUNT; | |
| 117 | + s32 ret; | |
| 118 | + | |
| 119 | + do | |
| 120 | + ret = i2c_smbus_write_i2c_block_data(client, reg, count, | |
| 121 | + values); | |
| 122 | + while ((ret == -ENXIO || ret == -EIO) && --try); | |
| 123 | + if (ret) | |
| 124 | + dev_err(&client->dev, | |
| 125 | + "Unable to write registers 0x%02x..0x%02x\n", | |
| 126 | + reg, reg + count - 1); | |
| 127 | + | |
| 128 | + return ret; | |
| 129 | +} | |
| 130 | + | |
| 59 | 131 | static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) |
| 60 | 132 | { |
| 61 | 133 | struct i2c_client *client = dev_id; |
| 62 | 134 | struct rv8803_data *rv8803 = i2c_get_clientdata(client); |
| 63 | 135 | unsigned long events = 0; |
| 64 | − int flags, try = 0; | |
| 136 | + int flags; | |
| 65 | 137 | |
| 66 | 138 | mutex_lock(&rv8803->flags_lock); |
| 67 | 139 | |
| 68 | − do { | |
| 69 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 70 | − try++; | |
| 71 | − } while ((flags == -ENXIO) && (try < 3)); | |
| 140 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 72 | 141 | if (flags <= 0) { |
| 73 | 142 | mutex_unlock(&rv8803->flags_lock); |
| 74 | 143 | return IRQ_NONE; |
| @@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) · 25 unmodified lines | ||
| 100 | 169 | |
| 101 | 170 | if (events) { |
| 102 | 171 | rtc_update_irq(rv8803->rtc, 1, events); |
| 103 | − i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | |
| 104 | − i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | |
| 105 | − rv8803->ctrl); | |
| 172 | + rv8803_write_reg(client, RV8803_FLAG, flags); | |
| 173 | + rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl); | |
| 106 | 174 | } |
| 107 | 175 | |
| 108 | 176 | mutex_unlock(&rv8803->flags_lock); |
| @@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) · 9 unmodified lines | ||
| 118 | 186 | u8 *date = date1; |
| 119 | 187 | int ret, flags; |
| 120 | 188 | |
| 121 | − flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); | |
| 189 | + flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); | |
| 122 | 190 | if (flags < 0) |
| 123 | 191 | return flags; |
| 124 | 192 | |
| @@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) · 2 unmodified lines | ||
| 127 | 195 | return -EINVAL; |
| 128 | 196 | } |
| 129 | 197 | |
| 130 | − ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, | |
| 131 | − 7, date); | |
| 132 | − if (ret != 7) | |
| 133 | − return ret < 0 ? ret : -EIO; | |
| 198 | + ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date); | |
| 199 | + if (ret) | |
| 200 | + return ret; | |
| 134 | 201 | |
| 135 | 202 | if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { |
| 136 | − ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, | |
| 137 | − 7, date2); | |
| 138 | − if (ret != 7) | |
| 139 | − return ret < 0 ? ret : -EIO; | |
| 203 | + ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2); | |
| 204 | + if (ret) | |
| 205 | + return ret; | |
| 140 | 206 | |
| 141 | 207 | if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) |
| 142 | 208 | date = date2; |
| @@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) · 2 unmodified lines | ||
| 145 | 211 | tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f); |
| 146 | 212 | tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f); |
| 147 | 213 | tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f); |
| 148 | − tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f); | |
| 214 | + tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f); | |
| 149 | 215 | tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f); |
| 150 | 216 | tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1; |
| 151 | 217 | tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100; |
| 152 | 218 | |
| 153 | − return rtc_valid_tm(tm); | |
| 219 | + return 0; | |
| 154 | 220 | } |
| 155 | 221 | |
| 156 | 222 | static int rv8803_set_time(struct device *dev, struct rtc_time *tm) |
| 157 | 223 | { |
| 158 | 224 | struct rv8803_data *rv8803 = dev_get_drvdata(dev); |
| 159 | 225 | u8 date[7]; |
| 160 | − int flags, ret; | |
| 226 | + int ctrl, flags, ret; | |
| 161 | 227 | |
| 162 | 228 | if ((tm->tm_year < 100) || (tm->tm_year > 199)) |
| 163 | 229 | return -EINVAL; |
| 164 | 230 | |
| 231 | + ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL); | |
| 232 | + if (ctrl < 0) | |
| 233 | + return ctrl; | |
| 234 | + | |
| 235 | + /* Stop the clock */ | |
| 236 | + ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, | |
| 237 | + ctrl | RV8803_CTRL_RESET); | |
| 238 | + if (ret) | |
| 239 | + return ret; | |
| 240 | + | |
| 165 | 241 | date[RV8803_SEC] = bin2bcd(tm->tm_sec); |
| 166 | 242 | date[RV8803_MIN] = bin2bcd(tm->tm_min); |
| 167 | 243 | date[RV8803_HOUR] = bin2bcd(tm->tm_hour); |
| @@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm) · 2 unmodified lines | ||
| 170 | 246 | date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1); |
| 171 | 247 | date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); |
| 172 | 248 | |
| 173 | − ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC, | |
| 174 | − 7, date); | |
| 175 | − if (ret < 0) | |
| 249 | + ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date); | |
| 250 | + if (ret) | |
| 251 | + return ret; | |
| 252 | + | |
| 253 | + /* Restart the clock */ | |
| 254 | + ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, | |
| 255 | + ctrl & ~RV8803_CTRL_RESET); | |
| 256 | + if (ret) | |
| 176 | 257 | return ret; |
| 177 | 258 | |
| 178 | 259 | mutex_lock(&rv8803->flags_lock); |
| 179 | 260 | |
| 180 | − flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); | |
| 261 | + flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); | |
| 181 | 262 | if (flags < 0) { |
| 182 | 263 | mutex_unlock(&rv8803->flags_lock); |
| 183 | 264 | return flags; |
| 184 | 265 | } |
| 185 | 266 | |
| 186 | − ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, | |
| 187 | − flags & ~RV8803_FLAG_V2F); | |
| 267 | + ret = rv8803_write_reg(rv8803->client, RV8803_FLAG, | |
| 268 | + flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F)); | |
| 188 | 269 | |
| 189 | 270 | mutex_unlock(&rv8803->flags_lock); |
| 190 | 271 | |
| @@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 7 unmodified lines | ||
| 198 | 279 | u8 alarmvals[3]; |
| 199 | 280 | int flags, ret; |
| 200 | 281 | |
| 201 | − ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN, | |
| 202 | − 3, alarmvals); | |
| 203 | − if (ret != 3) | |
| 204 | − return ret < 0 ? ret : -EIO; | |
| 282 | + ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals); | |
| 283 | + if (ret) | |
| 284 | + return ret; | |
| 205 | 285 | |
| 206 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 286 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 207 | 287 | if (flags < 0) |
| 208 | 288 | return flags; |
| 209 | 289 | |
| 210 | 290 | alrm->time.tm_sec = 0; |
| 211 | 291 | alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); |
| 212 | 292 | alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); |
| 213 | − alrm->time.tm_wday = -1; | |
| 214 | 293 | alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f); |
| 215 | − alrm->time.tm_mon = -1; | |
| 216 | − alrm->time.tm_year = -1; | |
| 217 | 294 | |
| 218 | 295 | alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE); |
| 219 | 296 | alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled; |
| @@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 19 unmodified lines | ||
| 239 | 316 | |
| 240 | 317 | mutex_lock(&rv8803->flags_lock); |
| 241 | 318 | |
| 242 | − ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl); | |
| 243 | − if (ret != 2) { | |
| 319 | + ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl); | |
| 320 | + if (ret) { | |
| 244 | 321 | mutex_unlock(&rv8803->flags_lock); |
| 245 | − return ret < 0 ? ret : -EIO; | |
| 322 | + return ret; | |
| 246 | 323 | } |
| 247 | 324 | |
| 248 | 325 | alarmvals[0] = bin2bcd(alrm->time.tm_min); |
| @@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 2 unmodified lines | ||
| 251 | 328 | |
| 252 | 329 | if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) { |
| 253 | 330 | rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE); |
| 254 | − err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | |
| 255 | − rv8803->ctrl); | |
| 331 | + err = rv8803_write_reg(rv8803->client, RV8803_CTRL, | |
| 332 | + rv8803->ctrl); | |
| 256 | 333 | if (err) { |
| 257 | 334 | mutex_unlock(&rv8803->flags_lock); |
| 258 | 335 | return err; |
| @@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 1 unmodified line | ||
| 260 | 337 | } |
| 261 | 338 | |
| 262 | 339 | ctrl[1] &= ~RV8803_FLAG_AF; |
| 263 | − err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]); | |
| 340 | + err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]); | |
| 264 | 341 | mutex_unlock(&rv8803->flags_lock); |
| 265 | 342 | if (err) |
| 266 | 343 | return err; |
| 267 | 344 | |
| 268 | − err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN, | |
| 269 | − 3, alarmvals); | |
| 345 | + err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals); | |
| 270 | 346 | if (err) |
| 271 | 347 | return err; |
| 272 | 348 | |
| @@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) · 3 unmodified lines | ||
| 276 | 352 | if (rv8803->rtc->aie_timer.enabled) |
| 277 | 353 | rv8803->ctrl |= RV8803_CTRL_AIE; |
| 278 | 354 | |
| 279 | − err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | |
| 280 | − rv8803->ctrl); | |
| 355 | + err = rv8803_write_reg(rv8803->client, RV8803_CTRL, | |
| 356 | + rv8803->ctrl); | |
| 281 | 357 | if (err) |
| 282 | 358 | return err; |
| 283 | 359 | } |
| @@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled) · 22 unmodified lines | ||
| 306 | 382 | } |
| 307 | 383 | |
| 308 | 384 | mutex_lock(&rv8803->flags_lock); |
| 309 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 385 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 310 | 386 | if (flags < 0) { |
| 311 | 387 | mutex_unlock(&rv8803->flags_lock); |
| 312 | 388 | return flags; |
| 313 | 389 | } |
| 314 | 390 | flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); |
| 315 | − err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | |
| 391 | + err = rv8803_write_reg(client, RV8803_FLAG, flags); | |
| 316 | 392 | mutex_unlock(&rv8803->flags_lock); |
| 317 | 393 | if (err) |
| 318 | 394 | return err; |
| 319 | 395 | |
| 320 | 396 | if (ctrl != rv8803->ctrl) { |
| 321 | 397 | rv8803->ctrl = ctrl; |
| 322 | − err = i2c_smbus_write_byte_data(client, RV8803_CTRL, | |
| 323 | − rv8803->ctrl); | |
| 398 | + err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl); | |
| 324 | 399 | if (err) |
| 325 | 400 | return err; |
| 326 | 401 | } |
| @@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) · 9 unmodified lines | ||
| 336 | 411 | |
| 337 | 412 | switch (cmd) { |
| 338 | 413 | case RTC_VL_READ: |
| 339 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 414 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 340 | 415 | if (flags < 0) |
| 341 | 416 | return flags; |
| 342 | 417 | |
| @@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) · 12 unmodified lines | ||
| 355 | 430 | |
| 356 | 431 | case RTC_VL_CLR: |
| 357 | 432 | mutex_lock(&rv8803->flags_lock); |
| 358 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 433 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 359 | 434 | if (flags < 0) { |
| 360 | 435 | mutex_unlock(&rv8803->flags_lock); |
| 361 | 436 | return flags; |
| 362 | 437 | } |
| 363 | 438 | |
| 364 | 439 | flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); |
| 365 | − ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | |
| 440 | + ret = rv8803_write_reg(client, RV8803_FLAG, flags); | |
| 366 | 441 | mutex_unlock(&rv8803->flags_lock); |
| 367 | − if (ret < 0) | |
| 442 | + if (ret) | |
| 368 | 443 | return ret; |
| 369 | 444 | |
| 370 | 445 | return 0; |
| @@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj, · 11 unmodified lines | ||
| 382 | 457 | struct i2c_client *client = to_i2c_client(dev); |
| 383 | 458 | int ret; |
| 384 | 459 | |
| 385 | − ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]); | |
| 386 | − if (ret < 0) | |
| 460 | + ret = rv8803_write_reg(client, RV8803_RAM, buf[0]); | |
| 461 | + if (ret) | |
| 387 | 462 | return ret; |
| 388 | 463 | |
| 389 | 464 | return 1; |
| @@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj, · 7 unmodified lines | ||
| 397 | 472 | struct i2c_client *client = to_i2c_client(dev); |
| 398 | 473 | int ret; |
| 399 | 474 | |
| 400 | − ret = i2c_smbus_read_byte_data(client, RV8803_RAM); | |
| 475 | + ret = rv8803_read_reg(client, RV8803_RAM); | |
| 401 | 476 | if (ret < 0) |
| 402 | 477 | return ret; |
| 403 | 478 | |
| @@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client, · 23 unmodified lines | ||
| 427 | 502 | { |
| 428 | 503 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
| 429 | 504 | struct rv8803_data *rv8803; |
| 430 | − int err, flags, try = 0; | |
| 505 | + int err, flags; | |
| 431 | 506 | |
| 432 | 507 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
| 433 | 508 | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
| @@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client, · 10 unmodified lines | ||
| 444 | 519 | rv8803->client = client; |
| 445 | 520 | i2c_set_clientdata(client, rv8803); |
| 446 | 521 | |
| 447 | − /* | |
| 448 | − * There is a 60µs window where the RTC may not reply on the i2c bus in | |
| 449 | − * that case, the transfer is not ACKed. In that case, ensure there are | |
| 450 | − * multiple attempts. | |
| 451 | − */ | |
| 452 | − do { | |
| 453 | − flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | |
| 454 | − try++; | |
| 455 | − } while ((flags == -ENXIO) && (try < 3)); | |
| 456 | − | |
| 522 | + flags = rv8803_read_reg(client, RV8803_FLAG); | |
| 457 | 523 | if (flags < 0) |
| 458 | 524 | return flags; |
| 459 | 525 | |
| @@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client, · 28 unmodified lines | ||
| 488 | 554 | return PTR_ERR(rv8803->rtc); |
| 489 | 555 | } |
| 490 | 556 | |
| 491 | − try = 0; | |
| 492 | − do { | |
| 493 | − err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, | |
| 494 | − RV8803_EXT_WADA); | |
| 495 | − try++; | |
| 496 | − } while ((err == -ENXIO) && (try < 3)); | |
| 557 | + err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); | |
| 497 | 558 | if (err) |
| 498 | 559 | return err; |
| 499 | 560 | |
| @@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) · 271 unmodified lines | ||
| 272 | 272 | t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); |
| 273 | 273 | t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); |
| 274 | 274 | |
| 275 | − if (alarmvals[2] & RX8010_ALARM_AE) | |
| 276 | − t->time.tm_mday = -1; | |
| 277 | − else | |
| 275 | + if (!(alarmvals[2] & RX8010_ALARM_AE)) | |
| 278 | 276 | t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f); |
| 279 | 277 | |
| 280 | − t->time.tm_wday = -1; | |
| 281 | − t->time.tm_mon = -1; | |
| 282 | − t->time.tm_year = -1; | |
| 283 | − | |
| 284 | 278 | t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE); |
| 285 | 279 | t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled; |
| 286 | 280 | |
| @@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) · 318 unmodified lines | ||
| 319 | 319 | t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12 |
| 320 | 320 | + (ald[1] & 0x20 ? 12 : 0); |
| 321 | 321 | |
| 322 | − t->time.tm_wday = -1; | |
| 323 | − t->time.tm_mday = -1; | |
| 324 | − t->time.tm_mon = -1; | |
| 325 | − t->time.tm_year = -1; | |
| 326 | − | |
| 327 | 322 | dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n", |
| 328 | 323 | __func__, |
| 329 | 324 | t->time.tm_sec, t->time.tm_min, t->time.tm_hour, |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/bitrev.h> |
| 16 | 16 | #include <linux/bcd.h> |
| 17 | 17 | #include <linux/slab.h> |
| 18 | +#include <linux/delay.h> | |
| 18 | 19 | |
| 19 | 20 | #define S35390A_CMD_STATUS1 0 |
| 20 | 21 | #define S35390A_CMD_STATUS2 1 |
| @@ -34,10 +35,14 @@ · 13 unmodified lines | ||
| 34 | 35 | #define S35390A_ALRM_BYTE_HOURS 1 |
| 35 | 36 | #define S35390A_ALRM_BYTE_MINS 2 |
| 36 | 37 | |
| 38 | +/* flags for STATUS1 */ | |
| 37 | 39 | #define S35390A_FLAG_POC 0x01 |
| 38 | 40 | #define S35390A_FLAG_BLD 0x02 |
| 41 | +#define S35390A_FLAG_INT2 0x04 | |
| 39 | 42 | #define S35390A_FLAG_24H 0x40 |
| 40 | 43 | #define S35390A_FLAG_RESET 0x80 |
| 44 | + | |
| 45 | +/* flag for STATUS2 */ | |
| 41 | 46 | #define S35390A_FLAG_TEST 0x01 |
| 42 | 47 | |
| 43 | 48 | #define S35390A_INT2_MODE_MASK 0xF0 |
| @@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) · 50 unmodified lines | ||
| 94 | 99 | return 0; |
| 95 | 100 | } |
| 96 | 101 | |
| 97 | −static int s35390a_reset(struct s35390a *s35390a) | |
| 102 | +/* | |
| 103 | + * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset. | |
| 104 | + * To keep the information if an irq is pending, pass the value read from | |
| 105 | + * STATUS1 to the caller. | |
| 106 | + */ | |
| 107 | +static int s35390a_reset(struct s35390a *s35390a, char *status1) | |
| 98 | 108 | { |
| 99 | − char buf[1]; | |
| 100 | − | |
| 101 | − if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) | |
| 102 | − return -EIO; | |
| 103 | − | |
| 104 | − if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) | |
| 109 | + char buf; | |
| 110 | + int ret; | |
| 111 | + unsigned initcount = 0; | |
| 112 | + | |
| 113 | + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1); | |
| 114 | + if (ret < 0) | |
| 115 | + return ret; | |
| 116 | + | |
| 117 | + if (*status1 & S35390A_FLAG_POC) | |
| 118 | + /* | |
| 119 | + * Do not communicate for 0.5 seconds since the power-on | |
| 120 | + * detection circuit is in operation. | |
| 121 | + */ | |
| 122 | + msleep(500); | |
| 123 | + else if (!(*status1 & S35390A_FLAG_BLD)) | |
| 124 | + /* | |
| 125 | + * If both POC and BLD are unset everything is fine. | |
| 126 | + */ | |
| 105 | 127 | return 0; |
| 106 | 128 | |
| 107 | − buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); | |
| 108 | − buf[0] &= 0xf0; | |
| 109 | − return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); | |
| 129 | + /* | |
| 130 | + * At least one of POC and BLD are set, so reinitialise chip. Keeping | |
| 131 | + * this information in the hardware to know later that the time isn't | |
| 132 | + * valid is unfortunately not possible because POC and BLD are cleared | |
| 133 | + * on read. So the reset is best done now. | |
| 134 | + * | |
| 135 | + * The 24H bit is kept over reset, so set it already here. | |
| 136 | + */ | |
| 137 | +initialize: | |
| 138 | + *status1 = S35390A_FLAG_24H; | |
| 139 | + buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; | |
| 140 | + ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); | |
| 141 | + | |
| 142 | + if (ret < 0) | |
| 143 | + return ret; | |
| 144 | + | |
| 145 | + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); | |
| 146 | + if (ret < 0) | |
| 147 | + return ret; | |
| 148 | + | |
| 149 | + if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { | |
| 150 | + /* Try up to five times to reset the chip */ | |
| 151 | + if (initcount < 5) { | |
| 152 | + ++initcount; | |
| 153 | + goto initialize; | |
| 154 | + } else | |
| 155 | + return -EIO; | |
| 156 | + } | |
| 157 | + | |
| 158 | + return 1; | |
| 110 | 159 | } |
| 111 | 160 | |
| 112 | 161 | 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) · 104 unmodified lines | ||
| 217 | 266 | alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, |
| 218 | 267 | alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); |
| 219 | 268 | |
| 220 | − /* disable interrupt */ | |
| 269 | + /* disable interrupt (which deasserts the irq line) */ | |
| 221 | 270 | err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); |
| 222 | 271 | if (err < 0) |
| 223 | 272 | return err; |
| 224 | 273 | |
| 225 | − /* clear pending interrupt, if any */ | |
| 274 | + /* clear pending interrupt (in STATUS1 only), if any */ | |
| 226 | 275 | err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); |
| 227 | 276 | if (err < 0) |
| 228 | 277 | return err; |
| @@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) · 13 unmodified lines | ||
| 242 | 291 | |
| 243 | 292 | if (alm->time.tm_wday != -1) |
| 244 | 293 | buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; |
| 294 | + else | |
| 295 | + buf[S35390A_ALRM_BYTE_WDAY] = 0; | |
| 245 | 296 | |
| 246 | 297 | buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, |
| 247 | 298 | alm->time.tm_hour) | 0x80; |
| @@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) · 21 unmodified lines | ||
| 269 | 320 | if (err < 0) |
| 270 | 321 | return err; |
| 271 | 322 | |
| 272 | − if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) | |
| 273 | − return -EINVAL; | |
| 323 | + if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { | |
| 324 | + /* | |
| 325 | + * When the alarm isn't enabled, the register to configure | |
| 326 | + * the alarm time isn't accessible. | |
| 327 | + */ | |
| 328 | + alm->enabled = 0; | |
| 329 | + return 0; | |
| 330 | + } else { | |
| 331 | + alm->enabled = 1; | |
| 332 | + } | |
| 274 | 333 | |
| 275 | 334 | err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); |
| 276 | 335 | if (err < 0) |
| 277 | 336 | return err; |
| 278 | 337 | |
| 279 | 338 | /* This chip returns the bits of each byte in reverse order */ |
| 280 | − for (i = 0; i < 3; ++i) { | |
| 339 | + for (i = 0; i < 3; ++i) | |
| 281 | 340 | buf[i] = bitrev8(buf[i]); |
| 282 | − buf[i] &= ~0x80; | |
| 283 | − } | |
| 284 | 341 | |
| 285 | − alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); | |
| 286 | − alm->time.tm_hour = s35390a_reg2hr(s35390a, | |
| 287 | − buf[S35390A_ALRM_BYTE_HOURS]); | |
| 288 | − alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); | |
| 342 | + /* | |
| 343 | + * B0 of the three matching registers is an enable flag. Iff it is set | |
| 344 | + * the configured value is used for matching. | |
| 345 | + */ | |
| 346 | + if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80) | |
| 347 | + alm->time.tm_wday = | |
| 348 | + bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80); | |
| 349 | + | |
| 350 | + if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80) | |
| 351 | + alm->time.tm_hour = | |
| 352 | + s35390a_reg2hr(s35390a, | |
| 353 | + buf[S35390A_ALRM_BYTE_HOURS] & ~0x80); | |
| 354 | + | |
| 355 | + if (buf[S35390A_ALRM_BYTE_MINS] & 0x80) | |
| 356 | + alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80); | |
| 357 | + | |
| 358 | + /* alarm triggers always at s=0 */ | |
| 359 | + alm->time.tm_sec = 0; | |
| 289 | 360 | |
| 290 | 361 | dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", |
| 291 | 362 | __func__, alm->time.tm_min, alm->time.tm_hour, |
| @@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver; · 35 unmodified lines | ||
| 327 | 398 | static int s35390a_probe(struct i2c_client *client, |
| 328 | 399 | const struct i2c_device_id *id) |
| 329 | 400 | { |
| 330 | − int err; | |
| 401 | + int err, err_reset; | |
| 331 | 402 | unsigned int i; |
| 332 | 403 | struct s35390a *s35390a; |
| 333 | 404 | struct rtc_time tm; |
| 334 | − char buf[1]; | |
| 405 | + char buf, status1; | |
| 335 | 406 | |
| 336 | 407 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| 337 | 408 | err = -ENODEV; |
| @@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client, · 22 unmodified lines | ||
| 360 | 431 | } |
| 361 | 432 | } |
| 362 | 433 | |
| 363 | − err = s35390a_reset(s35390a); | |
| 364 | − if (err < 0) { | |
| 434 | + err_reset = s35390a_reset(s35390a, &status1); | |
| 435 | + if (err_reset < 0) { | |
| 436 | + err = err_reset; | |
| 365 | 437 | dev_err(&client->dev, "error resetting chip\n"); |
| 366 | 438 | goto exit_dummy; |
| 367 | 439 | } |
| 368 | 440 | |
| 369 | − err = s35390a_disable_test_mode(s35390a); | |
| 370 | − if (err < 0) { | |
| 371 | − dev_err(&client->dev, "error disabling test mode\n"); | |
| 372 | − goto exit_dummy; | |
| 373 | − } | |
| 374 | − | |
| 375 | − err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); | |
| 376 | − if (err < 0) { | |
| 377 | − dev_err(&client->dev, "error checking 12/24 hour mode\n"); | |
| 378 | − goto exit_dummy; | |
| 379 | − } | |
| 380 | − if (buf[0] & S35390A_FLAG_24H) | |
| 441 | + if (status1 & S35390A_FLAG_24H) | |
| 381 | 442 | s35390a->twentyfourhour = 1; |
| 382 | 443 | else |
| 383 | 444 | s35390a->twentyfourhour = 0; |
| 384 | 445 | |
| 385 | − if (s35390a_get_datetime(client, &tm) < 0) | |
| 446 | + if (status1 & S35390A_FLAG_INT2) { | |
| 447 | + /* disable alarm (and maybe test mode) */ | |
| 448 | + buf = 0; | |
| 449 | + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); | |
| 450 | + if (err < 0) { | |
| 451 | + dev_err(&client->dev, "error disabling alarm"); | |
| 452 | + goto exit_dummy; | |
| 453 | + } | |
| 454 | + } else { | |
| 455 | + err = s35390a_disable_test_mode(s35390a); | |
| 456 | + if (err < 0) { | |
| 457 | + dev_err(&client->dev, "error disabling test mode\n"); | |
| 458 | + goto exit_dummy; | |
| 459 | + } | |
| 460 | + } | |
| 461 | + | |
| 462 | + if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0) | |
| 386 | 463 | dev_warn(&client->dev, "clock needs to be set\n"); |
| 387 | 464 | |
| 388 | 465 | device_set_wakeup_capable(&client->dev, 1); |
| @@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client, · 6 unmodified lines | ||
| 395 | 472 | err = PTR_ERR(s35390a->rtc); |
| 396 | 473 | goto exit_dummy; |
| 397 | 474 | } |
| 475 | + | |
| 476 | + if (status1 & S35390A_FLAG_INT2) | |
| 477 | + rtc_update_irq(s35390a->rtc, 1, RTC_AF); | |
| 478 | + | |
| 398 | 479 | return 0; |
| 399 | 480 | |
| 400 | 481 | exit_dummy: |
| @@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) · 148 unmodified lines | ||
| 149 | 149 | if (!is_power_of_2(freq)) |
| 150 | 150 | return -EINVAL; |
| 151 | 151 | |
| 152 | + s3c_rtc_enable_clk(info); | |
| 152 | 153 | spin_lock_irq(&info->pie_lock); |
| 153 | 154 | |
| 154 | 155 | if (info->data->set_freq) |
| 155 | 156 | info->data->set_freq(info, freq); |
| 156 | 157 | |
| 157 | 158 | spin_unlock_irq(&info->pie_lock); |
| 159 | + s3c_rtc_disable_clk(info); | |
| 158 | 160 | |
| 159 | 161 | return 0; |
| 160 | 162 | } |
| @@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) · 103 unmodified lines | ||
| 264 | 266 | /* decode the alarm enable field */ |
| 265 | 267 | if (alm_en & S3C2410_RTCALM_SECEN) |
| 266 | 268 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
| 267 | − else | |
| 268 | − alm_tm->tm_sec = -1; | |
| 269 | 269 | |
| 270 | 270 | if (alm_en & S3C2410_RTCALM_MINEN) |
| 271 | 271 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
| 272 | − else | |
| 273 | − alm_tm->tm_min = -1; | |
| 274 | 272 | |
| 275 | 273 | if (alm_en & S3C2410_RTCALM_HOUREN) |
| 276 | 274 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
| 277 | − else | |
| 278 | − alm_tm->tm_hour = -1; | |
| 279 | 275 | |
| 280 | 276 | if (alm_en & S3C2410_RTCALM_DAYEN) |
| 281 | 277 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
| 282 | − else | |
| 283 | − alm_tm->tm_mday = -1; | |
| 284 | 278 | |
| 285 | 279 | if (alm_en & S3C2410_RTCALM_MONEN) { |
| 286 | 280 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
| 287 | 281 | alm_tm->tm_mon -= 1; |
| 288 | − } else { | |
| 289 | − alm_tm->tm_mon = -1; | |
| 290 | 282 | } |
| 291 | 283 | |
| 292 | 284 | if (alm_en & S3C2410_RTCALM_YEAREN) |
| 293 | 285 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
| 294 | − else | |
| 295 | − alm_tm->tm_year = -1; | |
| 296 | 286 | |
| 297 | 287 | return 0; |
| 298 | 288 | } |
| @@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) · 278 unmodified lines | ||
| 577 | 567 | |
| 578 | 568 | s3c_rtc_setfreq(info, 1); |
| 579 | 569 | |
| 580 | − s3c_rtc_disable_clk(info); | |
| 581 | − | |
| 582 | 570 | return 0; |
| 583 | 571 | |
| 584 | 572 | err_nortc: |
| @@ -481,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) · 480 unmodified lines | ||
| 481 | 481 | tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR); |
| 482 | 482 | if (tm->tm_mon > 0) |
| 483 | 483 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ |
| 484 | − tm->tm_year = 0xffff; | |
| 485 | 484 | |
| 486 | 485 | wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0; |
| 487 | 486 | |
| @@ -500,52 +499,13 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, · 12 unmodified lines | ||
| 500 | 499 | writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off); |
| 501 | 500 | } |
| 502 | 501 | |
| 503 | −static int sh_rtc_check_alarm(struct rtc_time *tm) | |
| 504 | −{ | |
| 505 | − /* | |
| 506 | − * The original rtc says anything > 0xc0 is "don't care" or "match | |
| 507 | − * all" - most users use 0xff but rtc-dev uses -1 for the same thing. | |
| 508 | − * The original rtc doesn't support years - some things use -1 and | |
| 509 | − * some 0xffff. We use -1 to make out tests easier. | |
| 510 | − */ | |
| 511 | − if (tm->tm_year == 0xffff) | |
| 512 | − tm->tm_year = -1; | |
| 513 | − if (tm->tm_mon >= 0xff) | |
| 514 | − tm->tm_mon = -1; | |
| 515 | − if (tm->tm_mday >= 0xff) | |
| 516 | − tm->tm_mday = -1; | |
| 517 | − if (tm->tm_wday >= 0xff) | |
| 518 | − tm->tm_wday = -1; | |
| 519 | − if (tm->tm_hour >= 0xff) | |
| 520 | − tm->tm_hour = -1; | |
| 521 | − if (tm->tm_min >= 0xff) | |
| 522 | − tm->tm_min = -1; | |
| 523 | − if (tm->tm_sec >= 0xff) | |
| 524 | − tm->tm_sec = -1; | |
| 525 | − | |
| 526 | − if (tm->tm_year > 9999 || | |
| 527 | − tm->tm_mon >= 12 || | |
| 528 | − tm->tm_mday == 0 || tm->tm_mday >= 32 || | |
| 529 | − tm->tm_wday >= 7 || | |
| 530 | − tm->tm_hour >= 24 || | |
| 531 | − tm->tm_min >= 60 || | |
| 532 | − tm->tm_sec >= 60) | |
| 533 | − return -EINVAL; | |
| 534 | − | |
| 535 | − return 0; | |
| 536 | −} | |
| 537 | − | |
| 538 | 502 | static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
| 539 | 503 | { |
| 540 | 504 | struct platform_device *pdev = to_platform_device(dev); |
| 541 | 505 | struct sh_rtc *rtc = platform_get_drvdata(pdev); |
| 542 | 506 | unsigned int rcr1; |
| 543 | 507 | struct rtc_time *tm = &wkalrm->time; |
| 544 | − int mon, err; | |
| 545 | − | |
| 546 | − err = sh_rtc_check_alarm(tm); | |
| 547 | − if (unlikely(err < 0)) | |
| 548 | − return err; | |
| 508 | + int mon; | |
| 549 | 509 | |
| 550 | 510 | spin_lock_irq(&rtc->lock); |
| 551 | 511 | |
| @@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) · 178 unmodified lines | ||
| 179 | 179 | if (sec == 0) { |
| 180 | 180 | /* alarm is disabled. */ |
| 181 | 181 | alarm->enabled = 0; |
| 182 | − alarm->time.tm_mon = -1; | |
| 183 | − alarm->time.tm_mday = -1; | |
| 184 | − alarm->time.tm_year = -1; | |
| 185 | − alarm->time.tm_hour = -1; | |
| 186 | − alarm->time.tm_min = -1; | |
| 187 | − alarm->time.tm_sec = -1; | |
| 188 | 182 | } else { |
| 189 | 183 | /* alarm is enabled. */ |
| 190 | 184 | alarm->enabled = 1; |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/rtc.h> |
| 26 | 26 | #include <linux/types.h> |
| 27 | 27 | #include <linux/bcd.h> |
| 28 | −#include <linux/rtc-v3020.h> | |
| 28 | +#include <linux/platform_data/rtc-v3020.h> | |
| 29 | 29 | #include <linux/delay.h> |
| 30 | 30 | #include <linux/gpio.h> |
| 31 | 31 | #include <linux/slab.h> |
| @@ -1,66 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * ds17287rtc.h - register definitions for the ds1728[57] RTC / CMOS RAM | |
| 3 | − * | |
| 4 | − * This file is subject to the terms and conditions of the GNU General Public | |
| 5 | − * License. See the file "COPYING" in the main directory of this archive | |
| 6 | − * for more details. | |
| 7 | − * | |
| 8 | − * (C) 2003 Guido Guenther <agx@sigxcpu.org> | |
| 9 | − */ | |
| 10 | −#ifndef __LINUX_DS17287RTC_H | |
| 11 | −#define __LINUX_DS17287RTC_H | |
| 12 | − | |
| 13 | −#include <linux/rtc.h> /* get the user-level API */ | |
| 14 | −#include <linux/mc146818rtc.h> | |
| 15 | − | |
| 16 | −/* Register A */ | |
| 17 | −#define DS_REGA_DV2 0x40 /* countdown chain */ | |
| 18 | −#define DS_REGA_DV1 0x20 /* oscillator enable */ | |
| 19 | −#define DS_REGA_DV0 0x10 /* bank select */ | |
| 20 | − | |
| 21 | −/* bank 1 registers */ | |
| 22 | −#define DS_B1_MODEL 0x40 /* model number byte */ | |
| 23 | −#define DS_B1_SN1 0x41 /* serial number byte 1 */ | |
| 24 | −#define DS_B1_SN2 0x42 /* serial number byte 2 */ | |
| 25 | −#define DS_B1_SN3 0x43 /* serial number byte 3 */ | |
| 26 | −#define DS_B1_SN4 0x44 /* serial number byte 4 */ | |
| 27 | −#define DS_B1_SN5 0x45 /* serial number byte 5 */ | |
| 28 | −#define DS_B1_SN6 0x46 /* serial number byte 6 */ | |
| 29 | −#define DS_B1_CRC 0x47 /* CRC byte */ | |
| 30 | −#define DS_B1_CENTURY 0x48 /* Century byte */ | |
| 31 | −#define DS_B1_DALARM 0x49 /* date alarm */ | |
| 32 | −#define DS_B1_XCTRL4A 0x4a /* extendec control register 4a */ | |
| 33 | −#define DS_B1_XCTRL4B 0x4b /* extendec control register 4b */ | |
| 34 | −#define DS_B1_RTCADDR2 0x4e /* rtc address 2 */ | |
| 35 | −#define DS_B1_RTCADDR3 0x4f /* rtc address 3 */ | |
| 36 | −#define DS_B1_RAMLSB 0x50 /* extended ram LSB */ | |
| 37 | −#define DS_B1_RAMMSB 0x51 /* extended ram MSB */ | |
| 38 | −#define DS_B1_RAMDPORT 0x53 /* extended ram data port */ | |
| 39 | − | |
| 40 | −/* register details */ | |
| 41 | −/* extended control register 4a */ | |
| 42 | −#define DS_XCTRL4A_VRT2 0x80 /* valid ram and time */ | |
| 43 | −#define DS_XCTRL4A_INCR 0x40 /* increment progress status */ | |
| 44 | −#define DS_XCTRL4A_BME 0x20 /* burst mode enable */ | |
| 45 | −#define DS_XCTRL4A_PAB 0x08 /* power active bar ctrl */ | |
| 46 | −#define DS_XCTRL4A_RF 0x04 /* ram clear flag */ | |
| 47 | −#define DS_XCTRL4A_WF 0x02 /* wake up alarm flag */ | |
| 48 | −#define DS_XCTRL4A_KF 0x01 /* kickstart flag */ | |
| 49 | − | |
| 50 | −/* interrupt causes */ | |
| 51 | −#define DS_XCTRL4A_IFS (DS_XCTRL4A_RF|DS_XCTRL4A_WF|DS_XCTRL4A_KF) | |
| 52 | − | |
| 53 | −/* extended control register 4b */ | |
| 54 | −#define DS_XCTRL4B_ABE 0x80 /* auxiliary battery enable */ | |
| 55 | −#define DS_XCTRL4B_E32K 0x40 /* enable 32.768 kHz Output */ | |
| 56 | −#define DS_XCTRL4B_CS 0x20 /* crystal select */ | |
| 57 | −#define DS_XCTRL4B_RCE 0x10 /* ram clear enable */ | |
| 58 | −#define DS_XCTRL4B_PRS 0x08 /* PAB resec select */ | |
| 59 | −#define DS_XCTRL4B_RIE 0x04 /* ram clear interrupt enable */ | |
| 60 | −#define DS_XCTRL4B_WFE 0x02 /* wake up alarm interrupt enable */ | |
| 61 | −#define DS_XCTRL4B_KFE 0x01 /* kickstart interrupt enable */ | |
| 62 | − | |
| 63 | −/* interrupt enable bits */ | |
| 64 | −#define DS_XCTRL4B_IFES (DS_XCTRL4B_RIE|DS_XCTRL4B_WFE|DS_XCTRL4B_KFE) | |
| 65 | − | |
| 66 | −#endif /* __LINUX_DS17287RTC_H */ | |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <asm/io.h> |
| 15 | 15 | #include <linux/rtc.h> /* get the user-level API */ |
| 16 | 16 | #include <asm/mc146818rtc.h> /* register access macros */ |
| 17 | +#include <linux/bcd.h> | |
| 18 | +#include <linux/delay.h> | |
| 17 | 19 | |
| 18 | 20 | #ifdef __KERNEL__ |
| 19 | 21 | #include <linux/spinlock.h> /* spinlock_t */ |
| @@ -120,4 +122,7 @@ struct cmos_rtc_board_info { · 100 unmodified lines | ||
| 120 | 122 | #define RTC_IO_EXTENT_USED RTC_IO_EXTENT |
| 121 | 123 | #endif /* ARCH_RTC_LOCATION */ |
| 122 | 124 | |
| 125 | +unsigned int mc146818_get_time(struct rtc_time *time); | |
| 126 | +int mc146818_set_time(struct rtc_time *time); | |
| 127 | + | |
| 123 | 128 | #endif /* _MC146818RTC_H */ |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -144,11 +144,12 @@ test_READ: · 143 unmodified lines | ||
| 144 | 144 | |
| 145 | 145 | retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); |
| 146 | 146 | if (retval == -1) { |
| 147 | − if (errno == ENOTTY) { | |
| 147 | + if (errno == EINVAL) { | |
| 148 | 148 | fprintf(stderr, |
| 149 | 149 | "\n...Alarm IRQs not supported.\n"); |
| 150 | 150 | goto test_PIE; |
| 151 | 151 | } |
| 152 | + | |
| 152 | 153 | perror("RTC_ALM_SET ioctl"); |
| 153 | 154 | exit(errno); |
| 154 | 155 | } |
| @@ -166,6 +167,12 @@ test_READ: · 11 unmodified lines | ||
| 166 | 167 | /* Enable alarm interrupts */ |
| 167 | 168 | retval = ioctl(fd, RTC_AIE_ON, 0); |
| 168 | 169 | if (retval == -1) { |
| 170 | + if (errno == EINVAL) { | |
| 171 | + fprintf(stderr, | |
| 172 | + "\n...Alarm IRQs not supported.\n"); | |
| 173 | + goto test_PIE; | |
| 174 | + } | |
| 175 | + | |
| 169 | 176 | perror("RTC_AIE_ON ioctl"); |
| 170 | 177 | exit(errno); |
| 171 | 178 | } |
| @@ -193,7 +200,7 @@ test_PIE: · 21 unmodified lines | ||
| 193 | 200 | retval = ioctl(fd, RTC_IRQP_READ, &tmp); |
| 194 | 201 | if (retval == -1) { |
| 195 | 202 | /* not all RTCs support periodic IRQs */ |
| 196 | − if (errno == ENOTTY) { | |
| 203 | + if (errno == EINVAL) { | |
| 197 | 204 | fprintf(stderr, "\nNo periodic IRQ support\n"); |
| 198 | 205 | goto done; |
| 199 | 206 | } |
| @@ -211,7 +218,7 @@ test_PIE: · 11 unmodified lines | ||
| 211 | 218 | retval = ioctl(fd, RTC_IRQP_SET, tmp); |
| 212 | 219 | if (retval == -1) { |
| 213 | 220 | /* not all RTCs can change their periodic IRQ rate */ |
| 214 | − if (errno == ENOTTY) { | |
| 221 | + if (errno == EINVAL) { | |
| 215 | 222 | fprintf(stderr, |
| 216 | 223 | "\n...Periodic IRQ rate is fixed\n"); |
| 217 | 224 | goto done; |