Merge commit 'v2.6.26' into bkl-removal

This commit is contained in:
Jonathan Corbet
2008-07-14 15:29:34 -06:00
1975 changed files with 41893 additions and 19758 deletions

View File

@@ -256,6 +256,17 @@ config RTC_DRV_S35390A
This driver can also be built as a module. If so the module
will be called rtc-s35390a.
config RTC_DRV_FM3130
tristate "Ramtron FM3130"
help
If you say Y here you will get support for the
Ramtron FM3130 RTC chips.
Ramtron FM3130 is a chip with two separate devices inside,
RTC clock and FRAM. This driver provides only RTC functionality.
This driver can also be built as a module. If so the module
will be called rtc-fm3130.
endif # I2C
comment "SPI RTC drivers"
@@ -534,4 +545,12 @@ config RTC_DRV_RS5C313
help
If you say yes here you get support for the Ricoh RS5C313 RTC chips.
config RTC_DRV_PPC
tristate "PowerPC machine dependent RTC support"
depends on PPC_MERGE
help
The PowerPC kernel has machine-specific functions for accessing
the RTC. This exposes that functionality through the generic RTC
class.
endif # RTC_CLASS

View File

@@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o

View File

@@ -126,12 +126,25 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
int err;
struct rtc_time before, now;
int first_time = 1;
unsigned long t_now, t_alm;
enum { none, day, month, year } missing = none;
unsigned days;
/* The lower level RTC driver may not be capable of filling
* in all fields of the rtc_time struct (eg. rtc-cmos),
* and so might instead return -1 in some fields.
* We deal with that here by grabbing a current RTC timestamp
* and using values from that for any missing (-1) values.
/* The lower level RTC driver may return -1 in some fields,
* creating invalid alarm->time values, for reasons like:
*
* - The hardware may not be capable of filling them in;
* many alarms match only on time-of-day fields, not
* day/month/year calendar data.
*
* - Some hardware uses illegal values as "wildcard" match
* values, which non-Linux firmware (like a BIOS) may try
* to set up as e.g. "alarm 15 minutes after each hour".
* Linux uses only oneshot alarms.
*
* When we see that here, we deal with it by using values from
* a current RTC timestamp for any missing (-1) values. The
* RTC driver prevents "periodic alarm" modes.
*
* But this can be racey, because some fields of the RTC timestamp
* may have wrapped in the interval since we read the RTC alarm,
@@ -174,6 +187,10 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (!alarm->enabled)
return 0;
/* full-function RTCs won't have such missing fields */
if (rtc_valid_tm(&alarm->time) == 0)
return 0;
/* get the "after" timestamp, to detect wrapped fields */
err = rtc_read_time(rtc, &now);
if (err < 0)
@@ -183,22 +200,85 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
} while ( before.tm_min != now.tm_min
|| before.tm_hour != now.tm_hour
|| before.tm_mon != now.tm_mon
|| before.tm_year != now.tm_year
|| before.tm_isdst != now.tm_isdst);
|| before.tm_year != now.tm_year);
/* Fill in any missing alarm fields using the timestamp */
/* Fill in the missing alarm fields using the timestamp; we
* know there's at least one since alarm->time is invalid.
*/
if (alarm->time.tm_sec == -1)
alarm->time.tm_sec = now.tm_sec;
if (alarm->time.tm_min == -1)
alarm->time.tm_min = now.tm_min;
if (alarm->time.tm_hour == -1)
alarm->time.tm_hour = now.tm_hour;
if (alarm->time.tm_mday == -1)
/* For simplicity, only support date rollover for now */
if (alarm->time.tm_mday == -1) {
alarm->time.tm_mday = now.tm_mday;
if (alarm->time.tm_mon == -1)
missing = day;
}
if (alarm->time.tm_mon == -1) {
alarm->time.tm_mon = now.tm_mon;
if (alarm->time.tm_year == -1)
if (missing == none)
missing = month;
}
if (alarm->time.tm_year == -1) {
alarm->time.tm_year = now.tm_year;
if (missing == none)
missing = year;
}
/* with luck, no rollover is needed */
rtc_tm_to_time(&now, &t_now);
rtc_tm_to_time(&alarm->time, &t_alm);
if (t_now < t_alm)
goto done;
switch (missing) {
/* 24 hour rollover ... if it's now 10am Monday, an alarm that
* that will trigger at 5am will do so at 5am Tuesday, which
* could also be in the next month or year. This is a common
* case, especially for PCs.
*/
case day:
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
t_alm += 24 * 60 * 60;
rtc_time_to_tm(t_alm, &alarm->time);
break;
/* Month rollover ... if it's the 31th, an alarm on the 3rd will
* be next month. An alarm matching on the 30th, 29th, or 28th
* may end up in the month after that! Many newer PCs support
* this type of alarm.
*/
case month:
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
do {
if (alarm->time.tm_mon < 11)
alarm->time.tm_mon++;
else {
alarm->time.tm_mon = 0;
alarm->time.tm_year++;
}
days = rtc_month_days(alarm->time.tm_mon,
alarm->time.tm_year);
} while (days < alarm->time.tm_mday);
break;
/* Year rollover ... easy except for leap years! */
case year:
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
do {
alarm->time.tm_year++;
} while (!rtc_valid_tm(&alarm->time));
break;
default:
dev_warn(&rtc->dev, "alarm rollover not handled\n");
}
done:
return 0;
}
EXPORT_SYMBOL_GPL(rtc_read_alarm);

