diff options
author | Viresh Kumar <viresh.kumar@st.com> | 2012-03-23 18:02:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 19:58:39 -0400 |
commit | ee6c54ca64416c75aa6f5021e139f270192bae49 (patch) | |
tree | 32c16e2747c4414bdb52939909e071fa07ba7fae /drivers/rtc | |
parent | 131f8b75f1c00a5a822ff2103db588466e942490 (diff) |
rtc/rtc-spear: call platform_set_drvdata() before registering rtc device
rtc_device_register() calls rtc-spear routines internally. These
routines call dev_get_drvdata() to get struct spear_rtc_config.
Currently, platform_set_drvdata is called after rtc device is
registered. This causes system to crash, as dev_get_drvdata returns
NULL.
For this we need to call platform_set_drvdata() before registering rtc
device. This requires further cleanup, that leads to removal of
dev_set_drvdata on rtc->dev, which was just not required at all.
Also, we change the parameter to request_irq and pass pointer to config
instead of pointer to rtc struct.
This patch brings all above changes.
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Cc: Shiraz Hashim <shiraz.hashim@st.com>
Cc: Deepak Sikri <deepak.sikri@st.com>
Acked-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-spear.c | 61 |
1 files changed, 21 insertions, 40 deletions
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 646937473515..e38da0dc4187 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE) | 77 | #define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE) |
78 | 78 | ||
79 | struct spear_rtc_config { | 79 | struct spear_rtc_config { |
80 | struct rtc_device *rtc; | ||
80 | struct clk *clk; | 81 | struct clk *clk; |
81 | spinlock_t lock; | 82 | spinlock_t lock; |
82 | void __iomem *ioaddr; | 83 | void __iomem *ioaddr; |
@@ -150,8 +151,7 @@ static void rtc_wait_not_busy(struct spear_rtc_config *config) | |||
150 | 151 | ||
151 | static irqreturn_t spear_rtc_irq(int irq, void *dev_id) | 152 | static irqreturn_t spear_rtc_irq(int irq, void *dev_id) |
152 | { | 153 | { |
153 | struct rtc_device *rtc = (struct rtc_device *)dev_id; | 154 | struct spear_rtc_config *config = dev_id; |
154 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
155 | unsigned long flags, events = 0; | 155 | unsigned long flags, events = 0; |
156 | unsigned int irq_data; | 156 | unsigned int irq_data; |
157 | 157 | ||
@@ -162,7 +162,7 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id) | |||
162 | if ((irq_data & RTC_INT_MASK)) { | 162 | if ((irq_data & RTC_INT_MASK)) { |
163 | spear_rtc_clear_interrupt(config); | 163 | spear_rtc_clear_interrupt(config); |
164 | events = RTC_IRQF | RTC_AF; | 164 | events = RTC_IRQF | RTC_AF; |
165 | rtc_update_irq(rtc, 1, events); | 165 | rtc_update_irq(config->rtc, 1, events); |
166 | return IRQ_HANDLED; | 166 | return IRQ_HANDLED; |
167 | } else | 167 | } else |
168 | return IRQ_NONE; | 168 | return IRQ_NONE; |
@@ -204,9 +204,7 @@ static void bcd2tm(struct rtc_time *tm) | |||
204 | */ | 204 | */ |
205 | static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) | 205 | static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) |
206 | { | 206 | { |
207 | struct platform_device *pdev = to_platform_device(dev); | 207 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
208 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
209 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
210 | unsigned int time, date; | 208 | unsigned int time, date; |
211 | 209 | ||
212 | /* we don't report wday/yday/isdst ... */ | 210 | /* we don't report wday/yday/isdst ... */ |
@@ -235,9 +233,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
235 | */ | 233 | */ |
236 | static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) | 234 | static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) |
237 | { | 235 | { |
238 | struct platform_device *pdev = to_platform_device(dev); | 236 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
239 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
240 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
241 | unsigned int time, date, err = 0; | 237 | unsigned int time, date, err = 0; |
242 | 238 | ||
243 | if (tm2bcd(tm) < 0) | 239 | if (tm2bcd(tm) < 0) |
@@ -267,9 +263,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
267 | */ | 263 | */ |
268 | static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | 264 | static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) |
269 | { | 265 | { |
270 | struct platform_device *pdev = to_platform_device(dev); | 266 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
271 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
272 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
273 | unsigned int time, date; | 267 | unsigned int time, date; |
274 | 268 | ||
275 | rtc_wait_not_busy(config); | 269 | rtc_wait_not_busy(config); |
@@ -299,9 +293,7 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
299 | */ | 293 | */ |
300 | static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 294 | static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
301 | { | 295 | { |
302 | struct platform_device *pdev = to_platform_device(dev); | 296 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
303 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
304 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
305 | unsigned int time, date, err = 0; | 297 | unsigned int time, date, err = 0; |
306 | 298 | ||
307 | if (tm2bcd(&alm->time) < 0) | 299 | if (tm2bcd(&alm->time) < 0) |
@@ -330,9 +322,7 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
330 | 322 | ||
331 | static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled) | 323 | static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled) |
332 | { | 324 | { |
333 | struct platform_device *pdev = to_platform_device(dev); | 325 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
334 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
335 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
336 | int ret = 0; | 326 | int ret = 0; |
337 | 327 | ||
338 | spear_rtc_clear_interrupt(config); | 328 | spear_rtc_clear_interrupt(config); |
@@ -365,7 +355,6 @@ static struct rtc_class_ops spear_rtc_ops = { | |||
365 | static int __devinit spear_rtc_probe(struct platform_device *pdev) | 355 | static int __devinit spear_rtc_probe(struct platform_device *pdev) |
366 | { | 356 | { |
367 | struct resource *res; | 357 | struct resource *res; |
368 | struct rtc_device *rtc; | ||
369 | struct spear_rtc_config *config; | 358 | struct spear_rtc_config *config; |
370 | unsigned int status = 0; | 359 | unsigned int status = 0; |
371 | int irq; | 360 | int irq; |
@@ -405,19 +394,17 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
405 | } | 394 | } |
406 | 395 | ||
407 | spin_lock_init(&config->lock); | 396 | spin_lock_init(&config->lock); |
397 | platform_set_drvdata(pdev, config); | ||
408 | 398 | ||
409 | rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops, | 399 | config->rtc = rtc_device_register(pdev->name, &pdev->dev, |
410 | THIS_MODULE); | 400 | &spear_rtc_ops, THIS_MODULE); |
411 | if (IS_ERR(rtc)) { | 401 | if (IS_ERR(config->rtc)) { |
412 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 402 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
413 | PTR_ERR(rtc)); | 403 | PTR_ERR(config->rtc)); |
414 | status = PTR_ERR(rtc); | 404 | status = PTR_ERR(config->rtc); |
415 | goto err_iounmap; | 405 | goto err_iounmap; |
416 | } | 406 | } |
417 | 407 | ||
418 | platform_set_drvdata(pdev, rtc); | ||
419 | dev_set_drvdata(&rtc->dev, config); | ||
420 | |||
421 | /* alarm irqs */ | 408 | /* alarm irqs */ |
422 | irq = platform_get_irq(pdev, 0); | 409 | irq = platform_get_irq(pdev, 0); |
423 | if (irq < 0) { | 410 | if (irq < 0) { |
@@ -426,7 +413,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
426 | goto err_clear_platdata; | 413 | goto err_clear_platdata; |
427 | } | 414 | } |
428 | 415 | ||
429 | status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc); | 416 | status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config); |
430 | if (status) { | 417 | if (status) { |
431 | dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ | 418 | dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ |
432 | claimed\n", irq); | 419 | claimed\n", irq); |
@@ -440,8 +427,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
440 | 427 | ||
441 | err_clear_platdata: | 428 | err_clear_platdata: |
442 | platform_set_drvdata(pdev, NULL); | 429 | platform_set_drvdata(pdev, NULL); |
443 | dev_set_drvdata(&rtc->dev, NULL); | 430 | rtc_device_unregister(config->rtc); |
444 | rtc_device_unregister(rtc); | ||
445 | err_iounmap: | 431 | err_iounmap: |
446 | iounmap(config->ioaddr); | 432 | iounmap(config->ioaddr); |
447 | err_disable_clock: | 433 | err_disable_clock: |
@@ -458,8 +444,7 @@ err_release_region: | |||
458 | 444 | ||
459 | static int __devexit spear_rtc_remove(struct platform_device *pdev) | 445 | static int __devexit spear_rtc_remove(struct platform_device *pdev) |
460 | { | 446 | { |
461 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 447 | struct spear_rtc_config *config = platform_get_drvdata(pdev); |
462 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
463 | int irq; | 448 | int irq; |
464 | struct resource *res; | 449 | struct resource *res; |
465 | 450 | ||
@@ -477,8 +462,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) | |||
477 | if (res) | 462 | if (res) |
478 | release_mem_region(res->start, resource_size(res)); | 463 | release_mem_region(res->start, resource_size(res)); |
479 | platform_set_drvdata(pdev, NULL); | 464 | platform_set_drvdata(pdev, NULL); |
480 | dev_set_drvdata(&rtc->dev, NULL); | 465 | rtc_device_unregister(config->rtc); |
481 | rtc_device_unregister(rtc); | ||
482 | 466 | ||
483 | return 0; | 467 | return 0; |
484 | } | 468 | } |
@@ -487,8 +471,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) | |||
487 | 471 | ||
488 | static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 472 | static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
489 | { | 473 | { |
490 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 474 | struct spear_rtc_config *config = platform_get_drvdata(pdev); |
491 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
492 | int irq; | 475 | int irq; |
493 | 476 | ||
494 | irq = platform_get_irq(pdev, 0); | 477 | irq = platform_get_irq(pdev, 0); |
@@ -505,8 +488,7 @@ static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
505 | 488 | ||
506 | static int spear_rtc_resume(struct platform_device *pdev) | 489 | static int spear_rtc_resume(struct platform_device *pdev) |
507 | { | 490 | { |
508 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 491 | struct spear_rtc_config *config = platform_get_drvdata(pdev); |
509 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
510 | int irq; | 492 | int irq; |
511 | 493 | ||
512 | irq = platform_get_irq(pdev, 0); | 494 | irq = platform_get_irq(pdev, 0); |
@@ -531,8 +513,7 @@ static int spear_rtc_resume(struct platform_device *pdev) | |||
531 | 513 | ||
532 | static void spear_rtc_shutdown(struct platform_device *pdev) | 514 | static void spear_rtc_shutdown(struct platform_device *pdev) |
533 | { | 515 | { |
534 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 516 | struct spear_rtc_config *config = platform_get_drvdata(pdev); |
535 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
536 | 517 | ||
537 | spear_rtc_disable_interrupt(config); | 518 | spear_rtc_disable_interrupt(config); |
538 | clk_disable(config->clk); | 519 | clk_disable(config->clk); |