1
0
Fork 0

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
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCgAGBQJXokhIAAoJENiigzvaE+LCZqQP+wWzintN/N1u3dKiVB7iSdwq
 +S/jAXD9wW8OK9PI60/YUGRYeUXmZW9t4XYg1VKCxU9KpVC17LgOtDyXD8BufP1V
 uREJEzZw9O7zCCjeHp/ICFjBkc62Net6ZDOO+ZyXPNfddpS1Xq1uUgXLZc/202UR
 ID/kewu0pJRDnoxyqznWn9+8D33w/ygXs2slY2Ive0ONtjdgxGcsj2rNbb2RYn2z
 OP7br3lLg7qkFh4TtXb61eh/9GYIk6wzP/CrX5l/jH4SjQnrIk5g/X/Cd1qQ/qso
 JZzFoonOKvIp5Gw/+fZ9NP3YFcnkoRMv4NjZV8PAmsYLds+ibRiBcoB8u6FmiJV7
 WW5uopgPkfCGN5BV3+QHwJDVe+WlgnlzaT5zPUCcP5KWusDts4fWIgzP7vrtAzf4
 3OJLrgSGdBeOqWnJD21nxKUD27JOseX7D+BFtwxR4lMsXHqlHJfETpZ8gts1ZGH3
 2U353j/jkZvGWmc6dMcuxOXT2K4VqpYeIIqs0IcLu6hM9crtR89zPR2Iu1AilfDW
 h2NroF+Q//SgMMzWoTEG6Tn7RAc7MthgA/tRCFZF9CBMzNs988w0CTHnKsIHmjpU
 UKkMeJGAC9YrPYIcqrg0oYsmLUWXc8JuZbGJBnei3BzbaMTlcwIN9qj36zfq6xWc
 TMLpbWEoIsgFIZMP/hAP
 =rpGB
 -----END PGP SIGNATURE-----

Merge tag 'rtc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2016-08-05 09:48:22 -04:00
commit 6c84239d59
105 changed files with 848 additions and 1580 deletions

View File

@ -9828,10 +9828,14 @@ L: rtc-linux@googlegroups.com
Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
S: Maintained
F: Documentation/devicetree/bindings/rtc/
F: Documentation/rtc.txt
F: drivers/rtc/
F: include/linux/rtc.h
F: include/uapi/linux/rtc.h
F: include/linux/rtc/
F: include/linux/platform_data/rtc-*
F: tools/testing/selftests/timers/rtctest.c
REALTEK AUDIO CODECS
M: Bard Liao <bardliao@realtek.com>

View File

@ -1 +0,0 @@
#include <asm-generic/rtc.h>

View File

@ -24,7 +24,6 @@
#include <asm/gct.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/rtc.h>
#include <asm/vga.h>
#include "proto.h"

View File

@ -15,8 +15,6 @@
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <asm/rtc.h>
#include "proto.h"
@ -81,7 +79,7 @@ init_rtc_epoch(void)
static int
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
__get_rtc_time(tm);
mc146818_get_time(tm);
/* Adjust for non-default epochs. It's easier to depend on the
generic __get_rtc_time and adjust the epoch here than create
@ -112,7 +110,7 @@ alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
tm = &xtm;
}
return __set_rtc_time(tm);
return mc146818_set_time(tm);
}
static int

View File

@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/m48t86.h>
#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>

View File

@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>
#include <linux/m48t86.h>
#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/timeriomem-rng.h>

View File

@ -14,7 +14,7 @@
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/rtc-v3020.h>
#include <linux/platform_data/rtc-v3020.h>
#include <video/mbxfb.h>
#include <linux/spi/spi.h>

View File

@ -25,7 +25,7 @@
#include <linux/gpio.h>
#include <linux/dm9000.h>
#include <linux/leds.h>
#include <linux/rtc-v3020.h>
#include <linux/platform_data/rtc-v3020.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>

View File

@ -14,7 +14,7 @@
#include <linux/delay.h>
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
#include <linux/platform_data/rtc-v3020.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>

View File

@ -1,16 +0,0 @@
/* mc146818rtc.h: RTC defs
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_MC146818RTC_H
#define _ASM_MC146818RTC_H
#endif /* _ASM_MC146818RTC_H */

View File

@ -1,9 +0,0 @@
/*
* Machine dependent access functions for RTC registers.
*/
#ifndef _H8300_MC146818RTC_H
#define _H8300_MC146818RTC_H
/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
#endif /* _H8300_MC146818RTC_H */

View File

@ -1,10 +0,0 @@
#ifndef _ASM_IA64_MC146818RTC_H
#define _ASM_IA64_MC146818RTC_H
/*
* Machine dependent access functions for RTC registers.
*/
/* empty include file to satisfy the include in genrtc.c */
#endif /* _ASM_IA64_MC146818RTC_H */

View File

@ -35,7 +35,6 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/io.h>

View File

@ -15,7 +15,6 @@
#include <asm/pgtable.h>
#include <asm/apollohw.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
u_long sio01_physaddr;

View File

@ -34,7 +34,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/bvme6000hw.h>

View File

@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/rtc.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-hp300.h>
@ -20,7 +21,6 @@
#include <asm/blinken.h>
#include <asm/io.h> /* readb() and writeb() */
#include <asm/hp300hw.h>
#include <asm/rtc.h>
#include "time.h"

View File

@ -1,79 +0,0 @@
/* include/asm-m68k/rtc.h
*
* Copyright Richard Zidlicky
* implementation details for genrtc/q40rtc driver
*/
/* permission is hereby granted to copy, modify and redistribute this code
* in terms of the GNU Library General Public License, Version 2 or later,
* at your option.
*/
#ifndef _ASM_RTC_H
#define _ASM_RTC_H
#ifdef __KERNEL__
#include <linux/rtc.h>
#include <asm/errno.h>
#include <asm/machdep.h>
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
/* some dummy definitions */
#define RTC_BATT_BAD 0x100 /* battery bad */
#define RTC_SQWE 0x08 /* enable square-wave output */
#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
static inline unsigned int get_rtc_time(struct rtc_time *time)
{
/*
* Only the values that we read from the RTC are set. We leave
* tm_wday, tm_yday and tm_isdst untouched. Even though the
* RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
* by the RTC when initially set to a non-zero value.
*/
if (mach_hwclk)
mach_hwclk(0, time);
return RTC_24H;
}
static inline int set_rtc_time(struct rtc_time *time)
{
if (mach_hwclk)
return mach_hwclk(1, time);
return -EINVAL;
}
static inline unsigned int get_rtc_ss(void)
{
if (mach_get_ss)
return mach_get_ss();
else{
struct rtc_time h;
get_rtc_time(&h);
return h.tm_sec;
}
}
static inline int get_rtc_pll(struct rtc_pll_info *pll)
{
if (mach_get_rtc_pll)
return mach_get_rtc_pll(pll);
else
return -EINVAL;
}
static inline int set_rtc_pll(struct rtc_pll_info *pll)
{
if (mach_set_rtc_pll)
return mach_set_rtc_pll(pll);
else
return -EINVAL;
}
#endif /* __KERNEL__ */
#endif /* _ASM__RTC_H */

View File

@ -86,7 +86,49 @@ void read_persistent_clock(struct timespec *ts)
}
}
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
#if defined(CONFIG_ARCH_USES_GETTIMEOFFSET) && IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
mach_hwclk(0, tm);
return rtc_valid_tm(tm);
}
static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
{
if (mach_hwclk(1, tm) < 0)
return -EOPNOTSUPP;
return 0;
}
static int rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct rtc_pll_info pll;
struct rtc_pll_info __user *argp = (void __user *)arg;
switch (cmd) {
case RTC_PLL_GET:
if (!mach_get_rtc_pll || mach_get_rtc_pll(&pll))
return -EINVAL;
return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
case RTC_PLL_SET:
if (!mach_set_rtc_pll)
return -EINVAL;
if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&pll, argp, sizeof(pll)))
return -EFAULT;
return mach_set_rtc_pll(&pll);
}
return -ENOIOCTLCMD;
}
static const struct rtc_class_ops generic_rtc_ops = {
.ioctl = rtc_ioctl,
.read_time = rtc_generic_get_time,
.set_time = rtc_generic_set_time,
};
static int __init rtc_init(void)
{
@ -95,7 +137,9 @@ static int __init rtc_init(void)
if (!mach_hwclk)
return -ENODEV;
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
pdev = platform_device_register_data(NULL, "rtc-generic", -1,
&generic_rtc_ops,
sizeof(generic_rtc_ops));
return PTR_ERR_OR_ZERO(pdev);
}

View File

@ -10,6 +10,7 @@
* Miscellaneous linux stuff
*/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/mm.h>
@ -25,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/rtc.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
@ -34,7 +36,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/macintosh.h>

View File

@ -18,7 +18,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/rtc.h>
#include <asm/segment.h>
#include <asm/setup.h>
#include <asm/macintosh.h>

View File

@ -32,7 +32,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/mvme147hw.h>

View File

@ -35,7 +35,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/mvme16xhw.h>

View File

@ -12,6 +12,7 @@
* for more details.
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@ -27,7 +28,6 @@
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/rtc.h>
#include <asm/bootinfo.h>
#include <asm/pgtable.h>
#include <asm/setup.h>

View File

@ -26,7 +26,6 @@
#include <asm/pgalloc.h>
#include <asm/sun3-head.h>
#include <asm/sun3mmu.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/machines.h>
#include <asm/idprom.h>

View File

@ -14,8 +14,8 @@
#include <linux/rtc.h>
#include <asm/errno.h>
#include <asm/rtc.h>
#include <asm/intersil.h>
#include <asm/machdep.h>
/* bits to set for start/run of the intersil */

View File

@ -15,10 +15,10 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/traps.h>
#include <asm/sun3x.h>
#include <asm/sun3ints.h>
#include <asm/rtc.h>
#include "time.h"

View File

@ -7,7 +7,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/ds1286.h>
#include <linux/rtc/ds1286.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>

View File

@ -8,7 +8,6 @@
#include <asm/sni.h>
#include <asm/time.h>
#include <asm-generic/rtc.h>
#define SNI_CLOCK_TICK_RATE 3686400
#define SNI_COUNTER2_DIV 64

View File

@ -236,7 +236,9 @@ source "kernel/Kconfig.hz"
config MN10300_RTC
bool "Using MN10300 RTC"
depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
select GENERIC_CMOS_UPDATE
select RTC_CLASS
select RTC_DRV_CMOS
select RTC_SYSTOHC
default n
help
This option enables support for the RTC, thus enabling time to be

View File

@ -75,9 +75,9 @@
#define RTC_PORT(x) 0xd8600000
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
#define CMOS_READ(addr) __SYSREG(0xd8600000 + (addr), u8)
#define CMOS_READ(addr) __SYSREG(0xd8600000 + (u32)(addr), u8)
#define CMOS_WRITE(val, addr) \
do { __SYSREG(0xd8600000 + (addr), u8) = val; } while (0)
do { __SYSREG(0xd8600000 + (u32)(addr), u8) = val; } while (0)
#define RTC_IRQ RTIRQ

View File

@ -25,6 +25,4 @@ static inline void calibrate_clock(void)
#endif /* !CONFIG_MN10300_RTC */
#include <asm-generic/rtc.h>
#endif /* _ASM_RTC_H */

View File

