diff options
Diffstat (limited to 'drivers/rtc/rtc-mpc5121.c')
-rw-r--r-- | drivers/rtc/rtc-mpc5121.c | 81 |
1 files changed, 73 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2..da60915818b 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | 4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> |
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | 5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. |
6 | * Copyright 2011, Dmitry Eremin-Solenikov | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
150 | { | ||
151 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
152 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
153 | int tmp; | ||
154 | |||
155 | tm->tm_sec = in_8(®s->second); | ||
156 | tm->tm_min = in_8(®s->minute); | ||
157 | |||
158 | /* 12 hour format? */ | ||
159 | if (in_8(®s->hour) & 0x20) | ||
160 | tm->tm_hour = (in_8(®s->hour) >> 1) + | ||
161 | (in_8(®s->hour) & 1 ? 12 : 0); | ||
162 | else | ||
163 | tm->tm_hour = in_8(®s->hour); | ||
164 | |||
165 | tmp = in_8(®s->wday_mday); | ||
166 | tm->tm_mday = tmp & 0x1f; | ||
167 | tm->tm_mon = in_8(®s->month) - 1; | ||
168 | tm->tm_year = in_be16(®s->year) - 1900; | ||
169 | tm->tm_wday = (tmp >> 5) % 7; | ||
170 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
171 | tm->tm_isdst = 0; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
177 | { | ||
178 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
179 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
180 | |||
181 | mpc5121_rtc_update_smh(regs, tm); | ||
182 | |||
183 | /* date */ | ||
184 | out_8(®s->month_set, tm->tm_mon + 1); | ||
185 | out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); | ||
186 | out_8(®s->date_set, tm->tm_mday); | ||
187 | out_be16(®s->year_set, tm->tm_year + 1900); | ||
188 | |||
189 | /* set date sequence */ | ||
190 | out_8(®s->set_date, 0x1); | ||
191 | out_8(®s->set_date, 0x3); | ||
192 | out_8(®s->set_date, 0x1); | ||
193 | out_8(®s->set_date, 0x0); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 198 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
149 | { | 199 | { |
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | 200 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); |
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
248 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | 298 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, |
249 | }; | 299 | }; |
250 | 300 | ||
301 | static const struct rtc_class_ops mpc5200_rtc_ops = { | ||
302 | .read_time = mpc5200_rtc_read_time, | ||
303 | .set_time = mpc5200_rtc_set_time, | ||
304 | .read_alarm = mpc5121_rtc_read_alarm, | ||
305 | .set_alarm = mpc5121_rtc_set_alarm, | ||
306 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
307 | }; | ||
308 | |||
251 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) | 309 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) |
252 | { | 310 | { |
253 | struct mpc5121_rtc_data *rtc; | 311 | struct mpc5121_rtc_data *rtc; |
254 | int err = 0; | 312 | int err = 0; |
255 | u32 ka; | ||
256 | 313 | ||
257 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 314 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
258 | if (!rtc) | 315 | if (!rtc) |
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) | |||
287 | goto out_dispose2; | 344 | goto out_dispose2; |
288 | } | 345 | } |
289 | 346 | ||
290 | ka = in_be32(&rtc->regs->keep_alive); | 347 | if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { |
291 | if (ka & 0x02) { | 348 | u32 ka; |
292 | dev_warn(&op->dev, | 349 | ka = in_be32(&rtc->regs->keep_alive); |
293 | "mpc5121-rtc: Battery or oscillator failure!\n"); | 350 | if (ka & 0x02) { |
294 | out_be32(&rtc->regs->keep_alive, ka); | 351 | dev_warn(&op->dev, |
352 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
353 | out_be32(&rtc->regs->keep_alive, ka); | ||
354 | } | ||
355 | |||
356 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
357 | &mpc5121_rtc_ops, THIS_MODULE); | ||
358 | } else { | ||
359 | rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, | ||
360 | &mpc5200_rtc_ops, THIS_MODULE); | ||
295 | } | 361 | } |
296 | 362 | ||
297 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
298 | &mpc5121_rtc_ops, THIS_MODULE); | ||
299 | if (IS_ERR(rtc->rtc)) { | 363 | if (IS_ERR(rtc->rtc)) { |
300 | err = PTR_ERR(rtc->rtc); | 364 | err = PTR_ERR(rtc->rtc); |
301 | goto out_free_irq; | 365 | goto out_free_irq; |
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op) | |||
340 | 404 | ||
341 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | 405 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { |
342 | { .compatible = "fsl,mpc5121-rtc", }, | 406 | { .compatible = "fsl,mpc5121-rtc", }, |
407 | { .compatible = "fsl,mpc5200-rtc", }, | ||
343 | {}, | 408 | {}, |
344 | }; | 409 | }; |
345 | 410 | ||