| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * RTC driver for the Micro Crystal RV8803 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2015 Micro Crystal SA |
|---|
| 5 | | - * |
|---|
| 6 | | - * Alexandre Belloni <alexandre.belloni@free-electrons.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 6 | + * Alexandre Belloni <alexandre.belloni@bootlin.com> |
|---|
| 11 | 7 | * |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| .. | .. |
|---|
| 236 | 232 | u8 date[7]; |
|---|
| 237 | 233 | int ctrl, flags, ret; |
|---|
| 238 | 234 | |
|---|
| 239 | | - if ((tm->tm_year < 100) || (tm->tm_year > 199)) |
|---|
| 240 | | - return -EINVAL; |
|---|
| 241 | | - |
|---|
| 242 | 235 | ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL); |
|---|
| 243 | 236 | if (ctrl < 0) |
|---|
| 244 | 237 | return ctrl; |
|---|
| .. | .. |
|---|
| 418 | 411 | { |
|---|
| 419 | 412 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 420 | 413 | struct rv8803_data *rv8803 = dev_get_drvdata(dev); |
|---|
| 414 | + unsigned int vl = 0; |
|---|
| 421 | 415 | int flags, ret = 0; |
|---|
| 422 | 416 | |
|---|
| 423 | 417 | switch (cmd) { |
|---|
| .. | .. |
|---|
| 426 | 420 | if (flags < 0) |
|---|
| 427 | 421 | return flags; |
|---|
| 428 | 422 | |
|---|
| 429 | | - if (flags & RV8803_FLAG_V1F) |
|---|
| 423 | + if (flags & RV8803_FLAG_V1F) { |
|---|
| 430 | 424 | dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n"); |
|---|
| 425 | + vl = RTC_VL_ACCURACY_LOW; |
|---|
| 426 | + } |
|---|
| 431 | 427 | |
|---|
| 432 | 428 | if (flags & RV8803_FLAG_V2F) |
|---|
| 433 | | - dev_warn(&client->dev, "Voltage low, data loss detected.\n"); |
|---|
| 429 | + vl |= RTC_VL_DATA_INVALID; |
|---|
| 434 | 430 | |
|---|
| 435 | | - flags &= RV8803_FLAG_V1F | RV8803_FLAG_V2F; |
|---|
| 436 | | - |
|---|
| 437 | | - if (copy_to_user((void __user *)arg, &flags, sizeof(int))) |
|---|
| 438 | | - return -EFAULT; |
|---|
| 439 | | - |
|---|
| 440 | | - return 0; |
|---|
| 431 | + return put_user(vl, (unsigned int __user *)arg); |
|---|
| 441 | 432 | |
|---|
| 442 | 433 | case RTC_VL_CLR: |
|---|
| 443 | 434 | mutex_lock(&rv8803->flags_lock); |
|---|
| .. | .. |
|---|
| 447 | 438 | return flags; |
|---|
| 448 | 439 | } |
|---|
| 449 | 440 | |
|---|
| 450 | | - flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); |
|---|
| 441 | + flags &= ~RV8803_FLAG_V1F; |
|---|
| 451 | 442 | ret = rv8803_write_reg(client, RV8803_FLAG, flags); |
|---|
| 452 | 443 | mutex_unlock(&rv8803->flags_lock); |
|---|
| 453 | 444 | if (ret) |
|---|
| .. | .. |
|---|
| 463 | 454 | static int rv8803_nvram_write(void *priv, unsigned int offset, void *val, |
|---|
| 464 | 455 | size_t bytes) |
|---|
| 465 | 456 | { |
|---|
| 466 | | - int ret; |
|---|
| 467 | | - |
|---|
| 468 | | - ret = rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val); |
|---|
| 469 | | - if (ret) |
|---|
| 470 | | - return ret; |
|---|
| 471 | | - |
|---|
| 472 | | - return 0; |
|---|
| 457 | + return rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val); |
|---|
| 473 | 458 | } |
|---|
| 474 | 459 | |
|---|
| 475 | 460 | static int rv8803_nvram_read(void *priv, unsigned int offset, |
|---|
| .. | .. |
|---|
| 524 | 509 | static int rv8803_probe(struct i2c_client *client, |
|---|
| 525 | 510 | const struct i2c_device_id *id) |
|---|
| 526 | 511 | { |
|---|
| 527 | | - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
|---|
| 512 | + struct i2c_adapter *adapter = client->adapter; |
|---|
| 528 | 513 | struct rv8803_data *rv8803; |
|---|
| 529 | 514 | int err, flags; |
|---|
| 530 | 515 | struct nvmem_config nvmem_cfg = { |
|---|
| .. | .. |
|---|
| 571 | 556 | dev_warn(&client->dev, "An alarm maybe have been missed.\n"); |
|---|
| 572 | 557 | |
|---|
| 573 | 558 | rv8803->rtc = devm_rtc_allocate_device(&client->dev); |
|---|
| 574 | | - if (IS_ERR(rv8803->rtc)) { |
|---|
| 559 | + if (IS_ERR(rv8803->rtc)) |
|---|
| 575 | 560 | return PTR_ERR(rv8803->rtc); |
|---|
| 576 | | - } |
|---|
| 577 | 561 | |
|---|
| 578 | 562 | if (client->irq > 0) { |
|---|
| 579 | 563 | err = devm_request_threaded_irq(&client->dev, client->irq, |
|---|
| .. | .. |
|---|
| 602 | 586 | |
|---|
| 603 | 587 | rv8803->rtc->ops = &rv8803_rtc_ops; |
|---|
| 604 | 588 | rv8803->rtc->nvram_old_abi = true; |
|---|
| 589 | + rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; |
|---|
| 590 | + rv8803->rtc->range_max = RTC_TIMESTAMP_END_2099; |
|---|
| 605 | 591 | err = rtc_register_device(rv8803->rtc); |
|---|
| 606 | 592 | if (err) |
|---|
| 607 | 593 | return err; |
|---|
| .. | .. |
|---|
| 615 | 601 | |
|---|
| 616 | 602 | static const struct i2c_device_id rv8803_id[] = { |
|---|
| 617 | 603 | { "rv8803", rv_8803 }, |
|---|
| 604 | + { "rx8803", rv_8803 }, |
|---|
| 618 | 605 | { "rx8900", rx_8900 }, |
|---|
| 619 | 606 | { } |
|---|
| 620 | 607 | }; |
|---|
| .. | .. |
|---|
| 623 | 610 | static const struct of_device_id rv8803_of_match[] = { |
|---|
| 624 | 611 | { |
|---|
| 625 | 612 | .compatible = "microcrystal,rv8803", |
|---|
| 613 | + .data = (void *)rv_8803 |
|---|
| 614 | + }, |
|---|
| 615 | + { |
|---|
| 616 | + .compatible = "epson,rx8803", |
|---|
| 626 | 617 | .data = (void *)rv_8803 |
|---|
| 627 | 618 | }, |
|---|
| 628 | 619 | { |
|---|
| .. | .. |
|---|
| 643 | 634 | }; |
|---|
| 644 | 635 | module_i2c_driver(rv8803_driver); |
|---|
| 645 | 636 | |
|---|
| 646 | | -MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>"); |
|---|
| 637 | +MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>"); |
|---|
| 647 | 638 | MODULE_DESCRIPTION("Micro Crystal RV8803 RTC driver"); |
|---|
| 648 | 639 | MODULE_LICENSE("GPL v2"); |
|---|