@ -12,107 +12,19 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <linux/bcd.h>
#include <linux/timex.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <asm/rtc-regs.h>
#include <asm/rtc.h>
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
/*
* Read the current RTC time
*/
void read_persistent_clock(struct timespec *ts)
{
struct rtc_time tm;
get_rtc_time(&tm);
ts->tv_nsec = 0;
ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
/* if rtc is way off in the past, set something reasonable */
if (ts->tv_sec < 0)
ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0);
}
/*
* In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
* ms after the second nowtime has started, because when nowtime is written
* into the registers of the CMOS clock, it will jump to the next second
* precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
* sheet for details.
*
* BUG: This routine does not handle hour overflow properly; it just
* sets the minutes. Usually you'll only notice that after reboot!
*/
static int set_rtc_mmss(unsigned long nowtime)
{
unsigned char save_control, save_freq_select;
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
/* gets recalled with irq locally disabled */
spin_lock(&rtc_lock);
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
* set */
CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
* prescaler */
CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
cmos_minutes = CMOS_READ(RTC_MINUTES);
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
cmos_minutes = bcd2bin(cmos_minutes);
/*
* since we're only adjusting minutes and seconds,
* don't interfere with hour overflow. This avoids
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
real_seconds = nowtime % 60;
real_minutes = nowtime / 60;
if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
/* correct for half hour time zone */
real_minutes += 30;
real_minutes %= 60;
if (abs(real_minutes - cmos_minutes) < 30) {
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
real_seconds = bin2bcd(real_seconds);
real_minutes = bin2bcd(real_minutes);
}
CMOS_WRITE(real_seconds, RTC_SECONDS);
CMOS_WRITE(real_minutes, RTC_MINUTES);
} else {
printk_once(KERN_NOTICE
"set_rtc_mmss: can't update from %d to %d\n",
cmos_minutes, real_minutes);
retval = -1;
}
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
* battery and quartz) will not reset the oscillator and will not
* update precisely 500 ms later. You won't find this mentioned in
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
spin_unlock(&rtc_lock);
return retval;
}
int update_persistent_clock(struct timespec now)
{
return set_rtc_mmss(now.tv_sec);
}
static const __initdata struct resource res[] = {
DEFINE_RES_IO(RTC_PORT(0), RTC_IO_EXTENT),
DEFINE_RES_IRQ(RTC_IRQ),
};
/*
* calibrate the TSC clock against the RTC
@ -129,4 +41,6 @@ void __init calibrate_clock(void)
RTCRA |= RTCRA_DVR;
RTCRA &= ~RTCRA_DVR;
RTCRB &= ~RTCRB_SET;
platform_device_register_simple("rtc_cmos", -1, res, ARRAY_SIZE(res));
}

View File

@ -9,7 +9,10 @@
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/irq.h>
#include <asm/cacheflush.h>
#include <asm/fpu.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/busctl-regs.h>

View File

@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/cacheflush.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>

View File

@ -1,9 +0,0 @@
/*
* Machine dependent access functions for RTC registers.
*/
#ifndef _ASM_MC146818RTC_H
#define _ASM_MC146818RTC_H
/* empty include file to satisfy the include in genrtc.c */
#endif /* _ASM_MC146818RTC_H */

View File

@ -1,131 +0,0 @@
/*
* include/asm-parisc/rtc.h
*
* Copyright 2002 Randolph CHung <tausq@debian.org>
*
* Based on: include/asm-ppc/rtc.h and the genrtc driver in the
* 2.4 parisc linux tree
*/
#ifndef __ASM_RTC_H__
#define __ASM_RTC_H__
#ifdef __KERNEL__
#include <linux/rtc.h>
#include <asm/pdc.h>
#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
#define RTC_BATT_BAD 0x100 /* battery bad */
/* some dummy definitions */
#define RTC_SQWE 0x08 /* enable square-wave output */
#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
# define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
/* How many days come before each month (0-12). */
static const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
static inline unsigned int get_rtc_time(struct rtc_time *wtime)
{
struct pdc_tod tod_data;
long int days, rem, y;
const unsigned short int *ip;
memset(wtime, 0, sizeof(*wtime));
if (pdc_tod_read(&tod_data) < 0)
return RTC_24H | RTC_BATT_BAD;
// most of the remainder of this function is:
// Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
// This was originally a part of the GNU C Library.
// It is distributed under the GPL, and was swiped from offtime.c
days = tod_data.tod_sec / SECS_PER_DAY;
rem = tod_data.tod_sec % SECS_PER_DAY;
wtime->tm_hour = rem / SECS_PER_HOUR;
rem %= SECS_PER_HOUR;
wtime->tm_min = rem / 60;
wtime->tm_sec = rem % 60;
y = 1970;
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
while (days < 0 || days >= (__isleap (y) ? 366 : 365))
{
/* Guess a corrected year, assuming 365 days per year. */
long int yg = y + days / 365 - (days % 365 < 0);
/* Adjust DAYS and Y to match the guessed year. */
days -= ((yg - y) * 365
+ LEAPS_THRU_END_OF (yg - 1)
- LEAPS_THRU_END_OF (y - 1));
y = yg;
}
wtime->tm_year = y - 1900;
ip = __mon_yday[__isleap(y)];
for (y = 11; days < (long int) ip[y]; --y)
continue;
days -= ip[y];
wtime->tm_mon = y;
wtime->tm_mday = days + 1;
return RTC_24H;
}
static int set_rtc_time(struct rtc_time *wtime)
{
u_int32_t secs;
secs = mktime(wtime->tm_year + 1900, wtime->tm_mon + 1, wtime->tm_mday,
wtime->tm_hour, wtime->tm_min, wtime->tm_sec);
if(pdc_tod_set(secs, 0) < 0)
return -1;
else
return 0;
}
static inline unsigned int get_rtc_ss(void)
{
struct rtc_time h;
get_rtc_time(&h);
return h.tm_sec;
}
static inline int get_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
static inline int set_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
#endif /* __KERNEL__ */
#endif /* __ASM_RTC_H__ */

View File

@ -12,6 +12,7 @@
*/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
@ -248,14 +249,47 @@ void __init start_cpu_itimer(void)
per_cpu(cpu_data, cpu).it_value = next_tick;
}
#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
struct pdc_tod tod_data;
memset(tm, 0, sizeof(*tm));
if (pdc_tod_read(&tod_data) < 0)
return -EOPNOTSUPP;
/* we treat tod_sec as unsigned, so this can work until year 2106 */
rtc_time64_to_tm(tod_data.tod_sec, tm);
return rtc_valid_tm(tm);
}
static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
{
time64_t secs = rtc_tm_to_time64(tm);
if (pdc_tod_set(secs, 0) < 0)
return -EOPNOTSUPP;
return 0;
}
static const struct rtc_class_ops rtc_generic_ops = {
.read_time = rtc_generic_get_time,
.set_time = rtc_generic_set_time,
};
static int __init rtc_init(void)
{
struct platform_device *pdev;
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
pdev = platform_device_register_data(NULL, "rtc-generic", -1,
&rtc_generic_ops,
sizeof(rtc_generic_ops));
return PTR_ERR_OR_ZERO(pdev);
}
device_initcall(rtc_init);
#endif
void read_persistent_clock(struct timespec *ts)
{

View File

@ -1,78 +0,0 @@
/*
* Real-time clock definitions and interfaces
*
* Author: Tom Rini <trini@mvista.com>
*
* 2002 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*
* Based on:
* include/asm-m68k/rtc.h
*
* Copyright Richard Zidlicky
* implementation details for genrtc/q40rtc driver
*
* And the old drivers/macintosh/rtc.c which was heavily based on:
* Linux/SPARC Real Time Clock Driver
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
*
* With additional work by Paul Mackerras and Franz Sirl.
*/
#ifndef __ASM_POWERPC_RTC_H__
#define __ASM_POWERPC_RTC_H__
#ifdef __KERNEL__
#include <linux/rtc.h>
#include <asm/machdep.h>
#include <asm/time.h>
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
/* some dummy definitions */
#define RTC_BATT_BAD 0x100 /* battery bad */
#define RTC_SQWE 0x08 /* enable square-wave output */
#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
static inline unsigned int get_rtc_time(struct rtc_time *time)
{
if (ppc_md.get_rtc_time)
ppc_md.get_rtc_time(time);
return RTC_24H;
}
/* Set the current date and time in the real time clock. */
static inline int set_rtc_time(struct rtc_time *time)
{
if (ppc_md.set_rtc_time)
return ppc_md.set_rtc_time(time);
return -EINVAL;
}
static inline unsigned int get_rtc_ss(void)
{
struct rtc_time h;
get_rtc_time(&h);
return h.tm_sec;
}
static inline int get_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
static inline int set_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_RTC_H__ */

View File

@ -56,6 +56,7 @@
#include <linux/irq_work.h>
#include <linux/clk-provider.h>
#include <linux/suspend.h>
#include <linux/rtc.h>
#include <asm/trace.h>
#include <asm/io.h>
@ -1159,6 +1160,29 @@ void calibrate_delay(void)
loops_per_jiffy = tb_ticks_per_jiffy;
}
#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
ppc_md.get_rtc_time(tm);
return rtc_valid_tm(tm);
}
static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
{
if (!ppc_md.set_rtc_time)
return -EOPNOTSUPP;
if (ppc_md.set_rtc_time(tm) < 0)
return -EOPNOTSUPP;
return 0;
}
static const struct rtc_class_ops rtc_generic_ops = {
.read_time = rtc_generic_get_time,
.set_time = rtc_generic_set_time,
};
static int __init rtc_init(void)
{
struct platform_device *pdev;
@ -1166,9 +1190,12 @@ static int __init rtc_init(void)
if (!ppc_md.get_rtc_time)
return -ENODEV;
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
pdev = platform_device_register_data(NULL, "rtc-generic", -1,
&rtc_generic_ops,
sizeof(rtc_generic_ops));
return PTR_ERR_OR_ZERO(pdev);
}
device_initcall(rtc_init);
#endif

View File

@ -321,6 +321,17 @@ config OF_RTC
Uses information from the OF or flattened device tree to instantiate
platform devices for direct mapped RTC chips like the DS1742 or DS1743.
config GEN_RTC
bool "Use the platform RTC operations from user space"
select RTC_CLASS
select RTC_DRV_GENERIC
help
This option provides backwards compatibility with the old gen_rtc.ko
module that was traditionally used for old PowerPC machines.
Platforms should migrate to enabling the RTC_DRV_GENERIC by hand
replacing their get_rtc_time/set_rtc_time callbacks with
a proper RTC device driver.
config SIMPLE_GPIO
bool "Support for simple, memory-mapped GPIO controllers"
depends on PPC

View File

@ -20,9 +20,9 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <asm/firmware.h>
#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>

View File

@ -1,7 +0,0 @@
/*
* Machine dependent access functions for RTC registers.
*/
#ifndef _ASM_MC146818RTC_H
#define _ASM_MC146818RTC_H
#endif /* _ASM_MC146818RTC_H */

View File