View File

@@ -94,8 +94,11 @@ static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
spin_lock_irq(&rtc->lock);
rtc_time_to_tm(rtc->alarm_time, &alrm->time);
alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0;
spin_unlock_irq(&rtc->lock);
return 0;
}
@@ -119,7 +122,7 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
spin_lock_irq(&rtc->lock);
rtc->alarm_time = alarm_unix_time;
rtc_writel(rtc, TOP, rtc->alarm_time);
if (alrm->pending)
if (alrm->enabled)
rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
| RTC_BIT(CTRL_TOPEN));
else

View File

@@ -905,19 +905,7 @@ static struct pnp_driver cmos_pnp_driver = {
.resume = cmos_pnp_resume,
};
static int __init cmos_init(void)
{
return pnp_register_driver(&cmos_pnp_driver);
}
module_init(cmos_init);
static void __exit cmos_exit(void)
{
pnp_unregister_driver(&cmos_pnp_driver);
}
module_exit(cmos_exit);
#else /* no PNP */
#endif /* CONFIG_PNP */
/*----------------------------------------------------------------*/
@@ -958,20 +946,33 @@ static struct platform_driver cmos_platform_driver = {
static int __init cmos_init(void)
{
#ifdef CONFIG_PNP
if (pnp_platform_devices)
return pnp_register_driver(&cmos_pnp_driver);
else
return platform_driver_probe(&cmos_platform_driver,
cmos_platform_probe);
#else
return platform_driver_probe(&cmos_platform_driver,
cmos_platform_probe);
#endif /* CONFIG_PNP */
}
module_init(cmos_init);
static void __exit cmos_exit(void)
{
#ifdef CONFIG_PNP
if (pnp_platform_devices)
pnp_unregister_driver(&cmos_pnp_driver);
else
platform_driver_unregister(&cmos_platform_driver);
#else
platform_driver_unregister(&cmos_platform_driver);
#endif /* CONFIG_PNP */
}
module_exit(cmos_exit);
#endif /* !PNP */
MODULE_AUTHOR("David Brownell");
MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs");
MODULE_LICENSE("GPL");

View File

@@ -42,7 +42,7 @@
#define DS1374_REG_TCR 0x09 /* Trickle Charge */
static const struct i2c_device_id ds1374_id[] = {
{ "rtc-ds1374", 0 },
{ "ds1374", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1374_id);

501
drivers/rtc/rtc-fm3130.c Normal file
View File

@@ -0,0 +1,501 @@
/*
* rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip.
*
* Copyright (C) 2008 Sergey Lapin
* Based on ds1307 driver by James Chapman and David Brownell
*
* 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/module.h>
#include <linux/i2c.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#define FM3130_RTC_CONTROL (0x0)
#define FM3130_CAL_CONTROL (0x1)
#define FM3130_RTC_SECONDS (0x2)
#define FM3130_RTC_MINUTES (0x3)
#define FM3130_RTC_HOURS (0x4)
#define FM3130_RTC_DAY (0x5)
#define FM3130_RTC_DATE (0x6)
#define FM3130_RTC_MONTHS (0x7)
#define FM3130_RTC_YEARS (0x8)
#define FM3130_ALARM_SECONDS (0x9)
#define FM3130_ALARM_MINUTES (0xa)
#define FM3130_ALARM_HOURS (0xb)
#define FM3130_ALARM_DATE (0xc)
#define FM3130_ALARM_MONTHS (0xd)
#define FM3130_ALARM_WP_CONTROL (0xe)
#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */
#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */
#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */
#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */
#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */
#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */
#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */
#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */
#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */
#define FM3130_CLOCK_REGS 7
#define FM3130_ALARM_REGS 5
struct fm3130 {
u8 reg_addr_time;
u8 reg_addr_alarm;
u8 regs[15];
struct i2c_msg msg[4];
struct i2c_client *client;
struct rtc_device *rtc;
int data_valid;
int alarm;
};
static const struct i2c_device_id fm3130_id[] = {
{ "fm3130", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, fm3130_id);
#define FM3130_MODE_NORMAL 0
#define FM3130_MODE_WRITE 1
#define FM3130_MODE_READ 2
static void fm3130_rtc_mode(struct device *dev, int mode)
{
struct fm3130 *fm3130 = dev_get_drvdata(dev);
fm3130->regs[FM3130_RTC_CONTROL] =
i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
switch (mode) {
case FM3130_MODE_NORMAL:
fm3130->regs[FM3130_RTC_CONTROL] &=
~(FM3130_RTC_CONTROL_BIT_WRITE |
FM3130_RTC_CONTROL_BIT_READ);
break;
case FM3130_MODE_WRITE:
fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE;
break;
case FM3130_MODE_READ:
fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ;
break;
default:
dev_dbg(dev, "invalid mode %d\n", mode);
break;
}
/* Checking for alarm */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
fm3130->alarm = 1;
fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
}
i2c_smbus_write_byte_data(fm3130->client,
FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);
}
static int fm3130_get_time(struct device *dev, struct rtc_time *t)
{
struct fm3130 *fm3130 = dev_get_drvdata(dev);
int tmp;
if (!fm3130->data_valid) {
/* We have invalid data in RTC, probably due
to battery faults or other problems. Return EIO
for now, it will allow us to set data later insted
of error during probing which disables device */
return -EIO;
}
fm3130_rtc_mode(dev, FM3130_MODE_READ);
/* read the RTC date and time registers all at once */
tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
fm3130->msg, 2);
if (tmp != 2) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
}
fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x"
"%02x %02x %02x %02x %02x %02x %02x\n",
"read",
fm3130->regs[0], fm3130->regs[1],
fm3130->regs[2], fm3130->regs[3],
fm3130->regs[4], fm3130->regs[5],
fm3130->regs[6], fm3130->regs[7],
fm3130->regs[8], fm3130->regs[9],
fm3130->regs[0xa], fm3130->regs[0xb],
fm3130->regs[0xc], fm3130->regs[0xd],
fm3130->regs[0xe]);
t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
t->tm_hour = BCD2BIN(tmp);
t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
t->tm_mon = BCD2BIN(tmp) - 1;
/* assume 20YY not 19YY, and ignore CF bit */
t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100;
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
"read", t->tm_sec, t->tm_min,
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
/* initial clock setting can be undefined */
return rtc_valid_tm(t);
}
static int fm3130_set_time(struct device *dev, struct rtc_time *t)
{
struct fm3130 *fm3130 = dev_get_drvdata(dev);
int tmp, i;
u8 *buf = fm3130->regs;
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
"write", t->tm_sec, t->tm_min,
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
/* first register addr */
buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec);
buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min);
buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour);
buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1);
buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday);
buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1);
/* assume 20YY not 19YY */
tmp = t->tm_year - 100;
buf[FM3130_RTC_YEARS] = BIN2BCD(tmp);
dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x"
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
"write", buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7],
buf[8], buf[9], buf[0xa], buf[0xb],
buf[0xc], buf[0xd], buf[0xe]);
fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
/* Writing time registers, we don't support multibyte transfers */
for (i = 0; i < FM3130_CLOCK_REGS; i++) {
i2c_smbus_write_byte_data(fm3130->client,
FM3130_RTC_SECONDS + i,
fm3130->regs[FM3130_RTC_SECONDS + i]);
}
fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
/* We assume here that data are valid once written */
if (!fm3130->data_valid)
fm3130->data_valid = 1;
return 0;
}
static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct fm3130 *fm3130 = dev_get_drvdata(dev);
int tmp;
struct rtc_time *tm = &alrm->time;
/* read the RTC alarm registers all at once */
tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
&fm3130->msg[2], 2);
if (tmp != 2) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
}
dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
fm3130->regs[FM3130_ALARM_SECONDS],
fm3130->regs[FM3130_ALARM_MINUTES],
fm3130->regs[FM3130_ALARM_HOURS],
fm3130->regs[FM3130_ALARM_DATE],
fm3130->regs[FM3130_ALARM_MONTHS]);
tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
if (tm->tm_mon > 0)
tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
"read alarm", tm->tm_sec, tm->tm_min,
tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday);
return 0;
}
static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct fm3130 *fm3130 = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
int i;
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
"write alarm", tm->tm_sec, tm->tm_min,
tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday);
if (tm->tm_sec != -1)
fm3130->regs[FM3130_ALARM_SECONDS] =
BIN2BCD(tm->tm_sec) | 0x80;
if (tm->tm_min != -1)
fm3130->regs[FM3130_ALARM_MINUTES] =
BIN2BCD(tm->tm_min) | 0x80;
if (tm->tm_hour != -1)
fm3130->regs[FM3130_ALARM_HOURS] =
BIN2BCD(tm->tm_hour) | 0x80;
if (tm->tm_mday != -1)
fm3130->regs[FM3130_ALARM_DATE] =
BIN2BCD(tm->tm_mday) | 0x80;
if (tm->tm_mon != -1)
fm3130->regs[FM3130_ALARM_MONTHS] =
BIN2BCD(tm->tm_mon + 1) | 0x80;
dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
fm3130->regs[FM3130_ALARM_SECONDS],
fm3130->regs[FM3130_ALARM_MINUTES],
fm3130->regs[FM3130_ALARM_HOURS],
fm3130->regs[FM3130_ALARM_DATE],
fm3130->regs[FM3130_ALARM_MONTHS]);
/* Writing time registers, we don't support multibyte transfers */
for (i = 0; i < FM3130_ALARM_REGS; i++) {
i2c_smbus_write_byte_data(fm3130->client,
FM3130_ALARM_SECONDS + i,
fm3130->regs[FM3130_ALARM_SECONDS + i]);
}
fm3130->regs[FM3130_RTC_CONTROL] =
i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
/* Checking for alarm */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
fm3130->alarm = 1;
fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
}
if (alrm->enabled) {
i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
(fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_CAL)) |
FM3130_RTC_CONTROL_BIT_AEN);
} else {
i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_AEN));
}
return 0;
}
static const struct rtc_class_ops fm3130_rtc_ops = {
.read_time = fm3130_get_time,
.set_time = fm3130_set_time,
.read_alarm = fm3130_read_alarm,
.set_alarm = fm3130_set_alarm,
};
static struct i2c_driver fm3130_driver;
static int __devinit fm3130_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fm3130 *fm3130;
int err = -ENODEV;
int tmp;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
if (!i2c_check_functionality(adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return -EIO;
fm3130 = kzalloc(sizeof(struct fm3130), GFP_KERNEL);
if (!fm3130)
return -ENOMEM;
fm3130->client = client;
i2c_set_clientdata(client, fm3130);
fm3130->reg_addr_time = FM3130_RTC_SECONDS;
fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
/* Messages to read time */
fm3130->msg[0].addr = client->addr;
fm3130->msg[0].flags = 0;
fm3130->msg[0].len = 1;
fm3130->msg[0].buf = &fm3130->reg_addr_time;
fm3130->msg[1].addr = client->addr;
fm3130->msg[1].flags = I2C_M_RD;
fm3130->msg[1].len = FM3130_CLOCK_REGS;
fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
/* Messages to read alarm */
fm3130->msg[2].addr = client->addr;
fm3130->msg[2].flags = 0;
fm3130->msg[2].len = 1;
fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
fm3130->msg[3].addr = client->addr;
fm3130->msg[3].flags = I2C_M_RD;
fm3130->msg[3].len = FM3130_ALARM_REGS;
fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
fm3130->data_valid = 0;
tmp = i2c_transfer(adapter, fm3130->msg, 4);
if (tmp != 4) {
pr_debug("read error %d\n", tmp);
err = -EIO;
goto exit_free;
}
fm3130->regs[FM3130_RTC_CONTROL] =
i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
fm3130->regs[FM3130_CAL_CONTROL] =
i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
/* Checking for alarm */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
fm3130->alarm = 1;
fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
}
/* Disabling calibration mode */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL)
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_CAL));
dev_warn(&client->dev, "Disabling calibration mode!\n");
/* Disabling read and write modes */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ)
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_READ |
FM3130_RTC_CONTROL_BIT_WRITE));
dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
/* oscillator off? turn it on, so clock can tick. */
if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
fm3130->regs[FM3130_CAL_CONTROL] &
~(FM3130_CAL_CONTROL_BIT_nOSCEN));
/* oscillator fault? clear flag, and warn */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB)
dev_warn(&client->dev, "Low battery!\n");
/* oscillator fault? clear flag, and warn */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~FM3130_RTC_CONTROL_BIT_POR);
dev_warn(&client->dev, "SET TIME!\n");
}
/* ACS is controlled by alarm */
i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
/* TODO */
/* TODO need to sanity check alarm */
tmp = fm3130->regs[FM3130_RTC_SECONDS];
tmp = BCD2BIN(tmp & 0x7f);
if (tmp > 60)
goto exit_bad;
tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
if (tmp > 60)
goto exit_bad;
tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
if (tmp == 0 || tmp > 31)
goto exit_bad;
tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
if (tmp == 0 || tmp > 12)
goto exit_bad;
tmp = fm3130->regs[FM3130_RTC_HOURS];
fm3130->data_valid = 1;
exit_bad:
if (!fm3130->data_valid)
dev_dbg(&client->dev,
"%s: %02x %02x %02x %02x %02x %02x %02x %02x"
"%02x %02x %02x %02x %02x %02x %02x\n",
"bogus registers",
fm3130->regs[0], fm3130->regs[1],
fm3130->regs[2], fm3130->regs[3],
fm3130->regs[4], fm3130->regs[5],
fm3130->regs[6], fm3130->regs[7],
fm3130->regs[8], fm3130->regs[9],
fm3130->regs[0xa], fm3130->regs[0xb],
fm3130->regs[0xc], fm3130->regs[0xd],
fm3130->regs[0xe]);
/* We won't bail out here because we just got invalid data.
Time setting from u-boot doesn't work anyway */
fm3130->rtc = rtc_device_register(client->name, &client->dev,
&fm3130_rtc_ops, THIS_MODULE);
if (IS_ERR(fm3130->rtc)) {
err = PTR_ERR(fm3130->rtc);
dev_err(&client->dev,
"unable to register the class device\n");
goto exit_free;
}
return 0;
exit_free:
kfree(fm3130);
return err;
}
static int __devexit fm3130_remove(struct i2c_client *client)
{
struct fm3130 *fm3130 = i2c_get_clientdata(client);
rtc_device_unregister(fm3130->rtc);
kfree(fm3130);
return 0;
}
static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
.owner = THIS_MODULE,
},
.probe = fm3130_probe,
.remove = __devexit_p(fm3130_remove),
.id_table = fm3130_id,
};
static int __init fm3130_init(void)
{
return i2c_add_driver(&fm3130_driver);
}
module_init(fm3130_init);
static void __exit fm3130_exit(void)
{
i2c_del_driver(&fm3130_driver);
}
module_exit(fm3130_exit);
MODULE_DESCRIPTION("RTC driver for FM3130");
MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
MODULE_LICENSE("GPL");

