aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-02-21 19:44:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 20:22:28 -0500
commit36d6182411b9f597f9f85ec0c4bb00909fd16d59 (patch)
treeaa86752a0ad00906b66e978b150013cebfba004c
parent38ae176e01f6f9ef8159325703ef5985dee40034 (diff)
rtc: add RTC driver for TPS80031/TPS80032
Add an RTC driver for TPS80031/TPS80032 chips by TI. This driver supports: - Setting and getting time and date. - Setting and reading alarm time. - Alarm and interrupt functionlity. [akpm@linux-foundation.org: remove obsolete __devinit/__devexit] Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Devendra Naga <devendra.aaru@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rtc/Kconfig8
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-tps80031.c349
3 files changed, 358 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e94ae65af171..d52183440691 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -396,6 +396,14 @@ config RTC_DRV_TPS65910
396 This driver can also be built as a module. If so, the module 396 This driver can also be built as a module. If so, the module
397 will be called rtc-tps65910. 397 will be called rtc-tps65910.
398 398
399config RTC_DRV_TPS80031
400 tristate "TI TPS80031/TPS80032 RTC driver"
401 depends on MFD_TPS80031
402 help
403 TI Power Managment IC TPS80031 supports RTC functionality
404 along with alarm. This driver supports the RTC driver for
405 the TPS80031 RTC module.
406
399config RTC_DRV_RC5T583 407config RTC_DRV_RC5T583
400 tristate "RICOH 5T583 RTC driver" 408 tristate "RICOH 5T583 RTC driver"
401 depends on MFD_RC5T583 409 depends on MFD_RC5T583
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 1a837767b68d..cd03fb33c14c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o
116obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o 116obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
117obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o 117obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
118obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o 118obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
119obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o
119obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o 120obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
120obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o 121obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
121obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o 122obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c
new file mode 100644
index 000000000000..97406411d58c
--- /dev/null
+++ b/drivers/rtc/rtc-tps80031.c
@@ -0,0 +1,349 @@
1/*
2 * rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver
3 *
4 * RTC driver for TI TPS80031/TPS80032 Fully Integrated
5 * Power Management with Power Path and Battery Charger
6 *
7 * Copyright (c) 2012, NVIDIA Corporation.
8 *
9 * Author: Laxman Dewangan <ldewangan@nvidia.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation version 2.
14 *
15 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
16 * whether express or implied; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * 02111-1307, USA
24 */
25
26#include <linux/bcd.h>
27#include <linux/device.h>
28#include <linux/err.h>
29#include <linux/init.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/mfd/tps80031.h>
33#include <linux/platform_device.h>
34#include <linux/pm.h>
35#include <linux/rtc.h>
36#include <linux/slab.h>
37
38#define ENABLE_ALARM_INT 0x08
39#define ALARM_INT_STATUS 0x40
40
41/**
42 * Setting bit to 1 in STOP_RTC will run the RTC and
43 * setting this bit to 0 will freeze RTC.
44 */
45#define STOP_RTC 0x1
46
47/* Power on reset Values of RTC registers */
48#define TPS80031_RTC_POR_YEAR 0
49#define TPS80031_RTC_POR_MONTH 1
50#define TPS80031_RTC_POR_DAY 1
51
52/* Numbers of registers for time and alarms */
53#define TPS80031_RTC_TIME_NUM_REGS 7
54#define TPS80031_RTC_ALARM_NUM_REGS 6
55
56/**
57 * PMU RTC have only 2 nibbles to store year information, so using an
58 * offset of 100 to set the base year as 2000 for our driver.
59 */
60#define RTC_YEAR_OFFSET 100
61
62struct tps80031_rtc {
63 struct rtc_device *rtc;
64 int irq;
65};
66
67static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm)
68{
69 u8 buff[TPS80031_RTC_TIME_NUM_REGS];
70 int ret;
71
72 ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1,
73 TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff);
74 if (ret < 0) {
75 dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret);
76 return ret;
77 }
78
79 tm->tm_sec = bcd2bin(buff[0]);
80 tm->tm_min = bcd2bin(buff[1]);
81 tm->tm_hour = bcd2bin(buff[2]);
82 tm->tm_mday = bcd2bin(buff[3]);
83 tm->tm_mon = bcd2bin(buff[4]) - 1;
84 tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET;
85 tm->tm_wday = bcd2bin(buff[6]);
86 return 0;
87}
88
89static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm)
90{
91 u8 buff[7];
92 int ret;
93
94 buff[0] = bin2bcd(tm->tm_sec);
95 buff[1] = bin2bcd(tm->tm_min);
96 buff[2] = bin2bcd(tm->tm_hour);
97 buff[3] = bin2bcd(tm->tm_mday);
98 buff[4] = bin2bcd(tm->tm_mon + 1);
99 buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET);
100 buff[6] = bin2bcd(tm->tm_wday);
101
102 /* Stop RTC while updating the RTC time registers */
103 ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1,
104 TPS80031_RTC_CTRL_REG, STOP_RTC);
105 if (ret < 0) {
106 dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret);
107 return ret;
108 }
109
110 ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1,
111 TPS80031_SECONDS_REG,
112 TPS80031_RTC_TIME_NUM_REGS, buff);
113 if (ret < 0) {
114 dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret);
115 return ret;
116 }
117
118 ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1,
119 TPS80031_RTC_CTRL_REG, STOP_RTC);
120 if (ret < 0)
121 dev_err(dev->parent, "Start RTC failed, err = %d\n", ret);
122 return ret;
123}
124
125static int tps80031_rtc_alarm_irq_enable(struct device *dev,
126 unsigned int enable)
127{
128 int ret;
129
130 if (enable)
131 ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1,
132 TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT);
133 else
134 ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1,
135 TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT);
136 if (ret < 0) {
137 dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret);
138 return ret;
139 }
140 return 0;
141}
142
143static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
144{
145 u8 buff[TPS80031_RTC_ALARM_NUM_REGS];
146 int ret;
147
148 buff[0] = bin2bcd(alrm->time.tm_sec);
149 buff[1] = bin2bcd(alrm->time.tm_min);
150 buff[2] = bin2bcd(alrm->time.tm_hour);
151 buff[3] = bin2bcd(alrm->time.tm_mday);
152 buff[4] = bin2bcd(alrm->time.tm_mon + 1);
153 buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET);
154 ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1,
155 TPS80031_ALARM_SECONDS_REG,
156 TPS80031_RTC_ALARM_NUM_REGS, buff);
157 if (ret < 0) {
158 dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret);
159 return ret;
160 }