@ -6,17 +6,6 @@ extern void (*board_time_init)(void);
extern void (*rtc_sh_get_time)(struct timespec *);
extern int (*rtc_sh_set_time)(const time_t);
/* some dummy definitions */
#define RTC_BATT_BAD 0x100 /* battery bad */
#define RTC_SQWE 0x08 /* enable square-wave output */
#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
struct rtc_time;
unsigned int get_rtc_time(struct rtc_time *);
int set_rtc_time(struct rtc_time *);
#define RTC_CAP_4_DIGIT_YEAR (1 << 0)
struct sh_rtc_platform_info {

View File

@ -50,27 +50,31 @@ int update_persistent_clock(struct timespec now)
}
#endif
unsigned int get_rtc_time(struct rtc_time *tm)
static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
if (rtc_sh_get_time != null_rtc_get_time) {
struct timespec tv;
struct timespec tv;
rtc_sh_get_time(&tv);
rtc_time_to_tm(tv.tv_sec, tm);
}
return RTC_24H;
rtc_sh_get_time(&tv);
rtc_time_to_tm(tv.tv_sec, tm);
return 0;
}
EXPORT_SYMBOL(get_rtc_time);
int set_rtc_time(struct rtc_time *tm)
static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned long secs;
rtc_tm_to_time(tm, &secs);
return rtc_sh_set_time(secs);
if ((rtc_sh_set_time == null_rtc_set_time) ||
(rtc_sh_set_time(secs) < 0))
return -EOPNOTSUPP;
return 0;
}
EXPORT_SYMBOL(set_rtc_time);
static const struct rtc_class_ops rtc_generic_ops = {
.read_time = rtc_generic_get_time,
.set_time = rtc_generic_set_time,
};
static int __init rtc_generic_init(void)
{
@ -79,7 +83,10 @@ static int __init rtc_generic_init(void)
if (rtc_sh_get_time == null_rtc_get_time)
return -ENODEV;
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
pdev = platform_device_register_data(NULL, "rtc-generic", -1,
&rtc_generic_ops,
sizeof(rtc_generic_ops));
return PTR_ERR_OR_ZERO(pdev);
}

View File

@ -140,16 +140,6 @@ void ioport_unmap(void __iomem *);
struct pci_dev;
void pci_iounmap(struct pci_dev *dev, void __iomem *);
/*
* At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
* so rtc_port is static in it. This should not change unless a new
* hardware pops up.
*/
#define RTC_PORT(x) (rtc_port + (x))
#define RTC_ALWAYS_BCD 0
static inline int sbus_can_dma_64bit(void)
{
return 0; /* actually, sparc_cpu_model==sun4d */

View File

@ -152,6 +152,7 @@ config X86
select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
select PERF_EVENTS
select RTC_LIB
select RTC_MC146818_LIB
select SPARSE_IRQ
select SRCU
select SYSCTL_EXCEPTION_TRACE

View File

@ -6,7 +6,6 @@
#include <asm/io.h>
#include <asm/processor.h>
#include <linux/mc146818rtc.h>
#ifndef RTC_PORT
#define RTC_PORT(x) (0x70 + (x))

View File

@ -1 +0,0 @@
#include <asm-generic/rtc.h>

View File

@ -1019,7 +1019,6 @@ void hpet_disable(void)
*/
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
#include <asm/rtc.h>
#define DEFAULT_RTC_INT_FREQ 64
#define DEFAULT_RTC_SHIFT 6
@ -1243,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
memset(&curr_time, 0, sizeof(struct rtc_time));
if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
get_rtc_time(&curr_time);
mc146818_set_time(&curr_time);
if (hpet_rtc_flags & RTC_UIE &&
curr_time.tm_sec != hpet_prev_update_sec) {

View File

@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/hardirq.h>
#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/export.h>

View File

@ -13,7 +13,6 @@
#include <asm/x86_init.h>
#include <asm/time.h>
#include <asm/intel-mid.h>
#include <asm/rtc.h>
#include <asm/setup.h>
#ifdef CONFIG_X86_32
@ -47,7 +46,7 @@ int mach_set_rtc_mmss(const struct timespec *now)
rtc_time_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm)) {
retval = set_rtc_time(&tm);
retval = mc146818_set_time(&tm);
if (retval)
printk(KERN_ERR "%s: RTC write failed with error %d\n",
__func__, retval);

View File

@ -51,7 +51,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/x86_init.h>
#include <asm/rtc.h>
#include <asm/uv/uv.h>
static struct efi efi_phys __initdata;

View File

@ -25,6 +25,7 @@
#include <linux/bootmem.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <linux/efi.h>
#include <linux/uaccess.h>
#include <linux/io.h>

View File

@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>

View File

@ -14,7 +14,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm-generic/rtc.h>
#include <linux/mc146818rtc.h>
#include "internal.h"

View File

@ -11,7 +11,7 @@
#include <linux/export.h>
#include <linux/rtc.h>
#include <asm/rtc.h>
#include <linux/mc146818rtc.h>
#include "power.h"
@ -103,7 +103,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev
n /= 24;
time.tm_min = (n % 20) * 3;
n /= 20;
set_rtc_time(&time);
mc146818_set_time(&time);
return n ? -1 : 0;
}
@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
struct rtc_time time;
unsigned int val;
get_rtc_time(&time);
mc146818_get_time(&time);
pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
time.tm_hour, time.tm_min, time.tm_sec,
time.tm_mon + 1, time.tm_mday, time.tm_year % 100);

View File

@ -293,7 +293,7 @@ if RTC_LIB=n
config RTC
tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
depends on ALPHA || (MIPS && MACH_LOONGSON64) || MN10300
depends on ALPHA || (MIPS && MACH_LOONGSON64)
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@ -339,32 +339,6 @@ config JS_RTC
To compile this driver as a module, choose M here: the
module will be called js-rtc.
config GEN_RTC
tristate "Generic /dev/rtc emulation"
depends on RTC!=y
depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
will get access to the real time clock (or hardware clock) built
into your computer.
It reports status information via the file /proc/driver/rtc and its
behaviour is set by various ioctls on /dev/rtc. If you enable the
"extended RTC operation" below it will also provide an emulation
for RTC_UIE which is required by some programs and may improve
precision in some cases.
To compile this driver as a module, choose M here: the
module will be called genrtc.
config GEN_RTC_X
bool "Extended RTC operation"
depends on GEN_RTC
help
Provides an emulation for RTC_UIE which is required by some programs
and may improve precision of the generic RTC support in some cases.
config EFI_RTC
bool "EFI Real Time Clock Services"
depends on IA64

View File

@ -25,7 +25,6 @@ obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_SONYPI) += sonypi.o
obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_HPET) += hpet.o
obj-$(CONFIG_GEN_RTC) += genrtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/

View File

