Commit 6c84239d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
  ...
parents d4c06c70 6f367788
...@@ -244,7 +244,7 @@ static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -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); retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags);
if (retval < 0) { 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 retval;
} }
return 0; return 0;
...@@ -320,10 +320,8 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -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_sec = bcd2bin(alarmvals[4] & 0x7f);
alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f); alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f); alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f); alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f); alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f);
alrm->time.tm_year = -1;
alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE); alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled; alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
...@@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = { ...@@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = {
.proc = m41t80_rtc_proc, .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, static ssize_t flags_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client, ...@@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client,
return rc; return rc;
} }
rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group, rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group,
&client->dev); &client->dev);
if (rc) { if (rc) {
m41t80_remove_sysfs_group(&client->dev);
dev_err(&client->dev, dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n", rc); "Failed to add sysfs cleanup action: %d\n", rc);
return rc; return rc;
...@@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client) ...@@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client)
static struct i2c_driver m41t80_driver = { static struct i2c_driver m41t80_driver = {
.driver = { .driver = {
.name = "rtc-m41t80", .name = "rtc-m41t80",
.pm = &m41t80_pm,
}, },
.probe = m41t80_probe, .probe = m41t80_probe,
.remove = m41t80_remove, .remove = m41t80_remove,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/m48t86.h> #include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#define M48T86_REG_SEC 0x00 #define M48T86_REG_SEC 0x00
......
/* 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");
/*
* 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/bcd.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/export.h>
#include <linux/mc146818rtc.h>
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <linux/acpi.h> #include <linux/acpi.h>
#endif #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 * 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 char uip;
unsigned long flags; unsigned long flags;
...@@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void) ...@@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void)
return uip; 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 char ctrl;
unsigned long flags; unsigned long flags;
...@@ -60,11 +36,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) ...@@ -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 * 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. * 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 * 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. * immediately read /dev/rtc which will block until you get the IRQ.
* Once the read clears, read the RTC time (again via ioctl). Easy. * Once the read clears, read the RTC time (again via ioctl). Easy.
*/ */
if (rtc_is_updating()) if (mc146818_is_updating())
mdelay(20); mdelay(20);
/* /*
...@@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) ...@@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
return RTC_24H; return RTC_24H;
} }
EXPORT_SYMBOL_GPL(mc146818_get_time);
#ifndef get_rtc_time
#define get_rtc_time __get_rtc_time
#endif
/* Set the current date and time in the real time clock. */ /* 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 long flags;
unsigned char mon, day, hrs, min, sec; unsigned char mon, day, hrs, min, sec;
...@@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time) ...@@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(mc146818_set_time);
#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__ */
...@@ -32,11 +32,11 @@ ...@@ -32,11 +32,11 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sfi.h> #include <linux/sfi.h>
#include <asm-generic/rtc.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
#include <asm/intel-mid.h> #include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h> #include <asm/intel_mid_vrtc.h>
...@@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (mrst->irq <= 0) if (mrst->irq <= 0)
return -EIO; 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 */ /* vRTC only supports binary mode */
spin_lock_irq(&rtc_lock); spin_lock_irq(&rtc_lock);
t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
......
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
#define CD_TMR_TE BIT(3) /* Countdown timer enable */ #define CD_TMR_TE BIT(3) /* Countdown timer enable */
/* PCF2123_REG_OFFSET BITS */ /* 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_COARSE BIT(7) /* Coarse mode offset */
#define OFFSET_STEP (2170) /* Offset step in parts per billion */ #define OFFSET_STEP (2170) /* Offset step in parts per billion */
...@@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset) ...@@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)
if (reg & OFFSET_COARSE) if (reg & OFFSET_COARSE)
reg <<= 1; /* multiply by 2 and sign extend */ reg <<= 1; /* multiply by 2 and sign extend */
else else
reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */ reg = sign_extend32(reg, OFFSET_SIGN_BIT);
*offset = ((long)reg) * OFFSET_STEP; *offset = ((long)reg) * OFFSET_STEP;
......
...@@ -16,6 +16,16 @@ ...@@ -16,6 +16,16 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/module.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 0x00 /* status */
#define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL1_STOP BIT(5)
#define PCF85063_REG_CTRL2 0x01 #define PCF85063_REG_CTRL2 0x01
...@@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) ...@@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
return 0; return 0;
} }
/* static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
* In the routines that deal directly with the pcf85063 hardware, we use {
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. 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) static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{ {
int rc; int rc;
...@@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -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_wday = regs[4] & 0x07;
tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */ tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
tm->tm_year = bcd2bin(regs[6]); tm->tm_year = bcd2bin(regs[6]);
if (tm->tm_year < 70) tm->tm_year += 100;
tm->tm_year += 100; /* assume we are in 1970...2069 */
return rtc_valid_tm(tm); return rtc_valid_tm(tm);
} }
...@@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *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) static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{ {
int rc; 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 * to accurately set the time, reset the divider chain and keep it in
* reset state until all time/date registers are written * 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) if (rc != 0)
return rc; return rc;
...@@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
regs[5] = bin2bcd(tm->tm_mon + 1); regs[5] = bin2bcd(tm->tm_mon + 1);
/* year and century */ /* year and century */
regs[6] = bin2bcd(tm->tm_year % 100); 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;
/* write all registers at once */ /* write all registers at once */
rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC, 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) ...@@ -142,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return rc; 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; return 0;
} }
......
...@@ -341,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) ...@@ -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", "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
__func__, buf[0], buf[1], buf[2], buf[3]); __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_min = bcd2bin(buf[0] & 0x7F);
tm->time.tm_hour = bcd2bin(buf[1] & 0x3F); tm->time.tm_hour = bcd2bin(buf[1] & 0x3F);
tm->time.tm_mday = bcd2bin(buf[2] & 0x3F); tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
tm->time.tm_wday = bcd2bin(buf[3] & 0x7); 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); err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
if (err < 0) if (err < 0)
......
...@@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) ...@@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret; return ret;
} }
alm->time.tm_sec = 0;
alm->time.tm_min = bcd2bin(alarm_data[0]); alm->time.tm_min = bcd2bin(alarm_data[0]);
alm->time.tm_hour = bcd2bin(alarm_data[1]); alm->time.tm_hour = bcd2bin(alarm_data[1]);
alm->time.tm_mday = bcd2bin(alarm_data[2]); alm->time.tm_mday = bcd2bin(alarm_data[2]);
......
...@@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_sec = 0; t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); 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_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 */ /* ... and status */
t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE); t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
......
...@@ -13,12 +13,15 @@ ...@@ -13,12 +13,15 @@
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#define RV8803_I2C_TRY_COUNT 4
#define RV8803_SEC 0x00 #define RV8803_SEC 0x00
#define RV8803_MIN 0x01 #define RV8803_MIN 0x01
#define RV8803_HOUR 0x02 #define RV8803_HOUR 0x02
...@@ -56,19 +59,85 @@ struct rv8803_data { ...@@ -56,19 +59,85 @@ struct rv8803_data {
u8 ctrl; 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) static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{ {
struct i2c_client *client = dev_id; struct i2c_client *client = dev_id;
struct rv8803_data *rv8803 = i2c_get_clientdata(client); struct rv8803_data *rv8803 = i2c_get_clientdata(client);
unsigned long events = 0; unsigned long events = 0;
int flags, try = 0; int flags;
mutex_lock(&rv8803->flags_lock); mutex_lock(&rv8803->flags_lock);
do { flags = rv8803_read_reg(client, RV8803_FLAG);
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
try++;
} while ((flags == -ENXIO) && (try < 3));
if (flags <= 0) { if (flags <= 0) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return IRQ_NONE; return IRQ_NONE;
...@@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) ...@@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
if (events) { if (events) {
rtc_update_irq(rv8803->rtc, 1, events); rtc_update_irq(rv8803->rtc, 1, events);
i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); rv8803_write_reg(client, RV8803_FLAG, flags);
i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl);
rv8803->ctrl);
} }
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
...@@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) ...@@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
u8 *date = date1; u8 *date = date1;
int ret, flags; int ret, flags;
flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0) if (flags < 0)
return flags; return flags;
...@@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) ...@@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
return -EINVAL; return -EINVAL;
} }
ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date);
7, date); if (ret)
if (ret != 7) return ret;
return ret < 0 ? ret : -EIO;
if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2);
7, date2); if (ret)
if (ret != 7) return ret;
return ret < 0 ? ret : -EIO;
if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
date = date2; date = date2;
...@@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) ...@@ -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_sec = bcd2bin(date[RV8803_SEC] & 0x7f);
tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f); tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f);
tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f); 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_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1; tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100; 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) static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct rv8803_data *rv8803 = dev_get_drvdata(dev); struct rv8803_data *rv8803 = dev_get_drvdata(dev);
u8 date[7]; u8 date[7];
int flags, ret; int ctrl, flags, ret;
if ((tm->tm_year < 100) || (tm->tm_year > 199)) if ((tm->tm_year < 100) || (tm->tm_year > 199))
return -EINVAL; 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_SEC] = bin2bcd(tm->tm_sec);
date[RV8803_MIN] = bin2bcd(tm->tm_min); date[RV8803_MIN] = bin2bcd(tm->tm_min);
date[RV8803_HOUR] = bin2bcd(tm->tm_hour); date[RV8803_HOUR] = bin2bcd(tm->tm_hour);
...@@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm) ...@@ -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_MONTH] = bin2bcd(tm->tm_mon + 1);
date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100);
ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC, ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date);
7, date); if (ret)
if (ret < 0) return ret;
/* Restart the clock */
ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
ctrl & ~RV8803_CTRL_RESET);
if (ret)
return ret; return ret;
mutex_lock(&rv8803->flags_lock); 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) { if (flags < 0) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return flags; return flags;
} }
ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
flags & ~RV8803_FLAG_V2F); flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
...@@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 alarmvals[3]; u8 alarmvals[3];
int flags, ret; int flags, ret;
ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN, ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals);
3, alarmvals); if (ret)
if (ret != 3) return ret;
return ret < 0 ? ret : -EIO;
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) if (flags < 0)
return flags; return flags;
alrm->time.tm_sec = 0; alrm->time.tm_sec = 0;
alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f); 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->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled; alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
...@@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
mutex_lock(&rv8803->flags_lock); mutex_lock(&rv8803->flags_lock);
ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl); ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl);
if (ret != 2) { if (ret) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return ret < 0 ? ret : -EIO; return ret;
} }
alarmvals[0] = bin2bcd(alrm->time.tm_min); alarmvals[0] = bin2bcd(alrm->time.tm_min);
...@@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -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)) { if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
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, err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
rv8803->ctrl); rv8803->ctrl);
if (err) { if (err) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return err; return err;
...@@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
} }
ctrl[1] &= ~RV8803_FLAG_AF; 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); mutex_unlock(&rv8803->flags_lock);
if (err) if (err)
return err; return err;
err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN, err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals);
3, alarmvals);
if (err) if (err)
return err; return err;
...@@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rv8803->rtc->aie_timer.enabled) if (rv8803->rtc->aie_timer.enabled)
rv8803->ctrl |= RV8803_CTRL_AIE; rv8803->ctrl |= RV8803_CTRL_AIE;
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
rv8803->ctrl); rv8803->ctrl);
if (err) if (err)
return err; return err;
} }
...@@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
} }
mutex_lock(&rv8803->flags_lock); mutex_lock(&rv8803->flags_lock);
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) { if (flags < 0) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return flags; return flags;
} }
flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); 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); mutex_unlock(&rv8803->flags_lock);
if (err) if (err)
return err; return err;
if (ctrl != rv8803->ctrl) { if (ctrl != rv8803->ctrl) {
rv8803->ctrl = ctrl; rv8803->ctrl = ctrl;
err = i2c_smbus_write_byte_data(client, RV8803_CTRL, err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl);
rv8803->ctrl);
if (err) if (err)
return err; return err;
} }
...@@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) ...@@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
switch (cmd) { switch (cmd) {
case RTC_VL_READ: case RTC_VL_READ:
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) if (flags < 0)
return flags; return flags;
...@@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) ...@@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
case RTC_VL_CLR: case RTC_VL_CLR:
mutex_lock(&rv8803->flags_lock); mutex_lock(&rv8803->flags_lock);
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) { if (flags < 0) {
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
return flags; return flags;
} }
flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); 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); mutex_unlock(&rv8803->flags_lock);
if (ret < 0) if (ret)
return ret; return ret;
return 0; return 0;
...@@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int ret; int ret;
ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]); ret = rv8803_write_reg(client, RV8803_RAM, buf[0]);
if (ret < 0) if (ret)
return ret; return ret;
return 1; return 1;
...@@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int ret; int ret;
ret = i2c_smbus_read_byte_data(client, RV8803_RAM); ret = rv8803_read_reg(client, RV8803_RAM);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client,
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rv8803_data *rv8803; struct rv8803_data *rv8803;
int err, flags, try = 0; int err, flags;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK)) { I2C_FUNC_SMBUS_I2C_BLOCK)) {
...@@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client,
rv8803->client = client; rv8803->client = client;
i2c_set_clientdata(client, rv8803); i2c_set_clientdata(client, rv8803);
/* flags = rv8803_read_reg(client, RV8803_FLAG);
* 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));
if (flags < 0) if (flags < 0)
return flags; return flags;
...@@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client,
return PTR_ERR(rv8803->rtc); return PTR_ERR(rv8803->rtc);
} }
try = 0; err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
do {
err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
RV8803_EXT_WADA);
try++;
} while ((err == -ENXIO) && (try < 3));
if (err) if (err)
return err; return err;
......
...@@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -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_min = bcd2bin(alarmvals[0] & 0x7f);
t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
if (alarmvals[2] & RX8010_ALARM_AE) if (!(alarmvals[2] & RX8010_ALARM_AE))
t->time.tm_mday = -1;
else
t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f); 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->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled; t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;
......
...@@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -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 t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
+ (ald[1] & 0x20 ? 12 : 0); + (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", dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n",
__func__, __func__,
t->time.tm_sec, t->time.tm_min, t->time.tm_hour, t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/bitrev.h> #include <linux/bitrev.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#define S35390A_CMD_STATUS1 0 #define S35390A_CMD_STATUS1 0
#define S35390A_CMD_STATUS2 1 #define S35390A_CMD_STATUS2 1
...@@ -34,10 +35,14 @@ ...@@ -34,10 +35,14 @@
#define S35390A_ALRM_BYTE_HOURS 1 #define S35390A_ALRM_BYTE_HOURS 1
#define S35390A_ALRM_BYTE_MINS 2 #define S35390A_ALRM_BYTE_MINS 2
/* flags for STATUS1 */
#define S35390A_FLAG_POC 0x01 #define S35390A_FLAG_POC 0x01
#define S35390A_FLAG_BLD 0x02 #define S35390A_FLAG_BLD 0x02
#define S35390A_FLAG_INT2 0x04
#define S35390A_FLAG_24H 0x40 #define S35390A_FLAG_24H 0x40
#define S35390A_FLAG_RESET 0x80 #define S35390A_FLAG_RESET 0x80
/* flag for STATUS2 */
#define S35390A_FLAG_TEST 0x01 #define S35390A_FLAG_TEST 0x01
#define S35390A_INT2_MODE_MASK 0xF0 #define S35390A_INT2_MODE_MASK 0xF0
...@@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) ...@@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
return 0; 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;
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) unsigned initcount = 0;
return -EIO;
ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) if (ret < 0)
return ret;
if (*status1 & S35390A_FLAG_POC)
/*
* Do not communicate for 0.5 seconds since the power-on
* detection circuit is in operation.
*/
msleep(500);
else if (!(*status1 & S35390A_FLAG_BLD))
/*
* If both POC and BLD are unset everything is fine.
*/
return 0; return 0;
buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); /*
buf[0] &= 0xf0; * At least one of POC and BLD are set, so reinitialise chip. Keeping
return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); * 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) 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) ...@@ -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_min, alm->time.tm_hour, alm->time.tm_mday,
alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); 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)); err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0) if (err < 0)
return err; 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)); err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
if (err < 0) if (err < 0)
return err; return err;
...@@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ...@@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (alm->time.tm_wday != -1) if (alm->time.tm_wday != -1)
buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; 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, buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
alm->time.tm_hour) | 0x80; alm->time.tm_hour) | 0x80;
...@@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ...@@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (err < 0) if (err < 0)
return err; return err;
if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
return -EINVAL; /*
* 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)); err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
if (err < 0) if (err < 0)
return err; return err;
/* This chip returns the bits of each byte in reverse order */ /* 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] = bitrev8(buf[i]);
buf[i] &= ~0x80;
}
alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); /*
alm->time.tm_hour = s35390a_reg2hr(s35390a, * B0 of the three matching registers is an enable flag. Iff it is set
buf[S35390A_ALRM_BYTE_HOURS]); * the configured value is used for matching.
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); */
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", dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
__func__, alm->time.tm_min, alm->time.tm_hour, __func__, alm->time.tm_min, alm->time.tm_hour,
...@@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver; ...@@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver;
static int s35390a_probe(struct i2c_client *client, static int s35390a_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
int err; int err, err_reset;
unsigned int i; unsigned int i;
struct s35390a *s35390a; struct s35390a *s35390a;
struct rtc_time tm; struct rtc_time tm;
char buf[1]; char buf, status1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV; err = -ENODEV;
...@@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client, ...@@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client,
} }
} }
err = s35390a_reset(s35390a); err_reset = s35390a_reset(s35390a, &status1);
if (err < 0) { if (err_reset < 0) {
err = err_reset;
dev_err(&client->dev, "error resetting chip\n"); dev_err(&client->dev, "error resetting chip\n");
goto exit_dummy; goto exit_dummy;
} }
err = s35390a_disable_test_mode(s35390a); if (status1 & S35390A_FLAG_24H)
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)
s35390a->twentyfourhour = 1; s35390a->twentyfourhour = 1;
else else
s35390a->twentyfourhour = 0; 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"); dev_warn(&client->dev, "clock needs to be set\n");
device_set_wakeup_capable(&client->dev, 1); device_set_wakeup_capable(&client->dev, 1);
...@@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client, ...@@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client,
err = PTR_ERR(s35390a->rtc); err = PTR_ERR(s35390a->rtc);
goto exit_dummy; goto exit_dummy;
} }
if (status1 & S35390A_FLAG_INT2)
rtc_update_irq(s35390a->rtc, 1, RTC_AF);
return 0; return 0;
exit_dummy: exit_dummy:
......
...@@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) ...@@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
if (!is_power_of_2(freq)) if (!is_power_of_2(freq))
return -EINVAL; return -EINVAL;
s3c_rtc_enable_clk(info);
spin_lock_irq(&info->pie_lock); spin_lock_irq(&info->pie_lock);
if (info->data->set_freq) if (info->data->set_freq)
info->data->set_freq(info, freq); info->data->set_freq(info, freq);
spin_unlock_irq(&info->pie_lock); spin_unlock_irq(&info->pie_lock);
s3c_rtc_disable_clk(info);
return 0; return 0;
} }
...@@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* decode the alarm enable field */ /* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN) if (alm_en & S3C2410_RTCALM_SECEN)
alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
else
alm_tm->tm_sec = -1;
if (alm_en & S3C2410_RTCALM_MINEN) if (alm_en & S3C2410_RTCALM_MINEN)
alm_tm->tm_min = bcd2bin(alm_tm->tm_min); alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
else
alm_tm->tm_min = -1;
if (alm_en & S3C2410_RTCALM_HOUREN) if (alm_en & S3C2410_RTCALM_HOUREN)
alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
else
alm_tm->tm_hour = -1;
if (alm_en & S3C2410_RTCALM_DAYEN) if (alm_en & S3C2410_RTCALM_DAYEN)
alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
else
alm_tm->tm_mday = -1;
if (alm_en & S3C2410_RTCALM_MONEN) { if (alm_en & S3C2410_RTCALM_MONEN) {
alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
alm_tm->tm_mon -= 1; alm_tm->tm_mon -= 1;
} else {
alm_tm->tm_mon = -1;
} }
if (alm_en & S3C2410_RTCALM_YEAREN) if (alm_en & S3C2410_RTCALM_YEAREN)
alm_tm->tm_year = bcd2bin(alm_tm->tm_year); alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
else
alm_tm->tm_year = -1;
return 0; return 0;
} }
...@@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) ...@@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_setfreq(info, 1); s3c_rtc_setfreq(info, 1);
s3c_rtc_disable_clk(info);
return 0; return 0;
err_nortc: err_nortc:
......
...@@ -481,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) ...@@ -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); tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR);
if (tm->tm_mon > 0) if (tm->tm_mon > 0)
tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ 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; 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, ...@@ -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); 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) static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct sh_rtc *rtc = platform_get_drvdata(pdev); struct sh_rtc *rtc = platform_get_drvdata(pdev);
unsigned int rcr1; unsigned int rcr1;
struct rtc_time *tm = &wkalrm->time; struct rtc_time *tm = &wkalrm->time;
int mon, err; int mon;
err = sh_rtc_check_alarm(tm);
if (unlikely(err < 0))
return err;
spin_lock_irq(&rtc->lock); spin_lock_irq(&rtc->lock);
......
...@@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (sec == 0) { if (sec == 0) {
/* alarm is disabled. */ /* alarm is disabled. */
alarm->enabled = 0; 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 { } else {
/* alarm is enabled. */ /* alarm is enabled. */
alarm->enabled = 1; alarm->enabled = 1;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/rtc-v3020.h> #include <linux/platform_data/rtc-v3020.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
......
/*
* 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 */
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/rtc.h> /* get the user-level API */ #include <linux/rtc.h> /* get the user-level API */
#include <asm/mc146818rtc.h> /* register access macros */ #include <asm/mc146818rtc.h> /* register access macros */
#include <linux/bcd.h>
#include <linux/delay.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/spinlock.h> /* spinlock_t */ #include <linux/spinlock.h> /* spinlock_t */
...@@ -120,4 +122,7 @@ struct cmos_rtc_board_info { ...@@ -120,4 +122,7 @@ struct cmos_rtc_board_info {
#define RTC_IO_EXTENT_USED RTC_IO_EXTENT #define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */ #endif /* ARCH_RTC_LOCATION */
unsigned int mc146818_get_time(struct rtc_time *time);
int mc146818_set_time(struct rtc_time *time);
#endif /* _MC146818RTC_H */ #endif /* _MC146818RTC_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment