Commit 955dbea3c7133d3ccfaa79c7eba1244c1de42865
Committed by
Linus Torvalds
1 parent
7afe1845dd
Exists in
master
and in
4 other branches
drivers/rtc/rtc-mpc5121.c: add support for RTC on MPC5200
MPC5200B contains a limited version of RTC from MPC5121. Add support for the RTC on that CPU. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Anatolij Gustschin <agust@denx.de> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 75 additions and 10 deletions Side-by-side Diff
drivers/rtc/Kconfig
... | ... | @@ -1006,10 +1006,10 @@ |
1006 | 1006 | |
1007 | 1007 | config RTC_DRV_MPC5121 |
1008 | 1008 | tristate "Freescale MPC5121 built-in RTC" |
1009 | - depends on PPC_MPC512x && RTC_CLASS | |
1009 | + depends on PPC_MPC512x || PPC_MPC52xx | |
1010 | 1010 | help |
1011 | 1011 | If you say yes here you will get support for the |
1012 | - built-in RTC MPC5121. | |
1012 | + built-in RTC on MPC5121 or on MPC5200. | |
1013 | 1013 | |
1014 | 1014 | This driver can also be built as a module. If so, the module |
1015 | 1015 | will be called rtc-mpc5121. |
drivers/rtc/rtc-mpc5121.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | * |
4 | 4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> |
5 | 5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. |
6 | + * Copyright 2011, Dmitry Eremin-Solenikov | |
6 | 7 | * |
7 | 8 | * This program is free software; you can redistribute it and/or modify |
8 | 9 | * it under the terms of the GNU General Public License version 2 as |
... | ... | @@ -145,6 +146,55 @@ |
145 | 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 | 198 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
149 | 199 | { |
150 | 200 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); |
151 | 201 | |
... | ... | @@ -248,11 +298,18 @@ |
248 | 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 | 309 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) |
252 | 310 | { |
253 | 311 | struct mpc5121_rtc_data *rtc; |
254 | 312 | int err = 0; |
255 | - u32 ka; | |
256 | 313 | |
257 | 314 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
258 | 315 | if (!rtc) |
259 | 316 | |
... | ... | @@ -287,15 +344,22 @@ |
287 | 344 | goto out_dispose2; |
288 | 345 | } |
289 | 346 | |
290 | - ka = in_be32(&rtc->regs->keep_alive); | |
291 | - if (ka & 0x02) { | |
292 | - dev_warn(&op->dev, | |
293 | - "mpc5121-rtc: Battery or oscillator failure!\n"); | |
294 | - out_be32(&rtc->regs->keep_alive, ka); | |
347 | + if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { | |
348 | + u32 ka; | |
349 | + ka = in_be32(&rtc->regs->keep_alive); | |
350 | + if (ka & 0x02) { | |
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 | 363 | if (IS_ERR(rtc->rtc)) { |
300 | 364 | err = PTR_ERR(rtc->rtc); |
301 | 365 | goto out_free_irq; |
... | ... | @@ -340,6 +404,7 @@ |
340 | 404 | |
341 | 405 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { |
342 | 406 | { .compatible = "fsl,mpc5121-rtc", }, |
407 | + { .compatible = "fsl,mpc5200-rtc", }, | |
343 | 408 | {}, |
344 | 409 | }; |
345 | 410 |