@ -1,539 +0,0 @@
/*
* Real Time Clock interface for
* - q40 and other m68k machines,
* - HP PARISC machines
* - PowerPC machines
* emulate some RTC irq capabilities in software
*
* Copyright (C) 1999 Richard Zidlicky
*
* based on Paul Gortmaker's rtc.c device and
* Sam Creasey Generic rtc driver
*
* This driver allows use of the real time clock (built into
* nearly all computers) from user space. It exports the /dev/rtc
* interface supporting various ioctl() and also the /proc/driver/rtc
* pseudo-file for status information.
*
* The ioctls can be used to set the interrupt behaviour where
* supported.
*
* The /dev/rtc interface will block on reads until an interrupt
* has been received. If a RTC interrupt has already happened,
* it will output an unsigned long and then block. The output value
* contains the interrupt status in the low byte and the number of
* interrupts since the last read in the remaining high bytes. The
* /dev/rtc interface can also be used with the select(2) call.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* 1.01 fix for 2.3.X rz@linux-m68k.org
* 1.02 merged with code from genrtc.c rz@linux-m68k.org
* 1.03 make it more portable zippel@linux-m68k.org
* 1.04 removed useless timer code rz@linux-m68k.org
* 1.05 portable RTC_UIE emulation rz@linux-m68k.org
* 1.06 set_rtc_time can return an error trini@kernel.crashing.org
* 1.07 ported to HP PARISC (hppa) Helge Deller <deller@gmx.de>
*/
#define RTC_VERSION "1.07"
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/rtc.h>
/*
* We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add
* an ioctl, make sure you don't conflict with SPARC's RTC
* ioctls.
*/
static DEFINE_MUTEX(gen_rtc_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
/*
* Bits in gen_rtc_status.
*/
#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
static unsigned char gen_rtc_status; /* bitmapped status byte. */
static unsigned long gen_rtc_irq_data; /* our output to the world */
/* months start at 0 now */
static unsigned char days_in_mo[] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int irq_active;
#ifdef CONFIG_GEN_RTC_X
static struct work_struct genrtc_task;
static struct timer_list timer_task;
static unsigned int oldsecs;
static int lostint;
static unsigned long tt_exp;
static void gen_rtc_timer(unsigned long data);
static volatile int stask_active; /* schedule_work */
static volatile int ttask_active; /* timer_task */
static int stop_rtc_timers; /* don't requeue tasks */
static DEFINE_SPINLOCK(gen_rtc_lock);
static void gen_rtc_interrupt(unsigned long arg);
/*
* Routine to poll RTC seconds field for change as often as possible,
* after first RTC_UIE use timer to reduce polling
*/
static void genrtc_troutine(struct work_struct *work)
{
unsigned int tmp = get_rtc_ss();
if (stop_rtc_timers) {
stask_active = 0;
return;
}
if (oldsecs != tmp){
oldsecs = tmp;
timer_task.function = gen_rtc_timer;
timer_task.expires = jiffies + HZ - (HZ/10);
tt_exp=timer_task.expires;
ttask_active=1;
stask_active=0;
add_timer(&timer_task);
gen_rtc_interrupt(0);
} else if (schedule_work(&genrtc_task) == 0)
stask_active = 0;
}
static void gen_rtc_timer(unsigned long data)
{
lostint = get_rtc_ss() - oldsecs ;
if (lostint<0)
lostint = 60 - lostint;
if (time_after(jiffies, tt_exp))
printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n",
jiffies-tt_exp);
ttask_active=0;
stask_active=1;
if ((schedule_work(&genrtc_task) == 0))
stask_active = 0;
}
/*
* call gen_rtc_interrupt function to signal an RTC_UIE,
* arg is unused.
* Could be invoked either from a real interrupt handler or
* from some routine that periodically (eg 100HZ) monitors
* whether RTC_SECS changed
*/
static void gen_rtc_interrupt(unsigned long arg)
{
/* We store the status in the low byte and the number of
* interrupts received since the last read in the remainder
* of rtc_irq_data. */
gen_rtc_irq_data += 0x100;
gen_rtc_irq_data &= ~0xff;
gen_rtc_irq_data |= RTC_UIE;
if (lostint){
printk("genrtc: system delaying clock ticks?\n");
/* increment count so that userspace knows something is wrong */
gen_rtc_irq_data += ((lostint-1)<<8);
lostint = 0;
}
wake_up_interruptible(&gen_rtc_wait);
}
/*
* Now all the various file operations that we export.
*/
static ssize_t gen_rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long data;
ssize_t retval;
if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
return -EINVAL;
if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
return -EAGAIN;
retval = wait_event_interruptible(gen_rtc_wait,
(data = xchg(&gen_rtc_irq_data, 0)));
if (retval)
goto out;
/* first test allows optimizer to nuke this case for 32-bit machines */
if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
unsigned int uidata = data;
retval = put_user(uidata, (unsigned int __user *)buf) ?:
sizeof(unsigned int);
}
else {
retval = put_user(data, (unsigned long __user *)buf) ?:
sizeof(unsigned long);
}
out:
return retval;
}
static unsigned int gen_rtc_poll(struct file *file,
struct poll_table_struct *wait)
{
poll_wait(file, &gen_rtc_wait, wait);
if (gen_rtc_irq_data != 0)
return POLLIN | POLLRDNORM;
return 0;
}
#endif
/*
* Used to disable/enable interrupts, only RTC_UIE supported
* We also clear out any old irq data after an ioctl() that
* meddles with the interrupt enable/disable bits.
*/
static inline void gen_clear_rtc_irq_bit(unsigned char bit)
{
#ifdef CONFIG_GEN_RTC_X
stop_rtc_timers = 1;
if (ttask_active){
del_timer_sync(&timer_task);
ttask_active = 0;
}
while (stask_active)
schedule();
spin_lock(&gen_rtc_lock);
irq_active = 0;
spin_unlock(&gen_rtc_lock);
#endif
}
static inline int gen_set_rtc_irq_bit(unsigned char bit)
{
#ifdef CONFIG_GEN_RTC_X
spin_lock(&gen_rtc_lock);
if ( !irq_active ) {
irq_active = 1;
stop_rtc_timers = 0;
lostint = 0;
INIT_WORK(&genrtc_task, genrtc_troutine);
oldsecs = get_rtc_ss();
init_timer(&timer_task);
stask_active = 1;
if (schedule_work(&genrtc_task) == 0){
stask_active = 0;
}
}
spin_unlock(&gen_rtc_lock);
gen_rtc_irq_data = 0;
return 0;
#else
return -EINVAL;
#endif
}
static int gen_rtc_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct rtc_time wtime;
struct rtc_pll_info pll;
void __user *argp = (void __user *)arg;
switch (cmd) {
case RTC_PLL_GET:
if (get_rtc_pll(&pll))
return -EINVAL;
else
return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
case RTC_PLL_SET:
if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&pll, argp, sizeof(pll)))
return -EFAULT;
return set_rtc_pll(&pll);
case RTC_UIE_OFF: /* disable ints from RTC updates. */
gen_clear_rtc_irq_bit(RTC_UIE);
return 0;
case RTC_UIE_ON: /* enable ints for RTC updates. */
return gen_set_rtc_irq_bit(RTC_UIE);
case RTC_RD_TIME: /* Read the time/date from RTC */
/* this doesn't get week-day, who cares */
memset(&wtime, 0, sizeof(wtime));
get_rtc_time(&wtime);
return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
case RTC_SET_TIME: /* Set the RTC */
{
int year;
unsigned char leap_yr;
if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&wtime, argp, sizeof(wtime)))
return -EFAULT;
year = wtime.tm_year + 1900;
leap_yr = ((!(year % 4) && (year % 100)) ||
!(year % 400));
if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
return -EINVAL;
if (wtime.tm_mday < 0 || wtime.tm_mday >
(days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
return -EINVAL;
if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
wtime.tm_min < 0 || wtime.tm_min >= 60 ||
wtime.tm_sec < 0 || wtime.tm_sec >= 60)
return -EINVAL;
return set_rtc_time(&wtime);
}
}
return -EINVAL;
}
static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int ret;
mutex_lock(&gen_rtc_mutex);
ret = gen_rtc_ioctl(file, cmd, arg);
mutex_unlock(&gen_rtc_mutex);
return ret;
}
/*
* We enforce only one user at a time here with the open/close.
* Also clear the previous interrupt data on an open, and clean
* up things on a close.
*/
static int gen_rtc_open(struct inode *inode, struct file *file)
{
mutex_lock(&gen_rtc_mutex);
if (gen_rtc_status & RTC_IS_OPEN) {
mutex_unlock(&gen_rtc_mutex);
return -EBUSY;
}
gen_rtc_status |= RTC_IS_OPEN;
gen_rtc_irq_data = 0;
irq_active = 0;
mutex_unlock(&gen_rtc_mutex);
return 0;
}
static int gen_rtc_release(struct inode *inode, struct file *file)
{
/*
* Turn off all interrupts once the device is no longer
* in use and clear the data.
*/
gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
gen_rtc_status &= ~RTC_IS_OPEN;
return 0;
}
#ifdef CONFIG_PROC_FS
/*
* Info exported via "/proc/driver/rtc".
*/
static int gen_rtc_proc_show(struct seq_file *m, void *v)
{
struct rtc_time tm;
unsigned int flags;
struct rtc_pll_info pll;
flags = get_rtc_time(&tm);
seq_printf(m,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n"
"rtc_epoch\t: %04u\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900);
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
seq_puts(m, "alarm\t\t: ");
if (tm.tm_hour <= 24)
seq_printf(m, "%02d:", tm.tm_hour);
else
seq_puts(m, "**:");
if (tm.tm_min <= 59)
seq_printf(m, "%02d:", tm.tm_min);
else
seq_puts(m, "**:");
if (tm.tm_sec <= 59)
seq_printf(m, "%02d\n", tm.tm_sec);
else
seq_puts(m, "**\n");
seq_printf(m,
"DST_enable\t: %s\n"
"BCD\t\t: %s\n"
"24hr\t\t: %s\n"
"square_wave\t: %s\n"
"alarm_IRQ\t: %s\n"
"update_IRQ\t: %s\n"
"periodic_IRQ\t: %s\n"
"periodic_freq\t: %ld\n"
"batt_status\t: %s\n",
(flags & RTC_DST_EN) ? "yes" : "no",
(flags & RTC_DM_BINARY) ? "no" : "yes",
(flags & RTC_24H) ? "yes" : "no",
(flags & RTC_SQWE) ? "yes" : "no",
(flags & RTC_AIE) ? "yes" : "no",
irq_active ? "yes" : "no",
(flags & RTC_PIE) ? "yes" : "no",
0L /* freq */,
(flags & RTC_BATT_BAD) ? "bad" : "okay");
if (!get_rtc_pll(&pll))
seq_printf(m,
"PLL adjustment\t: %d\n"
"PLL max +ve adjustment\t: %d\n"
"PLL max -ve adjustment\t: %d\n"
"PLL +ve adjustment factor\t: %d\n"
"PLL -ve adjustment factor\t: %d\n"
"PLL frequency\t: %ld\n",
pll.pll_value,
pll.pll_max,
pll.pll_min,
pll.pll_posmult,
pll.pll_negmult,
pll.pll_clock);
return 0;
}
static int gen_rtc_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, gen_rtc_proc_show, NULL);
}
static const struct file_operations gen_rtc_proc_fops = {
.open = gen_rtc_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init gen_rtc_proc_init(void)
{
struct proc_dir_entry *r;
r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops);
if (!r)
return -ENOMEM;
return 0;
}
#else
static inline int gen_rtc_proc_init(void) { return 0; }
#endif /* CONFIG_PROC_FS */
/*
* The various file operations we support.
*/
static const struct file_operations gen_rtc_fops = {
.owner = THIS_MODULE,
#ifdef CONFIG_GEN_RTC_X
.read = gen_rtc_read,
.poll = gen_rtc_poll,
#endif
.unlocked_ioctl = gen_rtc_unlocked_ioctl,
.open = gen_rtc_open,
.release = gen_rtc_release,
.llseek = noop_llseek,
};
static struct miscdevice rtc_gen_dev =
{
.minor = RTC_MINOR,
.name = "rtc",
.fops = &gen_rtc_fops,
};
static int __init rtc_generic_init(void)
{
int retval;
printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
retval = misc_register(&rtc_gen_dev);
if (retval < 0)
return retval;
retval = gen_rtc_proc_init();
if (retval) {
misc_deregister(&rtc_gen_dev);
return retval;
}
return 0;
}
static void __exit rtc_generic_exit(void)
{
remove_proc_entry ("driver/rtc", NULL);
misc_deregister(&rtc_gen_dev);
}
module_init(rtc_generic_init);
module_exit(rtc_generic_exit);
MODULE_AUTHOR("Richard Zidlicky");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(RTC_MINOR);

View File

@ -5,6 +5,10 @@
config RTC_LIB
bool
config RTC_MC146818_LIB
bool
select RTC_LIB
menuconfig RTC_CLASS
bool "Real Time Clock"
default n
@ -574,10 +578,10 @@ config RTC_DRV_EM3027
will be called rtc-em3027.
config RTC_DRV_RV8803
tristate "Micro Crystal RV8803"
tristate "Micro Crystal RV8803, Epson RX8900"
help
If you say yes here you get support for the Micro Crystal
RV8803 RTC chips.
If you say yes here you get support for the Micro Crystal RV8803 and
Epson RX8900 RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-rv8803.
@ -670,6 +674,18 @@ config RTC_DRV_DS1390
This driver can also be built as a module. If so, the module
will be called rtc-ds1390.
config RTC_DRV_MAX6916
tristate "Maxim MAX6916"
help
If you say yes here you will get support for the
Maxim MAX6916 SPI RTC chip.
This driver only supports the RTC feature, and not other chip
features such as alarms.
This driver can also be built as a module. If so, the module
will be called rtc-max6916.
config RTC_DRV_R9701
tristate "Epson RTC-9701JE"
help
@ -795,8 +811,9 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on X86 || ARM || M32R || PPC || MIPS || SPARC64
depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300
default y if X86
select RTC_MC146818_LIB
help
Say "yes" here to get direct support for the real time clock
found in every PC or ACPI-based system, and some other boards.
@ -815,6 +832,7 @@ config RTC_DRV_CMOS
config RTC_DRV_ALPHA
bool "Alpha PC-style CMOS"
depends on ALPHA
select RTC_MC146818_LIB
default y
help
Direct support for the real-time clock found on every Alpha

View File

@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o
rtc-core-y := class.o interface.o
ifdef CONFIG_RTC_DRV_EFI
@ -85,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX6916) += rtc-max6916.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o

View File

@ -104,7 +104,17 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
else if (!rtc->ops->read_alarm)
err = -EINVAL;
else {
memset(alarm, 0, sizeof(struct rtc_wkalrm));
alarm->enabled = 0;
alarm->pending = 0;
alarm->time.tm_sec = -1;
alarm->time.tm_min = -1;
alarm->time.tm_hour = -1;
alarm->time.tm_mday = -1;
alarm->time.tm_mon = -1;
alarm->time.tm_year = -1;
alarm->time.tm_wday = -1;
alarm->time.tm_yday = -1;
alarm->time.tm_isdst = -1;
err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
}
@ -383,7 +393,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
rtc->aie_timer.period = ktime_set(0, 0);
/* Alarm has to be enabled & in the futrure for us to enqueue it */
/* Alarm has to be enabled & in the future for us to enqueue it */
if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
rtc->aie_timer.node.expires.tv64)) {
@ -395,8 +405,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
int err = mutex_lock_interruptible(&rtc->ops_lock);
@ -748,9 +756,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
*/
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
{
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
struct rtc_time tm;
ktime_t now;
timer->enabled = 1;
__rtc_read_time(rtc, &tm);
now = rtc_tm_to_ktime(tm);
/* Skip over expired timers */
while (next) {
if (next->expires.tv64 >= now.tv64)
break;
next = timerqueue_iterate_next(next);
}
timerqueue_add(&rtc->timerqueue, &timer->node);
if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
if (!next) {
struct rtc_wkalrm alarm;
int err;
alarm.time = rtc_ktime_to_tm(timer->node.expires);

View File

@ -643,17 +643,15 @@ static int abx80x_probe(struct i2c_client *client,
return err;
}
err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group,
&client->dev);
if (err) {
rtc_calib_remove_sysfs_group(&client->dev);
err = devm_add_action_or_reset(&client->dev,
rtc_calib_remove_sysfs_group,
&client->dev);
if (err)
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n",
err);
return err;
}
return 0;
return err;
}
static int abx80x_remove(struct i2c_client *client)

