diff options
Diffstat (limited to 'drivers/rtc/rtc-ds3232.c')
| -rw-r--r-- | drivers/rtc/rtc-ds3232.c | 81 |
1 files changed, 12 insertions, 69 deletions
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index f0ffd3f5d8f5..9857287215a9 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
| 21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
| 22 | #include <linux/bcd.h> | 22 | #include <linux/bcd.h> |
| 23 | #include <linux/workqueue.h> | ||
| 24 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 25 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
| 26 | 25 | ||
| @@ -52,7 +51,6 @@ struct ds3232 { | |||
| 52 | struct regmap *regmap; | 51 | struct regmap *regmap; |
| 53 | int irq; | 52 | int irq; |
| 54 | struct rtc_device *rtc; | 53 | struct rtc_device *rtc; |
| 55 | struct work_struct work; | ||
| 56 | 54 | ||
| 57 | /* The mutex protects alarm operations, and prevents a race | 55 | /* The mutex protects alarm operations, and prevents a race |
| 58 | * between the enable_irq() in the workqueue and the free_irq() | 56 | * between the enable_irq() in the workqueue and the free_irq() |
| @@ -60,7 +58,6 @@ struct ds3232 { | |||
| 60 | */ | 58 | */ |
| 61 | struct mutex mutex; | 59 | struct mutex mutex; |
| 62 | bool suspended; | 60 | bool suspended; |
| 63 | int exiting; | ||
| 64 | }; | 61 | }; |
| 65 | 62 | ||
| 66 | static int ds3232_check_rtc_status(struct device *dev) | 63 | static int ds3232_check_rtc_status(struct device *dev) |
| @@ -314,23 +311,6 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id) | |||
| 314 | { | 311 | { |
| 315 | struct device *dev = dev_id; | 312 | struct device *dev = dev_id; |
| 316 | struct ds3232 *ds3232 = dev_get_drvdata(dev); | 313 | struct ds3232 *ds3232 = dev_get_drvdata(dev); |
| 317 | |||
| 318 | disable_irq_nosync(irq); | ||
| 319 | |||
| 320 | /* | ||
| 321 | * If rtc as a wakeup source, can't schedule the work | ||
| 322 | * at system resume flow, because at this time the i2c bus | ||
| 323 | * has not been resumed. | ||
| 324 | */ | ||
| 325 | if (!ds3232->suspended) | ||
| 326 | schedule_work(&ds3232->work); | ||
| 327 | |||
| 328 | return IRQ_HANDLED; | ||
| 329 | } | ||
| 330 | |||
| 331 | static void ds3232_work(struct work_struct *work) | ||
| 332 | { | ||
| 333 | struct ds3232 *ds3232 = container_of(work, struct ds3232, work); | ||
| 334 | int ret; | 314 | int ret; |
| 335 | int stat, control; | 315 | int stat, control; |
| 336 | 316 | ||
| @@ -343,8 +323,8 @@ static void ds3232_work(struct work_struct *work) | |||
| 343 | if (stat & DS3232_REG_SR_A1F) { | 323 | if (stat & DS3232_REG_SR_A1F) { |
| 344 | ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control); | 324 | ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control); |
| 345 | if (ret) { | 325 | if (ret) { |
| 346 | pr_warn("Read Control Register error - Disable IRQ%d\n", | 326 | dev_warn(ds3232->dev, |
| 347 | ds3232->irq); | 327 | "Read Control Register error %d\n", ret); |
| 348 | } else { | 328 | } else { |
| 349 | /* disable alarm1 interrupt */ | 329 | /* disable alarm1 interrupt */ |
| 350 | control &= ~(DS3232_REG_CR_A1IE); | 330 | control &= ~(DS3232_REG_CR_A1IE); |
| @@ -368,14 +348,13 @@ static void ds3232_work(struct work_struct *work) | |||
| 368 | } | 348 | } |
| 369 | 349 | ||
| 370 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); | 350 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); |
| 371 | |||
| 372 | if (!ds3232->exiting) | ||
| 373 | enable_irq(ds3232->irq); | ||
| 374 | } | 351 | } |
| 375 | } | 352 | } |
| 376 | 353 | ||
| 377 | unlock: | 354 | unlock: |
| 378 | mutex_unlock(&ds3232->mutex); | 355 | mutex_unlock(&ds3232->mutex); |
| 356 | |||
| 357 | return IRQ_HANDLED; | ||
| 379 | } | 358 | } |
| 380 | 359 | ||
| 381 | static const struct rtc_class_ops ds3232_rtc_ops = { | 360 | static const struct rtc_class_ops ds3232_rtc_ops = { |
| @@ -401,7 +380,6 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, | |||
| 401 | ds3232->dev = dev; | 380 | ds3232->dev = dev; |
| 402 | dev_set_drvdata(dev, ds3232); | 381 | dev_set_drvdata(dev, ds3232); |
| 403 | 382 | ||
| 404 | INIT_WORK(&ds3232->work, ds3232_work); | ||
| 405 | mutex_init(&ds3232->mutex); | 383 | mutex_init(&ds3232->mutex); |
| 406 | 384 | ||
| 407 | ret = ds3232_check_rtc_status(dev); | 385 | ret = ds3232_check_rtc_status(dev); |
| @@ -409,8 +387,10 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, | |||
| 409 | return ret; | 387 | return ret; |
| 410 | 388 | ||
| 411 | if (ds3232->irq > 0) { | 389 | if (ds3232->irq > 0) { |
| 412 | ret = devm_request_irq(dev, ds3232->irq, ds3232_irq, | 390 | ret = devm_request_threaded_irq(dev, ds3232->irq, NULL, |
| 413 | IRQF_SHARED, name, dev); | 391 | ds3232_irq, |
| 392 | IRQF_SHARED | IRQF_ONESHOT, | ||
| 393 | name, dev); | ||
| 414 | if (ret) { | 394 | if (ret) { |
| 415 | ds3232->irq = 0; | 395 | ds3232->irq = 0; |
| 416 | dev_err(dev, "unable to request IRQ\n"); | 396 | dev_err(dev, "unable to request IRQ\n"); |
| @@ -423,33 +403,14 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, | |||
| 423 | return PTR_ERR_OR_ZERO(ds3232->rtc); | 403 | return PTR_ERR_OR_ZERO(ds3232->rtc); |
| 424 | } | 404 | } |
| 425 | 405 | ||
| 426 | static int ds3232_remove(struct device *dev) | ||
| 427 | { | ||
| 428 | struct ds3232 *ds3232 = dev_get_drvdata(dev); | ||
| 429 | |||
| 430 | if (ds3232->irq > 0) { | ||
| 431 | mutex_lock(&ds3232->mutex); | ||
| 432 | ds3232->exiting = 1; | ||
| 433 | mutex_unlock(&ds3232->mutex); | ||
| 434 | |||
| 435 | devm_free_irq(dev, ds3232->irq, dev); | ||
| 436 | cancel_work_sync(&ds3232->work); | ||
| 437 | } | ||
| 438 | |||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | #ifdef CONFIG_PM_SLEEP | 406 | #ifdef CONFIG_PM_SLEEP |
| 443 | static int ds3232_suspend(struct device *dev) | 407 | static int ds3232_suspend(struct device *dev) |
| 444 | { | 408 | { |
| 445 | struct ds3232 *ds3232 = dev_get_drvdata(dev); | 409 | struct ds3232 *ds3232 = dev_get_drvdata(dev); |
| 446 | 410 | ||
| 447 | if (device_can_wakeup(dev)) { | 411 | if (device_may_wakeup(dev)) { |
| 448 | ds3232->suspended = true; | 412 | if (enable_irq_wake(ds3232->irq)) |
| 449 | if (irq_set_irq_wake(ds3232->irq, 1)) { | ||
| 450 | dev_warn_once(dev, "Cannot set wakeup source\n"); | 413 | dev_warn_once(dev, "Cannot set wakeup source\n"); |
| 451 | ds3232->suspended = false; | ||
| 452 | } | ||
| 453 | } | 414 | } |
| 454 | 415 | ||
| 455 | return 0; | 416 | return 0; |
| @@ -459,14 +420,8 @@ static int ds3232_resume(struct device *dev) | |||
| 459 | { | 420 | { |
| 460 | struct ds3232 *ds3232 = dev_get_drvdata(dev); | 421 | struct ds3232 *ds3232 = dev_get_drvdata(dev); |
| 461 | 422 | ||
| 462 | if (ds3232->suspended) { | 423 | if (device_may_wakeup(dev)) |
| 463 | ds3232->suspended = false; | 424 | disable_irq_wake(ds3232->irq); |
| 464 | |||
| 465 | /* Clear the hardware alarm pend flag */ | ||
| 466 | schedule_work(&ds3232->work); | ||
| 467 | |||
| 468 | irq_set_irq_wake(ds3232->irq, 0); | ||
| 469 | } | ||
| 470 | 425 | ||
| 471 | return 0; | 426 | return 0; |
| 472 | } | 427 | } |
| @@ -497,11 +452,6 @@ static int ds3232_i2c_probe(struct i2c_client *client, | |||
| 497 | return ds3232_probe(&client->dev, regmap, client->irq, client->name); | 452 | return ds3232_probe(&client->dev, regmap, client->irq, client->name); |
| 498 | } | 453 | } |
| 499 | 454 | ||
| 500 | static int ds3232_i2c_remove(struct i2c_client *client) | ||
| 501 | { | ||
| 502 | return ds3232_remove(&client->dev); | ||
| 503 | } | ||
| 504 | |||
| 505 | static const struct i2c_device_id ds3232_id[] = { | 455 | static const struct i2c_device_id ds3232_id[] = { |
| 506 | { "ds3232", 0 }, | 456 | { "ds3232", 0 }, |
| 507 | { } | 457 | { } |
| @@ -514,7 +464,6 @@ static struct i2c_driver ds3232_driver = { | |||
| 514 | .pm = &ds3232_pm_ops, | 464 | .pm = &ds3232_pm_ops, |
| 515 | }, | 465 | }, |
| 516 | .probe = ds3232_i2c_probe, | 466 | .probe = ds3232_i2c_probe, |
| 517 | .remove = ds3232_i2c_remove, | ||
| 518 | .id_table = ds3232_id, | 467 | .id_table = ds3232_id, |
| 519 | }; | 468 | }; |
| 520 | 469 | ||
| @@ -611,17 +560,11 @@ static int ds3234_probe(struct spi_device *spi) | |||
| 611 | return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234"); | 560 | return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234"); |
| 612 | } | 561 | } |
| 613 | 562 | ||
| 614 | static int ds3234_remove(struct spi_device *spi) | ||
| 615 | { | ||
| 616 | return ds3232_remove(&spi->dev); | ||
| 617 | } | ||
| 618 | |||
| 619 | static struct spi_driver ds3234_driver = { | 563 | static struct spi_driver ds3234_driver = { |
| 620 | .driver = { | 564 | .driver = { |
| 621 | .name = "ds3234", | 565 | .name = "ds3234", |
| 622 | }, | 566 | }, |
| 623 | .probe = ds3234_probe, | 567 | .probe = ds3234_probe, |
| 624 | .remove = ds3234_remove, | ||
| 625 | }; | 568 | }; |
| 626 | 569 | ||
| 627 | static int ds3234_register_driver(void) | 570 | static int ds3234_register_driver(void) |
