forked from Minki/linux
RTC for 4.5
Core: - fix module reference count in rtc-proc - Replace simple_strtoul by kstrtoul New driver: - Epson RX8010SJ Subsystem wide cleanups: - use %ph for short hex dumps - constify *_chip_ops structures Drivers: - abx80x: Microcrystal rv1805 support, alarm support - cmos: prevent kernel warning on IRQ flags mismatch - s5m: various cleanups - rv8803: rx8900 compatibility, small error path fix - sunxi: various cleanups - lpc32xx: remove irq > NR_IRQS check from probe() - imxdi: fix spelling mistake in warning message - ds1685: don't try to micromanage sysfs output size - da9063: avoid writing undefined data to rtc - gemini: Remove unnecessary platform_set_drvdata() - efi: add efi_procfs in efi_rtc_ops - pcf8523: refuse to write dates later than 2099 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWnRQIAAoJEKbNnwlvZCyzb8kP/26N+iQNxQc1SjR4n/ZpJlBp aGcqyloPWcrpHPaAlQ7slo/TD0LLYdpYjCshiPnJjm4OLgA5+mba/ca5BgMAKOJM t0oXtLRVM7//TB+wLkpdHgM/OrwsTmYFMkB15G6YymsSB56Dc5YUxg4fIqCGcpIX j78AGyfwFinx7WzxMfGQSQIIz3Itym/s4Mc5HAjFikXuOPBQbd6RRZfj80gB/u4f k3XUsU8bOvQxqUa0SzgQTww90K11h4L5JYIjNh8dBvMbYcVX+xv6OFWfQYcVqrMa YYiAlznlOJ7O4puy7LSAFzc2Vm42NxqM9WHQ4VNcpRTiQ4nYgcreyPc5DhpY0Tc5 RdA2LmILEG6k+6b2d8yyGBEWOoXYVZyizelyCMkqJRixDXN4jow4Xc5qXDwP/bsX qQSQK7XFuvDTFFZ4hUqF2W/OWMWo2wIiaYaWY6EAQmh4iq3eFBQ+2yolSJn+1PEY mJqUyw7E7PNgPagbmfIVJ6g6Q6ZQ/J4G67feZTOFaEagbdFM5eP79HL6ZbtNYZce 4eqcmILvlUtmF0pzm0Ec8fhTIWL55GpPVuge6QkaIPFYq0lId8xiAuOX2L6G4oRf iAI6URijGwPWIHrCUx5dLGQgkxgauPdW5MpnuvSnxGWezGT2tCzLzV4ZHLyzayiX L8txbwQN0P1ykTJu1R0/ =xQhZ -----END PGP SIGNATURE----- Merge tag 'rtc-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "Core: - fix module reference count in rtc-proc - Replace simple_strtoul by kstrtoul New driver: - Epson RX8010SJ Subsystem wide cleanups: - use %ph for short hex dumps - constify *_chip_ops structures Drivers: - abx80x: Microcrystal rv1805 support, alarm support - cmos: prevent kernel warning on IRQ flags mismatch - s5m: various cleanups - rv8803: rx8900 compatibility, small error path fix - sunxi: various cleanups - lpc32xx: remove irq > NR_IRQS check from probe() - imxdi: fix spelling mistake in warning message - ds1685: don't try to micromanage sysfs output size - da9063: avoid writing undefined data to rtc - gemini: Remove unnecessary platform_set_drvdata() - efi: add efi_procfs in efi_rtc_ops - pcf8523: refuse to write dates later than 2099" * tag 'rtc-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (24 commits) rtc: cmos: prevent kernel warning on IRQ flags mismatch rtc: rtc-ds2404: constify ds2404_chip_ops structures rtc: s5m: Make register configuration per S2MPS device to remove exceptions rtc: s5m: Add separate field for storing auto-cleared mask in register config rtc: s5m: Cleanup by removing useless 'rtc' prefix from fields rtc: Replace simple_strtoul by kstrtoul rtc: abx80x: add alarm support rtc: abx80x: Add Microcrystal rv1805 support rtc: v3020: constify v3020_chip_ops structures rtc: rv8803: Extend compatibility with the rx8900 rtc: rv8803: fix handling return value of i2c_smbus_read_byte_data rtc: Add Epson RX8010SJ RTC driver rtc: lpc32xx: remove irq > NR_IRQS check from probe() rtc: imxdi: fix spelling mistake in warning message rtc: ds1685: don't try to micromanage sysfs output size rtc: use %ph for short hex dumps rtc: da9063: avoid writing undefined data to rtc rtc: sunxi: use of_device_get_match_data rtc: sunxi: constify the data_year_param structure rtc: sunxi: fix signedness issues ...
This commit is contained in:
commit
c38dec7166
@ -558,6 +558,16 @@ config RTC_DRV_FM3130
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-fm3130.
|
||||
|
||||
config RTC_DRV_RX8010
|
||||
tristate "Epson RX8010SJ"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the Epson RX8010SJ RTC
|
||||
chip.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-rx8010.
|
||||
|
||||
config RTC_DRV_RX8581
|
||||
tristate "Epson RX-8581"
|
||||
help
|
||||
|
@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
|
||||
obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
|
||||
obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
|
||||
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
|
||||
obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o
|
||||
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
|
||||
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
|
||||
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
|
||||
|
@ -27,10 +27,28 @@
|
||||
#define ABX8XX_REG_YR 0x06
|
||||
#define ABX8XX_REG_WD 0x07
|
||||
|
||||
#define ABX8XX_REG_AHTH 0x08
|
||||
#define ABX8XX_REG_ASC 0x09
|
||||
#define ABX8XX_REG_AMN 0x0a
|
||||
#define ABX8XX_REG_AHR 0x0b
|
||||
#define ABX8XX_REG_ADA 0x0c
|
||||
#define ABX8XX_REG_AMO 0x0d
|
||||
#define ABX8XX_REG_AWD 0x0e
|
||||
|
||||
#define ABX8XX_REG_STATUS 0x0f
|
||||
#define ABX8XX_STATUS_AF BIT(2)
|
||||
|
||||
#define ABX8XX_REG_CTRL1 0x10
|
||||
#define ABX8XX_CTRL_WRITE BIT(0)
|
||||
#define ABX8XX_CTRL_ARST BIT(2)
|
||||
#define ABX8XX_CTRL_12_24 BIT(6)
|
||||
|
||||
#define ABX8XX_REG_IRQ 0x12
|
||||
#define ABX8XX_IRQ_AIE BIT(2)
|
||||
#define ABX8XX_IRQ_IM_1_4 (0x3 << 5)
|
||||
|
||||
#define ABX8XX_REG_CD_TIMER_CTL 0x18
|
||||
|
||||
#define ABX8XX_REG_CFG_KEY 0x1f
|
||||
#define ABX8XX_CFG_KEY_MISC 0x9d
|
||||
|
||||
@ -63,8 +81,6 @@ static struct abx80x_cap abx80x_caps[] = {
|
||||
[ABX80X] = {.pn = 0}
|
||||
};
|
||||
|
||||
static struct i2c_driver abx80x_driver;
|
||||
|
||||
static int abx80x_enable_trickle_charger(struct i2c_client *client,
|
||||
u8 trickle_cfg)
|
||||
{
|
||||
@ -148,9 +164,111 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct i2c_client *client = dev_id;
|
||||
struct rtc_device *rtc = i2c_get_clientdata(client);
|
||||
int status;
|
||||
|
||||
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
|
||||
if (status < 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (status & ABX8XX_STATUS_AF)
|
||||
rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
|
||||
|
||||
i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int abx80x_read_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned char buf[7];
|
||||
|
||||
int irq_mask, err;
|
||||
|
||||
if (client->irq <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ASC,
|
||||
sizeof(buf), buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
irq_mask = i2c_smbus_read_byte_data(client, ABX8XX_REG_IRQ);
|
||||
if (irq_mask < 0)
|
||||
return irq_mask;
|
||||
|
||||
t->time.tm_sec = bcd2bin(buf[0] & 0x7F);
|
||||
t->time.tm_min = bcd2bin(buf[1] & 0x7F);
|
||||
t->time.tm_hour = bcd2bin(buf[2] & 0x3F);
|
||||
t->time.tm_mday = bcd2bin(buf[3] & 0x3F);
|
||||
t->time.tm_mon = bcd2bin(buf[4] & 0x1F) - 1;
|
||||
t->time.tm_wday = buf[5] & 0x7;
|
||||
|
||||
t->enabled = !!(irq_mask & ABX8XX_IRQ_AIE);
|
||||
t->pending = (buf[6] & ABX8XX_STATUS_AF) && t->enabled;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
u8 alarm[6];
|
||||
int err;
|
||||
|
||||
if (client->irq <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
alarm[0] = 0x0;
|
||||
alarm[1] = bin2bcd(t->time.tm_sec);
|
||||
alarm[2] = bin2bcd(t->time.tm_min);
|
||||
alarm[3] = bin2bcd(t->time.tm_hour);
|
||||
alarm[4] = bin2bcd(t->time.tm_mday);
|
||||
alarm[5] = bin2bcd(t->time.tm_mon + 1);
|
||||
|
||||
err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_AHTH,
|
||||
sizeof(alarm), alarm);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write alarm registers\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (t->enabled) {
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
|
||||
(ABX8XX_IRQ_IM_1_4 |
|
||||
ABX8XX_IRQ_AIE));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int err;
|
||||
|
||||
if (enabled)
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
|
||||
(ABX8XX_IRQ_IM_1_4 |
|
||||
ABX8XX_IRQ_AIE));
|
||||
else
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
|
||||
ABX8XX_IRQ_IM_1_4);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops abx80x_rtc_ops = {
|
||||
.read_time = abx80x_rtc_read_time,
|
||||
.set_time = abx80x_rtc_set_time,
|
||||
.read_alarm = abx80x_read_alarm,
|
||||
.set_alarm = abx80x_set_alarm,
|
||||
.alarm_irq_enable = abx80x_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static int abx80x_dt_trickle_cfg(struct device_node *np)
|
||||
@ -225,7 +343,8 @@ static int abx80x_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1,
|
||||
((data & ~ABX8XX_CTRL_12_24) |
|
||||
((data & ~(ABX8XX_CTRL_12_24 |
|
||||
ABX8XX_CTRL_ARST)) |
|
||||
ABX8XX_CTRL_WRITE));
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write control register\n");
|
||||
@ -260,7 +379,12 @@ static int abx80x_probe(struct i2c_client *client,
|
||||
abx80x_enable_trickle_charger(client, trickle_cfg);
|
||||
}
|
||||
|
||||
rtc = devm_rtc_device_register(&client->dev, abx80x_driver.driver.name,
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CD_TIMER_CTL,
|
||||
BIT(2));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rtc = devm_rtc_device_register(&client->dev, "abx8xx",
|
||||
&abx80x_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc))
|
||||
@ -268,6 +392,19 @@ static int abx80x_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, rtc);
|
||||
|
||||
if (client->irq > 0) {
|
||||
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
|
||||
abx80x_handle_irq,
|
||||
IRQF_SHARED | IRQF_ONESHOT,
|
||||
"abx8xx",
|
||||
client);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
|
||||
client->irq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -286,6 +423,7 @@ static const struct i2c_device_id abx80x_id[] = {
|
||||
{ "ab1803", AB1803 },
|
||||
{ "ab1804", AB1804 },
|
||||
{ "ab1805", AB1805 },
|
||||
{ "rv1805", AB1805 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, abx80x_id);
|
||||
|
@ -725,7 +725,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||
rtc_cmos_int_handler = cmos_interrupt;
|
||||
|
||||
retval = request_irq(rtc_irq, rtc_cmos_int_handler,
|
||||
0, dev_name(&cmos_rtc.rtc->dev),
|
||||
IRQF_SHARED, dev_name(&cmos_rtc.rtc->dev),
|
||||
cmos_rtc.rtc);
|
||||
if (retval < 0) {
|
||||
dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
|
||||
|
@ -191,24 +191,13 @@ static void da9063_tm_to_data(struct rtc_time *tm, u8 *data,
|
||||
{
|
||||
const struct da9063_compatible_rtc_regmap *config = rtc->config;
|
||||
|
||||
data[RTC_SEC] &= ~config->rtc_count_sec_mask;
|
||||
data[RTC_SEC] |= tm->tm_sec & config->rtc_count_sec_mask;
|
||||
|
||||
data[RTC_MIN] &= ~config->rtc_count_min_mask;
|
||||
data[RTC_MIN] |= tm->tm_min & config->rtc_count_min_mask;
|
||||
|
||||
data[RTC_HOUR] &= ~config->rtc_count_hour_mask;
|
||||
data[RTC_HOUR] |= tm->tm_hour & config->rtc_count_hour_mask;
|
||||
|
||||
data[RTC_DAY] &= ~config->rtc_count_day_mask;
|
||||
data[RTC_DAY] |= tm->tm_mday & config->rtc_count_day_mask;
|
||||
|
||||
data[RTC_MONTH] &= ~config->rtc_count_month_mask;
|
||||
data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) &
|
||||
data[RTC_SEC] = tm->tm_sec & config->rtc_count_sec_mask;
|
||||
data[RTC_MIN] = tm->tm_min & config->rtc_count_min_mask;
|
||||
data[RTC_HOUR] = tm->tm_hour & config->rtc_count_hour_mask;
|
||||
data[RTC_DAY] = tm->tm_mday & config->rtc_count_day_mask;
|
||||
data[RTC_MONTH] = MONTHS_TO_DA9063(tm->tm_mon) &
|
||||
config->rtc_count_month_mask;
|
||||
|
||||
data[RTC_YEAR] &= ~config->rtc_count_year_mask;
|
||||
data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) &
|
||||
data[RTC_YEAR] = YEARS_TO_DA9063(tm->tm_year) &
|
||||
config->rtc_count_year_mask;
|
||||
}
|
||||
|
||||
|
@ -186,9 +186,7 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time)
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
|
||||
"read", buf[0], buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5], buf[6]);
|
||||
dev_vdbg(dev, "%s: %3ph, %4ph\n", "read", &buf[0], &buf[3]);
|
||||
|
||||
/* Decode the registers */
|
||||
time->tm_sec = bcd2bin(buf[DS1305_SEC]);
|
||||
@ -232,9 +230,7 @@ static int ds1305_set_time(struct device *dev, struct rtc_time *time)
|
||||
*bp++ = bin2bcd(time->tm_mon + 1);
|
||||
*bp++ = bin2bcd(time->tm_year - 100);
|
||||
|
||||
dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
|
||||
"write", buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5], buf[6], buf[7]);
|
||||
dev_dbg(dev, "%s: %3ph, %4ph\n", "write", &buf[1], &buf[4]);
|
||||
|
||||
/* use write-then-read since dma from stack is nonportable */
|
||||
return spi_write_then_read(ds1305->spi, buf, sizeof(buf),
|
||||
|
@ -460,13 +460,8 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
|
||||
"alarm read",
|
||||
ds1307->regs[0], ds1307->regs[1],
|
||||
ds1307->regs[2], ds1307->regs[3],
|
||||
ds1307->regs[4], ds1307->regs[5],
|
||||
ds1307->regs[6], ds1307->regs[7],
|
||||
ds1307->regs[8]);
|
||||
dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read",
|
||||
&ds1307->regs[0], &ds1307->regs[4], &ds1307->regs[7]);
|
||||
|
||||
/*
|
||||
* report alarm time (ALARM1); assume 24 hour and day-of-month modes,
|
||||
@ -522,12 +517,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
control = ds1307->regs[7];
|
||||
status = ds1307->regs[8];
|
||||
|
||||
dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
|
||||
"alarm set (old status)",
|
||||
ds1307->regs[0], ds1307->regs[1],
|
||||
ds1307->regs[2], ds1307->regs[3],
|
||||
ds1307->regs[4], ds1307->regs[5],
|
||||
ds1307->regs[6], control, status);
|
||||
dev_dbg(dev, "%s: %4ph, %3ph, %02x %02x\n", "alarm set (old status)",
|
||||
&ds1307->regs[0], &ds1307->regs[4], control, status);
|
||||
|
||||
/* set ALARM1, using 24 hour and day-of-month modes */
|
||||
buf[0] = bin2bcd(t->time.tm_sec);
|
||||
|
@ -853,7 +853,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
"Periodic Rate\t: %s\n"
|
||||
"SQW Freq\t: %s\n"
|
||||
#ifdef CONFIG_RTC_DS1685_PROC_REGS
|
||||
"Serial #\t: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"
|
||||
"Serial #\t: %8phC\n"
|
||||
"Register Status\t:\n"
|
||||
" Ctrl A\t: UIP DV2 DV1 DV0 RS3 RS2 RS1 RS0\n"
|
||||
"\t\t: %s\n"
|
||||
@ -872,7 +872,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
" Ctrl 4B\t: ABE E32k CS RCE PRS RIE WIE KSE\n"
|
||||
"\t\t: %s\n",
|
||||
#else
|
||||
"Serial #\t: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
"Serial #\t: %8phC\n",
|
||||
#endif
|
||||
model,
|
||||
((ctrla & RTC_CTRL_A_DV1) ? "enabled" : "disabled"),
|
||||
@ -888,7 +888,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
(!((ctrl4b & RTC_CTRL_4B_E32K)) ?
|
||||
ds1685_rtc_sqw_freq[(ctrla & RTC_CTRL_A_RS_MASK)] : "32768Hz"),
|
||||
#ifdef CONFIG_RTC_DS1685_PROC_REGS
|
||||
ssn[0], ssn[1], ssn[2], ssn[3], ssn[4], ssn[5], ssn[6], ssn[7],
|
||||
ssn,
|
||||
ds1685_rtc_print_regs(ctrla, bits[0]),
|
||||
ds1685_rtc_print_regs(ctrlb, bits[1]),
|
||||
ds1685_rtc_print_regs(ctrlc, bits[2]),
|
||||
@ -896,7 +896,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
ds1685_rtc_print_regs(ctrl4a, bits[4]),
|
||||
ds1685_rtc_print_regs(ctrl4b, bits[5]));
|
||||
#else
|
||||
ssn[0], ssn[1], ssn[2], ssn[3], ssn[4], ssn[5], ssn[6], ssn[7]);
|
||||
ssn);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -1114,7 +1114,7 @@ ds1685_rtc_sysfs_battery_show(struct device *dev,
|
||||
|
||||
ctrld = rtc->read(rtc, RTC_CTRL_D);
|
||||
|
||||
return snprintf(buf, 13, "%s\n",
|
||||
return sprintf(buf, "%s\n",
|
||||
(ctrld & RTC_CTRL_D_VRT) ? "ok" : "not ok or N/A");
|
||||
}
|
||||
static DEVICE_ATTR(battery, S_IRUGO, ds1685_rtc_sysfs_battery_show, NULL);
|
||||
@ -1137,7 +1137,7 @@ ds1685_rtc_sysfs_auxbatt_show(struct device *dev,
|
||||
ctrl4a = rtc->read(rtc, RTC_EXT_CTRL_4A);
|
||||
ds1685_rtc_switch_to_bank0(rtc);
|
||||
|
||||
return snprintf(buf, 13, "%s\n",
|
||||
return sprintf(buf, "%s\n",
|
||||
(ctrl4a & RTC_CTRL_4A_VRT2) ? "ok" : "not ok or N/A");
|
||||
}
|
||||
static DEVICE_ATTR(auxbatt, S_IRUGO, ds1685_rtc_sysfs_auxbatt_show, NULL);
|
||||
@ -1160,11 +1160,7 @@ ds1685_rtc_sysfs_serial_show(struct device *dev,
|
||||
ds1685_rtc_get_ssn(rtc, ssn);
|
||||
ds1685_rtc_switch_to_bank0(rtc);
|
||||
|
||||
return snprintf(buf, 24, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
ssn[0], ssn[1], ssn[2], ssn[3], ssn[4], ssn[5],
|
||||
ssn[6], ssn[7]);
|
||||
|
||||
return 0;
|
||||
return sprintf(buf, "%8phC\n", ssn);
|
||||
}
|
||||
static DEVICE_ATTR(serial, S_IRUGO, ds1685_rtc_sysfs_serial_show, NULL);
|
||||
|
||||
@ -1287,7 +1283,7 @@ ds1685_rtc_sysfs_ctrl_regs_show(struct device *dev,
|
||||
tmp = rtc->read(rtc, reg_info->reg) & reg_info->bit;
|
||||
ds1685_rtc_switch_to_bank0(rtc);
|
||||
|
||||
return snprintf(buf, 2, "%d\n", (tmp ? 1 : 0));
|
||||
return sprintf(buf, "%d\n", (tmp ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1623,7 +1619,7 @@ ds1685_rtc_sysfs_time_regs_show(struct device *dev,
|
||||
tmp = ds1685_rtc_bcd2bin(rtc, tmp, bcd_reg_info->mask,
|
||||
bin_reg_info->mask);
|
||||
|
||||
return snprintf(buf, 4, "%d\n", tmp);
|
||||
return sprintf(buf, "%d\n", tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,7 @@ struct ds2404_gpio {
|
||||
|
||||
struct ds2404 {
|
||||
struct ds2404_gpio *gpio;
|
||||
struct ds2404_chip_ops *ops;
|
||||
const struct ds2404_chip_ops *ops;
|
||||
struct rtc_device *rtc;
|
||||
};
|
||||
|
||||
@ -95,7 +95,7 @@ static void ds2404_gpio_unmap(struct ds2404 *chip)
|
||||
gpio_free(ds2404_gpio[i].gpio);
|
||||
}
|
||||
|
||||
static struct ds2404_chip_ops ds2404_gpio_ops = {
|
||||
static const struct ds2404_chip_ops ds2404_gpio_ops = {
|
||||
.map_io = ds2404_gpio_map,
|
||||
.unmap_io = ds2404_gpio_unmap,
|
||||
};
|
||||
|
@ -191,11 +191,69 @@ static int efi_set_time(struct device *dev, struct rtc_time *tm)
|
||||
return status == EFI_SUCCESS ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int efi_procfs(struct device *dev, struct seq_file *seq)
|
||||
{
|
||||
efi_time_t eft, alm;
|
||||
efi_time_cap_t cap;
|
||||
efi_bool_t enabled, pending;
|
||||
|
||||
memset(&eft, 0, sizeof(eft));
|
||||
memset(&alm, 0, sizeof(alm));
|
||||
memset(&cap, 0, sizeof(cap));
|
||||
|
||||
efi.get_time(&eft, &cap);
|
||||
efi.get_wakeup_time(&enabled, &pending, &alm);
|
||||
|
||||
seq_printf(seq,
|
||||
"Time\t\t: %u:%u:%u.%09u\n"
|
||||
"Date\t\t: %u-%u-%u\n"
|
||||
"Daylight\t: %u\n",
|
||||
eft.hour, eft.minute, eft.second, eft.nanosecond,
|
||||
eft.year, eft.month, eft.day,
|
||||
eft.daylight);
|
||||
|
||||
if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
|
||||
seq_puts(seq, "Timezone\t: unspecified\n");
|
||||
else
|
||||
/* XXX fixme: convert to string? */
|
||||
seq_printf(seq, "Timezone\t: %u\n", eft.timezone);
|
||||
|
||||
seq_printf(seq,
|
||||
"Alarm Time\t: %u:%u:%u.%09u\n"
|
||||
"Alarm Date\t: %u-%u-%u\n"
|
||||
"Alarm Daylight\t: %u\n"
|
||||
"Enabled\t\t: %s\n"
|
||||
"Pending\t\t: %s\n",
|
||||
alm.hour, alm.minute, alm.second, alm.nanosecond,
|
||||
alm.year, alm.month, alm.day,
|
||||
alm.daylight,
|
||||
enabled == 1 ? "yes" : "no",
|
||||
pending == 1 ? "yes" : "no");
|
||||
|
||||
if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
|
||||
seq_puts(seq, "Timezone\t: unspecified\n");
|
||||
else
|
||||
/* XXX fixme: convert to string? */
|
||||
seq_printf(seq, "Timezone\t: %u\n", alm.timezone);
|
||||
|
||||
/*
|
||||
* now prints the capabilities
|
||||
*/
|
||||
seq_printf(seq,
|
||||
"Resolution\t: %u\n"
|
||||
"Accuracy\t: %u\n"
|
||||
"SetstoZero\t: %u\n",
|
||||
cap.resolution, cap.accuracy, cap.sets_to_zero);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops efi_rtc_ops = {
|
||||
.read_time = efi_read_time,
|
||||
.set_time = efi_set_time,
|
||||
.read_alarm = efi_read_alarm,
|
||||
.set_alarm = efi_set_alarm,
|
||||
.read_time = efi_read_time,
|
||||
.set_time = efi_set_time,
|
||||
.read_alarm = efi_read_alarm,
|
||||
.set_alarm = efi_set_alarm,
|
||||
.proc = efi_procfs,
|
||||
};
|
||||
|
||||
static int __init efi_rtc_probe(struct platform_device *dev)
|
||||
|
@ -156,7 +156,6 @@ static int gemini_rtc_remove(struct platform_device *pdev)
|
||||
struct gemini_rtc *rtc = platform_get_drvdata(pdev);
|
||||
|
||||
rtc_device_unregister(rtc->rtc_dev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
|
||||
sec = readl(imxdi->ioaddr + DTCMR);
|
||||
if (sec != 0)
|
||||
dev_warn(&imxdi->pdev->dev,
|
||||
"The security violation has happend at %u seconds\n",
|
||||
"The security violation has happened at %u seconds\n",
|
||||
sec);
|
||||
/*
|
||||
* the timer cannot be set/modified if
|
||||
|
@ -205,7 +205,7 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
|
||||
u32 tmp;
|
||||
|
||||
rtcirq = platform_get_irq(pdev, 0);
|
||||
if (rtcirq < 0 || rtcirq >= NR_IRQS) {
|
||||
if (rtcirq < 0) {
|
||||
dev_warn(&pdev->dev, "Can't get interrupt resource\n");
|
||||
rtcirq = -1;
|
||||
}
|
||||
|
@ -219,6 +219,17 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
u8 regs[8];
|
||||
int err;
|
||||
|
||||
/*
|
||||
* The hardware can only store values between 0 and 99 in it's YEAR
|
||||
* register (with 99 overflowing to 0 on increment).
|
||||
* After 2100-02-28 we could start interpreting the year to be in the
|
||||
* interval [2100, 2199], but there is no path to switch in a smooth way
|
||||
* because the chip handles YEAR=0x00 (and the out-of-spec
|
||||
* YEAR=0xa0) as a leap year, but 2100 isn't.
|
||||
*/
|
||||
if (tm->tm_year < 100 || tm->tm_year >= 200)
|
||||
return -EINVAL;
|
||||
|
||||
err = pcf8523_stop_rtc(client);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -112,19 +112,21 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
|
||||
int ret;
|
||||
struct rtc_device *rtc = PDE_DATA(inode);
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
if (!try_module_get(rtc->owner))
|
||||
return -ENODEV;
|
||||
|
||||
ret = single_open(file, rtc_proc_show, rtc);
|
||||
if (ret)
|
||||
module_put(THIS_MODULE);
|
||||
module_put(rtc->owner);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtc_proc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int res = single_release(inode, file);
|
||||
module_put(THIS_MODULE);
|
||||
struct rtc_device *rtc = PDE_DATA(inode);
|
||||
|
||||
module_put(rtc->owner);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ 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;
|
||||
u8 flags;
|
||||
int flags;
|
||||
|
||||
spin_lock(&rv8803->flags_lock);
|
||||
|
||||
@ -502,6 +502,7 @@ static int rv8803_remove(struct i2c_client *client)
|
||||
|
||||
static const struct i2c_device_id rv8803_id[] = {
|
||||
{ "rv8803", 0 },
|
||||
{ "rx8900", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rv8803_id);
|
||||
|
523
drivers/rtc/rtc-rx8010.c
Normal file
523
drivers/rtc/rtc-rx8010.c
Normal file
@ -0,0 +1,523 @@
|
||||
/*
|
||||
* Driver for the Epson RTC module RX-8010 SJ
|
||||
*
|
||||
* Copyright(C) Timesys Corporation 2015
|
||||
* Copyright(C) General Electric Company 2015
|
||||
*
|
||||
* 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/bcd.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#define RX8010_SEC 0x10
|
||||
#define RX8010_MIN 0x11
|
||||
#define RX8010_HOUR 0x12
|
||||
#define RX8010_WDAY 0x13
|
||||
#define RX8010_MDAY 0x14
|
||||
#define RX8010_MONTH 0x15
|
||||
#define RX8010_YEAR 0x16
|
||||
#define RX8010_YEAR 0x16
|
||||
#define RX8010_RESV17 0x17
|
||||
#define RX8010_ALMIN 0x18
|
||||
#define RX8010_ALHOUR 0x19
|
||||
#define RX8010_ALWDAY 0x1A
|
||||
#define RX8010_TCOUNT0 0x1B
|
||||
#define RX8010_TCOUNT1 0x1C
|
||||
#define RX8010_EXT 0x1D
|
||||
#define RX8010_FLAG 0x1E
|
||||
#define RX8010_CTRL 0x1F
|
||||
/* 0x20 to 0x2F are user registers */
|
||||
#define RX8010_RESV30 0x30
|
||||
#define RX8010_RESV31 0x32
|
||||
#define RX8010_IRQ 0x32
|
||||
|
||||
#define RX8010_EXT_WADA BIT(3)
|
||||
|
||||
#define RX8010_FLAG_VLF BIT(1)
|
||||
#define RX8010_FLAG_AF BIT(3)
|
||||
#define RX8010_FLAG_TF BIT(4)
|
||||
#define RX8010_FLAG_UF BIT(5)
|
||||
|
||||
#define RX8010_CTRL_AIE BIT(3)
|
||||
#define RX8010_CTRL_UIE BIT(5)
|
||||
#define RX8010_CTRL_STOP BIT(6)
|
||||
#define RX8010_CTRL_TEST BIT(7)
|
||||
|
||||
#define RX8010_ALARM_AE BIT(7)
|
||||
|
||||
static const struct i2c_device_id rx8010_id[] = {
|
||||
{ "rx8010", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rx8010_id);
|
||||
|
||||
struct rx8010_data {
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
u8 ctrlreg;
|
||||
spinlock_t flags_lock;
|
||||
};
|
||||
|
||||
static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct i2c_client *client = dev_id;
|
||||
struct rx8010_data *rx8010 = i2c_get_clientdata(client);
|
||||
int flagreg;
|
||||
|
||||
spin_lock(&rx8010->flags_lock);
|
||||
|
||||
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);
|
||||
|
||||
if (flagreg <= 0) {
|
||||
spin_unlock(&rx8010->flags_lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (flagreg & RX8010_FLAG_VLF)
|
||||
dev_warn(&client->dev, "Frequency stop detected\n");
|
||||
|
||||
if (flagreg & RX8010_FLAG_TF) {
|
||||
flagreg &= ~RX8010_FLAG_TF;
|
||||
rtc_update_irq(rx8010->rtc, 1, RTC_PF | RTC_IRQF);
|
||||
}
|
||||
|
||||
if (flagreg & RX8010_FLAG_AF) {
|
||||
flagreg &= ~RX8010_FLAG_AF;
|
||||
rtc_update_irq(rx8010->rtc, 1, RTC_AF | RTC_IRQF);
|
||||
}
|
||||
|
||||
if (flagreg & RX8010_FLAG_UF) {
|
||||
flagreg &= ~RX8010_FLAG_UF;
|
||||
rtc_update_irq(rx8010->rtc, 1, RTC_UF | RTC_IRQF);
|
||||
}
|
||||
|
||||
i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg);
|
||||
|
||||
spin_unlock(&rx8010->flags_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
u8 date[7];
|
||||
int flagreg;
|
||||
int err;
|
||||
|
||||
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
|
||||
if (flagreg < 0)
|
||||
return flagreg;
|
||||
|
||||
if (flagreg & RX8010_FLAG_VLF) {
|
||||
dev_warn(dev, "Frequency stop detected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(rx8010->client, RX8010_SEC,
|
||||
7, date);
|
||||
if (err != 7)
|
||||
return err < 0 ? err : -EIO;
|
||||
|
||||
dt->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f);
|
||||
dt->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f);
|
||||
dt->tm_hour = bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f);
|
||||
dt->tm_mday = bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f);
|
||||
dt->tm_mon = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f) - 1;
|
||||
dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100;
|
||||
dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f);
|
||||
|
||||
return rtc_valid_tm(dt);
|
||||
}
|
||||
|
||||
static int rx8010_set_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
u8 date[7];
|
||||
int ctrl, flagreg;
|
||||
int ret;
|
||||
unsigned long irqflags;
|
||||
|
||||
if ((dt->tm_year < 100) || (dt->tm_year > 199))
|
||||
return -EINVAL;
|
||||
|
||||
/* set STOP bit before changing clock/calendar */
|
||||
ctrl = i2c_smbus_read_byte_data(rx8010->client, RX8010_CTRL);
|
||||
if (ctrl < 0)
|
||||
return ctrl;
|
||||
rx8010->ctrlreg = ctrl | RX8010_CTRL_STOP;
|
||||
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
|
||||
rx8010->ctrlreg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
date[RX8010_SEC - RX8010_SEC] = bin2bcd(dt->tm_sec);
|
||||
date[RX8010_MIN - RX8010_SEC] = bin2bcd(dt->tm_min);
|
||||
date[RX8010_HOUR - RX8010_SEC] = bin2bcd(dt->tm_hour);
|
||||
date[RX8010_MDAY - RX8010_SEC] = bin2bcd(dt->tm_mday);
|
||||
date[RX8010_MONTH - RX8010_SEC] = bin2bcd(dt->tm_mon + 1);
|
||||
date[RX8010_YEAR - RX8010_SEC] = bin2bcd(dt->tm_year - 100);
|
||||
date[RX8010_WDAY - RX8010_SEC] = bin2bcd(1 << dt->tm_wday);
|
||||
|
||||
ret = i2c_smbus_write_i2c_block_data(rx8010->client,
|
||||
RX8010_SEC, 7, date);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* clear STOP bit after changing clock/calendar */
|
||||
ctrl = i2c_smbus_read_byte_data(rx8010->client, RX8010_CTRL);
|
||||
if (ctrl < 0)
|
||||
return ctrl;
|
||||
rx8010->ctrlreg = ctrl & ~RX8010_CTRL_STOP;
|
||||
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
|
||||
rx8010->ctrlreg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&rx8010->flags_lock, irqflags);
|
||||
|
||||
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
|
||||
if (flagreg < 0) {
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
return flagreg;
|
||||
}
|
||||
|
||||
if (flagreg & RX8010_FLAG_VLF)
|
||||
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG,
|
||||
flagreg & ~RX8010_FLAG_VLF);
|
||||
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx8010_init_client(struct i2c_client *client)
|
||||
{
|
||||
struct rx8010_data *rx8010 = i2c_get_clientdata(client);
|
||||
u8 ctrl[2];
|
||||
int need_clear = 0, err = 0;
|
||||
|
||||
/* Initialize reserved registers as specified in datasheet */
|
||||
err = i2c_smbus_write_byte_data(client, RX8010_RESV17, 0xD8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, RX8010_RESV30, 0x00);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, RX8010_RESV31, 0x08);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, RX8010_IRQ, 0x00);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(rx8010->client, RX8010_FLAG,
|
||||
2, ctrl);
|
||||
if (err != 2)
|
||||
return err < 0 ? err : -EIO;
|
||||
|
||||
if (ctrl[0] & RX8010_FLAG_VLF)
|
||||
dev_warn(&client->dev, "Frequency stop was detected\n");
|
||||
|
||||
if (ctrl[0] & RX8010_FLAG_AF) {
|
||||
dev_warn(&client->dev, "Alarm was detected\n");
|
||||
need_clear = 1;
|
||||
}
|
||||
|
||||
if (ctrl[0] & RX8010_FLAG_TF)
|
||||
need_clear = 1;
|
||||
|
||||
if (ctrl[0] & RX8010_FLAG_UF)
|
||||
need_clear = 1;
|
||||
|
||||
if (need_clear) {
|
||||
ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
|
||||
err = i2c_smbus_write_byte_data(client, RX8010_FLAG, ctrl[0]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
rx8010->ctrlreg = (ctrl[1] & ~RX8010_CTRL_TEST);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
{
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = rx8010->client;
|
||||
u8 alarmvals[3];
|
||||
int flagreg;
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(client, RX8010_ALMIN, 3, alarmvals);
|
||||
if (err != 3)
|
||||
return err < 0 ? err : -EIO;
|
||||
|
||||
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);
|
||||
if (flagreg < 0)
|
||||
return flagreg;
|
||||
|
||||
t->time.tm_sec = 0;
|
||||
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
|
||||
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;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
u8 alarmvals[3];
|
||||
int extreg, flagreg;
|
||||
int err;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&rx8010->flags_lock, irqflags);
|
||||
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);
|
||||
if (flagreg < 0) {
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
return flagreg;
|
||||
}
|
||||
|
||||
if (rx8010->ctrlreg & (RX8010_CTRL_AIE | RX8010_CTRL_UIE)) {
|
||||
rx8010->ctrlreg &= ~(RX8010_CTRL_AIE | RX8010_CTRL_UIE);
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
|
||||
rx8010->ctrlreg);
|
||||
if (err < 0) {
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
flagreg &= ~RX8010_FLAG_AF;
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg);
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
alarmvals[0] = bin2bcd(t->time.tm_min);
|
||||
alarmvals[1] = bin2bcd(t->time.tm_hour);
|
||||
alarmvals[2] = bin2bcd(t->time.tm_mday);
|
||||
|
||||
err = i2c_smbus_write_i2c_block_data(rx8010->client, RX8010_ALMIN,
|
||||
2, alarmvals);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
extreg = i2c_smbus_read_byte_data(client, RX8010_EXT);
|
||||
if (extreg < 0)
|
||||
return extreg;
|
||||
|
||||
extreg |= RX8010_EXT_WADA;
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_EXT, extreg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (alarmvals[2] == 0)
|
||||
alarmvals[2] |= RX8010_ALARM_AE;
|
||||
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_ALWDAY,
|
||||
alarmvals[2]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (t->enabled) {
|
||||
if (rx8010->rtc->uie_rtctimer.enabled)
|
||||
rx8010->ctrlreg |= RX8010_CTRL_UIE;
|
||||
if (rx8010->rtc->aie_timer.enabled)
|
||||
rx8010->ctrlreg |=
|
||||
(RX8010_CTRL_AIE | RX8010_CTRL_UIE);
|
||||
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
|
||||
rx8010->ctrlreg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx8010_alarm_irq_enable(struct device *dev,
|
||||
unsigned int enabled)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
int flagreg;
|
||||
u8 ctrl;
|
||||
int err;
|
||||
|
||||
ctrl = rx8010->ctrlreg;
|
||||
|
||||
if (enabled) {
|
||||
if (rx8010->rtc->uie_rtctimer.enabled)
|
||||
ctrl |= RX8010_CTRL_UIE;
|
||||
if (rx8010->rtc->aie_timer.enabled)
|
||||
ctrl |= (RX8010_CTRL_AIE | RX8010_CTRL_UIE);
|
||||
} else {
|
||||
if (!rx8010->rtc->uie_rtctimer.enabled)
|
||||
ctrl &= ~RX8010_CTRL_UIE;
|
||||
if (!rx8010->rtc->aie_timer.enabled)
|
||||
ctrl &= ~RX8010_CTRL_AIE;
|
||||
}
|
||||
|
||||
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);
|
||||
if (flagreg < 0)
|
||||
return flagreg;
|
||||
|
||||
flagreg &= ~RX8010_FLAG_AF;
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (ctrl != rx8010->ctrlreg) {
|
||||
rx8010->ctrlreg = ctrl;
|
||||
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
|
||||
rx8010->ctrlreg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
int ret, tmp;
|
||||
int flagreg;
|
||||
unsigned long irqflags;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_VL_READ:
|
||||
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
|
||||
if (flagreg < 0)
|
||||
return flagreg;
|
||||
|
||||
tmp = !!(flagreg & RX8010_FLAG_VLF);
|
||||
if (copy_to_user((void __user *)arg, &tmp, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
case RTC_VL_CLR:
|
||||
spin_lock_irqsave(&rx8010->flags_lock, irqflags);
|
||||
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
|
||||
if (flagreg < 0) {
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
return flagreg;
|
||||
}
|
||||
|
||||
flagreg &= ~RX8010_FLAG_VLF;
|
||||
ret = i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg);
|
||||
spin_unlock_irqrestore(&rx8010->flags_lock, irqflags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
static struct rtc_class_ops rx8010_rtc_ops = {
|
||||
.read_time = rx8010_get_time,
|
||||
.set_time = rx8010_set_time,
|
||||
.ioctl = rx8010_ioctl,
|
||||
};
|
||||
|
||||
static int rx8010_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
struct rx8010_data *rx8010;
|
||||
int err = 0;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
||||
| I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||
dev_err(&adapter->dev, "doesn't support required functionality\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rx8010 = devm_kzalloc(&client->dev, sizeof(struct rx8010_data),
|
||||
GFP_KERNEL);
|
||||
if (!rx8010)
|
||||
return -ENOMEM;
|
||||
|
||||
rx8010->client = client;
|
||||
i2c_set_clientdata(client, rx8010);
|
||||
|
||||
spin_lock_init(&rx8010->flags_lock);
|
||||
|
||||
err = rx8010_init_client(client);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (client->irq > 0) {
|
||||
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
|
||||
rx8010_irq_1_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"rx8010", client);
|
||||
|
||||
if (err) {
|
||||
dev_err(&client->dev, "unable to request IRQ\n");
|
||||
client->irq = 0;
|
||||
} else {
|
||||
rx8010_rtc_ops.read_alarm = rx8010_read_alarm;
|
||||
rx8010_rtc_ops.set_alarm = rx8010_set_alarm;
|
||||
rx8010_rtc_ops.alarm_irq_enable = rx8010_alarm_irq_enable;
|
||||
}
|
||||
}
|
||||
|
||||
rx8010->rtc = devm_rtc_device_register(&client->dev, client->name,
|
||||
&rx8010_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rx8010->rtc)) {
|
||||
dev_err(&client->dev, "unable to register the class device\n");
|
||||
return PTR_ERR(rx8010->rtc);
|
||||
}
|
||||
|
||||
rx8010->rtc->max_user_freq = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct i2c_driver rx8010_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rx8010",
|
||||
},
|
||||
.probe = rx8010_probe,
|
||||
.id_table = rx8010_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(rx8010_driver);
|
||||
|
||||
MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
|
||||
MODULE_DESCRIPTION("Epson RX8010SJ RTC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -38,7 +38,22 @@
|
||||
*/
|
||||
#define UDR_READ_RETRY_CNT 5
|
||||
|
||||
/* Registers used by the driver which are different between chipsets. */
|
||||
/*
|
||||
* Registers used by the driver which are different between chipsets.
|
||||
*
|
||||
* Operations like read time and write alarm/time require updating
|
||||
* specific fields in UDR register. These fields usually are auto-cleared
|
||||
* (with some exceptions).
|
||||
*
|
||||
* Table of operations per device:
|
||||
*
|
||||
* Device | Write time | Read time | Write alarm
|
||||
* =================================================
|
||||
* S5M8767 | UDR + TIME | | UDR
|
||||
* S2MPS11/14 | WUDR | RUDR | WUDR + RUDR
|
||||
* S2MPS13 | WUDR | RUDR | WUDR + AUDR
|
||||
* S2MPS15 | WUDR | RUDR | AUDR
|
||||
*/
|
||||
struct s5m_rtc_reg_config {
|
||||
/* Number of registers used for setting time/alarm0/alarm1 */
|
||||
unsigned int regs_count;
|
||||
@ -55,9 +70,16 @@ struct s5m_rtc_reg_config {
|
||||
* will enable update of time or alarm register. Then it will be
|
||||
* auto-cleared after successful update.
|
||||
*/
|
||||
unsigned int rtc_udr_update;
|
||||
/* Mask for UDR field in 'rtc_udr_update' register */
|
||||
unsigned int rtc_udr_mask;
|
||||
unsigned int udr_update;
|
||||
/* Auto-cleared mask in UDR field for writing time and alarm */
|
||||
unsigned int autoclear_udr_mask;
|
||||
/*
|
||||
* Masks in UDR field for time and alarm operations.
|
||||
* The read time mask can be 0. Rest should not.
|
||||
*/
|
||||
unsigned int read_time_udr_mask;
|
||||
unsigned int write_time_udr_mask;
|
||||
unsigned int write_alarm_udr_mask;
|
||||
};
|
||||
|
||||
/* Register map for S5M8763 and S5M8767 */
|
||||
@ -67,22 +89,56 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
|
||||
.ctrl = S5M_ALARM1_CONF,
|
||||
.alarm0 = S5M_ALARM0_SEC,
|
||||
.alarm1 = S5M_ALARM1_SEC,
|
||||
.rtc_udr_update = S5M_RTC_UDR_CON,
|
||||
.rtc_udr_mask = S5M_RTC_UDR_MASK,
|
||||
.udr_update = S5M_RTC_UDR_CON,
|
||||
.autoclear_udr_mask = S5M_RTC_UDR_MASK,
|
||||
.read_time_udr_mask = 0, /* Not needed */
|
||||
.write_time_udr_mask = S5M_RTC_UDR_MASK | S5M_RTC_TIME_EN_MASK,
|
||||
.write_alarm_udr_mask = S5M_RTC_UDR_MASK,
|
||||
};
|
||||
|
||||
/*
|
||||
* Register map for S2MPS14.
|
||||
* It may be also suitable for S2MPS11 but this was not tested.
|
||||
*/
|
||||
static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
|
||||
/* Register map for S2MPS13 */
|
||||
static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
|
||||
.regs_count = 7,
|
||||
.time = S2MPS_RTC_SEC,
|
||||
.ctrl = S2MPS_RTC_CTRL,
|
||||
.alarm0 = S2MPS_ALARM0_SEC,
|
||||
.alarm1 = S2MPS_ALARM1_SEC,
|
||||
.rtc_udr_update = S2MPS_RTC_UDR_CON,
|
||||
.rtc_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.udr_update = S2MPS_RTC_UDR_CON,
|
||||
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
|
||||
.write_time_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.write_alarm_udr_mask = S2MPS_RTC_WUDR_MASK | S2MPS13_RTC_AUDR_MASK,
|
||||
};
|
||||
|
||||
/* Register map for S2MPS11/14 */
|
||||
static const struct s5m_rtc_reg_config s2mps14_rtc_regs = {
|
||||
.regs_count = 7,
|
||||
.time = S2MPS_RTC_SEC,
|
||||
.ctrl = S2MPS_RTC_CTRL,
|
||||
.alarm0 = S2MPS_ALARM0_SEC,
|
||||
.alarm1 = S2MPS_ALARM1_SEC,
|
||||
.udr_update = S2MPS_RTC_UDR_CON,
|
||||
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
|
||||
.write_time_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.write_alarm_udr_mask = S2MPS_RTC_WUDR_MASK | S2MPS_RTC_RUDR_MASK,
|
||||
};
|
||||
|
||||
/*
|
||||
* Register map for S2MPS15 - in comparison to S2MPS14 the WUDR and AUDR bits
|
||||
* are swapped.
|
||||
*/
|
||||
static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
|
||||
.regs_count = 7,
|
||||
.time = S2MPS_RTC_SEC,
|
||||
.ctrl = S2MPS_RTC_CTRL,
|
||||
.alarm0 = S2MPS_ALARM0_SEC,
|
||||
.alarm1 = S2MPS_ALARM1_SEC,
|
||||
.udr_update = S2MPS_RTC_UDR_CON,
|
||||
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
|
||||
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
|
||||
.write_time_udr_mask = S2MPS15_RTC_WUDR_MASK,
|
||||
.write_alarm_udr_mask = S2MPS15_RTC_AUDR_MASK,
|
||||
};
|
||||
|
||||
struct s5m_rtc_info {
|
||||
@ -166,9 +222,8 @@ static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
|
||||
unsigned int data;
|
||||
|
||||
do {
|
||||
ret = regmap_read(info->regmap, info->regs->rtc_udr_update,
|
||||
&data);
|
||||
} while (--retry && (data & info->regs->rtc_udr_mask) && !ret);
|
||||
ret = regmap_read(info->regmap, info->regs->udr_update, &data);
|
||||
} while (--retry && (data & info->regs->autoclear_udr_mask) && !ret);
|
||||
|
||||
if (!retry)
|
||||
dev_err(info->dev, "waiting for UDR update, reached max number of retries\n");
|
||||
@ -214,30 +269,15 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
|
||||
int ret;
|
||||
unsigned int data;
|
||||
|
||||
ret = regmap_read(info->regmap, info->regs->rtc_udr_update, &data);
|
||||
ret = regmap_read(info->regmap, info->regs->udr_update, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "failed to read update reg(%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (info->device_type) {
|
||||
case S5M8763X:
|
||||
case S5M8767X:
|
||||
data |= info->regs->rtc_udr_mask | S5M_RTC_TIME_EN_MASK;
|
||||
case S2MPS15X:
|
||||
/* As per UM, for write time register, set WUDR bit to high */
|
||||
data |= S2MPS15_RTC_WUDR_MASK;
|
||||
break;
|
||||
case S2MPS14X:
|
||||
case S2MPS13X:
|
||||
data |= info->regs->rtc_udr_mask;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
data |= info->regs->write_time_udr_mask;
|
||||
|
||||
|
||||
ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
|
||||
ret = regmap_write(info->regmap, info->regs->udr_update, data);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "failed to write update reg(%d)\n", ret);
|
||||
return ret;
|
||||
@ -253,35 +293,29 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
|
||||
int ret;
|
||||
unsigned int data;
|
||||
|
||||
ret = regmap_read(info->regmap, info->regs->rtc_udr_update, &data);
|
||||
ret = regmap_read(info->regmap, info->regs->udr_update, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to read update reg(%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data |= info->regs->rtc_udr_mask;
|
||||
data |= info->regs->write_alarm_udr_mask;
|
||||
switch (info->device_type) {
|
||||
case S5M8763X:
|
||||
case S5M8767X:
|
||||
data &= ~S5M_RTC_TIME_EN_MASK;
|
||||
break;
|
||||
case S2MPS15X:
|
||||
/* As per UM, for write alarm, set A_UDR(bit[4]) to high
|
||||
* rtc_udr_mask above sets bit[4]
|
||||
*/
|
||||
break;
|
||||
case S2MPS14X:
|
||||
data |= S2MPS_RTC_RUDR_MASK;
|
||||
break;
|
||||
case S2MPS13X:
|
||||
data |= S2MPS13_RTC_AUDR_MASK;
|
||||
/* No exceptions needed */
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
|
||||
ret = regmap_write(info->regmap, info->regs->udr_update, data);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "%s: fail to write update reg(%d)\n",
|
||||
__func__, ret);
|
||||
@ -292,7 +326,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
|
||||
|
||||
/* On S2MPS13 the AUDR is not auto-cleared */
|
||||
if (info->device_type == S2MPS13X)
|
||||
regmap_update_bits(info->regmap, info->regs->rtc_udr_update,
|
||||
regmap_update_bits(info->regmap, info->regs->udr_update,
|
||||
S2MPS13_RTC_AUDR_MASK, 0);
|
||||
|
||||
return ret;
|
||||
@ -336,11 +370,11 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
u8 data[info->regs->regs_count];
|
||||
int ret;
|
||||
|
||||
if (info->device_type == S2MPS15X || info->device_type == S2MPS14X ||
|
||||
info->device_type == S2MPS13X) {
|
||||
if (info->regs->read_time_udr_mask) {
|
||||
ret = regmap_update_bits(info->regmap,
|
||||
info->regs->rtc_udr_update,
|
||||
S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
|
||||
info->regs->udr_update,
|
||||
info->regs->read_time_udr_mask,
|
||||
info->regs->read_time_udr_mask);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to prepare registers for time reading: %d\n",
|
||||
@ -707,10 +741,18 @@ static int s5m_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
switch (platform_get_device_id(pdev)->driver_data) {
|
||||
case S2MPS15X:
|
||||
regmap_cfg = &s2mps14_rtc_regmap_config;
|
||||
info->regs = &s2mps15_rtc_regs;
|
||||
alarm_irq = S2MPS14_IRQ_RTCA0;
|
||||
break;
|
||||
case S2MPS14X:
|
||||
regmap_cfg = &s2mps14_rtc_regmap_config;
|
||||
info->regs = &s2mps14_rtc_regs;
|
||||
alarm_irq = S2MPS14_IRQ_RTCA0;
|
||||
break;
|
||||
case S2MPS13X:
|
||||
regmap_cfg = &s2mps14_rtc_regmap_config;
|
||||
info->regs = &s2mps_rtc_regs;
|
||||
info->regs = &s2mps13_rtc_regs;
|
||||
alarm_irq = S2MPS14_IRQ_RTCA0;
|
||||
break;
|
||||
case S5M8763X:
|
||||
|
@ -133,7 +133,7 @@ struct sunxi_rtc_data_year {
|
||||
unsigned char leap_shift; /* bit shift to get the leap year */
|
||||
};
|
||||
|
||||
static struct sunxi_rtc_data_year data_year_param[] = {
|
||||
static const struct sunxi_rtc_data_year data_year_param[] = {
|
||||
[0] = {
|
||||
.min = 2010,
|
||||
.max = 2073,
|
||||
@ -151,7 +151,7 @@ static struct sunxi_rtc_data_year data_year_param[] = {
|
||||
struct sunxi_rtc_dev {
|
||||
struct rtc_device *rtc;
|
||||
struct device *dev;
|
||||
struct sunxi_rtc_data_year *data_year;
|
||||
const struct sunxi_rtc_data_year *data_year;
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
};
|
||||
@ -175,7 +175,7 @@ static irqreturn_t sunxi_rtc_alarmirq(int irq, void *id)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static void sunxi_rtc_setaie(int to, struct sunxi_rtc_dev *chip)
|
||||
static void sunxi_rtc_setaie(unsigned int to, struct sunxi_rtc_dev *chip)
|
||||
{
|
||||
u32 alrm_val = 0;
|
||||
u32 alrm_irq_val = 0;
|
||||
@ -343,7 +343,7 @@ static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
|
||||
struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
|
||||
u32 date = 0;
|
||||
u32 time = 0;
|
||||
int year;
|
||||
unsigned int year;
|
||||
|
||||
/*
|
||||
* the input rtc_tm->tm_year is the offset relative to 1900. We use
|
||||
@ -353,8 +353,8 @@ static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
|
||||
|
||||
year = rtc_tm->tm_year + 1900;
|
||||
if (year < chip->data_year->min || year > chip->data_year->max) {
|
||||
dev_err(dev, "rtc only supports year in range %d - %d\n",
|
||||
chip->data_year->min, chip->data_year->max);
|
||||
dev_err(dev, "rtc only supports year in range %u - %u\n",
|
||||
chip->data_year->min, chip->data_year->max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -436,7 +436,6 @@ static int sunxi_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sunxi_rtc_dev *chip;
|
||||
struct resource *res;
|
||||
const struct of_device_id *of_id;
|
||||
int ret;
|
||||
|
||||
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
|
||||
@ -463,12 +462,11 @@ static int sunxi_rtc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_id = of_match_device(sunxi_rtc_dt_ids, &pdev->dev);
|
||||
if (!of_id) {
|
||||
chip->data_year = of_device_get_match_data(&pdev->dev);
|
||||
if (!chip->data_year) {
|
||||
dev_err(&pdev->dev, "Unable to setup RTC data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
chip->data_year = (struct sunxi_rtc_data_year *) of_id->data;
|
||||
|
||||
/* clear the alarm count value */
|
||||
writel(0, chip->base + SUNXI_ALRM_DHMS);
|
||||
|
@ -91,7 +91,12 @@ max_user_freq_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t n)
|
||||
{
|
||||
struct rtc_device *rtc = to_rtc_device(dev);
|
||||
unsigned long val = simple_strtoul(buf, NULL, 0);
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
err = kstrtoul(buf, 0, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val >= 4096 || val == 0)
|
||||
return -EINVAL;
|
||||
@ -175,7 +180,9 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
|
||||
} else
|
||||
adjust = 1;
|
||||
}
|
||||
alarm = simple_strtoul(buf_ptr, NULL, 0);
|
||||
retval = kstrtoul(buf_ptr, 0, &alarm);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (adjust) {
|
||||
alarm += now;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ struct v3020 {
|
||||
/* GPIO access */
|
||||
struct gpio *gpio;
|
||||
|
||||
struct v3020_chip_ops *ops;
|
||||
const struct v3020_chip_ops *ops;
|
||||
|
||||
struct rtc_device *rtc;
|
||||
};
|
||||
@ -95,7 +95,7 @@ static unsigned char v3020_mmio_read_bit(struct v3020 *chip)
|
||||
return !!(readl(chip->ioaddress) & (1 << chip->leftshift));
|
||||
}
|
||||
|
||||
static struct v3020_chip_ops v3020_mmio_ops = {
|
||||
static const struct v3020_chip_ops v3020_mmio_ops = {
|
||||
.map_io = v3020_mmio_map,
|
||||
.unmap_io = v3020_mmio_unmap,
|
||||
.read_bit = v3020_mmio_read_bit,
|
||||
@ -158,7 +158,7 @@ static unsigned char v3020_gpio_read_bit(struct v3020 *chip)
|
||||
return bit;
|
||||
}
|
||||
|
||||
static struct v3020_chip_ops v3020_gpio_ops = {
|
||||
static const struct v3020_chip_ops v3020_gpio_ops = {
|
||||
.map_io = v3020_gpio_map,
|
||||
.unmap_io = v3020_gpio_unmap,
|
||||
.read_bit = v3020_gpio_read_bit,
|
||||
|
@ -105,6 +105,8 @@ enum s2mps_rtc_reg {
|
||||
#define S5M_RTC_UDR_MASK (1 << S5M_RTC_UDR_SHIFT)
|
||||
#define S2MPS_RTC_WUDR_SHIFT 4
|
||||
#define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT)
|
||||
#define S2MPS15_RTC_AUDR_SHIFT 4
|
||||
#define S2MPS15_RTC_AUDR_MASK (1 << S2MPS15_RTC_AUDR_SHIFT)
|
||||
#define S2MPS13_RTC_AUDR_SHIFT 1
|
||||
#define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT)
|
||||
#define S2MPS15_RTC_WUDR_SHIFT 1
|
||||
|
Loading…
Reference in New Issue
Block a user