View File

@ -343,7 +343,6 @@ static struct platform_driver asm9260_rtc_driver = {
.remove = asm9260_rtc_remove,
.driver = {
.name = "asm9260-rtc",
.owner = THIS_MODULE,
.of_match_table = asm9260_dt_ids,
},
};

View File

@ -375,6 +375,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (!rtc)
return -ENOMEM;
spin_lock_init(&rtc->lock);
rtc->irq = irq;
/* platform setup code should have handled this; sigh */

View File

@ -43,7 +43,7 @@
#include <linux/of_platform.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
#include <linux/mc146818rtc.h>
struct cmos_rtc {
struct rtc_device *rtc;
@ -190,10 +190,10 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
* that instead of the heuristic in get_rtc_time().
* that instead of the heuristic in mc146818_get_time().
* That'll make Y3K compatility (year > 2070) easy!
*/
get_rtc_time(t);
mc146818_get_time(t);
return 0;
}
@ -205,7 +205,7 @@ static int cmos_set_time(struct device *dev, struct rtc_time *t)
* takes effect exactly 500ms after we write the register.
* (Also queueing and other delays before we get this far.)
*/
return set_rtc_time(t);
return mc146818_set_time(t);
}
static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
@ -220,8 +220,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
* Some also support day and month, for alarms up to a year in
* the future.
*/
t->time.tm_mday = -1;
t->time.tm_mon = -1;
spin_lock_irq(&rtc_lock);
t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
@ -272,7 +270,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
}
}
}
t->time.tm_year = -1;
t->enabled = !!(rtc_control & RTC_AIE);
t->pending = 0;
@ -630,7 +627,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
address_space = 64;
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \
|| defined(__sparc__) || defined(__mips__) \
|| defined(__powerpc__)
|| defined(__powerpc__) || defined(CONFIG_MN10300)
address_space = 128;
#else
#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@ -1142,14 +1139,14 @@ static __init void cmos_of_init(struct platform_device *pdev)
if (val)
CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
get_rtc_time(&time);
cmos_read_time(&pdev->dev, &time);
ret = rtc_valid_tm(&time);
if (ret) {
struct rtc_time def_time = {
.tm_year = 1,
.tm_mday = 1,
};
set_rtc_time(&def_time);
cmos_set_time(&pdev->dev, &def_time);
}
}
#else

View File

@ -85,6 +85,7 @@ static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN;
rtc_tm->tm_sec = 0;
ret = rtc_valid_tm(rtc_tm);
return ret;

View File

@ -74,6 +74,7 @@ static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY;
rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR;
rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN;
rtc_tm->tm_sec = 0;
return rtc_valid_tm(rtc_tm);
}

View File

@ -388,6 +388,8 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
u8 day0, day1;
unsigned long flags;
alm->time.tm_sec = 0;
spin_lock_irqsave(&davinci_rtc_lock, flags);
davinci_rtcss_calendar_wait(davinci_rtc);

View File

@ -16,7 +16,7 @@
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/bcd.h>
#include <linux/ds1286.h>
#include <linux/rtc/ds1286.h>
#include <linux/io.h>
#include <linux/slab.h>

View File

@ -313,13 +313,6 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]);
alm->time.tm_min = bcd2bin(buf[DS1305_MIN]);
alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
alm->time.tm_mday = -1;
alm->time.tm_mon = -1;
alm->time.tm_year = -1;
/* next three fields are unused by Linux */
alm->time.tm_wday = -1;
alm->time.tm_mday = -1;
alm->time.tm_isdst = -1;
return 0;
}

View File

@ -482,11 +482,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
t->time.tm_mon = -1;
t->time.tm_year = -1;
t->time.tm_wday = -1;
t->time.tm_yday = -1;
t->time.tm_isdst = -1;
/* ... and status */
t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
@ -602,6 +597,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
* Alarm support for mcp794xx devices.
*/
#define MCP794XX_REG_WEEKDAY 0x3
#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7
#define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10
# define MCP794XX_BIT_ALM1_EN 0x20
@ -1231,13 +1228,16 @@ static int ds1307_probe(struct i2c_client *client,
{
struct ds1307 *ds1307;
int err = -ENODEV;
int tmp;
int tmp, wday;
struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
bool ds1307_can_wakeup_device = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
struct rtc_time tm;
unsigned long timestamp;
irq_handler_t irq_handler = ds1307_irq;
static const int bbsqi_bitpos[] = {
@ -1526,6 +1526,27 @@ read_rtc:
bin2bcd(tmp));
}
/*
* Some IPs have weekday reset value = 0x1 which might not correct
* hence compute the wday using the current date/month/year values
*/
ds1307_get_time(&client->dev, &tm);
wday = tm.tm_wday;
timestamp = rtc_tm_to_time64(&tm);
rtc_time64_to_tm(timestamp, &tm);
/*
* Check if reset wday is different from the computed wday
* If different then set the wday which we computed using
* timestamp
*/
if (wday != tm.tm_wday) {
wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY);
wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK;
wday = wday | (tm.tm_wday + 1);
i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday);
}
if (want_irq) {
device_set_wakeup_capable(&client->dev, true);
set_bit(HAS_ALARM, &ds1307->flags);

View File

@ -504,12 +504,6 @@ static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour;
alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday;
alarm->time.tm_mon = -1;
alarm->time.tm_year = -1;
alarm->time.tm_wday = -1;
alarm->time.tm_yday = -1;
alarm->time.tm_isdst = -1;
out:
mutex_unlock(&priv->mutex);
return res;

View File

@ -102,6 +102,26 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask)
return (val & bin_mask);
}
/**
* s1685_rtc_check_mday - check validity of the day of month.
* @rtc: pointer to the ds1685 rtc structure.
* @mday: day of month.
*
* Returns -EDOM if the day of month is not within 1..31 range.
*/
static inline int
ds1685_rtc_check_mday(struct ds1685_priv *rtc, u8 mday)
{
if (rtc->bcd_mode) {
if (mday < 0x01 || mday > 0x31 || (mday & 0x0f) > 0x09)
return -EDOM;
} else {
if (mday < 1 || mday > 31)
return -EDOM;
}
return 0;
}
/**
* ds1685_rtc_switch_to_bank0 - switch the rtc to bank 0.
* @rtc: pointer to the ds1685 rtc structure.
@ -377,6 +397,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
int ret;
/* Fetch the alarm info from the RTC alarm registers. */
ds1685_rtc_begin_data_access(rtc);
@ -388,34 +409,29 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ctrlc = rtc->read(rtc, RTC_CTRL_C);
ds1685_rtc_end_data_access(rtc);
/* Check month date. */
if (!(mday >= 1) && (mday <= 31))
return -EDOM;
/* Check the month date for validity. */
ret = ds1685_rtc_check_mday(rtc, mday);
if (ret)
return ret;
/*
* Check the three alarm bytes.
*
* The Linux RTC system doesn't support the "don't care" capability
* of this RTC chip. We check for it anyways in case support is
* added in the future.
* added in the future and only assign when we care.
*/
if (unlikely(seconds >= 0xc0))
alrm->time.tm_sec = -1;
else
if (likely(seconds < 0xc0))
alrm->time.tm_sec = ds1685_rtc_bcd2bin(rtc, seconds,
RTC_SECS_BCD_MASK,
RTC_SECS_BIN_MASK);
if (unlikely(minutes >= 0xc0))
alrm->time.tm_min = -1;
else
if (likely(minutes < 0xc0))
alrm->time.tm_min = ds1685_rtc_bcd2bin(rtc, minutes,
RTC_MINS_BCD_MASK,
RTC_MINS_BIN_MASK);
if (unlikely(hours >= 0xc0))
alrm->time.tm_hour = -1;
else
if (likely(hours < 0xc0))
alrm->time.tm_hour = ds1685_rtc_bcd2bin(rtc, hours,
RTC_HRS_24_BCD_MASK,
RTC_HRS_24_BIN_MASK);
@ -423,11 +439,6 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Write the data to rtc_wkalrm. */
alrm->time.tm_mday = ds1685_rtc_bcd2bin(rtc, mday, RTC_MDAY_BCD_MASK,
RTC_MDAY_BIN_MASK);
alrm->time.tm_mon = -1;
alrm->time.tm_year = -1;
alrm->time.tm_wday = -1;
alrm->time.tm_yday = -1;
alrm->time.tm_isdst = -1;
alrm->enabled = !!(ctrlb & RTC_CTRL_B_AIE);
alrm->pending = !!(ctrlc & RTC_CTRL_C_AF);
@ -445,6 +456,7 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
u8 ctrlb, seconds, minutes, hours, mday;
int ret;
/* Fetch the alarm info and convert to BCD. */
seconds = ds1685_rtc_bin2bcd(rtc, alrm->time.tm_sec,
@ -461,8 +473,9 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
RTC_MDAY_BCD_MASK);
/* Check the month date for validity. */
if (!(mday >= 1) && (mday <= 31))
return -EDOM;
ret = ds1685_rtc_check_mday(rtc, mday);
if (ret)
return ret;
/*
* Check the three alarm bytes.

View File

@ -13,7 +13,7 @@
#include <linux/rtc.h>
#include <linux/types.h>
#include <linux/bcd.h>
#include <linux/rtc-ds2404.h>
#include <linux/platform_data/rtc-ds2404.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>

View File

@ -197,12 +197,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
alarm->time.tm_mon = -1;
alarm->time.tm_year = -1;
alarm->time.tm_wday = -1;
alarm->time.tm_yday = -1;
alarm->time.tm_isdst = -1;
alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
alarm->pending = !!(stat & DS3232_REG_SR_A1F);

View File

@ -259,6 +259,12 @@ static const struct rtc_class_ops efi_rtc_ops = {
static int __init efi_rtc_probe(struct platform_device *dev)
{
struct rtc_device *rtc;
efi_time_t eft;
efi_time_cap_t cap;
/* First check if the RTC is usable */
if (efi.get_time(&eft, &cap) != EFI_SUCCESS)
return -ENODEV;
rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops,
THIS_MODULE);

View File

@ -9,44 +9,10 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
#include <asm/rtc.h>
static int generic_get_time(struct device *dev, struct rtc_time *tm)
{
unsigned int ret = get_rtc_time(tm);
if (ret & RTC_BATT_BAD)
return -EOPNOTSUPP;
return rtc_valid_tm(tm);
}
static int generic_set_time(struct device *dev, struct rtc_time *tm)
{
if (set_rtc_time(tm) < 0)
return -EOPNOTSUPP;
return 0;
}
static const struct rtc_class_ops generic_rtc_ops = {
.read_time = generic_get_time,
.set_time = generic_set_time,
};
#else
#define generic_rtc_ops *(struct rtc_class_ops*)NULL
#endif
static int __init generic_rtc_probe(struct platform_device *dev)
{
struct rtc_device *rtc;
const struct rtc_class_ops *ops;
ops = dev_get_platdata(&dev->dev);
if (!ops)
ops = &generic_rtc_ops;
const struct rtc_class_ops *ops = dev_get_platdata(&dev->dev);
rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
ops, THIS_MODULE);

View File

@ -198,7 +198,7 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
/* The alarm only has a minute accuracy */
alm_tm->tm_sec = -1;
alm_tm->tm_sec = 0;
alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?
-1 :
@ -213,9 +213,6 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
-1 :
bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);
alm_tm->tm_mon = -1;
alm_tm->tm_year = -1;
ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
if (ret < 0)
return ret;

