aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig21
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-msm6242.c269
-rw-r--r--drivers/rtc/rtc-pcf50633.c3
-rw-r--r--drivers/rtc/rtc-rp5c01.c222
-rw-r--r--drivers/rtc/rtc-x1205.c6
6 files changed, 518 insertions, 5 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3c20dae43ce2..f2e1004d12c7 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -509,6 +509,15 @@ config RTC_DRV_M48T59
509 This driver can also be built as a module, if so, the module 509 This driver can also be built as a module, if so, the module
510 will be called "rtc-m48t59". 510 will be called "rtc-m48t59".
511 511
512config RTC_DRV_MSM6242
513 tristate "Oki MSM6242"
514 help
515 If you say yes here you get support for the Oki MSM6242
516 timekeeping chip. It is used in some Amiga models (e.g. A2000).
517
518 This driver can also be built as a module. If so, the module
519 will be called rtc-msm6242.
520
512config RTC_MXC 521config RTC_MXC
513 tristate "Freescale MXC Real Time Clock" 522 tristate "Freescale MXC Real Time Clock"
514 depends on ARCH_MXC 523 depends on ARCH_MXC
@@ -529,6 +538,16 @@ config RTC_DRV_BQ4802
529 This driver can also be built as a module. If so, the module 538 This driver can also be built as a module. If so, the module
530 will be called rtc-bq4802. 539 will be called rtc-bq4802.
531 540
541config RTC_DRV_RP5C01
542 tristate "Ricoh RP5C01"
543 help
544 If you say yes here you get support for the Ricoh RP5C01
545 timekeeping chip. It is used in some Amiga models (e.g. A3000
546 and A4000).
547
548 This driver can also be built as a module. If so, the module
549 will be called rtc-rp5c01.
550
532config RTC_DRV_V3020 551config RTC_DRV_V3020
533 tristate "EM Microelectronic V3020" 552 tristate "EM Microelectronic V3020"
534 help 553 help
@@ -780,7 +799,7 @@ config RTC_DRV_TX4939
780 799
781config RTC_DRV_MV 800config RTC_DRV_MV
782 tristate "Marvell SoC RTC" 801 tristate "Marvell SoC RTC"
783 depends on ARCH_KIRKWOOD 802 depends on ARCH_KIRKWOOD || ARCH_DOVE
784 help 803 help
785 If you say yes here you will get support for the in-chip RTC 804 If you say yes here you will get support for the in-chip RTC
786 that can be found in some of Marvell's SoC devices, such as 805 that can be found in some of Marvell's SoC devices, such as
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index aa3fbd5517a1..af1ba7ae2857 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
52obj-$(CONFIG_RTC_MXC) += rtc-mxc.o 52obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
53obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o 53obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
54obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o 54obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
55obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
55obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o 56obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
56obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o 57obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
57obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o 58obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
@@ -64,6 +65,7 @@ obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
64obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o 65obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
65obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o 66obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
66obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o 67obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
68obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
67obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o 69obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
68obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o 70obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
69obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o 71obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c
new file mode 100644
index 000000000000..5f5968a48925
--- /dev/null
+++ b/drivers/rtc/rtc-msm6242.c
@@ -0,0 +1,269 @@
1/*
2 * Oki MSM6242 RTC Driver
3 *
4 * Copyright 2009 Geert Uytterhoeven
5 *
6 * Based on the A2000 TOD code in arch/m68k/amiga/config.c
7 * Copyright (C) 1993 Hamish Macdonald
8 */
9
10#include <linux/delay.h>
11#include <linux/io.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/rtc.h>
16
17
18enum {
19 MSM6242_SECOND1 = 0x0, /* 1-second digit register */
20 MSM6242_SECOND10 = 0x1, /* 10-second digit register */
21 MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */
22 MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */
23 MSM6242_HOUR1 = 0x4, /* 1-hour digit register */
24 MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */
25 MSM6242_DAY1 = 0x6, /* 1-day digit register */
26 MSM6242_DAY10 = 0x7, /* 10-day digit register */
27 MSM6242_MONTH1 = 0x8, /* 1-month digit register */
28 MSM6242_MONTH10 = 0x9, /* 10-month digit register */
29 MSM6242_YEAR1 = 0xa, /* 1-year digit register */
30 MSM6242_YEAR10 = 0xb, /* 10-year digit register */
31 MSM6242_WEEK = 0xc, /* Week register */
32 MSM6242_CD = 0xd, /* Control Register D */
33 MSM6242_CE = 0xe, /* Control Register E */
34 MSM6242_CF = 0xf, /* Control Register F */
35};
36
37#define MSM6242_HOUR10_AM (0 << 2)
38#define MSM6242_HOUR10_PM (1 << 2)
39#define MSM6242_HOUR10_HR_MASK (3 << 0)
40
41#define MSM6242_WEEK_SUNDAY 0
42#define MSM6242_WEEK_MONDAY 1
43#define MSM6242_WEEK_TUESDAY 2
44#define MSM6242_WEEK_WEDNESDAY 3
45#define MSM6242_WEEK_THURSDAY 4
46#define MSM6242_WEEK_FRIDAY 5
47#define MSM6242_WEEK_SATURDAY 6
48
49#define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */
50#define MSM6242_CD_IRQ_FLAG (1 << 2)
51#define MSM6242_CD_BUSY (1 << 1)
52#define MSM6242_CD_HOLD (1 << 0)
53
54#define MSM6242_CE_T_MASK (3 << 2)
55#define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */
56#define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */
57#define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */
58#define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */
59
60#define MSM6242_CE_ITRPT_STND (1 << 1)
61#define MSM6242_CE_MASK (1 << 0) /* STD.P output control */
62
63#define MSM6242_CF_TEST (1 << 3)
64#define MSM6242_CF_12H (0 << 2)
65#define MSM6242_CF_24H (1 << 2)
66#define MSM6242_CF_STOP (1 << 1)
67#define MSM6242_CF_REST (1 << 0) /* reset */
68
69
70struct msm6242_priv {
71 u32 __iomem *regs;
72 struct rtc_device *rtc;
73};
74
75static inline unsigned int msm6242_read(struct msm6242_priv *priv,
76 unsigned int reg)
77{
78 return __raw_readl(&priv->regs[reg]) & 0xf;
79}
80
81static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val,
82 unsigned int reg)
83{
84 return __raw_writel(val, &priv->regs[reg]);
85}
86
87static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val,
88 unsigned int reg)
89{
90 msm6242_write(priv, msm6242_read(priv, reg) | val, reg);
91}
92
93static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val,
94 unsigned int reg)
95{
96 msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg);
97}
98
99static void msm6242_lock(struct msm6242_priv *priv)
100{
101 int cnt = 5;
102
103 msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD);
104
105 while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt) {
106 msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD);
107 udelay(70);
108 msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD);
109 cnt--;
110 }
111
112 if (!cnt)
113 pr_warning("msm6242: timed out waiting for RTC (0x%x)\n",
114 msm6242_read(priv, MSM6242_CD));
115}
116
117static void msm6242_unlock(struct msm6242_priv *priv)
118{
119 msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD);
120}
121
122static int msm6242_read_time(struct device *dev, struct rtc_time *tm)
123{
124 struct msm6242_priv *priv = dev_get_drvdata(dev);
125
126 msm6242_lock(priv);
127
128 tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 +
129 msm6242_read(priv, MSM6242_SECOND1);
130 tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 +
131 msm6242_read(priv, MSM6242_MINUTE1);
132 tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 +
133 msm6242_read(priv, MSM6242_HOUR1);
134 tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 +
135 msm6242_read(priv, MSM6242_DAY1);
136 tm->tm_wday = msm6242_read(priv, MSM6242_WEEK);
137 tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 +
138 msm6242_read(priv, MSM6242_MONTH1) - 1;
139 tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 +
140 msm6242_read(priv, MSM6242_YEAR1);
141 if (tm->tm_year <= 69)
142 tm->tm_year += 100;
143
144 if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) {
145 unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) &
146 MSM6242_HOUR10_PM;
147 if (!pm && tm->tm_hour == 12)
148 tm->tm_hour = 0;
149 else if (pm && tm->tm_hour != 12)
150 tm->tm_hour += 12;
151 }
152
153 msm6242_unlock(priv);
154
155 return rtc_valid_tm(tm);
156}
157
158static int msm6242_set_time(struct device *dev, struct rtc_time *tm)
159{
160 struct msm6242_priv *priv = dev_get_drvdata(dev);
161
162 msm6242_lock(priv);
163
164 msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10);
165 msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1);
166 msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10);
167 msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1);
168 if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)
169 msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10);
170 else if (tm->tm_hour >= 12)
171 msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10,
172 MSM6242_HOUR10);
173 else
174 msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10);
175 msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1);
176 msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10);
177 msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1);
178 if (tm->tm_wday != -1)
179 msm6242_write(priv, tm->tm_wday, MSM6242_WEEK);
180 msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10);
181 msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1);
182 if (tm->tm_year >= 100)
183 tm->tm_year -= 100;
184 msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10);
185 msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1);
186
187 msm6242_unlock(priv);
188 return 0;
189}
190
191static const struct rtc_class_ops msm6242_rtc_ops = {
192 .read_time = msm6242_read_time,
193 .set_time = msm6242_set_time,
194};
195
196static int __init msm6242_rtc_probe(struct platform_device *dev)
197{
198 struct resource *res;
199 struct msm6242_priv *priv;
200 struct rtc_device *rtc;
201 int error;
202
203 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
204 if (!res)
205 return -ENODEV;
206
207 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
208 if (!priv)
209 return -ENOMEM;
210
211 priv->regs = ioremap(res->start, resource_size(res));
212 if (!priv->regs) {
213 error = -ENOMEM;
214 goto out_free_priv;
215 }
216
217 rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops,
218 THIS_MODULE);
219 if (IS_ERR(rtc)) {
220 error = PTR_ERR(rtc);
221 goto out_unmap;
222 }
223
224 priv->rtc = rtc;
225 platform_set_drvdata(dev, priv);
226 return 0;
227
228out_unmap:
229 iounmap(priv->regs);
230out_free_priv:
231 kfree(priv);
232 return error;
233}
234
235static int __exit msm6242_rtc_remove(struct platform_device *dev)
236{
237 struct msm6242_priv *priv = platform_get_drvdata(dev);
238
239 rtc_device_unregister(priv->rtc);
240 iounmap(priv->regs);
241 kfree(priv);
242 return 0;
243}
244
245static struct platform_driver msm6242_rtc_driver = {
246 .driver = {
247 .name = "rtc-msm6242",
248 .owner = THIS_MODULE,
249 },
250 .remove = __exit_p(msm6242_rtc_remove),
251};
252
253static int __init msm6242_rtc_init(void)
254{
255 return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe);
256}
257
258static void __exit msm6242_rtc_fini(void)
259{
260 platform_driver_unregister(&msm6242_rtc_driver);
261}
262
263module_init(msm6242_rtc_init);
264module_exit(msm6242_rtc_fini);
265
266MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
267MODULE_LICENSE("GPL");
268MODULE_DESCRIPTION("Oki MSM6242 RTC driver");
269MODULE_ALIAS("platform:rtc-msm6242");
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 33a10c47260e..4c5d5d0c4cfc 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -292,8 +292,9 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
292 &pcf50633_rtc_ops, THIS_MODULE); 292 &pcf50633_rtc_ops, THIS_MODULE);
293 293
294 if (IS_ERR(rtc->rtc_dev)) { 294 if (IS_ERR(rtc->rtc_dev)) {
295 int ret = PTR_ERR(rtc->rtc_dev);
295 kfree(rtc); 296 kfree(rtc);
296 return PTR_ERR(rtc->rtc_dev); 297 return ret;
297 } 298 }
298 299
299 pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, 300 pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
new file mode 100644
index 000000000000..e1313feb060f
--- /dev/null
+++ b/drivers/rtc/rtc-rp5c01.c
@@ -0,0 +1,222 @@
1/*
2 * Ricoh RP5C01 RTC Driver
3 *
4 * Copyright 2009 Geert Uytterhoeven
5 *
6 * Based on the A3000 TOD code in arch/m68k/amiga/config.c
7 * Copyright (C) 1993 Hamish Macdonald
8 */
9
10#include <linux/io.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/rtc.h>
15
16
17enum {
18 RP5C01_1_SECOND = 0x0, /* MODE 00 */
19 RP5C01_10_SECOND = 0x1, /* MODE 00 */
20 RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */
21 RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */
22 RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */
23 RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */
24 RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */
25 RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */
26 RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */
27 RP5C01_1_MONTH = 0x9, /* MODE 00 */
28 RP5C01_10_MONTH = 0xa, /* MODE 00 */
29 RP5C01_1_YEAR = 0xb, /* MODE 00 */
30 RP5C01_10_YEAR = 0xc, /* MODE 00 */
31
32 RP5C01_12_24_SELECT = 0xa, /* MODE 01 */
33 RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */
34
35 RP5C01_MODE = 0xd, /* all modes */
36 RP5C01_TEST = 0xe, /* all modes */
37 RP5C01_RESET = 0xf, /* all modes */
38};
39
40#define RP5C01_12_24_SELECT_12 (0 << 0)
41#define RP5C01_12_24_SELECT_24 (1 << 0)
42
43#define RP5C01_10_HOUR_AM (0 << 1)
44#define RP5C01_10_HOUR_PM (1 << 1)
45
46#define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */
47#define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */
48
49#define RP5C01_MODE_MODE_MASK (3 << 0)
50#define RP5C01_MODE_MODE00 (0 << 0) /* time */
51#define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */
52#define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */
53#define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */
54
55#define RP5C01_RESET_1HZ_PULSE (1 << 3)
56#define RP5C01_RESET_16HZ_PULSE (1 << 2)
57#define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */
58 /* seconds or smaller units */
59#define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */
60
61
62struct rp5c01_priv {
63 u32 __iomem *regs;
64 struct rtc_device *rtc;
65};
66
67static inline unsigned int rp5c01_read(struct rp5c01_priv *priv,
68 unsigned int reg)
69{
70 return __raw_readl(&priv->regs[reg]) & 0xf;
71}
72
73static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val,
74 unsigned int reg)
75{
76 return __raw_writel(val, &priv->regs[reg]);
77}
78
79static void rp5c01_lock(struct rp5c01_priv *priv)
80{
81 rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE);
82}
83
84static void rp5c01_unlock(struct rp5c01_priv *priv)
85{
86 rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01,
87 RP5C01_MODE);
88}
89
90static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
91{
92 struct rp5c01_priv *priv = dev_get_drvdata(dev);
93
94 rp5c01_lock(priv);
95
96 tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 +
97 rp5c01_read(priv, RP5C01_1_SECOND);
98 tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 +
99 rp5c01_read(priv, RP5C01_1_MINUTE);
100 tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 +
101 rp5c01_read(priv, RP5C01_1_HOUR);
102 tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 +
103 rp5c01_read(priv, RP5C01_1_DAY);
104 tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK);
105 tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 +
106 rp5c01_read(priv, RP5C01_1_MONTH) - 1;
107 tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 +
108 rp5c01_read(priv, RP5C01_1_YEAR);
109 if (tm->tm_year <= 69)
110 tm->tm_year += 100;
111
112 rp5c01_unlock(priv);
113
114 return rtc_valid_tm(tm);
115}
116
117static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
118{
119 struct rp5c01_priv *priv = dev_get_drvdata(dev);
120
121 rp5c01_lock(priv);
122
123 rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND);
124 rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND);
125 rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE);
126 rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE);
127 rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR);
128 rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR);
129 rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY);
130 rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY);
131 if (tm->tm_wday != -1)
132 rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK);
133 rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH);
134 rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH);
135 if (tm->tm_year >= 100)
136 tm->tm_year -= 100;
137 rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR);
138 rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR);
139
140 rp5c01_unlock(priv);
141 return 0;
142}
143
144static const struct rtc_class_ops rp5c01_rtc_ops = {
145 .read_time = rp5c01_read_time,
146 .set_time = rp5c01_set_time,
147};
148
149static int __init rp5c01_rtc_probe(struct platform_device *dev)
150{
151 struct resource *res;
152 struct rp5c01_priv *priv;
153 struct rtc_device *rtc;
154 int error;
155
156 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
157 if (!res)
158 return -ENODEV;
159
160 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
161 if (!priv)
162 return -ENOMEM;
163
164 priv->regs = ioremap(res->start, resource_size(res));
165 if (!priv->regs) {
166 error = -ENOMEM;
167 goto out_free_priv;
168 }
169
170 rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops,
171 THIS_MODULE);
172 if (IS_ERR(rtc)) {
173 error = PTR_ERR(rtc);
174 goto out_unmap;
175 }
176
177 priv->rtc = rtc;
178 platform_set_drvdata(dev, priv);
179 return 0;
180
181out_unmap:
182 iounmap(priv->regs);
183out_free_priv:
184 kfree(priv);
185 return error;
186}
187
188static int __exit rp5c01_rtc_remove(struct platform_device *dev)
189{
190 struct rp5c01_priv *priv = platform_get_drvdata(dev);
191
192 rtc_device_unregister(priv->rtc);
193 iounmap(priv->regs);
194 kfree(priv);
195 return 0;
196}
197
198static struct platform_driver rp5c01_rtc_driver = {
199 .driver = {
200 .name = "rtc-rp5c01",
201 .owner = THIS_MODULE,
202 },
203 .remove = __exit_p(rp5c01_rtc_remove),
204};
205
206static int __init rp5c01_rtc_init(void)
207{
208 return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe);
209}
210
211static void __exit rp5c01_rtc_fini(void)
212{
213 platform_driver_unregister(&rp5c01_rtc_driver);
214}
215
216module_init(rp5c01_rtc_init);
217module_exit(rp5c01_rtc_fini);
218
219MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
220MODULE_LICENSE("GPL");
221MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver");
222MODULE_ALIAS("platform:rtc-rp5c01");
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 310c10795e9a..6583c1a8b070 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -195,7 +195,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
195 /* year, since the rtc epoch*/ 195 /* year, since the rtc epoch*/
196 buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); 196 buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
197 buf[CCR_WDAY] = tm->tm_wday & 0x07; 197 buf[CCR_WDAY] = tm->tm_wday & 0x07;
198 buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100); 198 buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);
199 } 199 }
200 200
201 /* If writing alarm registers, set compare bits on registers 0-4 */ 201 /* If writing alarm registers, set compare bits on registers 0-4 */
@@ -280,9 +280,9 @@ static int x1205_fix_osc(struct i2c_client *client)
280 int err; 280 int err;
281 struct rtc_time tm; 281 struct rtc_time tm;
282 282
283 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 283 memset(&tm, 0, sizeof(tm));
284 284
285 err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0); 285 err = x1205_set_datetime(client, &tm, 1, X1205_CCR_BASE, 0);
286 if (err < 0) 286 if (err < 0)
287 dev_err(&client->dev, "unable to restart the oscillator\n"); 287 dev_err(&client->dev, "unable to restart the oscillator\n");
288 288