View File

@@ -302,6 +302,7 @@ static int pcf8563_remove(struct i2c_client *client)
static const struct i2c_device_id pcf8563_id[] = {
{ "pcf8563", 0 },
{ "rtc8564", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8563_id);

69
drivers/rtc/rtc-ppc.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* RTC driver for ppc_md RTC functions
*
* © 2007 Red Hat, Inc.
*
* Author: David Woodhouse <dwmw2@infradead.org>
*
* 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/module.h>
#include <linux/err.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <asm/machdep.h>
static int ppc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
ppc_md.get_rtc_time(tm);
return 0;
}
static int ppc_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return ppc_md.set_rtc_time(tm);
}
static const struct rtc_class_ops ppc_rtc_ops = {
.set_time = ppc_rtc_set_time,
.read_time = ppc_rtc_read_time,
};
static struct rtc_device *rtc;
static struct platform_device *ppc_rtc_pdev;
static int __init ppc_rtc_init(void)
{
if (!ppc_md.get_rtc_time || !ppc_md.set_rtc_time)
return -ENODEV;
ppc_rtc_pdev = platform_device_register_simple("ppc-rtc", 0, NULL, 0);
if (IS_ERR(ppc_rtc_pdev))
return PTR_ERR(ppc_rtc_pdev);
rtc = rtc_device_register("ppc_md", &ppc_rtc_pdev->dev,
&ppc_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
platform_device_unregister(ppc_rtc_pdev);
return PTR_ERR(rtc);
}
return 0;
}
static void __exit ppc_rtc_exit(void)
{
rtc_device_unregister(rtc);
platform_device_unregister(ppc_rtc_pdev);
}
module_init(ppc_rtc_init);
module_exit(ppc_rtc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Generic RTC class driver for PowerPC");

View File

@@ -331,14 +331,14 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
RCNR = 0;
}
device_init_wakeup(&pdev->dev, 1);
rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
device_init_wakeup(&pdev->dev, 1);
platform_set_drvdata(pdev, rtc);
return 0;