View File

@ -245,8 +245,7 @@ static int isl12057_rtc_update_alarm(struct device *dev, int enable)
static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
struct rtc_time rtc_tm, *alarm_tm = &alarm->time;
unsigned long rtc_secs, alarm_secs;
struct rtc_time *alarm_tm = &alarm->time;
u8 regs[ISL12057_A1_SEC_LEN];
unsigned int ir;
int ret;
@ -264,36 +263,6 @@ static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f);
alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f);
alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f);
alarm_tm->tm_wday = -1;
/*
* The alarm section does not store year/month. We use the ones in rtc
* section as a basis and increment month and then year if needed to get
* alarm after current time.
*/
ret = _isl12057_rtc_read_time(dev, &rtc_tm);
if (ret)
goto err_unlock;
alarm_tm->tm_year = rtc_tm.tm_year;
alarm_tm->tm_mon = rtc_tm.tm_mon;
ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
if (ret)
goto err_unlock;
ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
if (ret)
goto err_unlock;
if (alarm_secs < rtc_secs) {
if (alarm_tm->tm_mon == 11) {
alarm_tm->tm_mon = 0;
alarm_tm->tm_year += 1;
} else {
alarm_tm->tm_mon += 1;
}
}
ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir);
if (ret) {

View File

@ -244,7 +244,7 @@ static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags);
if (retval < 0) {
dev_info(dev, "Unable to enable alarm IRQ %d\n", retval);
dev_err(dev, "Unable to enable alarm IRQ %d\n", retval);
return retval;
}
return 0;
@ -320,10 +320,8 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_sec = bcd2bin(alarmvals[4] & 0x7f);
alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f);
alrm->time.tm_year = -1;
alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = {
.proc = m41t80_rtc_proc,
};
#ifdef CONFIG_PM_SLEEP
static int m41t80_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (client->irq >= 0 && device_may_wakeup(dev))
enable_irq_wake(client->irq);
return 0;
}
static int m41t80_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (client->irq >= 0 && device_may_wakeup(dev))
disable_irq_wake(client->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume);
static ssize_t flags_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client,
return rc;
}
rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group,
&client->dev);
rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group,
&client->dev);
if (rc) {
m41t80_remove_sysfs_group(&client->dev);
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n", rc);
return rc;
@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client)
static struct i2c_driver m41t80_driver = {
.driver = {
.name = "rtc-m41t80",
.pm = &m41t80_pm,
},
.probe = m41t80_probe,
.remove = m41t80_remove,

View File

@ -16,7 +16,7 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/m48t86.h>
#include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h>
#define M48T86_REG_SEC 0x00

View File

@ -0,0 +1,164 @@
/* rtc-max6916.c
*
* Driver for MAXIM max6916 Low Current, SPI Compatible
* Real Time Clock
*
* Author : Venkat Prashanth B U <venkat.prashanth2498@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
/* Registers in max6916 rtc */
#define MAX6916_SECONDS_REG 0x01
#define MAX6916_MINUTES_REG 0x02
#define MAX6916_HOURS_REG 0x03
#define MAX6916_DATE_REG 0x04
#define MAX6916_MONTH_REG 0x05
#define MAX6916_DAY_REG 0x06
#define MAX6916_YEAR_REG 0x07
#define MAX6916_CONTROL_REG 0x08
#define MAX6916_STATUS_REG 0x0C
#define MAX6916_CLOCK_BURST 0x3F
static int max6916_read_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
struct spi_device *spi = to_spi_device(dev);
*data = address | 0x80;
return spi_write_then_read(spi, data, 1, data, 1);
}
static int max6916_write_reg(struct device *dev, unsigned char address,
unsigned char data)
{
struct spi_device *spi = to_spi_device(dev);
unsigned char buf[2];
buf[0] = address & 0x7F;
buf[1] = data;
return spi_write_then_read(spi, buf, 2, NULL, 0);
}
static int max6916_read_time(struct device *dev, struct rtc_time *dt)
{
struct spi_device *spi = to_spi_device(dev);
int err;
unsigned char buf[8];
buf[0] = MAX6916_CLOCK_BURST | 0x80;
err = spi_write_then_read(spi, buf, 1, buf, 8);
if (err)
return err;
dt->tm_sec = bcd2bin(buf[0]);
dt->tm_min = bcd2bin(buf[1]);
dt->tm_hour = bcd2bin(buf[2] & 0x3F);
dt->tm_mday = bcd2bin(buf[3]);
dt->tm_mon = bcd2bin(buf[4]) - 1;
dt->tm_wday = bcd2bin(buf[5]) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100;
return rtc_valid_tm(dt);
}
static int max6916_set_time(struct device *dev, struct rtc_time *dt)
{
struct spi_device *spi = to_spi_device(dev);
unsigned char buf[9];
if (dt->tm_year < 100 || dt->tm_year > 199) {
dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n",
dt->tm_year + 1900);
return -EINVAL;
}
buf[0] = MAX6916_CLOCK_BURST & 0x7F;
buf[1] = bin2bcd(dt->tm_sec);
buf[2] = bin2bcd(dt->tm_min);
buf[3] = (bin2bcd(dt->tm_hour) & 0X3F);
buf[4] = bin2bcd(dt->tm_mday);
buf[5] = bin2bcd(dt->tm_mon + 1);
buf[6] = bin2bcd(dt->tm_wday + 1);
buf[7] = bin2bcd(dt->tm_year % 100);
buf[8] = bin2bcd(0x00);
/* write the rtc settings */
return spi_write_then_read(spi, buf, 9, NULL, 0);
}
static const struct rtc_class_ops max6916_rtc_ops = {
.read_time = max6916_read_time,
.set_time = max6916_set_time,
};
static int max6916_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
unsigned char data;
int res;
/* spi setup with max6916 in mode 3 and bits per word as 8 */
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
/* RTC Settings */
res = max6916_read_reg(&spi->dev, MAX6916_SECONDS_REG, &data);
if (res)
return res;
/* Disable the write protect of rtc */
max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
data = data & ~(1 << 7);
max6916_write_reg(&spi->dev, MAX6916_CONTROL_REG, data);
/*Enable oscillator,disable oscillator stop flag, glitch filter*/
max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
data = data & 0x1B;
max6916_write_reg(&spi->dev, MAX6916_STATUS_REG, data);
/* display the settings */
max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
dev_info(&spi->dev, "MAX6916 RTC CTRL Reg = 0x%02x\n", data);
max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
dev_info(&spi->dev, "MAX6916 RTC Status Reg = 0x%02x\n", data);
rtc = devm_rtc_device_register(&spi->dev, "max6916",
&max6916_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
spi_set_drvdata(spi, rtc);
return 0;
}
static struct spi_driver max6916_driver = {
.driver = {
.name = "max6916",
},
.probe = max6916_probe,
};
module_spi_driver(max6916_driver);
MODULE_DESCRIPTION("MAX6916 SPI RTC DRIVER");
MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@gmail.com>");
MODULE_LICENSE("GPL v2");

View File

@ -1,40 +1,16 @@
/*
* include/asm-generic/rtc.h
*
* Author: Tom Rini <trini@mvista.com>
*
* Based on:
* drivers/char/rtc.c
*
* Please read the COPYING file for all license details.
*/
#ifndef __ASM_RTC_H__
#define __ASM_RTC_H__
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/mc146818rtc.h>
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
/* some dummy definitions */
#define RTC_BATT_BAD 0x100 /* battery bad */
#define RTC_SQWE 0x08 /* enable square-wave output */
#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
/*
* Returns true if a clock update is in progress
*/
static inline unsigned char rtc_is_updating(void)
static inline unsigned char mc146818_is_updating(void)
{
unsigned char uip;
unsigned long flags;
@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void)
return uip;
}
static inline unsigned int __get_rtc_time(struct rtc_time *time)
unsigned int mc146818_get_time(struct rtc_time *time)
{
unsigned char ctrl;
unsigned long flags;
@ -60,11 +36,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
* can take just over 2ms. We wait 20ms. There is no need to
* to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
* If you need to know *exactly* when a second has started, enable
* periodic update complete interrupts, (via ioctl) and then
* periodic update complete interrupts, (via ioctl) and then
* immediately read /dev/rtc which will block until you get the IRQ.
* Once the read clears, read the RTC time (again via ioctl). Easy.
*/
if (rtc_is_updating())
if (mc146818_is_updating())
mdelay(20);
/*
@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
return RTC_24H;
}
#ifndef get_rtc_time
#define get_rtc_time __get_rtc_time
#endif
EXPORT_SYMBOL_GPL(mc146818_get_time);
/* Set the current date and time in the real time clock. */
static inline int __set_rtc_time(struct rtc_time *time)
int mc146818_set_time(struct rtc_time *time)
{
unsigned long flags;
unsigned char mon, day, hrs, min, sec;
@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time)
return 0;
}
#ifndef set_rtc_time
#define set_rtc_time __set_rtc_time
#endif
static inline unsigned int get_rtc_ss(void)
{
struct rtc_time h;
get_rtc_time(&h);
return h.tm_sec;
}
static inline int get_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
static inline int set_rtc_pll(struct rtc_pll_info *pll)
{
return -EINVAL;
}
#endif /* __ASM_RTC_H__ */
EXPORT_SYMBOL_GPL(mc146818_set_time);

View File

@ -32,11 +32,11 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <asm-generic/rtc.h>
#include <asm/intel_scu_ipc.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>
@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (mrst->irq <= 0)
return -EIO;
/* Basic alarms only support hour, minute, and seconds fields.
* Some also support day and month, for alarms up to a year in
* the future.
*/
t->time.tm_mday = -1;
t->time.tm_mon = -1;
t->time.tm_year = -1;
/* vRTC only supports binary mode */
spin_lock_irq(&rtc_lock);
t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);

View File

@ -96,7 +96,7 @@
#define CD_TMR_TE BIT(3) /* Countdown timer enable */
/* PCF2123_REG_OFFSET BITS */
#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */
#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */
#define OFFSET_COARSE BIT(7) /* Coarse mode offset */
#define OFFSET_STEP (2170) /* Offset step in parts per billion */
@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)
if (reg & OFFSET_COARSE)
reg <<= 1; /* multiply by 2 and sign extend */
else
reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
reg = sign_extend32(reg, OFFSET_SIGN_BIT);
*offset = ((long)reg) * OFFSET_STEP;

View File

