summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2011-02-02 10:56:49 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-02-02 17:20:44 -0800
commit7184d208813f73be5e53e5c9b001be43e29bad52 (patch)
treed3d05438700c3ab686a081710480d8f2d7b8250c
parent78967cc4639b425dbc2da1e005db0df879f58cb5 (diff)
mfd: tps6586x: fix alarm1 support
instead of clearing the irq for alarm enable/disable, the proper bit in RTC_CONFIG has to be set/cleared. tps6586 does not support 1/sec update counter so remove support for update_irq_enable. replace it with alarm_irq_enable. Change-Id: Iee66a6625e810169253a750faf3f12d20d65d7d9 Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/17990 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--drivers/rtc/Kconfig3
-rw-r--r--drivers/rtc/rtc-tps6586x.c79
-rw-r--r--include/linux/mfd/tps6586x.h10
3 files changed, 57 insertions, 35 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 350750d60fea..2532d54eb111 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -316,8 +316,7 @@ config RTC_DRV_DM355EVM
config RTC_DRV_TPS6586X
tristate "TI TPS6586X RTC"
- depends on I2C
- select MFD_TPS6586X
+ depends on MFD_TPS6586X
help
This driver supports TPS6586X RTC
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index ca6138bbda4b..2ff339a21a5c 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -29,19 +29,16 @@
#include <linux/rtc.h>
#include <linux/slab.h>
-#define TPS_EPOCH 2009
-
#define RTC_CTRL 0xc0
-# define RTC_ENABLE (1 << 5) /* enables tick updates */
-# define RTC_HIRES (1 << 4) /* 1Khz or 32Khz updates */
+#define RTC_ENABLE BIT(5) /* enables alarm */
+#define RTC_HIRES BIT(4) /* 1Khz or 32Khz updates */
#define RTC_ALARM1_HI 0xc1
#define RTC_COUNT4 0xc6
struct tps6586x_rtc {
- unsigned long epoch_start;
- int irq;
- bool irq_en;
- struct rtc_device *rtc;
+ unsigned long epoch_start;
+ int irq;
+ struct rtc_device *rtc;
};
static inline struct device *to_tps6586x_dev(struct device *dev)
@@ -142,11 +139,6 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return -EINVAL;
}
- if (rtc->irq_en && rtc->irq_en && (rtc->irq != -1)) {
- disable_irq(rtc->irq);
- rtc->irq_en = false;
- }
-
seconds -= rtc->epoch_start;
ticks = (unsigned long long)seconds << 10;
@@ -155,15 +147,8 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
buff[2] = ticks & 0xff;
err = tps6586x_writes(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff);
- if (err) {
+ if (err)
dev_err(tps_dev, "unable to program alarm\n");
- return err;
- }
-
- if (alrm->enabled && (rtc->irq != -1)) {
- enable_irq(rtc->irq);
- rtc->irq_en = true;
- }
return err;
}
@@ -186,29 +171,47 @@ static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
seconds += rtc->epoch_start;
rtc_time_to_tm(seconds, &alrm->time);
- alrm->enabled = rtc->irq_en;
return 0;
}
-static int tps6586x_rtc_update_irq_enable(struct device *dev,
- unsigned int enabled)
+static int tps6586x_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+ struct device *tps_dev = to_tps6586x_dev(dev);
+ u8 buff;
+ int err;
if (rtc->irq == -1)
return -EIO;
- enabled = !!enabled;
- if (enabled == rtc->irq_en)
+ err = tps6586x_read(tps_dev, RTC_CTRL, &buff);
+ if (err < 0) {
+ dev_err(dev, "failed to read RTC_CTRL\n");
+ return err;
+ }
+
+ if ((enabled && (buff & RTC_ENABLE)) ||
+ (!enabled && !(buff & RTC_ENABLE)))
return 0;
- if (enabled)
+ if (enabled) {
+ err = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
+ if (err < 0) {
+ dev_err(dev, "failed to set RTC_ENABLE\n");
+ return err;
+ }
enable_irq(rtc->irq);
- else
+ } else {
+ err = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
+ if (err < 0) {
+ dev_err(dev, "failed to clear RTC_ENABLE\n");
+ return err;
+ }
disable_irq(rtc->irq);
+ }
- rtc->irq_en = enabled;
return 0;
}
@@ -217,7 +220,7 @@ static const struct rtc_class_ops tps6586x_rtc_ops = {
.set_time = tps6586x_rtc_set_time,
.set_alarm = tps6586x_rtc_set_alarm,
.read_alarm = tps6586x_rtc_read_alarm,
- .update_irq_enable = tps6586x_rtc_update_irq_enable,
+ .alarm_irq_enable = tps6586x_rtc_alarm_irq_enable,
};
static irqreturn_t tps6586x_rtc_irq(int irq, void *data)
@@ -235,6 +238,7 @@ static int __devinit tps6586x_rtc_probe(struct platform_device *pdev)
struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
struct tps6586x_rtc *rtc;
int err;
+ struct tps6586x_epoch_start *epoch;
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
@@ -242,10 +246,18 @@ static int __devinit tps6586x_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
rtc->irq = -1;
- if (!pdata || (pdata->irq < 0))
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform_data specified\n");
+ return -EINVAL;
+ }
+
+ if (pdata->irq < 0)
dev_warn(&pdev->dev, "no IRQ specified, wakeup is disabled\n");
- rtc->epoch_start = mktime(TPS_EPOCH, 1, 1, 0, 0, 0);
+ epoch = &pdata->start;
+ rtc->epoch_start = mktime(epoch->year, epoch->month, epoch->day,
+ epoch->hour, epoch->min, epoch->sec);
rtc->rtc = rtc_device_register("tps6586x-rtc", &pdev->dev,
&tps6586x_rtc_ops, THIS_MODULE);
@@ -270,7 +282,7 @@ static int __devinit tps6586x_rtc_probe(struct platform_device *pdev)
IRQF_ONESHOT, "tps6586x-rtc",
&pdev->dev);
if (err) {
- dev_warn(&pdev->dev, "unable to request IRQ\n");
+ dev_warn(&pdev->dev, "unable to request IRQ(%d)\n", rtc->irq);
rtc->irq = -1;
} else {
device_init_wakeup(&pdev->dev, 1);
@@ -323,3 +335,4 @@ module_exit(tps6586x_rtc_exit);
MODULE_DESCRIPTION("TI TPS6586x RTC driver");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rtc-tps6586x")
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index bd20aa696485..9002714f1f68 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -54,8 +54,18 @@ struct tps6586x_subdev_info {
void *platform_data;
};
+struct tps6586x_epoch_start {
+ int year;
+ int month;
+ int day;
+ int hour;
+ int min;
+ int sec;
+};
+
struct tps6586x_rtc_platform_data {
int irq;
+ struct tps6586x_epoch_start start;
};
struct tps6586x_platform_data {