Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: ds1307: Add support for Epson RX8130CE

Add support for yet another RTC chip, Epson RX8130CE. This time around,
the chip has slightly permutated registers and also the register starts
at 0x10 instead of 0x0 .

So far, we only support the RTC and NVRAM parts of the chip, Alarm and
Timer is not supported.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

authored by

Marek Vasut and committed by
Alexandre Belloni
ee0981be 498bcf31

+175
+175
drivers/rtc/rtc-ds1307.c
··· 44 44 m41t00, 45 45 mcp794xx, 46 46 rx_8025, 47 + rx_8130, 47 48 last_ds_type /* always last */ 48 49 /* rs5c372 too? different address... */ 49 50 }; ··· 170 169 [ds_3231] = { 171 170 .alarm = 1, 172 171 }, 172 + [rx_8130] = { 173 + .alarm = 1, 174 + /* this is battery backed SRAM */ 175 + .nvram_offset = 0x20, 176 + .nvram_size = 4, /* 32bit (4 word x 8 bit) */ 177 + }, 173 178 [mcp794xx] = { 174 179 .alarm = 1, 175 180 /* this is battery backed SRAM */ ··· 199 192 { "pt7c4338", ds_1307 }, 200 193 { "rx8025", rx_8025 }, 201 194 { "isl12057", ds_1337 }, 195 + { "rx8130", rx_8130 }, 202 196 { } 203 197 }; 204 198 MODULE_DEVICE_TABLE(i2c, ds1307_id); ··· 590 582 .read_alarm = ds1337_read_alarm, 591 583 .set_alarm = ds1337_set_alarm, 592 584 .alarm_irq_enable = ds1307_alarm_irq_enable, 585 + }; 586 + 587 + /*----------------------------------------------------------------------*/ 588 + 589 + /* 590 + * Alarm support for rx8130 devices. 591 + */ 592 + 593 + #define RX8130_REG_ALARM_MIN 0x07 594 + #define RX8130_REG_ALARM_HOUR 0x08 595 + #define RX8130_REG_ALARM_WEEK_OR_DAY 0x09 596 + #define RX8130_REG_EXTENSION 0x0c 597 + #define RX8130_REG_EXTENSION_WADA (1 << 3) 598 + #define RX8130_REG_FLAG 0x0d 599 + #define RX8130_REG_FLAG_AF (1 << 3) 600 + #define RX8130_REG_CONTROL0 0x0e 601 + #define RX8130_REG_CONTROL0_AIE (1 << 3) 602 + 603 + static irqreturn_t rx8130_irq(int irq, void *dev_id) 604 + { 605 + struct ds1307 *ds1307 = dev_id; 606 + struct mutex *lock = &ds1307->rtc->ops_lock; 607 + u8 ctl[3]; 608 + int ret; 609 + 610 + mutex_lock(lock); 611 + 612 + /* Read control registers. */ 613 + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 614 + if (ret < 0) 615 + goto out; 616 + if (!(ctl[1] & RX8130_REG_FLAG_AF)) 617 + goto out; 618 + ctl[1] &= ~RX8130_REG_FLAG_AF; 619 + ctl[2] &= ~RX8130_REG_CONTROL0_AIE; 620 + 621 + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 622 + if (ret < 0) 623 + goto out; 624 + 625 + rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); 626 + 627 + out: 628 + mutex_unlock(lock); 629 + 630 + return IRQ_HANDLED; 631 + } 632 + 633 + static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) 634 + { 635 + struct ds1307 *ds1307 = dev_get_drvdata(dev); 636 + u8 ald[3], ctl[3]; 637 + int ret; 638 + 639 + if (!test_bit(HAS_ALARM, &ds1307->flags)) 640 + return -EINVAL; 641 + 642 + /* Read alarm registers. */ 643 + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); 644 + if (ret < 0) 645 + return ret; 646 + 647 + /* Read control registers. */ 648 + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 649 + if (ret < 0) 650 + return ret; 651 + 652 + t->enabled = !!(ctl[2] & RX8130_REG_CONTROL0_AIE); 653 + t->pending = !!(ctl[1] & RX8130_REG_FLAG_AF); 654 + 655 + /* Report alarm 0 time assuming 24-hour and day-of-month modes. */ 656 + t->time.tm_sec = -1; 657 + t->time.tm_min = bcd2bin(ald[0] & 0x7f); 658 + t->time.tm_hour = bcd2bin(ald[1] & 0x7f); 659 + t->time.tm_wday = -1; 660 + t->time.tm_mday = bcd2bin(ald[2] & 0x7f); 661 + t->time.tm_mon = -1; 662 + t->time.tm_year = -1; 663 + t->time.tm_yday = -1; 664 + t->time.tm_isdst = -1; 665 + 666 + dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d enabled=%d\n", 667 + __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, 668 + t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled); 669 + 670 + return 0; 671 + } 672 + 673 + static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) 674 + { 675 + struct ds1307 *ds1307 = dev_get_drvdata(dev); 676 + u8 ald[3], ctl[3]; 677 + int ret; 678 + 679 + if (!test_bit(HAS_ALARM, &ds1307->flags)) 680 + return -EINVAL; 681 + 682 + dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " 683 + "enabled=%d pending=%d\n", __func__, 684 + t->time.tm_sec, t->time.tm_min, t->time.tm_hour, 685 + t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, 686 + t->enabled, t->pending); 687 + 688 + /* Read control registers. */ 689 + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 690 + if (ret < 0) 691 + return ret; 692 + 693 + ctl[0] &= ~RX8130_REG_EXTENSION_WADA; 694 + ctl[1] |= RX8130_REG_FLAG_AF; 695 + ctl[2] &= ~RX8130_REG_CONTROL0_AIE; 696 + 697 + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 698 + if (ret < 0) 699 + return ret; 700 + 701 + /* Hardware alarm precision is 1 minute! */ 702 + ald[0] = bin2bcd(t->time.tm_min); 703 + ald[1] = bin2bcd(t->time.tm_hour); 704 + ald[2] = bin2bcd(t->time.tm_mday); 705 + 706 + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); 707 + if (ret < 0) 708 + return ret; 709 + 710 + if (!t->enabled) 711 + return 0; 712 + 713 + ctl[2] |= RX8130_REG_CONTROL0_AIE; 714 + 715 + return regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); 716 + } 717 + 718 + static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) 719 + { 720 + struct ds1307 *ds1307 = dev_get_drvdata(dev); 721 + int ret, reg; 722 + 723 + if (!test_bit(HAS_ALARM, &ds1307->flags)) 724 + return -EINVAL; 725 + 726 + ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, &reg); 727 + if (ret < 0) 728 + return ret; 729 + 730 + if (enabled) 731 + reg |= RX8130_REG_CONTROL0_AIE; 732 + else 733 + reg &= ~RX8130_REG_CONTROL0_AIE; 734 + 735 + return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg); 736 + } 737 + 738 + static const struct rtc_class_ops rx8130_rtc_ops = { 739 + .read_time = ds1307_get_time, 740 + .set_time = ds1307_set_time, 741 + .read_alarm = rx8130_read_alarm, 742 + .set_alarm = rx8130_set_alarm, 743 + .alarm_irq_enable = rx8130_alarm_irq_enable, 593 744 }; 594 745 595 746 /*----------------------------------------------------------------------*/ ··· 1567 1400 1568 1401 regmap_write(ds1307->regmap, 1569 1402 DS1307_REG_HOUR << 4 | 0x08, hour); 1403 + } 1404 + break; 1405 + case rx_8130: 1406 + ds1307->offset = 0x10; /* Seconds starts at 0x10 */ 1407 + rtc_ops = &rx8130_rtc_ops; 1408 + if (chip->alarm && ds1307->irq > 0) { 1409 + irq_handler = rx8130_irq; 1410 + want_irq = true; 1570 1411 } 1571 1412 break; 1572 1413 case ds_1388: