1182ae2bbSAlexandre Belloni // SPDX-License-Identifier: GPL-2.0 21e3929efSAlexandre Belloni /* 31e3929efSAlexandre Belloni * RTC driver for the Micro Crystal RV8803 41e3929efSAlexandre Belloni * 51e3929efSAlexandre Belloni * Copyright (C) 2015 Micro Crystal SA 67d1e5bfeSAlexandre Belloni * Alexandre Belloni <alexandre.belloni@bootlin.com> 71e3929efSAlexandre Belloni * 81e3929efSAlexandre Belloni */ 91e3929efSAlexandre Belloni 101e3929efSAlexandre Belloni #include <linux/bcd.h> 111e3929efSAlexandre Belloni #include <linux/bitops.h> 12c27fee16SAhmad Fatoum #include <linux/bitfield.h> 13a1e98e09SBenoît Thébaudeau #include <linux/log2.h> 141e3929efSAlexandre Belloni #include <linux/i2c.h> 151e3929efSAlexandre Belloni #include <linux/interrupt.h> 161e3929efSAlexandre Belloni #include <linux/kernel.h> 171e3929efSAlexandre Belloni #include <linux/module.h> 18740ad8f4SJavier Martinez Canillas #include <linux/of_device.h> 191e3929efSAlexandre Belloni #include <linux/rtc.h> 201e3929efSAlexandre Belloni 21d522649eSBenoît Thébaudeau #define RV8803_I2C_TRY_COUNT 4 22d522649eSBenoît Thébaudeau 231e3929efSAlexandre Belloni #define RV8803_SEC 0x00 241e3929efSAlexandre Belloni #define RV8803_MIN 0x01 251e3929efSAlexandre Belloni #define RV8803_HOUR 0x02 261e3929efSAlexandre Belloni #define RV8803_WEEK 0x03 271e3929efSAlexandre Belloni #define RV8803_DAY 0x04 281e3929efSAlexandre Belloni #define RV8803_MONTH 0x05 291e3929efSAlexandre Belloni #define RV8803_YEAR 0x06 301e3929efSAlexandre Belloni #define RV8803_RAM 0x07 311e3929efSAlexandre Belloni #define RV8803_ALARM_MIN 0x08 321e3929efSAlexandre Belloni #define RV8803_ALARM_HOUR 0x09 331e3929efSAlexandre Belloni #define RV8803_ALARM_WEEK_OR_DAY 0x0A 341e3929efSAlexandre Belloni #define RV8803_EXT 0x0D 351e3929efSAlexandre Belloni #define RV8803_FLAG 0x0E 361e3929efSAlexandre Belloni #define RV8803_CTRL 0x0F 37c27fee16SAhmad Fatoum #define RV8803_OSC_OFFSET 0x2C 381e3929efSAlexandre Belloni 391e3929efSAlexandre Belloni #define RV8803_EXT_WADA BIT(6) 401e3929efSAlexandre Belloni 411e3929efSAlexandre Belloni #define RV8803_FLAG_V1F BIT(0) 421e3929efSAlexandre Belloni #define RV8803_FLAG_V2F BIT(1) 431e3929efSAlexandre Belloni #define RV8803_FLAG_AF BIT(3) 441e3929efSAlexandre Belloni #define RV8803_FLAG_TF BIT(4) 451e3929efSAlexandre Belloni #define RV8803_FLAG_UF BIT(5) 461e3929efSAlexandre Belloni 471e3929efSAlexandre Belloni #define RV8803_CTRL_RESET BIT(0) 481e3929efSAlexandre Belloni 491e3929efSAlexandre Belloni #define RV8803_CTRL_EIE BIT(2) 501e3929efSAlexandre Belloni #define RV8803_CTRL_AIE BIT(3) 511e3929efSAlexandre Belloni #define RV8803_CTRL_TIE BIT(4) 521e3929efSAlexandre Belloni #define RV8803_CTRL_UIE BIT(5) 531e3929efSAlexandre Belloni 54c27fee16SAhmad Fatoum #define RX8803_CTRL_CSEL GENMASK(7, 6) 55c27fee16SAhmad Fatoum 561cd71376SOleksij Rempel #define RX8900_BACKUP_CTRL 0x18 571cd71376SOleksij Rempel #define RX8900_FLAG_SWOFF BIT(2) 581cd71376SOleksij Rempel #define RX8900_FLAG_VDETOFF BIT(3) 591cd71376SOleksij Rempel 601cd71376SOleksij Rempel enum rv8803_type { 611cd71376SOleksij Rempel rv_8803, 62c27fee16SAhmad Fatoum rx_8803, 635c0189a8SFabio Estevam rx_8804, 641cd71376SOleksij Rempel rx_8900 651cd71376SOleksij Rempel }; 661cd71376SOleksij Rempel 671e3929efSAlexandre Belloni struct rv8803_data { 681e3929efSAlexandre Belloni struct i2c_client *client; 691e3929efSAlexandre Belloni struct rtc_device *rtc; 709d1fa4c3SOleksij Rempel struct mutex flags_lock; 711e3929efSAlexandre Belloni u8 ctrl; 728c798e1eSAhmad Fatoum u8 backup; 73e5c59423SSascha Hauer u8 alarm_invalid:1; 741cd71376SOleksij Rempel enum rv8803_type type; 751e3929efSAlexandre Belloni }; 761e3929efSAlexandre Belloni 77d522649eSBenoît Thébaudeau static int rv8803_read_reg(const struct i2c_client *client, u8 reg) 78d522649eSBenoît Thébaudeau { 79d522649eSBenoît Thébaudeau int try = RV8803_I2C_TRY_COUNT; 80d522649eSBenoît Thébaudeau s32 ret; 81d522649eSBenoît Thébaudeau 82d522649eSBenoît Thébaudeau /* 83d522649eSBenoît Thébaudeau * There is a 61µs window during which the RTC does not acknowledge I2C 84d522649eSBenoît Thébaudeau * transfers. In that case, ensure that there are multiple attempts. 85d522649eSBenoît Thébaudeau */ 86d522649eSBenoît Thébaudeau do 87d522649eSBenoît Thébaudeau ret = i2c_smbus_read_byte_data(client, reg); 88d522649eSBenoît Thébaudeau while ((ret == -ENXIO || ret == -EIO) && --try); 89d522649eSBenoît Thébaudeau if (ret < 0) 90d522649eSBenoît Thébaudeau dev_err(&client->dev, "Unable to read register 0x%02x\n", reg); 91d522649eSBenoît Thébaudeau 92d522649eSBenoît Thébaudeau return ret; 93d522649eSBenoît Thébaudeau } 94d522649eSBenoît Thébaudeau 95d522649eSBenoît Thébaudeau static int rv8803_read_regs(const struct i2c_client *client, 96d522649eSBenoît Thébaudeau u8 reg, u8 count, u8 *values) 97d522649eSBenoît Thébaudeau { 98d522649eSBenoît Thébaudeau int try = RV8803_I2C_TRY_COUNT; 99d522649eSBenoît Thébaudeau s32 ret; 100d522649eSBenoît Thébaudeau 101d522649eSBenoît Thébaudeau do 102d522649eSBenoît Thébaudeau ret = i2c_smbus_read_i2c_block_data(client, reg, count, values); 103d522649eSBenoît Thébaudeau while ((ret == -ENXIO || ret == -EIO) && --try); 104d522649eSBenoît Thébaudeau if (ret != count) { 105d522649eSBenoît Thébaudeau dev_err(&client->dev, 106d522649eSBenoît Thébaudeau "Unable to read registers 0x%02x..0x%02x\n", 107d522649eSBenoît Thébaudeau reg, reg + count - 1); 108d522649eSBenoît Thébaudeau return ret < 0 ? ret : -EIO; 109d522649eSBenoît Thébaudeau } 110d522649eSBenoît Thébaudeau 111d522649eSBenoît Thébaudeau return 0; 112d522649eSBenoît Thébaudeau } 113d522649eSBenoît Thébaudeau 114d522649eSBenoît Thébaudeau static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value) 115d522649eSBenoît Thébaudeau { 116d522649eSBenoît Thébaudeau int try = RV8803_I2C_TRY_COUNT; 117d522649eSBenoît Thébaudeau s32 ret; 118d522649eSBenoît Thébaudeau 119d522649eSBenoît Thébaudeau do 120d522649eSBenoît Thébaudeau ret = i2c_smbus_write_byte_data(client, reg, value); 121d522649eSBenoît Thébaudeau while ((ret == -ENXIO || ret == -EIO) && --try); 122d522649eSBenoît Thébaudeau if (ret) 123d522649eSBenoît Thébaudeau dev_err(&client->dev, "Unable to write register 0x%02x\n", reg); 124d522649eSBenoît Thébaudeau 125d522649eSBenoît Thébaudeau return ret; 126d522649eSBenoît Thébaudeau } 127d522649eSBenoît Thébaudeau 128d522649eSBenoît Thébaudeau static int rv8803_write_regs(const struct i2c_client *client, 129d522649eSBenoît Thébaudeau u8 reg, u8 count, const u8 *values) 130d522649eSBenoît Thébaudeau { 131d522649eSBenoît Thébaudeau int try = RV8803_I2C_TRY_COUNT; 132d522649eSBenoît Thébaudeau s32 ret; 133d522649eSBenoît Thébaudeau 134d522649eSBenoît Thébaudeau do 135d522649eSBenoît Thébaudeau ret = i2c_smbus_write_i2c_block_data(client, reg, count, 136d522649eSBenoît Thébaudeau values); 137d522649eSBenoît Thébaudeau while ((ret == -ENXIO || ret == -EIO) && --try); 138d522649eSBenoît Thébaudeau if (ret) 139d522649eSBenoît Thébaudeau dev_err(&client->dev, 140d522649eSBenoît Thébaudeau "Unable to write registers 0x%02x..0x%02x\n", 141d522649eSBenoît Thébaudeau reg, reg + count - 1); 142d522649eSBenoît Thébaudeau 143d522649eSBenoît Thébaudeau return ret; 144d522649eSBenoît Thébaudeau } 145d522649eSBenoît Thébaudeau 146c27fee16SAhmad Fatoum static int rv8803_regs_init(struct rv8803_data *rv8803) 147c27fee16SAhmad Fatoum { 148c27fee16SAhmad Fatoum int ret; 149c27fee16SAhmad Fatoum 150c27fee16SAhmad Fatoum ret = rv8803_write_reg(rv8803->client, RV8803_OSC_OFFSET, 0x00); 151c27fee16SAhmad Fatoum if (ret) 152c27fee16SAhmad Fatoum return ret; 153c27fee16SAhmad Fatoum 154c27fee16SAhmad Fatoum ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, 155c27fee16SAhmad Fatoum FIELD_PREP(RX8803_CTRL_CSEL, 1)); /* 2s */ 156c27fee16SAhmad Fatoum if (ret) 157c27fee16SAhmad Fatoum return ret; 158c27fee16SAhmad Fatoum 159c27fee16SAhmad Fatoum ret = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, 160c27fee16SAhmad Fatoum (u8[]){ 0, 0, 0 }); 161c27fee16SAhmad Fatoum if (ret) 162c27fee16SAhmad Fatoum return ret; 163c27fee16SAhmad Fatoum 164c27fee16SAhmad Fatoum return rv8803_write_reg(rv8803->client, RV8803_RAM, 0x00); 165c27fee16SAhmad Fatoum } 166c27fee16SAhmad Fatoum 167f8176e0bSAhmad Fatoum static int rv8803_regs_configure(struct rv8803_data *rv8803); 168f8176e0bSAhmad Fatoum 169e5c59423SSascha Hauer static int rv8803_regs_reset(struct rv8803_data *rv8803, bool full) 170f8176e0bSAhmad Fatoum { 171c27fee16SAhmad Fatoum /* 172c27fee16SAhmad Fatoum * The RV-8803 resets all registers to POR defaults after voltage-loss, 173c27fee16SAhmad Fatoum * the Epson RTCs don't, so we manually reset the remainder here. 174c27fee16SAhmad Fatoum */ 175e5c59423SSascha Hauer if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900) { 176c27fee16SAhmad Fatoum int ret = rv8803_regs_init(rv8803); 177c27fee16SAhmad Fatoum if (ret) 178c27fee16SAhmad Fatoum return ret; 179c27fee16SAhmad Fatoum } 180c27fee16SAhmad Fatoum 181f8176e0bSAhmad Fatoum return rv8803_regs_configure(rv8803); 182f8176e0bSAhmad Fatoum } 183f8176e0bSAhmad Fatoum 1841e3929efSAlexandre Belloni static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) 1851e3929efSAlexandre Belloni { 1861e3929efSAlexandre Belloni struct i2c_client *client = dev_id; 1871e3929efSAlexandre Belloni struct rv8803_data *rv8803 = i2c_get_clientdata(client); 1881e3929efSAlexandre Belloni unsigned long events = 0; 189d522649eSBenoît Thébaudeau int flags; 1901e3929efSAlexandre Belloni 1919d1fa4c3SOleksij Rempel mutex_lock(&rv8803->flags_lock); 1921e3929efSAlexandre Belloni 193d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 1941e3929efSAlexandre Belloni if (flags <= 0) { 1959d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 1961e3929efSAlexandre Belloni return IRQ_NONE; 1971e3929efSAlexandre Belloni } 1981e3929efSAlexandre Belloni 1991e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V1F) 2001e3929efSAlexandre Belloni dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n"); 2011e3929efSAlexandre Belloni 2021e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V2F) 2031e3929efSAlexandre Belloni dev_warn(&client->dev, "Voltage low, data loss detected.\n"); 2041e3929efSAlexandre Belloni 2051e3929efSAlexandre Belloni if (flags & RV8803_FLAG_TF) { 2061e3929efSAlexandre Belloni flags &= ~RV8803_FLAG_TF; 2071e3929efSAlexandre Belloni rv8803->ctrl &= ~RV8803_CTRL_TIE; 2081e3929efSAlexandre Belloni events |= RTC_PF; 2091e3929efSAlexandre Belloni } 2101e3929efSAlexandre Belloni 2111e3929efSAlexandre Belloni if (flags & RV8803_FLAG_AF) { 2121e3929efSAlexandre Belloni flags &= ~RV8803_FLAG_AF; 2131e3929efSAlexandre Belloni rv8803->ctrl &= ~RV8803_CTRL_AIE; 2141e3929efSAlexandre Belloni events |= RTC_AF; 2151e3929efSAlexandre Belloni } 2161e3929efSAlexandre Belloni 2171e3929efSAlexandre Belloni if (flags & RV8803_FLAG_UF) { 2181e3929efSAlexandre Belloni flags &= ~RV8803_FLAG_UF; 2191e3929efSAlexandre Belloni rv8803->ctrl &= ~RV8803_CTRL_UIE; 2201e3929efSAlexandre Belloni events |= RTC_UF; 2211e3929efSAlexandre Belloni } 2221e3929efSAlexandre Belloni 2231e3929efSAlexandre Belloni if (events) { 2241e3929efSAlexandre Belloni rtc_update_irq(rv8803->rtc, 1, events); 225d522649eSBenoît Thébaudeau rv8803_write_reg(client, RV8803_FLAG, flags); 226d522649eSBenoît Thébaudeau rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl); 2271e3929efSAlexandre Belloni } 2281e3929efSAlexandre Belloni 2299d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 2301e3929efSAlexandre Belloni 2311e3929efSAlexandre Belloni return IRQ_HANDLED; 2321e3929efSAlexandre Belloni } 2331e3929efSAlexandre Belloni 2341e3929efSAlexandre Belloni static int rv8803_get_time(struct device *dev, struct rtc_time *tm) 2351e3929efSAlexandre Belloni { 2361e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 2371e3929efSAlexandre Belloni u8 date1[7]; 2381e3929efSAlexandre Belloni u8 date2[7]; 2391e3929efSAlexandre Belloni u8 *date = date1; 2401e3929efSAlexandre Belloni int ret, flags; 2411e3929efSAlexandre Belloni 242e5c59423SSascha Hauer if (rv8803->alarm_invalid) { 243e5c59423SSascha Hauer dev_warn(dev, "Corruption detected, data may be invalid.\n"); 244e5c59423SSascha Hauer return -EINVAL; 245e5c59423SSascha Hauer } 246e5c59423SSascha Hauer 247d522649eSBenoît Thébaudeau flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); 2481e3929efSAlexandre Belloni if (flags < 0) 2491e3929efSAlexandre Belloni return flags; 2501e3929efSAlexandre Belloni 2511e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V2F) { 2521e3929efSAlexandre Belloni dev_warn(dev, "Voltage low, data is invalid.\n"); 2531e3929efSAlexandre Belloni return -EINVAL; 2541e3929efSAlexandre Belloni } 2551e3929efSAlexandre Belloni 256d522649eSBenoît Thébaudeau ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date); 257d522649eSBenoît Thébaudeau if (ret) 258d522649eSBenoît Thébaudeau return ret; 2591e3929efSAlexandre Belloni 2601e3929efSAlexandre Belloni if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { 261d522649eSBenoît Thébaudeau ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2); 262d522649eSBenoît Thébaudeau if (ret) 263d522649eSBenoît Thébaudeau return ret; 2641e3929efSAlexandre Belloni 2651e3929efSAlexandre Belloni if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) 2661e3929efSAlexandre Belloni date = date2; 2671e3929efSAlexandre Belloni } 2681e3929efSAlexandre Belloni 2691e3929efSAlexandre Belloni tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f); 2701e3929efSAlexandre Belloni tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f); 2711e3929efSAlexandre Belloni tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f); 272a1e98e09SBenoît Thébaudeau tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f); 2731e3929efSAlexandre Belloni tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f); 2741e3929efSAlexandre Belloni tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1; 2751e3929efSAlexandre Belloni tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100; 2761e3929efSAlexandre Belloni 27796acb25cSBenoît Thébaudeau return 0; 2781e3929efSAlexandre Belloni } 2791e3929efSAlexandre Belloni 2801e3929efSAlexandre Belloni static int rv8803_set_time(struct device *dev, struct rtc_time *tm) 2811e3929efSAlexandre Belloni { 2821e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 2831e3929efSAlexandre Belloni u8 date[7]; 284d3700b6bSBenoît Thébaudeau int ctrl, flags, ret; 2851e3929efSAlexandre Belloni 286d3700b6bSBenoît Thébaudeau ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL); 287d3700b6bSBenoît Thébaudeau if (ctrl < 0) 288d3700b6bSBenoît Thébaudeau return ctrl; 289d3700b6bSBenoît Thébaudeau 290d3700b6bSBenoît Thébaudeau /* Stop the clock */ 291d3700b6bSBenoît Thébaudeau ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, 292d3700b6bSBenoît Thébaudeau ctrl | RV8803_CTRL_RESET); 293d3700b6bSBenoît Thébaudeau if (ret) 294d3700b6bSBenoît Thébaudeau return ret; 295d3700b6bSBenoît Thébaudeau 2961e3929efSAlexandre Belloni date[RV8803_SEC] = bin2bcd(tm->tm_sec); 2971e3929efSAlexandre Belloni date[RV8803_MIN] = bin2bcd(tm->tm_min); 2981e3929efSAlexandre Belloni date[RV8803_HOUR] = bin2bcd(tm->tm_hour); 2991e3929efSAlexandre Belloni date[RV8803_WEEK] = 1 << (tm->tm_wday); 3001e3929efSAlexandre Belloni date[RV8803_DAY] = bin2bcd(tm->tm_mday); 3011e3929efSAlexandre Belloni date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1); 3021e3929efSAlexandre Belloni date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); 3031e3929efSAlexandre Belloni 304d522649eSBenoît Thébaudeau ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date); 305d522649eSBenoît Thébaudeau if (ret) 3061e3929efSAlexandre Belloni return ret; 3071e3929efSAlexandre Belloni 308d3700b6bSBenoît Thébaudeau /* Restart the clock */ 309d3700b6bSBenoît Thébaudeau ret = rv8803_write_reg(rv8803->client, RV8803_CTRL, 310d3700b6bSBenoît Thébaudeau ctrl & ~RV8803_CTRL_RESET); 311d3700b6bSBenoît Thébaudeau if (ret) 312d3700b6bSBenoît Thébaudeau return ret; 313d3700b6bSBenoît Thébaudeau 3149d1fa4c3SOleksij Rempel mutex_lock(&rv8803->flags_lock); 3151e3929efSAlexandre Belloni 316d522649eSBenoît Thébaudeau flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); 3171e3929efSAlexandre Belloni if (flags < 0) { 3189d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 3191e3929efSAlexandre Belloni return flags; 3201e3929efSAlexandre Belloni } 3211e3929efSAlexandre Belloni 322e5c59423SSascha Hauer if ((flags & RV8803_FLAG_V2F) || rv8803->alarm_invalid) { 323e5c59423SSascha Hauer /* 324e5c59423SSascha Hauer * If we sense corruption in the alarm registers, but see no 325e5c59423SSascha Hauer * voltage loss flag, we can't rely on other registers having 326e5c59423SSascha Hauer * sensible values. Reset them fully. 327e5c59423SSascha Hauer */ 328e5c59423SSascha Hauer ret = rv8803_regs_reset(rv8803, rv8803->alarm_invalid); 329bb42b7e9SYang Yingliang if (ret) { 330bb42b7e9SYang Yingliang mutex_unlock(&rv8803->flags_lock); 331f8176e0bSAhmad Fatoum return ret; 332f8176e0bSAhmad Fatoum } 333e5c59423SSascha Hauer 334e5c59423SSascha Hauer rv8803->alarm_invalid = false; 335bb42b7e9SYang Yingliang } 336f8176e0bSAhmad Fatoum 337d522649eSBenoît Thébaudeau ret = rv8803_write_reg(rv8803->client, RV8803_FLAG, 3386f367788SBenoît Thébaudeau flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F)); 3391e3929efSAlexandre Belloni 3409d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 3411e3929efSAlexandre Belloni 3421e3929efSAlexandre Belloni return ret; 3431e3929efSAlexandre Belloni } 3441e3929efSAlexandre Belloni 3451e3929efSAlexandre Belloni static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) 3461e3929efSAlexandre Belloni { 3471e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 3481e3929efSAlexandre Belloni struct i2c_client *client = rv8803->client; 3491e3929efSAlexandre Belloni u8 alarmvals[3]; 3501e3929efSAlexandre Belloni int flags, ret; 3511e3929efSAlexandre Belloni 352d522649eSBenoît Thébaudeau ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals); 353d522649eSBenoît Thébaudeau if (ret) 354d522649eSBenoît Thébaudeau return ret; 3551e3929efSAlexandre Belloni 356d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 3571e3929efSAlexandre Belloni if (flags < 0) 3581e3929efSAlexandre Belloni return flags; 3591e3929efSAlexandre Belloni 360e5c59423SSascha Hauer alarmvals[0] &= 0x7f; 361e5c59423SSascha Hauer alarmvals[1] &= 0x3f; 362e5c59423SSascha Hauer alarmvals[2] &= 0x3f; 363e5c59423SSascha Hauer 364e5c59423SSascha Hauer if (!bcd_is_valid(alarmvals[0]) || 365e5c59423SSascha Hauer !bcd_is_valid(alarmvals[1]) || 366e5c59423SSascha Hauer !bcd_is_valid(alarmvals[2])) 367e5c59423SSascha Hauer goto err_invalid; 368e5c59423SSascha Hauer 3691e3929efSAlexandre Belloni alrm->time.tm_sec = 0; 370e5c59423SSascha Hauer alrm->time.tm_min = bcd2bin(alarmvals[0]); 371e5c59423SSascha Hauer alrm->time.tm_hour = bcd2bin(alarmvals[1]); 372e5c59423SSascha Hauer alrm->time.tm_mday = bcd2bin(alarmvals[2]); 3731e3929efSAlexandre Belloni 3741e3929efSAlexandre Belloni alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE); 3751e3929efSAlexandre Belloni alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled; 3761e3929efSAlexandre Belloni 377e5c59423SSascha Hauer if ((unsigned int)alrm->time.tm_mday > 31 || 378e5c59423SSascha Hauer (unsigned int)alrm->time.tm_hour >= 24 || 379e5c59423SSascha Hauer (unsigned int)alrm->time.tm_min >= 60) 380e5c59423SSascha Hauer goto err_invalid; 381e5c59423SSascha Hauer 3821e3929efSAlexandre Belloni return 0; 383e5c59423SSascha Hauer 384e5c59423SSascha Hauer err_invalid: 385e5c59423SSascha Hauer rv8803->alarm_invalid = true; 386e5c59423SSascha Hauer return -EINVAL; 3871e3929efSAlexandre Belloni } 3881e3929efSAlexandre Belloni 3891e3929efSAlexandre Belloni static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 3901e3929efSAlexandre Belloni { 3911e3929efSAlexandre Belloni struct i2c_client *client = to_i2c_client(dev); 3921e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 3931e3929efSAlexandre Belloni u8 alarmvals[3]; 3941e3929efSAlexandre Belloni u8 ctrl[2]; 3951e3929efSAlexandre Belloni int ret, err; 3961e3929efSAlexandre Belloni 3971e3929efSAlexandre Belloni /* The alarm has no seconds, round up to nearest minute */ 3981e3929efSAlexandre Belloni if (alrm->time.tm_sec) { 3991e3929efSAlexandre Belloni time64_t alarm_time = rtc_tm_to_time64(&alrm->time); 4001e3929efSAlexandre Belloni 4011e3929efSAlexandre Belloni alarm_time += 60 - alrm->time.tm_sec; 4021e3929efSAlexandre Belloni rtc_time64_to_tm(alarm_time, &alrm->time); 4031e3929efSAlexandre Belloni } 4041e3929efSAlexandre Belloni 4059d1fa4c3SOleksij Rempel mutex_lock(&rv8803->flags_lock); 4061e3929efSAlexandre Belloni 407d522649eSBenoît Thébaudeau ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl); 408d522649eSBenoît Thébaudeau if (ret) { 4099d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 410d522649eSBenoît Thébaudeau return ret; 4111e3929efSAlexandre Belloni } 4121e3929efSAlexandre Belloni 4131e3929efSAlexandre Belloni alarmvals[0] = bin2bcd(alrm->time.tm_min); 4141e3929efSAlexandre Belloni alarmvals[1] = bin2bcd(alrm->time.tm_hour); 4151e3929efSAlexandre Belloni alarmvals[2] = bin2bcd(alrm->time.tm_mday); 4161e3929efSAlexandre Belloni 4171e3929efSAlexandre Belloni if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) { 4181e3929efSAlexandre Belloni rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE); 419d522649eSBenoît Thébaudeau err = rv8803_write_reg(rv8803->client, RV8803_CTRL, 4201e3929efSAlexandre Belloni rv8803->ctrl); 4211e3929efSAlexandre Belloni if (err) { 4229d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 4231e3929efSAlexandre Belloni return err; 4241e3929efSAlexandre Belloni } 4251e3929efSAlexandre Belloni } 4261e3929efSAlexandre Belloni 42703a86cdaSDominique Martinet ctrl[0] &= ~RV8803_FLAG_AF; 42803a86cdaSDominique Martinet err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[0]); 4299d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 4301e3929efSAlexandre Belloni if (err) 4311e3929efSAlexandre Belloni return err; 4321e3929efSAlexandre Belloni 433d522649eSBenoît Thébaudeau err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals); 4341e3929efSAlexandre Belloni if (err) 4351e3929efSAlexandre Belloni return err; 4361e3929efSAlexandre Belloni 4371e3929efSAlexandre Belloni if (alrm->enabled) { 4381e3929efSAlexandre Belloni if (rv8803->rtc->uie_rtctimer.enabled) 4391e3929efSAlexandre Belloni rv8803->ctrl |= RV8803_CTRL_UIE; 4401e3929efSAlexandre Belloni if (rv8803->rtc->aie_timer.enabled) 4411e3929efSAlexandre Belloni rv8803->ctrl |= RV8803_CTRL_AIE; 4421e3929efSAlexandre Belloni 443d522649eSBenoît Thébaudeau err = rv8803_write_reg(rv8803->client, RV8803_CTRL, 4441e3929efSAlexandre Belloni rv8803->ctrl); 4451e3929efSAlexandre Belloni if (err) 4461e3929efSAlexandre Belloni return err; 4471e3929efSAlexandre Belloni } 4481e3929efSAlexandre Belloni 4491e3929efSAlexandre Belloni return 0; 4501e3929efSAlexandre Belloni } 4511e3929efSAlexandre Belloni 4521e3929efSAlexandre Belloni static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled) 4531e3929efSAlexandre Belloni { 4541e3929efSAlexandre Belloni struct i2c_client *client = to_i2c_client(dev); 4551e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 4561e3929efSAlexandre Belloni int ctrl, flags, err; 4571e3929efSAlexandre Belloni 4581e3929efSAlexandre Belloni ctrl = rv8803->ctrl; 4591e3929efSAlexandre Belloni 4601e3929efSAlexandre Belloni if (enabled) { 4611e3929efSAlexandre Belloni if (rv8803->rtc->uie_rtctimer.enabled) 4621e3929efSAlexandre Belloni ctrl |= RV8803_CTRL_UIE; 4631e3929efSAlexandre Belloni if (rv8803->rtc->aie_timer.enabled) 4641e3929efSAlexandre Belloni ctrl |= RV8803_CTRL_AIE; 4651e3929efSAlexandre Belloni } else { 4661e3929efSAlexandre Belloni if (!rv8803->rtc->uie_rtctimer.enabled) 4671e3929efSAlexandre Belloni ctrl &= ~RV8803_CTRL_UIE; 4681e3929efSAlexandre Belloni if (!rv8803->rtc->aie_timer.enabled) 4691e3929efSAlexandre Belloni ctrl &= ~RV8803_CTRL_AIE; 4701e3929efSAlexandre Belloni } 4711e3929efSAlexandre Belloni 4729d1fa4c3SOleksij Rempel mutex_lock(&rv8803->flags_lock); 473d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 4741e3929efSAlexandre Belloni if (flags < 0) { 4759d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 4761e3929efSAlexandre Belloni return flags; 4771e3929efSAlexandre Belloni } 4781e3929efSAlexandre Belloni flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); 479d522649eSBenoît Thébaudeau err = rv8803_write_reg(client, RV8803_FLAG, flags); 4809d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 4811e3929efSAlexandre Belloni if (err) 4821e3929efSAlexandre Belloni return err; 4831e3929efSAlexandre Belloni 4841e3929efSAlexandre Belloni if (ctrl != rv8803->ctrl) { 4851e3929efSAlexandre Belloni rv8803->ctrl = ctrl; 486d522649eSBenoît Thébaudeau err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl); 4871e3929efSAlexandre Belloni if (err) 4881e3929efSAlexandre Belloni return err; 4891e3929efSAlexandre Belloni } 4901e3929efSAlexandre Belloni 4911e3929efSAlexandre Belloni return 0; 4921e3929efSAlexandre Belloni } 4931e3929efSAlexandre Belloni 4941e3929efSAlexandre Belloni static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 4951e3929efSAlexandre Belloni { 4961e3929efSAlexandre Belloni struct i2c_client *client = to_i2c_client(dev); 4971e3929efSAlexandre Belloni struct rv8803_data *rv8803 = dev_get_drvdata(dev); 498bcd17c50SAlexandre Belloni unsigned int vl = 0; 4991e3929efSAlexandre Belloni int flags, ret = 0; 5001e3929efSAlexandre Belloni 5011e3929efSAlexandre Belloni switch (cmd) { 5021e3929efSAlexandre Belloni case RTC_VL_READ: 503d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 5041e3929efSAlexandre Belloni if (flags < 0) 5051e3929efSAlexandre Belloni return flags; 5061e3929efSAlexandre Belloni 507bcd17c50SAlexandre Belloni if (flags & RV8803_FLAG_V1F) { 5081e3929efSAlexandre Belloni dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n"); 509bcd17c50SAlexandre Belloni vl = RTC_VL_ACCURACY_LOW; 510bcd17c50SAlexandre Belloni } 5111e3929efSAlexandre Belloni 5121e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V2F) 513bcd17c50SAlexandre Belloni vl |= RTC_VL_DATA_INVALID; 5141e3929efSAlexandre Belloni 515bcd17c50SAlexandre Belloni return put_user(vl, (unsigned int __user *)arg); 5161e3929efSAlexandre Belloni 5171e3929efSAlexandre Belloni case RTC_VL_CLR: 5189d1fa4c3SOleksij Rempel mutex_lock(&rv8803->flags_lock); 519d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 5201e3929efSAlexandre Belloni if (flags < 0) { 5219d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 5221e3929efSAlexandre Belloni return flags; 5231e3929efSAlexandre Belloni } 5241e3929efSAlexandre Belloni 5257e890a0fSAlexandre Belloni flags &= ~RV8803_FLAG_V1F; 526d522649eSBenoît Thébaudeau ret = rv8803_write_reg(client, RV8803_FLAG, flags); 5279d1fa4c3SOleksij Rempel mutex_unlock(&rv8803->flags_lock); 528d522649eSBenoît Thébaudeau if (ret) 5291e3929efSAlexandre Belloni return ret; 5301e3929efSAlexandre Belloni 5311e3929efSAlexandre Belloni return 0; 5321e3929efSAlexandre Belloni 5331e3929efSAlexandre Belloni default: 5341e3929efSAlexandre Belloni return -ENOIOCTLCMD; 5351e3929efSAlexandre Belloni } 5361e3929efSAlexandre Belloni } 5371e3929efSAlexandre Belloni 53816d70a78SAlexandre Belloni static int rv8803_nvram_write(void *priv, unsigned int offset, void *val, 53916d70a78SAlexandre Belloni size_t bytes) 5401e3929efSAlexandre Belloni { 541179b4bccSLiu Shixin return rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val); 5421e3929efSAlexandre Belloni } 5431e3929efSAlexandre Belloni 54416d70a78SAlexandre Belloni static int rv8803_nvram_read(void *priv, unsigned int offset, 54516d70a78SAlexandre Belloni void *val, size_t bytes) 5461e3929efSAlexandre Belloni { 5471e3929efSAlexandre Belloni int ret; 5481e3929efSAlexandre Belloni 54916d70a78SAlexandre Belloni ret = rv8803_read_reg(priv, RV8803_RAM); 5501e3929efSAlexandre Belloni if (ret < 0) 5511e3929efSAlexandre Belloni return ret; 5521e3929efSAlexandre Belloni 55316d70a78SAlexandre Belloni *(u8 *)val = ret; 5541e3929efSAlexandre Belloni 55516d70a78SAlexandre Belloni return 0; 5561e3929efSAlexandre Belloni } 5571e3929efSAlexandre Belloni 55845909e5cSAlexandre Belloni static const struct rtc_class_ops rv8803_rtc_ops = { 5591e3929efSAlexandre Belloni .read_time = rv8803_get_time, 5601e3929efSAlexandre Belloni .set_time = rv8803_set_time, 5611e3929efSAlexandre Belloni .ioctl = rv8803_ioctl, 56245909e5cSAlexandre Belloni .read_alarm = rv8803_get_alarm, 56345909e5cSAlexandre Belloni .set_alarm = rv8803_set_alarm, 56445909e5cSAlexandre Belloni .alarm_irq_enable = rv8803_alarm_irq_enable, 5651e3929efSAlexandre Belloni }; 5661e3929efSAlexandre Belloni 5671cd71376SOleksij Rempel static int rx8900_trickle_charger_init(struct rv8803_data *rv8803) 5681cd71376SOleksij Rempel { 5691cd71376SOleksij Rempel struct i2c_client *client = rv8803->client; 5701cd71376SOleksij Rempel struct device_node *node = client->dev.of_node; 5711cd71376SOleksij Rempel int err; 5721cd71376SOleksij Rempel u8 flags; 5731cd71376SOleksij Rempel 5741cd71376SOleksij Rempel if (!node) 5751cd71376SOleksij Rempel return 0; 5761cd71376SOleksij Rempel 5771cd71376SOleksij Rempel if (rv8803->type != rx_8900) 5781cd71376SOleksij Rempel return 0; 5791cd71376SOleksij Rempel 5801cd71376SOleksij Rempel err = i2c_smbus_read_byte_data(rv8803->client, RX8900_BACKUP_CTRL); 5811cd71376SOleksij Rempel if (err < 0) 5821cd71376SOleksij Rempel return err; 5831cd71376SOleksij Rempel 5848c798e1eSAhmad Fatoum flags = (u8)err; 5858c798e1eSAhmad Fatoum flags &= ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF); 5868c798e1eSAhmad Fatoum flags |= rv8803->backup; 5871cd71376SOleksij Rempel 5881cd71376SOleksij Rempel return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL, 5891cd71376SOleksij Rempel flags); 5901cd71376SOleksij Rempel } 5911cd71376SOleksij Rempel 5928c798e1eSAhmad Fatoum /* configure registers with values different than the Power-On reset defaults */ 5938c798e1eSAhmad Fatoum static int rv8803_regs_configure(struct rv8803_data *rv8803) 5948c798e1eSAhmad Fatoum { 5958c798e1eSAhmad Fatoum int err; 5968c798e1eSAhmad Fatoum 5978c798e1eSAhmad Fatoum err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); 5988c798e1eSAhmad Fatoum if (err) 5998c798e1eSAhmad Fatoum return err; 6008c798e1eSAhmad Fatoum 6018c798e1eSAhmad Fatoum err = rx8900_trickle_charger_init(rv8803); 6028c798e1eSAhmad Fatoum if (err) { 6038c798e1eSAhmad Fatoum dev_err(&rv8803->client->dev, "failed to init charger\n"); 6048c798e1eSAhmad Fatoum return err; 6058c798e1eSAhmad Fatoum } 6068c798e1eSAhmad Fatoum 6078c798e1eSAhmad Fatoum return 0; 6088c798e1eSAhmad Fatoum } 6098c798e1eSAhmad Fatoum 61084c2fb38SUwe Kleine-König static const struct i2c_device_id rv8803_id[] = { 61184c2fb38SUwe Kleine-König { "rv8803", rv_8803 }, 61284c2fb38SUwe Kleine-König { "rv8804", rx_8804 }, 61384c2fb38SUwe Kleine-König { "rx8803", rx_8803 }, 61484c2fb38SUwe Kleine-König { "rx8900", rx_8900 }, 61584c2fb38SUwe Kleine-König { } 61684c2fb38SUwe Kleine-König }; 61784c2fb38SUwe Kleine-König MODULE_DEVICE_TABLE(i2c, rv8803_id); 61884c2fb38SUwe Kleine-König 61984c2fb38SUwe Kleine-König static int rv8803_probe(struct i2c_client *client) 6201e3929efSAlexandre Belloni { 6215cb17269SWolfram Sang struct i2c_adapter *adapter = client->adapter; 6221e3929efSAlexandre Belloni struct rv8803_data *rv8803; 623d522649eSBenoît Thébaudeau int err, flags; 624c07fd9deSAlexandre Belloni struct nvmem_config nvmem_cfg = { 625c07fd9deSAlexandre Belloni .name = "rv8803_nvram", 626c07fd9deSAlexandre Belloni .word_size = 1, 627c07fd9deSAlexandre Belloni .stride = 1, 628c07fd9deSAlexandre Belloni .size = 1, 629c07fd9deSAlexandre Belloni .reg_read = rv8803_nvram_read, 630c07fd9deSAlexandre Belloni .reg_write = rv8803_nvram_write, 631c07fd9deSAlexandre Belloni .priv = client, 632c07fd9deSAlexandre Belloni }; 6331e3929efSAlexandre Belloni 6341e3929efSAlexandre Belloni if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | 6351e3929efSAlexandre Belloni I2C_FUNC_SMBUS_I2C_BLOCK)) { 6361e3929efSAlexandre Belloni dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n"); 6371e3929efSAlexandre Belloni return -EIO; 6381e3929efSAlexandre Belloni } 6391e3929efSAlexandre Belloni 6401e3929efSAlexandre Belloni rv8803 = devm_kzalloc(&client->dev, sizeof(struct rv8803_data), 6411e3929efSAlexandre Belloni GFP_KERNEL); 6421e3929efSAlexandre Belloni if (!rv8803) 6431e3929efSAlexandre Belloni return -ENOMEM; 6441e3929efSAlexandre Belloni 6459d1fa4c3SOleksij Rempel mutex_init(&rv8803->flags_lock); 6461e3929efSAlexandre Belloni rv8803->client = client; 64784c2fb38SUwe Kleine-König if (client->dev.of_node) { 648740ad8f4SJavier Martinez Canillas rv8803->type = (enum rv8803_type) 649740ad8f4SJavier Martinez Canillas of_device_get_match_data(&client->dev); 65084c2fb38SUwe Kleine-König } else { 65184c2fb38SUwe Kleine-König const struct i2c_device_id *id = i2c_match_id(rv8803_id, client); 65284c2fb38SUwe Kleine-König 6531cd71376SOleksij Rempel rv8803->type = id->driver_data; 65484c2fb38SUwe Kleine-König } 6551e3929efSAlexandre Belloni i2c_set_clientdata(client, rv8803); 6561e3929efSAlexandre Belloni 657d522649eSBenoît Thébaudeau flags = rv8803_read_reg(client, RV8803_FLAG); 6581e3929efSAlexandre Belloni if (flags < 0) 6591e3929efSAlexandre Belloni return flags; 6601e3929efSAlexandre Belloni 6611e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V1F) 6621e3929efSAlexandre Belloni dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n"); 6631e3929efSAlexandre Belloni 6641e3929efSAlexandre Belloni if (flags & RV8803_FLAG_V2F) 6651e3929efSAlexandre Belloni dev_warn(&client->dev, "Voltage low, data loss detected.\n"); 6661e3929efSAlexandre Belloni 6671e3929efSAlexandre Belloni if (flags & RV8803_FLAG_AF) 6681e3929efSAlexandre Belloni dev_warn(&client->dev, "An alarm maybe have been missed.\n"); 6691e3929efSAlexandre Belloni 6707133eca1SAlexandre Belloni rv8803->rtc = devm_rtc_allocate_device(&client->dev); 67144c638ceSAlexandre Belloni if (IS_ERR(rv8803->rtc)) 6727133eca1SAlexandre Belloni return PTR_ERR(rv8803->rtc); 6737133eca1SAlexandre Belloni 6741e3929efSAlexandre Belloni if (client->irq > 0) { 67511bfd6fcSAlexandre Belloni unsigned long irqflags = IRQF_TRIGGER_LOW; 67611bfd6fcSAlexandre Belloni 67711bfd6fcSAlexandre Belloni if (dev_fwnode(&client->dev)) 67811bfd6fcSAlexandre Belloni irqflags = 0; 67911bfd6fcSAlexandre Belloni 6801e3929efSAlexandre Belloni err = devm_request_threaded_irq(&client->dev, client->irq, 6811e3929efSAlexandre Belloni NULL, rv8803_handle_irq, 68211bfd6fcSAlexandre Belloni irqflags | IRQF_ONESHOT, 6831e3929efSAlexandre Belloni "rv8803", client); 6841e3929efSAlexandre Belloni if (err) { 6851e3929efSAlexandre Belloni dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); 6861e3929efSAlexandre Belloni client->irq = 0; 6871e3929efSAlexandre Belloni } 6881e3929efSAlexandre Belloni } 68945909e5cSAlexandre Belloni if (!client->irq) 69045909e5cSAlexandre Belloni clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features); 6911e3929efSAlexandre Belloni 6928c798e1eSAhmad Fatoum if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable")) 6938c798e1eSAhmad Fatoum rv8803->backup |= RX8900_FLAG_VDETOFF; 6948c798e1eSAhmad Fatoum 6958c798e1eSAhmad Fatoum if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable")) 6968c798e1eSAhmad Fatoum rv8803->backup |= RX8900_FLAG_SWOFF; 6978c798e1eSAhmad Fatoum 6988c798e1eSAhmad Fatoum err = rv8803_regs_configure(rv8803); 6991e3929efSAlexandre Belloni if (err) 7001e3929efSAlexandre Belloni return err; 7011e3929efSAlexandre Belloni 702ce1ae8ebSAlexandre Belloni rv8803->rtc->ops = &rv8803_rtc_ops; 7032e17f8b9SAlexandre Belloni rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 7042e17f8b9SAlexandre Belloni rv8803->rtc->range_max = RTC_TIMESTAMP_END_2099; 705fdcfd854SBartosz Golaszewski err = devm_rtc_register_device(rv8803->rtc); 706ce1ae8ebSAlexandre Belloni if (err) 707ce1ae8ebSAlexandre Belloni return err; 708ce1ae8ebSAlexandre Belloni 7093a905c2dSBartosz Golaszewski devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg); 710ce1ae8ebSAlexandre Belloni 7111e3929efSAlexandre Belloni rv8803->rtc->max_user_freq = 1; 7121e3929efSAlexandre Belloni 7131e3929efSAlexandre Belloni return 0; 7141e3929efSAlexandre Belloni } 7151e3929efSAlexandre Belloni 716da826321SAlexandre Belloni static const __maybe_unused struct of_device_id rv8803_of_match[] = { 717740ad8f4SJavier Martinez Canillas { 718740ad8f4SJavier Martinez Canillas .compatible = "microcrystal,rv8803", 719c856618dSAlexandre Belloni .data = (void *)rv_8803 720740ad8f4SJavier Martinez Canillas }, 721740ad8f4SJavier Martinez Canillas { 722ac771ed7SAlexandre Belloni .compatible = "epson,rx8803", 723c27fee16SAhmad Fatoum .data = (void *)rx_8803 724ac771ed7SAlexandre Belloni }, 725ac771ed7SAlexandre Belloni { 7265c0189a8SFabio Estevam .compatible = "epson,rx8804", 7275c0189a8SFabio Estevam .data = (void *)rx_8804 7285c0189a8SFabio Estevam }, 7295c0189a8SFabio Estevam { 730740ad8f4SJavier Martinez Canillas .compatible = "epson,rx8900", 731740ad8f4SJavier Martinez Canillas .data = (void *)rx_8900 732740ad8f4SJavier Martinez Canillas }, 733740ad8f4SJavier Martinez Canillas { } 734740ad8f4SJavier Martinez Canillas }; 735740ad8f4SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, rv8803_of_match); 736740ad8f4SJavier Martinez Canillas 7371e3929efSAlexandre Belloni static struct i2c_driver rv8803_driver = { 7381e3929efSAlexandre Belloni .driver = { 7391e3929efSAlexandre Belloni .name = "rtc-rv8803", 740740ad8f4SJavier Martinez Canillas .of_match_table = of_match_ptr(rv8803_of_match), 7411e3929efSAlexandre Belloni }, 742*31b0cecbSUwe Kleine-König .probe = rv8803_probe, 7431e3929efSAlexandre Belloni .id_table = rv8803_id, 7441e3929efSAlexandre Belloni }; 7451e3929efSAlexandre Belloni module_i2c_driver(rv8803_driver); 7461e3929efSAlexandre Belloni 7477d1e5bfeSAlexandre Belloni MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>"); 7481e3929efSAlexandre Belloni MODULE_DESCRIPTION("Micro Crystal RV8803 RTC driver"); 7491e3929efSAlexandre Belloni MODULE_LICENSE("GPL v2"); 750