aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-ds3232.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 813c6aa70d3d..adaf06c41479 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -57,6 +57,7 @@ struct ds3232 {
57 * in the remove function. 57 * in the remove function.
58 */ 58 */
59 struct mutex mutex; 59 struct mutex mutex;
60 bool suspended;
60 int exiting; 61 int exiting;
61}; 62};
62 63
@@ -345,7 +346,15 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id)
345 struct ds3232 *ds3232 = i2c_get_clientdata(client); 346 struct ds3232 *ds3232 = i2c_get_clientdata(client);
346 347
347 disable_irq_nosync(irq); 348 disable_irq_nosync(irq);
348 schedule_work(&ds3232->work); 349
350 /*
351 * If rtc as a wakeup source, can't schedule the work
352 * at system resume flow, because at this time the i2c bus
353 * has not been resumed.
354 */
355 if (!ds3232->suspended)
356 schedule_work(&ds3232->work);
357
349 return IRQ_HANDLED; 358 return IRQ_HANDLED;
350} 359}
351 360
@@ -363,22 +372,26 @@ static void ds3232_work(struct work_struct *work)
363 372
364 if (stat & DS3232_REG_SR_A1F) { 373 if (stat & DS3232_REG_SR_A1F) {
365 control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); 374 control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
366 if (control < 0) 375 if (control < 0) {
367 goto out; 376 pr_warn("Read DS3232 Control Register error."
368 /* disable alarm1 interrupt */ 377 "Disable IRQ%d.\n", client->irq);
369 control &= ~(DS3232_REG_CR_A1IE); 378 } else {
370 i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); 379 /* disable alarm1 interrupt */
371 380 control &= ~(DS3232_REG_CR_A1IE);
372 /* clear the alarm pend flag */ 381 i2c_smbus_write_byte_data(client, DS3232_REG_CR,
373 stat &= ~DS3232_REG_SR_A1F; 382 control);
374 i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); 383
375 384 /* clear the alarm pend flag */
376 rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); 385 stat &= ~DS3232_REG_SR_A1F;
386 i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
387
388 rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
389
390 if (!ds3232->exiting)
391 enable_irq(client->irq);
392 }
377 } 393 }
378 394
379out:
380 if (!ds3232->exiting)
381 enable_irq(client->irq);
382unlock: 395unlock:
383 mutex_unlock(&ds3232->mutex); 396 mutex_unlock(&ds3232->mutex);
384} 397}
@@ -411,21 +424,17 @@ static int ds3232_probe(struct i2c_client *client,
411 if (ret) 424 if (ret)
412 return ret; 425 return ret;
413 426
414 ds3232->rtc = devm_rtc_device_register(&client->dev, client->name, 427 if (client->irq > 0) {
415 &ds3232_rtc_ops, THIS_MODULE);
416 if (IS_ERR(ds3232->rtc)) {
417 return PTR_ERR(ds3232->rtc);
418 }
419
420 if (client->irq >= 0) {
421 ret = devm_request_irq(&client->dev, client->irq, ds3232_irq, 428 ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
422 IRQF_SHARED, "ds3232", client); 429 IRQF_SHARED, "ds3232", client);
423 if (ret) { 430 if (ret) {
424 dev_err(&client->dev, "unable to request IRQ\n"); 431 dev_err(&client->dev, "unable to request IRQ\n");
425 } 432 }
433 device_init_wakeup(&client->dev, 1);
426 } 434 }
427 435 ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
428 return 0; 436 &ds3232_rtc_ops, THIS_MODULE);
437 return PTR_ERR_OR_ZERO(ds3232->rtc);
429} 438}
430 439
431static int ds3232_remove(struct i2c_client *client) 440static int ds3232_remove(struct i2c_client *client)
@@ -444,6 +453,42 @@ static int ds3232_remove(struct i2c_client *client)
444 return 0; 453 return 0;
445} 454}
446 455
456#ifdef CONFIG_PM_SLEEP
457static int ds3232_suspend(struct device *dev)
458{
459 struct ds3232 *ds3232 = dev_get_drvdata(dev);
460 struct i2c_client *client = to_i2c_client(dev);
461
462 if (device_can_wakeup(dev)) {
463 ds3232->suspended = true;
464 irq_set_irq_wake(client->irq, 1);
465 }
466
467 return 0;
468}
469
470static int ds3232_resume(struct device *dev)
471{
472 struct ds3232 *ds3232 = dev_get_drvdata(dev);
473 struct i2c_client *client = to_i2c_client(dev);
474
475 if (ds3232->suspended) {
476 ds3232->suspended = false;
477
478 /* Clear the hardware alarm pend flag */
479 schedule_work(&ds3232->work);
480
481 irq_set_irq_wake(client->irq, 0);
482 }
483
484 return 0;
485}
486#endif
487
488static const struct dev_pm_ops ds3232_pm_ops = {
489 SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
490};
491
447static const struct i2c_device_id ds3232_id[] = { 492static const struct i2c_device_id ds3232_id[] = {
448 { "ds3232", 0 }, 493 { "ds3232", 0 },
449 { } 494 { }
@@ -454,6 +499,7 @@ static struct i2c_driver ds3232_driver = {
454 .driver = { 499 .driver = {
455 .name = "rtc-ds3232", 500 .name = "rtc-ds3232",
456 .owner = THIS_MODULE, 501 .owner = THIS_MODULE,
502 .pm = &ds3232_pm_ops,
457 }, 503 },
458 .probe = ds3232_probe, 504 .probe = ds3232_probe,
459 .remove = ds3232_remove, 505 .remove = ds3232_remove,