xref: /openbmc/linux/drivers/rtc/rtc-pcf50633.c (revision eae854b22d25a6d08524c0783a2c772e67121840)
1*eae854b2SBalaji Rao /* NXP PCF50633 RTC Driver
2*eae854b2SBalaji Rao  *
3*eae854b2SBalaji Rao  * (C) 2006-2008 by Openmoko, Inc.
4*eae854b2SBalaji Rao  * Author: Balaji Rao <balajirrao@openmoko.org>
5*eae854b2SBalaji Rao  * All rights reserved.
6*eae854b2SBalaji Rao  *
7*eae854b2SBalaji Rao  * Broken down from monstrous PCF50633 driver mainly by
8*eae854b2SBalaji Rao  * Harald Welte, Andy Green and Werner Almesberger
9*eae854b2SBalaji Rao  *
10*eae854b2SBalaji Rao  *  This program is free software; you can redistribute  it and/or modify it
11*eae854b2SBalaji Rao  *  under  the terms of  the GNU General  Public License as published by the
12*eae854b2SBalaji Rao  *  Free Software Foundation;  either version 2 of the  License, or (at your
13*eae854b2SBalaji Rao  *  option) any later version.
14*eae854b2SBalaji Rao  *
15*eae854b2SBalaji Rao  */
16*eae854b2SBalaji Rao 
17*eae854b2SBalaji Rao #include <linux/kernel.h>
18*eae854b2SBalaji Rao #include <linux/module.h>
19*eae854b2SBalaji Rao #include <linux/init.h>
20*eae854b2SBalaji Rao #include <linux/device.h>
21*eae854b2SBalaji Rao #include <linux/platform_device.h>
22*eae854b2SBalaji Rao #include <linux/rtc.h>
23*eae854b2SBalaji Rao #include <linux/bcd.h>
24*eae854b2SBalaji Rao #include <linux/err.h>
25*eae854b2SBalaji Rao 
26*eae854b2SBalaji Rao #include <linux/mfd/pcf50633/core.h>
27*eae854b2SBalaji Rao 
28*eae854b2SBalaji Rao #define PCF50633_REG_RTCSC	0x59 /* Second */
29*eae854b2SBalaji Rao #define PCF50633_REG_RTCMN	0x5a /* Minute */
30*eae854b2SBalaji Rao #define PCF50633_REG_RTCHR	0x5b /* Hour */
31*eae854b2SBalaji Rao #define PCF50633_REG_RTCWD	0x5c /* Weekday */
32*eae854b2SBalaji Rao #define PCF50633_REG_RTCDT	0x5d /* Day */
33*eae854b2SBalaji Rao #define PCF50633_REG_RTCMT	0x5e /* Month */
34*eae854b2SBalaji Rao #define PCF50633_REG_RTCYR	0x5f /* Year */
35*eae854b2SBalaji Rao #define PCF50633_REG_RTCSCA	0x60 /* Alarm Second */
36*eae854b2SBalaji Rao #define PCF50633_REG_RTCMNA	0x61 /* Alarm Minute */
37*eae854b2SBalaji Rao #define PCF50633_REG_RTCHRA	0x62 /* Alarm Hour */
38*eae854b2SBalaji Rao #define PCF50633_REG_RTCWDA	0x63 /* Alarm Weekday */
39*eae854b2SBalaji Rao #define PCF50633_REG_RTCDTA	0x64 /* Alarm Day */
40*eae854b2SBalaji Rao #define PCF50633_REG_RTCMTA	0x65 /* Alarm Month */
41*eae854b2SBalaji Rao #define PCF50633_REG_RTCYRA	0x66 /* Alarm Year */
42*eae854b2SBalaji Rao 
43*eae854b2SBalaji Rao enum pcf50633_time_indexes {
44*eae854b2SBalaji Rao 	PCF50633_TI_SEC,
45*eae854b2SBalaji Rao 	PCF50633_TI_MIN,
46*eae854b2SBalaji Rao 	PCF50633_TI_HOUR,
47*eae854b2SBalaji Rao 	PCF50633_TI_WKDAY,
48*eae854b2SBalaji Rao 	PCF50633_TI_DAY,
49*eae854b2SBalaji Rao 	PCF50633_TI_MONTH,
50*eae854b2SBalaji Rao 	PCF50633_TI_YEAR,
51*eae854b2SBalaji Rao 	PCF50633_TI_EXTENT /* always last */
52*eae854b2SBalaji Rao };
53*eae854b2SBalaji Rao 
54*eae854b2SBalaji Rao struct pcf50633_time {
55*eae854b2SBalaji Rao 	u_int8_t time[PCF50633_TI_EXTENT];
56*eae854b2SBalaji Rao };
57*eae854b2SBalaji Rao 
58*eae854b2SBalaji Rao struct pcf50633_rtc {
59*eae854b2SBalaji Rao 	int alarm_enabled;
60*eae854b2SBalaji Rao 	int second_enabled;
61*eae854b2SBalaji Rao 
62*eae854b2SBalaji Rao 	struct pcf50633 *pcf;
63*eae854b2SBalaji Rao 	struct rtc_device *rtc_dev;
64*eae854b2SBalaji Rao };
65*eae854b2SBalaji Rao 
66*eae854b2SBalaji Rao static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
67*eae854b2SBalaji Rao {
68*eae854b2SBalaji Rao 	rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]);
69*eae854b2SBalaji Rao 	rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]);
70*eae854b2SBalaji Rao 	rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
71*eae854b2SBalaji Rao 	rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
72*eae854b2SBalaji Rao 	rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
73*eae854b2SBalaji Rao 	rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]);
74*eae854b2SBalaji Rao 	rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
75*eae854b2SBalaji Rao }
76*eae854b2SBalaji Rao 
77*eae854b2SBalaji Rao static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc)
78*eae854b2SBalaji Rao {
79*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec);
80*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min);
81*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
82*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
83*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
84*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon);
85*eae854b2SBalaji Rao 	pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
86*eae854b2SBalaji Rao }
87*eae854b2SBalaji Rao 
88*eae854b2SBalaji Rao static int
89*eae854b2SBalaji Rao pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
90*eae854b2SBalaji Rao {
91*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
92*eae854b2SBalaji Rao 	int err;
93*eae854b2SBalaji Rao 
94*eae854b2SBalaji Rao 	if (enabled)
95*eae854b2SBalaji Rao 		err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
96*eae854b2SBalaji Rao 	else
97*eae854b2SBalaji Rao 		err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
98*eae854b2SBalaji Rao 
99*eae854b2SBalaji Rao 	if (err < 0)
100*eae854b2SBalaji Rao 		return err;
101*eae854b2SBalaji Rao 
102*eae854b2SBalaji Rao 	rtc->alarm_enabled = enabled;
103*eae854b2SBalaji Rao 
104*eae854b2SBalaji Rao 	return 0;
105*eae854b2SBalaji Rao }
106*eae854b2SBalaji Rao 
107*eae854b2SBalaji Rao static int
108*eae854b2SBalaji Rao pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
109*eae854b2SBalaji Rao {
110*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
111*eae854b2SBalaji Rao 	int err;
112*eae854b2SBalaji Rao 
113*eae854b2SBalaji Rao 	if (enabled)
114*eae854b2SBalaji Rao 		err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
115*eae854b2SBalaji Rao 	else
116*eae854b2SBalaji Rao 		err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
117*eae854b2SBalaji Rao 
118*eae854b2SBalaji Rao 	if (err < 0)
119*eae854b2SBalaji Rao 		return err;
120*eae854b2SBalaji Rao 
121*eae854b2SBalaji Rao 	rtc->second_enabled = enabled;
122*eae854b2SBalaji Rao 
123*eae854b2SBalaji Rao 	return 0;
124*eae854b2SBalaji Rao }
125*eae854b2SBalaji Rao 
126*eae854b2SBalaji Rao static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
127*eae854b2SBalaji Rao {
128*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
129*eae854b2SBalaji Rao 	struct pcf50633_time pcf_tm;
130*eae854b2SBalaji Rao 	int ret;
131*eae854b2SBalaji Rao 
132*eae854b2SBalaji Rao 	rtc = dev_get_drvdata(dev);
133*eae854b2SBalaji Rao 
134*eae854b2SBalaji Rao 	ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC,
135*eae854b2SBalaji Rao 					    PCF50633_TI_EXTENT,
136*eae854b2SBalaji Rao 					    &pcf_tm.time[0]);
137*eae854b2SBalaji Rao 	if (ret != PCF50633_TI_EXTENT) {
138*eae854b2SBalaji Rao 		dev_err(dev, "Failed to read time\n");
139*eae854b2SBalaji Rao 		return -EIO;
140*eae854b2SBalaji Rao 	}
141*eae854b2SBalaji Rao 
142*eae854b2SBalaji Rao 	dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
143*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_DAY],
144*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_MONTH],
145*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_YEAR],
146*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_HOUR],
147*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_MIN],
148*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_SEC]);
149*eae854b2SBalaji Rao 
150*eae854b2SBalaji Rao 	pcf2rtc_time(tm, &pcf_tm);
151*eae854b2SBalaji Rao 
152*eae854b2SBalaji Rao 	dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
153*eae854b2SBalaji Rao 		tm->tm_mday, tm->tm_mon, tm->tm_year,
154*eae854b2SBalaji Rao 		tm->tm_hour, tm->tm_min, tm->tm_sec);
155*eae854b2SBalaji Rao 
156*eae854b2SBalaji Rao 	return rtc_valid_tm(tm);
157*eae854b2SBalaji Rao }
158*eae854b2SBalaji Rao 
159*eae854b2SBalaji Rao static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
160*eae854b2SBalaji Rao {
161*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
162*eae854b2SBalaji Rao 	struct pcf50633_time pcf_tm;
163*eae854b2SBalaji Rao 	int second_masked, alarm_masked, ret = 0;
164*eae854b2SBalaji Rao 
165*eae854b2SBalaji Rao 	rtc = dev_get_drvdata(dev);
166*eae854b2SBalaji Rao 
167*eae854b2SBalaji Rao 	dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
168*eae854b2SBalaji Rao 		tm->tm_mday, tm->tm_mon, tm->tm_year,
169*eae854b2SBalaji Rao 		tm->tm_hour, tm->tm_min, tm->tm_sec);
170*eae854b2SBalaji Rao 
171*eae854b2SBalaji Rao 	rtc2pcf_time(&pcf_tm, tm);
172*eae854b2SBalaji Rao 
173*eae854b2SBalaji Rao 	dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
174*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_DAY],
175*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_MONTH],
176*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_YEAR],
177*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_HOUR],
178*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_MIN],
179*eae854b2SBalaji Rao 		pcf_tm.time[PCF50633_TI_SEC]);
180*eae854b2SBalaji Rao 
181*eae854b2SBalaji Rao 
182*eae854b2SBalaji Rao 	second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND);
183*eae854b2SBalaji Rao 	alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
184*eae854b2SBalaji Rao 
185*eae854b2SBalaji Rao 	if (!second_masked)
186*eae854b2SBalaji Rao 		pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
187*eae854b2SBalaji Rao 	if (!alarm_masked)
188*eae854b2SBalaji Rao 		pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
189*eae854b2SBalaji Rao 
190*eae854b2SBalaji Rao 	/* Returns 0 on success */
191*eae854b2SBalaji Rao 	ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC,
192*eae854b2SBalaji Rao 					     PCF50633_TI_EXTENT,
193*eae854b2SBalaji Rao 					     &pcf_tm.time[0]);
194*eae854b2SBalaji Rao 
195*eae854b2SBalaji Rao 	if (!second_masked)
196*eae854b2SBalaji Rao 		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
197*eae854b2SBalaji Rao 	if (!alarm_masked)
198*eae854b2SBalaji Rao 		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
199*eae854b2SBalaji Rao 
200*eae854b2SBalaji Rao 	return ret;
201*eae854b2SBalaji Rao }
202*eae854b2SBalaji Rao 
203*eae854b2SBalaji Rao static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
204*eae854b2SBalaji Rao {
205*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
206*eae854b2SBalaji Rao 	struct pcf50633_time pcf_tm;
207*eae854b2SBalaji Rao 	int ret = 0;
208*eae854b2SBalaji Rao 
209*eae854b2SBalaji Rao 	rtc = dev_get_drvdata(dev);
210*eae854b2SBalaji Rao 
211*eae854b2SBalaji Rao 	alrm->enabled = rtc->alarm_enabled;
212*eae854b2SBalaji Rao 
213*eae854b2SBalaji Rao 	ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
214*eae854b2SBalaji Rao 				PCF50633_TI_EXTENT, &pcf_tm.time[0]);
215*eae854b2SBalaji Rao 	if (ret != PCF50633_TI_EXTENT) {
216*eae854b2SBalaji Rao 		dev_err(dev, "Failed to read time\n");
217*eae854b2SBalaji Rao 		return -EIO;
218*eae854b2SBalaji Rao 	}
219*eae854b2SBalaji Rao 
220*eae854b2SBalaji Rao 	pcf2rtc_time(&alrm->time, &pcf_tm);
221*eae854b2SBalaji Rao 
222*eae854b2SBalaji Rao 	return rtc_valid_tm(&alrm->time);
223*eae854b2SBalaji Rao }
224*eae854b2SBalaji Rao 
225*eae854b2SBalaji Rao static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
226*eae854b2SBalaji Rao {
227*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
228*eae854b2SBalaji Rao 	struct pcf50633_time pcf_tm;
229*eae854b2SBalaji Rao 	int alarm_masked, ret = 0;
230*eae854b2SBalaji Rao 
231*eae854b2SBalaji Rao 	rtc = dev_get_drvdata(dev);
232*eae854b2SBalaji Rao 
233*eae854b2SBalaji Rao 	rtc2pcf_time(&pcf_tm, &alrm->time);
234*eae854b2SBalaji Rao 
235*eae854b2SBalaji Rao 	/* do like mktime does and ignore tm_wday */
236*eae854b2SBalaji Rao 	pcf_tm.time[PCF50633_TI_WKDAY] = 7;
237*eae854b2SBalaji Rao 
238*eae854b2SBalaji Rao 	alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
239*eae854b2SBalaji Rao 
240*eae854b2SBalaji Rao 	/* disable alarm interrupt */
241*eae854b2SBalaji Rao 	if (!alarm_masked)
242*eae854b2SBalaji Rao 		pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
243*eae854b2SBalaji Rao 
244*eae854b2SBalaji Rao 	/* Returns 0 on success */
245*eae854b2SBalaji Rao 	ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
246*eae854b2SBalaji Rao 				PCF50633_TI_EXTENT, &pcf_tm.time[0]);
247*eae854b2SBalaji Rao 
248*eae854b2SBalaji Rao 	if (!alarm_masked)
249*eae854b2SBalaji Rao 		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
250*eae854b2SBalaji Rao 
251*eae854b2SBalaji Rao 	return ret;
252*eae854b2SBalaji Rao }
253*eae854b2SBalaji Rao 
254*eae854b2SBalaji Rao static struct rtc_class_ops pcf50633_rtc_ops = {
255*eae854b2SBalaji Rao 	.read_time		= pcf50633_rtc_read_time,
256*eae854b2SBalaji Rao 	.set_time		= pcf50633_rtc_set_time,
257*eae854b2SBalaji Rao 	.read_alarm		= pcf50633_rtc_read_alarm,
258*eae854b2SBalaji Rao 	.set_alarm		= pcf50633_rtc_set_alarm,
259*eae854b2SBalaji Rao 	.alarm_irq_enable 	= pcf50633_rtc_alarm_irq_enable,
260*eae854b2SBalaji Rao 	.update_irq_enable 	= pcf50633_rtc_update_irq_enable,
261*eae854b2SBalaji Rao };
262*eae854b2SBalaji Rao 
263*eae854b2SBalaji Rao static void pcf50633_rtc_irq(int irq, void *data)
264*eae854b2SBalaji Rao {
265*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc = data;
266*eae854b2SBalaji Rao 
267*eae854b2SBalaji Rao 	switch (irq) {
268*eae854b2SBalaji Rao 	case PCF50633_IRQ_ALARM:
269*eae854b2SBalaji Rao 		rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
270*eae854b2SBalaji Rao 		break;
271*eae854b2SBalaji Rao 	case PCF50633_IRQ_SECOND:
272*eae854b2SBalaji Rao 		rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
273*eae854b2SBalaji Rao 		break;
274*eae854b2SBalaji Rao 	}
275*eae854b2SBalaji Rao }
276*eae854b2SBalaji Rao 
277*eae854b2SBalaji Rao static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
278*eae854b2SBalaji Rao {
279*eae854b2SBalaji Rao 	struct pcf50633_subdev_pdata *pdata;
280*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
281*eae854b2SBalaji Rao 
282*eae854b2SBalaji Rao 
283*eae854b2SBalaji Rao 	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
284*eae854b2SBalaji Rao 	if (!rtc)
285*eae854b2SBalaji Rao 		return -ENOMEM;
286*eae854b2SBalaji Rao 
287*eae854b2SBalaji Rao 	pdata = pdev->dev.platform_data;
288*eae854b2SBalaji Rao 	rtc->pcf = pdata->pcf;
289*eae854b2SBalaji Rao 	platform_set_drvdata(pdev, rtc);
290*eae854b2SBalaji Rao 	rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev,
291*eae854b2SBalaji Rao 				&pcf50633_rtc_ops, THIS_MODULE);
292*eae854b2SBalaji Rao 
293*eae854b2SBalaji Rao 	if (IS_ERR(rtc->rtc_dev)) {
294*eae854b2SBalaji Rao 		kfree(rtc);
295*eae854b2SBalaji Rao 		return PTR_ERR(rtc->rtc_dev);
296*eae854b2SBalaji Rao 	}
297*eae854b2SBalaji Rao 
298*eae854b2SBalaji Rao 	pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
299*eae854b2SBalaji Rao 					pcf50633_rtc_irq, rtc);
300*eae854b2SBalaji Rao 	pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND,
301*eae854b2SBalaji Rao 					pcf50633_rtc_irq, rtc);
302*eae854b2SBalaji Rao 
303*eae854b2SBalaji Rao 	return 0;
304*eae854b2SBalaji Rao }
305*eae854b2SBalaji Rao 
306*eae854b2SBalaji Rao static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
307*eae854b2SBalaji Rao {
308*eae854b2SBalaji Rao 	struct pcf50633_rtc *rtc;
309*eae854b2SBalaji Rao 
310*eae854b2SBalaji Rao 	rtc = platform_get_drvdata(pdev);
311*eae854b2SBalaji Rao 
312*eae854b2SBalaji Rao 	pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM);
313*eae854b2SBalaji Rao 	pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND);
314*eae854b2SBalaji Rao 
315*eae854b2SBalaji Rao 	rtc_device_unregister(rtc->rtc_dev);
316*eae854b2SBalaji Rao 	kfree(rtc);
317*eae854b2SBalaji Rao 
318*eae854b2SBalaji Rao 	return 0;
319*eae854b2SBalaji Rao }
320*eae854b2SBalaji Rao 
321*eae854b2SBalaji Rao static struct platform_driver pcf50633_rtc_driver = {
322*eae854b2SBalaji Rao 	.driver = {
323*eae854b2SBalaji Rao 		.name = "pcf50633-rtc",
324*eae854b2SBalaji Rao 	},
325*eae854b2SBalaji Rao 	.probe = pcf50633_rtc_probe,
326*eae854b2SBalaji Rao 	.remove = __devexit_p(pcf50633_rtc_remove),
327*eae854b2SBalaji Rao };
328*eae854b2SBalaji Rao 
329*eae854b2SBalaji Rao static int __init pcf50633_rtc_init(void)
330*eae854b2SBalaji Rao {
331*eae854b2SBalaji Rao 	return platform_driver_register(&pcf50633_rtc_driver);
332*eae854b2SBalaji Rao }
333*eae854b2SBalaji Rao module_init(pcf50633_rtc_init);
334*eae854b2SBalaji Rao 
335*eae854b2SBalaji Rao static void __exit pcf50633_rtc_exit(void)
336*eae854b2SBalaji Rao {
337*eae854b2SBalaji Rao 	platform_driver_unregister(&pcf50633_rtc_driver);
338*eae854b2SBalaji Rao }
339*eae854b2SBalaji Rao module_exit(pcf50633_rtc_exit);
340*eae854b2SBalaji Rao 
341*eae854b2SBalaji Rao MODULE_DESCRIPTION("PCF50633 RTC driver");
342*eae854b2SBalaji Rao MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
343*eae854b2SBalaji Rao MODULE_LICENSE("GPL");
344*eae854b2SBalaji Rao 
345