1/*
2 * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock
3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
5 * Author: Venu Byravarasu <vbyravarasu@nvidia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/rtc.h>
25#include <linux/bcd.h>
26#include <linux/platform_device.h>
27#include <linux/interrupt.h>
28#include <linux/mfd/rc5t583.h>
29
30struct rc5t583_rtc {
31	struct rtc_device	*rtc;
32	/* To store the list of enabled interrupts, during system suspend */
33	u32 irqen;
34};
35
36/* Total number of RTC registers needed to set time*/
37#define NUM_TIME_REGS	(RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1)
38
39/* Total number of RTC registers needed to set Y-Alarm*/
40#define NUM_YAL_REGS	(RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1)
41
42/* Set Y-Alarm interrupt */
43#define SET_YAL BIT(5)
44
45/* Get Y-Alarm interrupt status*/
46#define GET_YAL_STATUS BIT(3)
47
48static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
49{
50	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
51	u8 val;
52
53	/* Set Y-Alarm, based on 'enabled' */
54	val = enabled ? SET_YAL : 0;
55
56	return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL,
57		val);
58}
59
60/*
61 * Gets current rc5t583 RTC time and date parameters.
62 *
63 * The RTC's time/alarm representation is not what gmtime(3) requires
64 * Linux to use:
65 *
66 *  - Months are 1..12 vs Linux 0-11
67 *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
68 */
69static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm)
70{
71	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
72	u8 rtc_data[NUM_TIME_REGS];
73	int ret;
74
75	ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
76		NUM_TIME_REGS);
77	if (ret < 0) {
78		dev_err(dev, "RTC read time failed with err:%d\n", ret);
79		return ret;
80	}
81
82	tm->tm_sec = bcd2bin(rtc_data[0]);
83	tm->tm_min = bcd2bin(rtc_data[1]);
84	tm->tm_hour = bcd2bin(rtc_data[2]);
85	tm->tm_wday = bcd2bin(rtc_data[3]);
86	tm->tm_mday = bcd2bin(rtc_data[4]);
87	tm->tm_mon = bcd2bin(rtc_data[5]) - 1;
88	tm->tm_year = bcd2bin(rtc_data[6]) + 100;
89
90	return ret;
91}
92
93static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm)
94{
95	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
96	unsigned char rtc_data[NUM_TIME_REGS];
97	int ret;
98
99	rtc_data[0] = bin2bcd(tm->tm_sec);
100	rtc_data[1] = bin2bcd(tm->tm_min);
101	rtc_data[2] = bin2bcd(tm->tm_hour);
102	rtc_data[3] = bin2bcd(tm->tm_wday);
103	rtc_data[4] = bin2bcd(tm->tm_mday);
104	rtc_data[5] = bin2bcd(tm->tm_mon + 1);
105	rtc_data[6] = bin2bcd(tm->tm_year - 100);
106
107	ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
108		NUM_TIME_REGS);
109	if (ret < 0) {
110		dev_err(dev, "RTC set time failed with error %d\n", ret);
111		return ret;
112	}
113
114	return ret;
115}
116
117static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
118{
119	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
120	unsigned char alarm_data[NUM_YAL_REGS];
121	u32 interrupt_enable;
122	int ret;
123
124	ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
125		NUM_YAL_REGS);
126	if (ret < 0) {
127		dev_err(dev, "rtc_read_alarm error %d\n", ret);
128		return ret;
129	}
130
131	alm->time.tm_min = bcd2bin(alarm_data[0]);
132	alm->time.tm_hour = bcd2bin(alarm_data[1]);
133	alm->time.tm_mday = bcd2bin(alarm_data[2]);
134	alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1;
135	alm->time.tm_year = bcd2bin(alarm_data[4]) + 100;
136
137	ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable);
138	if (ret < 0)
139		return ret;
140
141	/* check if YALE is set */
142	if (interrupt_enable & SET_YAL)
143		alm->enabled = 1;
144
145	return ret;
146}
147
148static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
149{
150	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
151	unsigned char alarm_data[NUM_YAL_REGS];
152	int ret;
153
154	ret = rc5t583_rtc_alarm_irq_enable(dev, 0);
155	if (ret)
156		return ret;
157
158	alarm_data[0] = bin2bcd(alm->time.tm_min);
159	alarm_data[1] = bin2bcd(alm->time.tm_hour);
160	alarm_data[2] = bin2bcd(alm->time.tm_mday);
161	alarm_data[3] = bin2bcd(alm->time.tm_mon + 1);
162	alarm_data[4] = bin2bcd(alm->time.tm_year - 100);
163
164	ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
165		NUM_YAL_REGS);
166	if (ret) {
167		dev_err(dev, "rtc_set_alarm error %d\n", ret);
168		return ret;
169	}
170
171	if (alm->enabled)
172		ret = rc5t583_rtc_alarm_irq_enable(dev, 1);
173
174	return ret;
175}
176
177static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc)
178{
179	struct device *dev = rtc;
180	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
181	struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
182	unsigned long events = 0;
183	int ret;
184	u32 rtc_reg;
185
186	ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg);
187	if (ret < 0)
188		return IRQ_NONE;
189
190	if (rtc_reg & GET_YAL_STATUS) {
191		events = RTC_IRQF | RTC_AF;
192		/* clear pending Y-alarm interrupt bit */
193		rtc_reg &= ~GET_YAL_STATUS;
194	}
195
196	ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg);
197	if (ret)
198		return IRQ_NONE;
199
200	/* Notify RTC core on event */
201	rtc_update_irq(rc5t583_rtc->rtc, 1, events);
202
203	return IRQ_HANDLED;
204}
205
206static const struct rtc_class_ops rc5t583_rtc_ops = {
207	.read_time	= rc5t583_rtc_read_time,
208	.set_time	= rc5t583_rtc_set_time,
209	.read_alarm	= rc5t583_rtc_read_alarm,
210	.set_alarm	= rc5t583_rtc_set_alarm,
211	.alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,
212};
213
214static int rc5t583_rtc_probe(struct platform_device *pdev)
215{
216	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
217	struct rc5t583_rtc *ricoh_rtc;
218	struct rc5t583_platform_data *pmic_plat_data;
219	int ret;
220	int irq;
221
222	ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc),
223			GFP_KERNEL);
224	if (!ricoh_rtc)
225		return -ENOMEM;
226
227	platform_set_drvdata(pdev, ricoh_rtc);
228
229	/* Clear pending interrupts */
230	ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0);
231	if (ret < 0)
232		return ret;
233
234	/* clear RTC Adjust register */
235	ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0);
236	if (ret < 0) {
237		dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
238		return -EBUSY;
239	}
240
241	pmic_plat_data = dev_get_platdata(rc5t583->dev);
242	irq = pmic_plat_data->irq_base;
243	if (irq <= 0) {
244		dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
245			irq);
246		return ret;
247	}
248
249	irq += RC5T583_IRQ_YALE;
250	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
251		rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW,
252		"rtc-rc5t583", &pdev->dev);
253	if (ret < 0) {
254		dev_err(&pdev->dev, "IRQ is not free.\n");
255		return ret;
256	}
257	device_init_wakeup(&pdev->dev, 1);
258
259	ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
260		&rc5t583_rtc_ops, THIS_MODULE);
261	if (IS_ERR(ricoh_rtc->rtc)) {
262		ret = PTR_ERR(ricoh_rtc->rtc);
263		dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
264		return ret;
265	}
266
267	return 0;
268}
269
270/*
271 * Disable rc5t583 RTC interrupts.
272 * Sets status flag to free.
273 */
274static int rc5t583_rtc_remove(struct platform_device *pdev)
275{
276	struct rc5t583_rtc *rc5t583_rtc = platform_get_drvdata(pdev);
277
278	rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0);
279	return 0;
280}
281
282#ifdef CONFIG_PM_SLEEP
283static int rc5t583_rtc_suspend(struct device *dev)
284{
285	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
286	struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
287	int ret;
288
289	/* Store current list of enabled interrupts*/
290	ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1,
291		&rc5t583_rtc->irqen);
292	return ret;
293}
294
295static int rc5t583_rtc_resume(struct device *dev)
296{
297	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
298	struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
299
300	/* Restore list of enabled interrupts before suspend */
301	return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1,
302		rc5t583_rtc->irqen);
303}
304#endif
305
306static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
307			rc5t583_rtc_resume);
308
309static struct platform_driver rc5t583_rtc_driver = {
310	.probe		= rc5t583_rtc_probe,
311	.remove		= rc5t583_rtc_remove,
312	.driver		= {
313		.owner	= THIS_MODULE,
314		.name	= "rtc-rc5t583",
315		.pm	= &rc5t583_rtc_pm_ops,
316	},
317};
318
319module_platform_driver(rc5t583_rtc_driver);
320MODULE_ALIAS("platform:rtc-rc5t583");
321MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
322MODULE_LICENSE("GPL v2");
323