View File

@@ -71,6 +71,7 @@
#define X1205_SR_RTCF 0x01 /* Clock failure */
#define X1205_SR_WEL 0x02 /* Write Enable Latch */
#define X1205_SR_RWEL 0x04 /* Register Write Enable */
#define X1205_SR_AL0 0x20 /* Alarm 0 match */
#define X1205_DTR_DTR0 0x01
#define X1205_DTR_DTR1 0x02
@@ -78,6 +79,8 @@
#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
#define X1205_INT_AL0E 0x20 /* Alarm 0 enable */
static struct i2c_driver x1205_driver;
/*
@@ -89,8 +92,8 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
unsigned char reg_base)
{
unsigned char dt_addr[2] = { 0, reg_base };
unsigned char buf[8];
int i;
struct i2c_msg msgs[] = {
{ client->addr, 0, 2, dt_addr }, /* setup read ptr */
@@ -98,7 +101,7 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
};
/* read date registers */
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
@@ -110,6 +113,11 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
/* Mask out the enable bits if these are alarm registers */
if (reg_base < X1205_CCR_BASE)
for (i = 0; i <= 4; i++)
buf[i] &= 0x7F;
tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
tm->tm_min = BCD2BIN(buf[CCR_MIN]);
tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
@@ -138,7 +146,7 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
};
/* read status register */
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
@@ -147,10 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
}
static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
int datetoo, u8 reg_base)
int datetoo, u8 reg_base, unsigned char alm_enable)
{
int i, xfer;
int i, xfer, nbytes;
unsigned char buf[8];
unsigned char rdata[10] = { 0, reg_base };
static const unsigned char wel[3] = { 0, X1205_REG_SR,
X1205_SR_WEL };
@@ -189,6 +198,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
}
/* If writing alarm registers, set compare bits on registers 0-4 */
if (reg_base < X1205_CCR_BASE)
for (i = 0; i <= 4; i++)
buf[i] |= 0x80;
/* this sequence is required to unlock the chip */
if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer);
@@ -200,19 +214,57 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
return -EIO;
}
/* write register's data */
for (i = 0; i < (datetoo ? 8 : 3); i++) {
unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
xfer = i2c_master_send(client, rdata, 3);
/* write register's data */
if (datetoo)
nbytes = 8;
else
nbytes = 3;
for (i = 0; i < nbytes; i++)
rdata[2+i] = buf[i];
xfer = i2c_master_send(client, rdata, nbytes+2);
if (xfer != nbytes+2) {
dev_err(&client->dev,
"%s: result=%d addr=%02x, data=%02x\n",
__func__,
xfer, rdata[1], rdata[2]);
return -EIO;
}
/* If we wrote to the nonvolatile region, wait 10msec for write cycle*/
if (reg_base < X1205_CCR_BASE) {
unsigned char al0e[3] = { 0, X1205_REG_INT, 0 };
msleep(10);
/* ...and set or clear the AL0E bit in the INT register */
/* Need to set RWEL again as the write has cleared it */
xfer = i2c_master_send(client, rwel, 3);
if (xfer != 3) {
dev_err(&client->dev,
"%s: xfer=%d addr=%02x, data=%02x\n",
"%s: aloe rwel - %d\n",
__func__,
xfer, rdata[1], rdata[2]);
xfer);
return -EIO;
}
};
if (alm_enable)
al0e[2] = X1205_INT_AL0E;
xfer = i2c_master_send(client, al0e, 3);
if (xfer != 3) {
dev_err(&client->dev,
"%s: al0e - %d\n",
__func__,
xfer);
return -EIO;
}
/* and wait 10msec again for this write to complete */
msleep(10);
}
/* disable further writes */
if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
@@ -230,9 +282,9 @@ static int x1205_fix_osc(struct i2c_client *client)
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
dev_err(&client->dev,
"unable to restart the oscillator\n");
err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0);
if (err < 0)
dev_err(&client->dev, "unable to restart the oscillator\n");
return err;
}
@@ -248,7 +300,7 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
};
/* read dtr register */
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
@@ -280,7 +332,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
};
/* read atr register */
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
@@ -403,14 +455,33 @@ static int x1205_validate_client(struct i2c_client *client)
static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
return x1205_get_datetime(to_i2c_client(dev),
&alrm->time, X1205_ALM0_BASE);
int err;
unsigned char intreg, status;
static unsigned char int_addr[2] = { 0, X1205_REG_INT };
struct i2c_client *client = to_i2c_client(dev);
struct i2c_msg msgs[] = {
{ client->addr, 0, 2, int_addr }, /* setup read ptr */
{ client->addr, I2C_M_RD, 1, &intreg }, /* read INT register */
};
/* read interrupt register and status register */
if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
err = x1205_get_status(client, &status);
if (err == 0) {
alrm->pending = (status & X1205_SR_AL0) ? 1 : 0;
alrm->enabled = (intreg & X1205_INT_AL0E) ? 1 : 0;
err = x1205_get_datetime(client, &alrm->time, X1205_ALM0_BASE);
}
return err;
}
static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
return x1205_set_datetime(to_i2c_client(dev),
&alrm->time, 1, X1205_ALM0_BASE);
&alrm->time, 1, X1205_ALM0_BASE, alrm->enabled);
}
static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -422,7 +493,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return x1205_set_datetime(to_i2c_client(dev),
tm, 1, X1205_CCR_BASE);
tm, 1, X1205_CCR_BASE, 0);
}
static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)