@ -16,6 +16,16 @@
#include <linux/rtc.h>
#include <linux/module.h>
/*
* Information for this driver was pulled from the following datasheets.
*
* http://www.nxp.com/documents/data_sheet/PCF85063A.pdf
* http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
*
* PCF85063A -- Rev. 6 18 November 2015
* PCF85063TP -- Rev. 4 6 May 2015
*/
#define PCF85063_REG_CTRL1 0x00 /* status */
#define PCF85063_REG_CTRL1_STOP BIT(5)
#define PCF85063_REG_CTRL2 0x01
@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
return 0;
}
/*
* In the routines that deal directly with the pcf85063 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
{
s32 ret;
/* start the clock */
ctrl1 &= PCF85063_REG_CTRL1_STOP;
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
if (ret < 0) {
dev_err(&client->dev, "Failing to start the clock\n");
return -EIO;
}
return 0;
}
static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
int rc;
@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_wday = regs[4] & 0x07;
tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
tm->tm_year = bcd2bin(regs[6]);
if (tm->tm_year < 70)
tm->tm_year += 100; /* assume we are in 1970...2069 */
tm->tm_year += 100;
return rtc_valid_tm(tm);
}
@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
int rc;
u8 regs[8];
u8 regs[7];
u8 ctrl1;
if ((tm->tm_year < 100) || (tm->tm_year > 199))
return -EINVAL;
/*
* to accurately set the time, reset the divider chain and keep it in
* reset state until all time/date registers are written
*/
rc = pcf85063_stop_clock(client, &regs[7]);
rc = pcf85063_stop_clock(client, &ctrl1);
if (rc != 0)
return rc;
@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
regs[5] = bin2bcd(tm->tm_mon + 1);
/* year and century */
regs[6] = bin2bcd(tm->tm_year % 100);
/*
* after all time/date registers are written, let the 'address auto
* increment' feature wrap around and write register CTRL1 to re-enable
* the clock divider chain again
*/
regs[7] &= ~PCF85063_REG_CTRL1_STOP;
regs[6] = bin2bcd(tm->tm_year - 100);
/* write all registers at once */
rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
@ -142,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return rc;
}
/*
* Write the control register as a separate action since the size of
* the register space is different between the PCF85063TP and
* PCF85063A devices. The rollover point can not be used.
*/
rc = pcf85063_start_clock(client, ctrl1);
if (rc != 0)
return rc;
return 0;
}

View File

@ -341,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
__func__, buf[0], buf[1], buf[2], buf[3]);
tm->time.tm_sec = 0;
tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
tm->time.tm_hour = bcd2bin(buf[1] & 0x3F);
tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
tm->time.tm_mon = -1;
tm->time.tm_year = -1;
tm->time.tm_yday = -1;
tm->time.tm_isdst = -1;
err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
if (err < 0)

View File

@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
}
alm->time.tm_sec = 0;
alm->time.tm_min = bcd2bin(alarm_data[0]);
alm->time.tm_hour = bcd2bin(alarm_data[1]);
alm->time.tm_mday = bcd2bin(alarm_data[2]);

View File

@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
t->time.tm_mday = -1;
t->time.tm_mon = -1;
t->time.tm_year = -1;
t->time.tm_wday = -1;
t->time.tm_yday = -1;
t->time.tm_isdst = -1;
/* ... and status */
t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);

View File

@ -13,12 +13,15 @@
#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rtc.h>
#define RV8803_I2C_TRY_COUNT 4
#define RV8803_SEC 0x00
#define RV8803_MIN 0x01
#define RV8803_HOUR 0x02
@ -56,19 +59,85 @@ struct rv8803_data {
u8 ctrl;
};
static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
{
int try = RV8803_I2C_TRY_COUNT;
s32 ret;
/*
* There is a 61µs window during which the RTC does not acknowledge I2C
* transfers. In that case, ensure that there are multiple attempts.
*/
do
ret = i2c_smbus_read_byte_data(client, reg);
while ((ret == -ENXIO || ret == -EIO) && --try);
if (ret < 0)
dev_err(&client->dev, "Unable to read register 0x%02x\n", reg);
return ret;
}
static int rv8803_read_regs(const struct i2c_client *client,
u8 reg, u8 count, u8 *values)
{
int try = RV8803_I2C_TRY_COUNT;
s32 ret;
do
ret = i2c_smbus_read_i2c_block_data(client, reg, count, values);
while ((ret == -ENXIO || ret == -EIO) && --try);
if (ret != count) {
dev_err(&client->dev,
"Unable to read registers 0x%02x..0x%02x\n",
reg, reg + count - 1);
return ret < 0 ? ret : -EIO;
}
return 0;
}
static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value)
{
int try = RV8803_I2C_TRY_COUNT;
s32 ret;
do
ret = i2c_smbus_write_byte_data(client, reg, value);
while ((ret == -ENXIO || ret == -EIO) && --try);
if (ret)
dev_err(&client->dev, "Unable to write register 0x%02x\n", reg);
return ret;
}
static int rv8803_write_regs(const struct i2c_client *client,
u8 reg, u8 count, const u8 *values)
{
int try = RV8803_I2C_TRY_COUNT;
s32 ret;
do
ret = i2c_smbus_write_i2c_block_data(client, reg, count,
values);
while ((ret == -ENXIO || ret == -EIO) && --try);
if (ret)
dev_err(&client->dev,
"Unable to write registers 0x%02x..0x%02x\n",
reg, reg + count - 1);
return ret;
}
static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct rv8803_data *rv8803 = i2c_get_clientdata(client);
unsigned long events = 0;
int flags, try = 0;
int flags;
mutex_lock(&rv8803->flags_lock);
do {
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
try++;
} while ((flags == -ENXIO) && (try < 3));
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags <= 0) {
mutex_unlock(&rv8803->flags_lock);
return IRQ_NONE;
@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
if (events) {
rtc_update_irq(rv8803->rtc, 1, events);
i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
rv8803_write_reg(client, RV8803_FLAG, flags);
rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl);
}
mutex_unlock(&rv8803->flags_lock);
@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
u8 *date = date1;
int ret, flags;
flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0)
return flags;
@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
7, date);
if (ret != 7)
return ret < 0 ? ret : -EIO;
ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date);
if (ret)
return ret;
if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
7, date2);
if (ret != 7)
return ret < 0 ? ret : -EIO;
ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2);
if (ret)
return ret;
if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
date = date2;
@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f);
tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f);
tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f);
tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f);
tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f);
tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100;
return rtc_valid_tm(tm);
return 0;
}
static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
{
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
u8 date[7];
int flags, ret;
int ctrl, flags, ret;
if ((tm->tm_year < 100) || (tm->tm_year > 199))
return -EINVAL;
ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL);
if (ctrl < 0)
return ctrl;
/* Stop the clock */
ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
ctrl | RV8803_CTRL_RESET);
if (ret)
return ret;
date[RV8803_SEC] = bin2bcd(tm->tm_sec);
date[RV8803_MIN] = bin2bcd(tm->tm_min);
date[RV8803_HOUR] = bin2bcd(tm->tm_hour);
@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1);
date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100);
ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC,
7, date);
if (ret < 0)
ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date);
if (ret)
return ret;
/* Restart the clock */
ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
ctrl & ~RV8803_CTRL_RESET);
if (ret)
return ret;
mutex_lock(&rv8803->flags_lock);
flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
flags & ~RV8803_FLAG_V2F);
ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
mutex_unlock(&rv8803->flags_lock);
@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 alarmvals[3];
int flags, ret;
ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN,
3, alarmvals);
if (ret != 3)
return ret < 0 ? ret : -EIO;
ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals);
if (ret)
return ret;
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
alrm->time.tm_sec = 0;
alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
alrm->time.tm_mon = -1;
alrm->time.tm_year = -1;
alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
mutex_lock(&rv8803->flags_lock);
ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
if (ret != 2) {
ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl);
if (ret) {
mutex_unlock(&rv8803->flags_lock);
return ret < 0 ? ret : -EIO;
return ret;
}
alarmvals[0] = bin2bcd(alrm->time.tm_min);
@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE);
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
if (err) {
mutex_unlock(&rv8803->flags_lock);
return err;
@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
ctrl[1] &= ~RV8803_FLAG_AF;
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]);
mutex_unlock(&rv8803->flags_lock);
if (err)
return err;
err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN,
3, alarmvals);
err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals);
if (err)
return err;
@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rv8803->rtc->aie_timer.enabled)
rv8803->ctrl |= RV8803_CTRL_AIE;
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
if (err)
return err;
}
@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
}
mutex_lock(&rv8803->flags_lock);
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
err = rv8803_write_reg(client, RV8803_FLAG, flags);
mutex_unlock(&rv8803->flags_lock);
if (err)
return err;
if (ctrl != rv8803->ctrl) {
rv8803->ctrl = ctrl;
err = i2c_smbus_write_byte_data(client, RV8803_CTRL,
rv8803->ctrl);
err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl);
if (err)
return err;
}
@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
switch (cmd) {
case RTC_VL_READ:
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
case RTC_VL_CLR:
mutex_lock(&rv8803->flags_lock);
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
ret = rv8803_write_reg(client, RV8803_FLAG, flags);
mutex_unlock(&rv8803->flags_lock);
if (ret < 0)
if (ret)
return ret;
return 0;
@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev);
int ret;
ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]);
if (ret < 0)
ret = rv8803_write_reg(client, RV8803_RAM, buf[0]);
if (ret)
return ret;
return 1;
@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev);
int ret;
ret = i2c_smbus_read_byte_data(client, RV8803_RAM);
ret = rv8803_read_reg(client, RV8803_RAM);
if (ret < 0)
return ret;
@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rv8803_data *rv8803;
int err, flags, try = 0;
int err, flags;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK)) {
@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client,
rv8803->client = client;
i2c_set_clientdata(client, rv8803);
/*
* There is a 60µs window where the RTC may not reply on the i2c bus in
* that case, the transfer is not ACKed. In that case, ensure there are
* multiple attempts.
*/
do {
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
try++;
} while ((flags == -ENXIO) && (try < 3));
flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client,
return PTR_ERR(rv8803->rtc);
}
try = 0;
do {
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
RV8803_EXT_WADA);
try++;
} while ((err == -ENXIO) && (try < 3));
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err)
return err;

View File

@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
if (alarmvals[2] & RX8010_ALARM_AE)
t->time.tm_mday = -1;
else
if (!(alarmvals[2] & RX8010_ALARM_AE))
t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f);
t->time.tm_wday = -1;
t->time.tm_mon = -1;
t->time.tm_year = -1;
t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;

View File

@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
+ (ald[1] & 0x20 ? 12 : 0);
t->time.tm_wday = -1;
t->time.tm_mday = -1;
t->time.tm_mon = -1;
t->time.tm_year = -1;
dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n",
__func__,
t->time.tm_sec, t->time.tm_min, t->time.tm_hour,

View File

