summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-max77663.c24
-rw-r--r--drivers/rtc/rtc-tps6591x.c8
-rw-r--r--drivers/rtc/rtc-tps80031.c49
3 files changed, 72 insertions, 9 deletions
diff --git a/drivers/rtc/rtc-max77663.c b/drivers/rtc/rtc-max77663.c
index 874a2df86dc1..13d8062e1def 100644
--- a/drivers/rtc/rtc-max77663.c
+++ b/drivers/rtc/rtc-max77663.c
@@ -2,8 +2,8 @@
* drivers/rtc/rtc-max77663.c
* Max77663 RTC driver
*
- * Copyright 2011 Maxim Integrated Products, Inc.
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright 2011-2012, Maxim Integrated Products, Inc.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -97,6 +97,7 @@ struct max77663_rtc {
struct mutex io_lock;
int irq;
u8 irq_mask;
+ bool shutdown_ongoing;
};
static inline struct device *_to_parent(struct max77663_rtc *rtc)
@@ -443,6 +444,11 @@ static int max77663_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 buf[RTC_NR];
int ret;
+ if (rtc->shutdown_ongoing) {
+ dev_warn(rtc->dev, "rtc_set_alarm: "
+ "Device shutdown on-going, skip alarm setting.\n");
+ return -ESHUTDOWN;
+ }
dev_dbg(rtc->dev, "rtc_set_alarm: "
"tm: %d-%02d-%02d %02d:%02d:%02d, wday=%d [%s]\n",
alrm->time.tm_year, alrm->time.tm_mon, alrm->time.tm_mday,
@@ -534,7 +540,7 @@ static int max77663_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "probe: kzalloc() failed\n");
return -ENOMEM;
}
-
+ rtc->shutdown_ongoing = false;
dev_set_drvdata(&pdev->dev, rtc);
rtc->dev = &pdev->dev;
mutex_init(&rtc->io_lock);
@@ -591,6 +597,17 @@ static int __devexit max77663_rtc_remove(struct platform_device *pdev)
return 0;
}
+static void max77663_rtc_shutdown(struct platform_device *pdev)
+{
+ struct max77663_rtc *rtc = dev_get_drvdata(&pdev->dev);
+ u8 buf[RTC_NR] = { 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x1 };
+
+ rtc->shutdown_ongoing = true;
+ dev_info(rtc->dev, "rtc_shutdown: clean alarm\n");
+ max77663_rtc_write(rtc, MAX77663_RTC_ALARM_SEC1, buf, sizeof(buf), 1);
+ max77663_rtc_alarm_irq_enable(&pdev->dev, 0);
+}
+
static struct platform_driver max77663_rtc_driver = {
.probe = max77663_rtc_probe,
.remove = __devexit_p(max77663_rtc_remove),
@@ -598,6 +615,7 @@ static struct platform_driver max77663_rtc_driver = {
.name = "max77663-rtc",
.owner = THIS_MODULE,
},
+ .shutdown = max77663_rtc_shutdown,
};
static int __init max77663_rtc_init(void)
diff --git a/drivers/rtc/rtc-tps6591x.c b/drivers/rtc/rtc-tps6591x.c
index 6223f1108f06..ebc46b4cf46e 100644
--- a/drivers/rtc/rtc-tps6591x.c
+++ b/drivers/rtc/rtc-tps6591x.c
@@ -162,7 +162,7 @@ static int tps6591x_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour = buff[2];
tm->tm_mday = buff[3];
tm->tm_mon = buff[4] - 1;
- tm->tm_year = buff[5];
+ tm->tm_year = buff[5] + RTC_YEAR_OFFSET;
tm->tm_wday = buff[6];
print_time(dev, tm);
return tps6591x_rtc_valid_tm(tm);
@@ -250,7 +250,7 @@ static int tps6591x_rtc_set_time(struct device *dev, struct rtc_time *tm)
buff[2] = tm->tm_hour;
buff[3] = tm->tm_mday;
buff[4] = tm->tm_mon + 1;
- buff[5] = tm->tm_year;
+ buff[5] = tm->tm_year % RTC_YEAR_OFFSET;
buff[6] = tm->tm_wday;
print_time(dev, tm);
@@ -345,7 +345,7 @@ static int tps6591x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
buff[2] = alrm->time.tm_hour;
buff[3] = alrm->time.tm_mday;
buff[4] = alrm->time.tm_mon + 1;
- buff[5] = alrm->time.tm_year;
+ buff[5] = alrm->time.tm_year % RTC_YEAR_OFFSET;
convert_decimal_to_bcd(buff, sizeof(buff));
err = tps6591x_write_regs(dev, RTC_ALARM, sizeof(buff), buff);
if (err)
@@ -369,7 +369,7 @@ static int tps6591x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_hour = buff[2];
alrm->time.tm_mday = buff[3];
alrm->time.tm_mon = buff[4] - 1;
- alrm->time.tm_year = buff[5];
+ alrm->time.tm_year = buff[5] + RTC_YEAR_OFFSET;
dev_info(dev->parent, "\n getting alarm time::\n");
print_time(dev, &alrm->time);
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c
index 70d6734a5708..b2b9d04171c5 100644
--- a/drivers/rtc/rtc-tps80031.c
+++ b/drivers/rtc/rtc-tps80031.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#define RTC_CTRL 0x10
#define RTC_STATUS 0x11
@@ -65,8 +66,25 @@ struct tps80031_rtc {
int irq;
struct rtc_device *rtc;
u8 alarm_irq_enabled;
+ int msecure_gpio;
};
+static inline void tps80031_enable_rtc_write(struct device *dev)
+{
+ struct tps80031_rtc *rtc = dev_get_drvdata(dev);
+
+ if (rtc->msecure_gpio >= 0)
+ gpio_set_value(rtc->msecure_gpio, 1);
+}
+
+static inline void tps80031_disable_rtc_write(struct device *dev)
+{
+ struct tps80031_rtc *rtc = dev_get_drvdata(dev);
+
+ if (rtc->msecure_gpio >= 0)
+ gpio_set_value(rtc->msecure_gpio, 0);
+}
+
static int tps80031_read_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
@@ -93,13 +111,16 @@ static int tps80031_write_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
int ret;
+
+ tps80031_enable_rtc_write(dev);
ret = tps80031_writes(dev->parent, 1, reg, len, val);
if (ret < 0) {
+ tps80031_disable_rtc_write(dev);
dev_err(dev->parent, "failed writing reg: %d\n", reg);
WARN_ON(1);
return ret;
}
-
+ tps80031_disable_rtc_write(dev);
return 0;
}
@@ -150,18 +171,24 @@ static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int tps80031_rtc_stop(struct device *dev)
{
int err;
+
+ tps80031_enable_rtc_write(dev);
err = tps80031_clr_bits(dev->parent, 1, RTC_CTRL, STOP_RTC);
if (err < 0)
dev_err(dev->parent, "failed to stop RTC. err: %d\n", err);
+ tps80031_disable_rtc_write(dev);
return err;
}
static int tps80031_rtc_start(struct device *dev)
{
int err;
+
+ tps80031_enable_rtc_write(dev);
err = tps80031_set_bits(dev->parent, 1, RTC_CTRL, STOP_RTC);
if (err < 0)
dev_err(dev->parent, "failed to start RTC. err: %d\n", err);
+ tps80031_disable_rtc_write(dev);
return err;
}
@@ -262,7 +289,9 @@ static int tps80031_rtc_alarm_irq_enable(struct device *dev,
if (rtc->alarm_irq_enabled)
return 0;
+ tps80031_enable_rtc_write(dev);
err = tps80031_set_bits(p, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(dev);
if (err < 0) {
dev_err(p, "failed to set ALRM int. err: %d\n", err);
return err;
@@ -271,7 +300,9 @@ static int tps80031_rtc_alarm_irq_enable(struct device *dev,
} else {
if(!rtc->alarm_irq_enabled)
return 0;
+ tps80031_enable_rtc_write(dev);
err = tps80031_clr_bits(p, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(dev);
if (err < 0) {
dev_err(p, "failed to clear ALRM int. err: %d\n", err);
return err;
@@ -303,8 +334,10 @@ static irqreturn_t tps80031_rtc_irq(int irq, void *data)
return -EBUSY;
}
+ tps80031_enable_rtc_write(dev);
err = tps80031_force_update(dev->parent, 1, RTC_STATUS,
ALARM_INT_STATUS, ALARM_INT_STATUS);
+ tps80031_disable_rtc_write(dev);
if (err) {
dev_err(dev->parent, "unable to set Alarm INT\n");
return -EBUSY;
@@ -335,8 +368,19 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
if (pdata->irq < 0)
dev_err(&pdev->dev, "no IRQ specified, wakeup is disabled\n");
+ rtc->msecure_gpio = -1;
+ if (gpio_is_valid(pdata->msecure_gpio)) {
+ err = gpio_request(pdata->msecure_gpio, "tps80031 msecure");
+ if (err == 0) {
+ rtc->msecure_gpio = pdata->msecure_gpio;
+ gpio_direction_output(rtc->msecure_gpio, 0);
+ } else
+ dev_warn(&pdev->dev, "could not get msecure GPIO\n");
+ }
+
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
&tps80031_rtc_ops, THIS_MODULE);
+ dev_set_drvdata(&pdev->dev, rtc);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
@@ -379,7 +423,9 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
return -EBUSY;
}
+ tps80031_enable_rtc_write(&pdev->dev);
err = tps80031_set_bits(pdev->dev.parent, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(&pdev->dev);
if (err) {
dev_err(&pdev->dev, "unable to program Interrupt Mask reg\n");
err = -EBUSY;
@@ -388,7 +434,6 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
} else
rtc->alarm_irq_enabled = 1;
- dev_set_drvdata(&pdev->dev, rtc);
if (pdata && (pdata->irq >= 0)) {
rtc->irq = pdata->irq;
err = request_threaded_irq(pdata->irq, NULL, tps80031_rtc_irq,