@ -15,6 +15,7 @@
#include <linux/bitrev.h>
#include <linux/bcd.h>
#include <linux/slab.h>
#include <linux/delay.h>
#define S35390A_CMD_STATUS1 0
#define S35390A_CMD_STATUS2 1
@ -34,10 +35,14 @@
#define S35390A_ALRM_BYTE_HOURS 1
#define S35390A_ALRM_BYTE_MINS 2
/* flags for STATUS1 */
#define S35390A_FLAG_POC 0x01
#define S35390A_FLAG_BLD 0x02
#define S35390A_FLAG_INT2 0x04
#define S35390A_FLAG_24H 0x40
#define S35390A_FLAG_RESET 0x80
/* flag for STATUS2 */
#define S35390A_FLAG_TEST 0x01
#define S35390A_INT2_MODE_MASK 0xF0
@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
return 0;
}
static int s35390a_reset(struct s35390a *s35390a)
/*
* Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
* To keep the information if an irq is pending, pass the value read from
* STATUS1 to the caller.
*/
static int s35390a_reset(struct s35390a *s35390a, char *status1)
{
char buf[1];
char buf;
int ret;
unsigned initcount = 0;
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
return -EIO;
ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
if (ret < 0)
return ret;
if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
if (*status1 & S35390A_FLAG_POC)
/*
* Do not communicate for 0.5 seconds since the power-on
* detection circuit is in operation.
*/
msleep(500);
else if (!(*status1 & S35390A_FLAG_BLD))
/*
* If both POC and BLD are unset everything is fine.
*/
return 0;
buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
buf[0] &= 0xf0;
return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
/*
* At least one of POC and BLD are set, so reinitialise chip. Keeping
* this information in the hardware to know later that the time isn't
* valid is unfortunately not possible because POC and BLD are cleared
* on read. So the reset is best done now.
*
* The 24H bit is kept over reset, so set it already here.
*/
initialize:
*status1 = S35390A_FLAG_24H;
buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
if (ret < 0)
return ret;
ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
if (ret < 0)
return ret;
if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
/* Try up to five times to reset the chip */
if (initcount < 5) {
++initcount;
goto initialize;
} else
return -EIO;
}
return 1;
}
static int s35390a_disable_test_mode(struct s35390a *s35390a)
@ -217,12 +266,12 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
/* disable interrupt */
/* disable interrupt (which deasserts the irq line) */
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0)
return err;
/* clear pending interrupt, if any */
/* clear pending interrupt (in STATUS1 only), if any */
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
if (err < 0)
return err;
@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (alm->time.tm_wday != -1)
buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
else
buf[S35390A_ALRM_BYTE_WDAY] = 0;
buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
alm->time.tm_hour) | 0x80;
@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (err < 0)
return err;
if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
return -EINVAL;
if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
/*
* When the alarm isn't enabled, the register to configure
* the alarm time isn't accessible.
*/
alm->enabled = 0;
return 0;
} else {
alm->enabled = 1;
}
err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
if (err < 0)
return err;
/* This chip returns the bits of each byte in reverse order */
for (i = 0; i < 3; ++i) {
for (i = 0; i < 3; ++i)
buf[i] = bitrev8(buf[i]);
buf[i] &= ~0x80;
}
alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
alm->time.tm_hour = s35390a_reg2hr(s35390a,
buf[S35390A_ALRM_BYTE_HOURS]);
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
/*
* B0 of the three matching registers is an enable flag. Iff it is set
* the configured value is used for matching.
*/
if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
alm->time.tm_wday =
bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
alm->time.tm_hour =
s35390a_reg2hr(s35390a,
buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
/* alarm triggers always at s=0 */
alm->time.tm_sec = 0;
dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
__func__, alm->time.tm_min, alm->time.tm_hour,
@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver;
static int s35390a_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
int err, err_reset;
unsigned int i;
struct s35390a *s35390a;
struct rtc_time tm;
char buf[1];
char buf, status1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client,
}
}
err = s35390a_reset(s35390a);
if (err < 0) {
err_reset = s35390a_reset(s35390a, &status1);
if (err_reset < 0) {
err = err_reset;
dev_err(&client->dev, "error resetting chip\n");
goto exit_dummy;
}
err = s35390a_disable_test_mode(s35390a);
if (err < 0) {
dev_err(&client->dev, "error disabling test mode\n");
goto exit_dummy;
}
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
if (err < 0) {
dev_err(&client->dev, "error checking 12/24 hour mode\n");
goto exit_dummy;
}
if (buf[0] & S35390A_FLAG_24H)
if (status1 & S35390A_FLAG_24H)
s35390a->twentyfourhour = 1;
else
s35390a->twentyfourhour = 0;
if (s35390a_get_datetime(client, &tm) < 0)
if (status1 & S35390A_FLAG_INT2) {
/* disable alarm (and maybe test mode) */
buf = 0;
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
if (err < 0) {
dev_err(&client->dev, "error disabling alarm");
goto exit_dummy;
}
} else {
err = s35390a_disable_test_mode(s35390a);
if (err < 0) {
dev_err(&client->dev, "error disabling test mode\n");
goto exit_dummy;
}
}
if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
dev_warn(&client->dev, "clock needs to be set\n");
device_set_wakeup_capable(&client->dev, 1);
@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client,
err = PTR_ERR(s35390a->rtc);
goto exit_dummy;
}
if (status1 & S35390A_FLAG_INT2)
rtc_update_irq(s35390a->rtc, 1, RTC_AF);
return 0;
exit_dummy:

View File

@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
if (!is_power_of_2(freq))
return -EINVAL;
s3c_rtc_enable_clk(info);
spin_lock_irq(&info->pie_lock);
if (info->data->set_freq)
info->data->set_freq(info, freq);
spin_unlock_irq(&info->pie_lock);
s3c_rtc_disable_clk(info);
return 0;
}
@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN)
alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
else
alm_tm->tm_sec = -1;
if (alm_en & S3C2410_RTCALM_MINEN)
alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
else
alm_tm->tm_min = -1;
if (alm_en & S3C2410_RTCALM_HOUREN)
alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
else
alm_tm->tm_hour = -1;
if (alm_en & S3C2410_RTCALM_DAYEN)
alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
else
alm_tm->tm_mday = -1;
if (alm_en & S3C2410_RTCALM_MONEN) {
alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
alm_tm->tm_mon -= 1;
} else {
alm_tm->tm_mon = -1;
}
if (alm_en & S3C2410_RTCALM_YEAREN)
alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
else
alm_tm->tm_year = -1;
return 0;
}
@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_setfreq(info, 1);
s3c_rtc_disable_clk(info);
return 0;
err_nortc:

View File

@ -481,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR);
if (tm->tm_mon > 0)
tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
tm->tm_year = 0xffff;
wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
@ -500,52 +499,13 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off);
}
static int sh_rtc_check_alarm(struct rtc_time *tm)
{
/*
* The original rtc says anything > 0xc0 is "don't care" or "match
* all" - most users use 0xff but rtc-dev uses -1 for the same thing.
* The original rtc doesn't support years - some things use -1 and
* some 0xffff. We use -1 to make out tests easier.
*/
if (tm->tm_year == 0xffff)
tm->tm_year = -1;
if (tm->tm_mon >= 0xff)
tm->tm_mon = -1;
if (tm->tm_mday >= 0xff)
tm->tm_mday = -1;
if (tm->tm_wday >= 0xff)
tm->tm_wday = -1;
if (tm->tm_hour >= 0xff)
tm->tm_hour = -1;
if (tm->tm_min >= 0xff)
tm->tm_min = -1;
if (tm->tm_sec >= 0xff)
tm->tm_sec = -1;
if (tm->tm_year > 9999 ||
tm->tm_mon >= 12 ||
tm->tm_mday == 0 || tm->tm_mday >= 32 ||
tm->tm_wday >= 7 ||
tm->tm_hour >= 24 ||
tm->tm_min >= 60 ||
tm->tm_sec >= 60)
return -EINVAL;
return 0;
}
static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_rtc *rtc = platform_get_drvdata(pdev);
unsigned int rcr1;
struct rtc_time *tm = &wkalrm->time;
int mon, err;
err = sh_rtc_check_alarm(tm);
if (unlikely(err < 0))
return err;
int mon;
spin_lock_irq(&rtc->lock);

View File

@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (sec == 0) {
/* alarm is disabled. */
alarm->enabled = 0;
alarm->time.tm_mon = -1;
alarm->time.tm_mday = -1;
alarm->time.tm_year = -1;
alarm->time.tm_hour = -1;
alarm->time.tm_min = -1;
alarm->time.tm_sec = -1;
} else {
/* alarm is enabled. */
alarm->enabled = 1;

View File

@ -25,7 +25,7 @@
#include <linux/rtc.h>
#include <linux/types.h>
#include <linux/bcd.h>
#include <linux/rtc-v3020.h>
#include <linux/platform_data/rtc-v3020.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>

View File

@ -1,66 +0,0 @@
/*
* ds17287rtc.h - register definitions for the ds1728[57] RTC / CMOS RAM
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) 2003 Guido Guenther <agx@sigxcpu.org>
*/
#ifndef __LINUX_DS17287RTC_H
#define __LINUX_DS17287RTC_H
#include <linux/rtc.h> /* get the user-level API */
#include <linux/mc146818rtc.h>
/* Register A */
#define DS_REGA_DV2 0x40 /* countdown chain */
#define DS_REGA_DV1 0x20 /* oscillator enable */
#define DS_REGA_DV0 0x10 /* bank select */
/* bank 1 registers */
#define DS_B1_MODEL 0x40 /* model number byte */
#define DS_B1_SN1 0x41 /* serial number byte 1 */
#define DS_B1_SN2 0x42 /* serial number byte 2 */
#define DS_B1_SN3 0x43 /* serial number byte 3 */
#define DS_B1_SN4 0x44 /* serial number byte 4 */
#define DS_B1_SN5 0x45 /* serial number byte 5 */
#define DS_B1_SN6 0x46 /* serial number byte 6 */
#define DS_B1_CRC 0x47 /* CRC byte */
#define DS_B1_CENTURY 0x48 /* Century byte */
#define DS_B1_DALARM 0x49 /* date alarm */
#define DS_B1_XCTRL4A 0x4a /* extendec control register 4a */
#define DS_B1_XCTRL4B 0x4b /* extendec control register 4b */
#define DS_B1_RTCADDR2 0x4e /* rtc address 2 */
#define DS_B1_RTCADDR3 0x4f /* rtc address 3 */
#define DS_B1_RAMLSB 0x50 /* extended ram LSB */
#define DS_B1_RAMMSB 0x51 /* extended ram MSB */
#define DS_B1_RAMDPORT 0x53 /* extended ram data port */
/* register details */
/* extended control register 4a */
#define DS_XCTRL4A_VRT2 0x80 /* valid ram and time */
#define DS_XCTRL4A_INCR 0x40 /* increment progress status */
#define DS_XCTRL4A_BME 0x20 /* burst mode enable */
#define DS_XCTRL4A_PAB 0x08 /* power active bar ctrl */
#define DS_XCTRL4A_RF 0x04 /* ram clear flag */
#define DS_XCTRL4A_WF 0x02 /* wake up alarm flag */
#define DS_XCTRL4A_KF 0x01 /* kickstart flag */
/* interrupt causes */
#define DS_XCTRL4A_IFS (DS_XCTRL4A_RF|DS_XCTRL4A_WF|DS_XCTRL4A_KF)
/* extended control register 4b */
#define DS_XCTRL4B_ABE 0x80 /* auxiliary battery enable */
#define DS_XCTRL4B_E32K 0x40 /* enable 32.768 kHz Output */
#define DS_XCTRL4B_CS 0x20 /* crystal select */
#define DS_XCTRL4B_RCE 0x10 /* ram clear enable */
#define DS_XCTRL4B_PRS 0x08 /* PAB resec select */
#define DS_XCTRL4B_RIE 0x04 /* ram clear interrupt enable */
#define DS_XCTRL4B_WFE 0x02 /* wake up alarm interrupt enable */
#define DS_XCTRL4B_KFE 0x01 /* kickstart interrupt enable */
/* interrupt enable bits */
#define DS_XCTRL4B_IFES (DS_XCTRL4B_RIE|DS_XCTRL4B_WFE|DS_XCTRL4B_KFE)
#endif /* __LINUX_DS17287RTC_H */

View File

@ -14,6 +14,8 @@
#include <asm/io.h>
#include <linux/rtc.h> /* get the user-level API */
#include <asm/mc146818rtc.h> /* register access macros */
#include <linux/bcd.h>
#include <linux/delay.h>
#ifdef __KERNEL__
#include <linux/spinlock.h> /* spinlock_t */
@ -120,4 +122,7 @@ struct cmos_rtc_board_info {
#define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */
unsigned int mc146818_get_time(struct rtc_time *time);
int mc146818_set_time(struct rtc_time *time);
#endif /* _MC146818RTC_H */

Some files were not shown because too many files have changed in this diff Show More