18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * An I2C driver for the Epson RX8581 RTC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Martyn Welch <martyn.welch@ge.com> 68c2ecf20Sopenharmony_ci * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) 98c2ecf20Sopenharmony_ci * Copyright 2005-06 Tower Technologies 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/i2c.h> 148c2ecf20Sopenharmony_ci#include <linux/bcd.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/of_device.h> 178c2ecf20Sopenharmony_ci#include <linux/regmap.h> 188c2ecf20Sopenharmony_ci#include <linux/rtc.h> 198c2ecf20Sopenharmony_ci#include <linux/log2.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define RX8581_REG_SC 0x00 /* Second in BCD */ 228c2ecf20Sopenharmony_ci#define RX8581_REG_MN 0x01 /* Minute in BCD */ 238c2ecf20Sopenharmony_ci#define RX8581_REG_HR 0x02 /* Hour in BCD */ 248c2ecf20Sopenharmony_ci#define RX8581_REG_DW 0x03 /* Day of Week */ 258c2ecf20Sopenharmony_ci#define RX8581_REG_DM 0x04 /* Day of Month in BCD */ 268c2ecf20Sopenharmony_ci#define RX8581_REG_MO 0x05 /* Month in BCD */ 278c2ecf20Sopenharmony_ci#define RX8581_REG_YR 0x06 /* Year in BCD */ 288c2ecf20Sopenharmony_ci#define RX8581_REG_RAM 0x07 /* RAM */ 298c2ecf20Sopenharmony_ci#define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/ 308c2ecf20Sopenharmony_ci#define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */ 318c2ecf20Sopenharmony_ci#define RX8581_REG_ADM 0x0A 328c2ecf20Sopenharmony_ci#define RX8581_REG_ADW 0x0A 338c2ecf20Sopenharmony_ci#define RX8581_REG_TMR0 0x0B 348c2ecf20Sopenharmony_ci#define RX8581_REG_TMR1 0x0C 358c2ecf20Sopenharmony_ci#define RX8581_REG_EXT 0x0D /* Extension Register */ 368c2ecf20Sopenharmony_ci#define RX8581_REG_FLAG 0x0E /* Flag Register */ 378c2ecf20Sopenharmony_ci#define RX8581_REG_CTRL 0x0F /* Control Register */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* Flag Register bit definitions */ 418c2ecf20Sopenharmony_ci#define RX8581_FLAG_UF 0x20 /* Update */ 428c2ecf20Sopenharmony_ci#define RX8581_FLAG_TF 0x10 /* Timer */ 438c2ecf20Sopenharmony_ci#define RX8581_FLAG_AF 0x08 /* Alarm */ 448c2ecf20Sopenharmony_ci#define RX8581_FLAG_VLF 0x02 /* Voltage Low */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* Control Register bit definitions */ 478c2ecf20Sopenharmony_ci#define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */ 488c2ecf20Sopenharmony_ci#define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ 498c2ecf20Sopenharmony_ci#define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ 508c2ecf20Sopenharmony_ci#define RX8581_CTRL_STOP 0x02 /* STOP bit */ 518c2ecf20Sopenharmony_ci#define RX8581_CTRL_RESET 0x01 /* RESET bit */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define RX8571_USER_RAM 0x10 548c2ecf20Sopenharmony_ci#define RX8571_NVRAM_SIZE 0x10 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistruct rx8581 { 578c2ecf20Sopenharmony_ci struct regmap *regmap; 588c2ecf20Sopenharmony_ci struct rtc_device *rtc; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistruct rx85x1_config { 628c2ecf20Sopenharmony_ci struct regmap_config regmap; 638c2ecf20Sopenharmony_ci unsigned int num_nvram; 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* 678c2ecf20Sopenharmony_ci * In the routines that deal directly with the rx8581 hardware, we use 688c2ecf20Sopenharmony_ci * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_cistatic int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 738c2ecf20Sopenharmony_ci unsigned char date[7]; 748c2ecf20Sopenharmony_ci unsigned int data; 758c2ecf20Sopenharmony_ci int err; 768c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = i2c_get_clientdata(client); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* First we ensure that the "update flag" is not set, we read the 798c2ecf20Sopenharmony_ci * time and date then re-read the "update flag". If the update flag 808c2ecf20Sopenharmony_ci * has been set, we know that the time has changed during the read so 818c2ecf20Sopenharmony_ci * we repeat the whole process again. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); 848c2ecf20Sopenharmony_ci if (err < 0) 858c2ecf20Sopenharmony_ci return err; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (data & RX8581_FLAG_VLF) { 888c2ecf20Sopenharmony_ci dev_warn(dev, 898c2ecf20Sopenharmony_ci "low voltage detected, date/time is not reliable.\n"); 908c2ecf20Sopenharmony_ci return -EINVAL; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci do { 948c2ecf20Sopenharmony_ci /* If update flag set, clear it */ 958c2ecf20Sopenharmony_ci if (data & RX8581_FLAG_UF) { 968c2ecf20Sopenharmony_ci err = regmap_write(rx8581->regmap, RX8581_REG_FLAG, 978c2ecf20Sopenharmony_ci data & ~RX8581_FLAG_UF); 988c2ecf20Sopenharmony_ci if (err < 0) 998c2ecf20Sopenharmony_ci return err; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* Now read time and date */ 1038c2ecf20Sopenharmony_ci err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date, 1048c2ecf20Sopenharmony_ci sizeof(date)); 1058c2ecf20Sopenharmony_ci if (err < 0) 1068c2ecf20Sopenharmony_ci return err; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Check flag register */ 1098c2ecf20Sopenharmony_ci err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); 1108c2ecf20Sopenharmony_ci if (err < 0) 1118c2ecf20Sopenharmony_ci return err; 1128c2ecf20Sopenharmony_ci } while (data & RX8581_FLAG_UF); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " 1158c2ecf20Sopenharmony_ci "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", 1168c2ecf20Sopenharmony_ci __func__, 1178c2ecf20Sopenharmony_ci date[0], date[1], date[2], date[3], date[4], date[5], date[6]); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F); 1208c2ecf20Sopenharmony_ci tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F); 1218c2ecf20Sopenharmony_ci tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */ 1228c2ecf20Sopenharmony_ci tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); 1238c2ecf20Sopenharmony_ci tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); 1248c2ecf20Sopenharmony_ci tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ 1258c2ecf20Sopenharmony_ci tm->tm_year = bcd2bin(date[RX8581_REG_YR]) + 100; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " 1288c2ecf20Sopenharmony_ci "mday=%d, mon=%d, year=%d, wday=%d\n", 1298c2ecf20Sopenharmony_ci __func__, 1308c2ecf20Sopenharmony_ci tm->tm_sec, tm->tm_min, tm->tm_hour, 1318c2ecf20Sopenharmony_ci tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci return 0; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 1398c2ecf20Sopenharmony_ci int err; 1408c2ecf20Sopenharmony_ci unsigned char buf[7]; 1418c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = i2c_get_clientdata(client); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " 1448c2ecf20Sopenharmony_ci "mday=%d, mon=%d, year=%d, wday=%d\n", 1458c2ecf20Sopenharmony_ci __func__, 1468c2ecf20Sopenharmony_ci tm->tm_sec, tm->tm_min, tm->tm_hour, 1478c2ecf20Sopenharmony_ci tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* hours, minutes and seconds */ 1508c2ecf20Sopenharmony_ci buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec); 1518c2ecf20Sopenharmony_ci buf[RX8581_REG_MN] = bin2bcd(tm->tm_min); 1528c2ecf20Sopenharmony_ci buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* month, 1 - 12 */ 1578c2ecf20Sopenharmony_ci buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* year and century */ 1608c2ecf20Sopenharmony_ci buf[RX8581_REG_YR] = bin2bcd(tm->tm_year - 100); 1618c2ecf20Sopenharmony_ci buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Stop the clock */ 1648c2ecf20Sopenharmony_ci err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, 1658c2ecf20Sopenharmony_ci RX8581_CTRL_STOP, RX8581_CTRL_STOP); 1668c2ecf20Sopenharmony_ci if (err < 0) 1678c2ecf20Sopenharmony_ci return err; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* write register's data */ 1708c2ecf20Sopenharmony_ci err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC, 1718c2ecf20Sopenharmony_ci buf, sizeof(buf)); 1728c2ecf20Sopenharmony_ci if (err < 0) 1738c2ecf20Sopenharmony_ci return err; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* get VLF and clear it */ 1768c2ecf20Sopenharmony_ci err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG, 1778c2ecf20Sopenharmony_ci RX8581_FLAG_VLF, 0); 1788c2ecf20Sopenharmony_ci if (err < 0) 1798c2ecf20Sopenharmony_ci return err; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* Restart the clock */ 1828c2ecf20Sopenharmony_ci return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, 1838c2ecf20Sopenharmony_ci RX8581_CTRL_STOP, 0); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic const struct rtc_class_ops rx8581_rtc_ops = { 1878c2ecf20Sopenharmony_ci .read_time = rx8581_rtc_read_time, 1888c2ecf20Sopenharmony_ci .set_time = rx8581_rtc_set_time, 1898c2ecf20Sopenharmony_ci}; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic int rx8571_nvram_read(void *priv, unsigned int offset, void *val, 1928c2ecf20Sopenharmony_ci size_t bytes) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = priv; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci return regmap_bulk_read(rx8581->regmap, RX8571_USER_RAM + offset, 1978c2ecf20Sopenharmony_ci val, bytes); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int rx8571_nvram_write(void *priv, unsigned int offset, void *val, 2018c2ecf20Sopenharmony_ci size_t bytes) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = priv; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci return regmap_bulk_write(rx8581->regmap, RX8571_USER_RAM + offset, 2068c2ecf20Sopenharmony_ci val, bytes); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int rx85x1_nvram_read(void *priv, unsigned int offset, void *val, 2108c2ecf20Sopenharmony_ci size_t bytes) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = priv; 2138c2ecf20Sopenharmony_ci unsigned int tmp_val; 2148c2ecf20Sopenharmony_ci int ret; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci ret = regmap_read(rx8581->regmap, RX8581_REG_RAM, &tmp_val); 2178c2ecf20Sopenharmony_ci (*(unsigned char *)val) = (unsigned char) tmp_val; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return ret; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic int rx85x1_nvram_write(void *priv, unsigned int offset, void *val, 2238c2ecf20Sopenharmony_ci size_t bytes) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct rx8581 *rx8581 = priv; 2268c2ecf20Sopenharmony_ci unsigned char tmp_val; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci tmp_val = *((unsigned char *)val); 2298c2ecf20Sopenharmony_ci return regmap_write(rx8581->regmap, RX8581_REG_RAM, 2308c2ecf20Sopenharmony_ci (unsigned int)tmp_val); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic const struct rx85x1_config rx8581_config = { 2348c2ecf20Sopenharmony_ci .regmap = { 2358c2ecf20Sopenharmony_ci .reg_bits = 8, 2368c2ecf20Sopenharmony_ci .val_bits = 8, 2378c2ecf20Sopenharmony_ci .max_register = 0xf, 2388c2ecf20Sopenharmony_ci }, 2398c2ecf20Sopenharmony_ci .num_nvram = 1 2408c2ecf20Sopenharmony_ci}; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic const struct rx85x1_config rx8571_config = { 2438c2ecf20Sopenharmony_ci .regmap = { 2448c2ecf20Sopenharmony_ci .reg_bits = 8, 2458c2ecf20Sopenharmony_ci .val_bits = 8, 2468c2ecf20Sopenharmony_ci .max_register = 0x1f, 2478c2ecf20Sopenharmony_ci }, 2488c2ecf20Sopenharmony_ci .num_nvram = 2 2498c2ecf20Sopenharmony_ci}; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int rx8581_probe(struct i2c_client *client, 2528c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct rx8581 *rx8581; 2558c2ecf20Sopenharmony_ci const struct rx85x1_config *config = &rx8581_config; 2568c2ecf20Sopenharmony_ci const void *data = of_device_get_match_data(&client->dev); 2578c2ecf20Sopenharmony_ci static struct nvmem_config nvmem_cfg[] = { 2588c2ecf20Sopenharmony_ci { 2598c2ecf20Sopenharmony_ci .name = "rx85x1-", 2608c2ecf20Sopenharmony_ci .word_size = 1, 2618c2ecf20Sopenharmony_ci .stride = 1, 2628c2ecf20Sopenharmony_ci .size = 1, 2638c2ecf20Sopenharmony_ci .reg_read = rx85x1_nvram_read, 2648c2ecf20Sopenharmony_ci .reg_write = rx85x1_nvram_write, 2658c2ecf20Sopenharmony_ci }, { 2668c2ecf20Sopenharmony_ci .name = "rx8571-", 2678c2ecf20Sopenharmony_ci .word_size = 1, 2688c2ecf20Sopenharmony_ci .stride = 1, 2698c2ecf20Sopenharmony_ci .size = RX8571_NVRAM_SIZE, 2708c2ecf20Sopenharmony_ci .reg_read = rx8571_nvram_read, 2718c2ecf20Sopenharmony_ci .reg_write = rx8571_nvram_write, 2728c2ecf20Sopenharmony_ci }, 2738c2ecf20Sopenharmony_ci }; 2748c2ecf20Sopenharmony_ci int ret, i; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "%s\n", __func__); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (data) 2798c2ecf20Sopenharmony_ci config = data; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL); 2828c2ecf20Sopenharmony_ci if (!rx8581) 2838c2ecf20Sopenharmony_ci return -ENOMEM; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci i2c_set_clientdata(client, rx8581); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci rx8581->regmap = devm_regmap_init_i2c(client, &config->regmap); 2888c2ecf20Sopenharmony_ci if (IS_ERR(rx8581->regmap)) 2898c2ecf20Sopenharmony_ci return PTR_ERR(rx8581->regmap); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci rx8581->rtc = devm_rtc_allocate_device(&client->dev); 2928c2ecf20Sopenharmony_ci if (IS_ERR(rx8581->rtc)) 2938c2ecf20Sopenharmony_ci return PTR_ERR(rx8581->rtc); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci rx8581->rtc->ops = &rx8581_rtc_ops; 2968c2ecf20Sopenharmony_ci rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 2978c2ecf20Sopenharmony_ci rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099; 2988c2ecf20Sopenharmony_ci rx8581->rtc->start_secs = 0; 2998c2ecf20Sopenharmony_ci rx8581->rtc->set_start_time = true; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci ret = rtc_register_device(rx8581->rtc); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci for (i = 0; i < config->num_nvram; i++) { 3048c2ecf20Sopenharmony_ci nvmem_cfg[i].priv = rx8581; 3058c2ecf20Sopenharmony_ci rtc_nvmem_register(rx8581->rtc, &nvmem_cfg[i]); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci return ret; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic const struct i2c_device_id rx8581_id[] = { 3128c2ecf20Sopenharmony_ci { "rx8581", 0 }, 3138c2ecf20Sopenharmony_ci { } 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rx8581_id); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct of_device_id rx8581_of_match[] = { 3188c2ecf20Sopenharmony_ci { .compatible = "epson,rx8571", .data = &rx8571_config }, 3198c2ecf20Sopenharmony_ci { .compatible = "epson,rx8581", .data = &rx8581_config }, 3208c2ecf20Sopenharmony_ci { /* sentinel */ } 3218c2ecf20Sopenharmony_ci}; 3228c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rx8581_of_match); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic struct i2c_driver rx8581_driver = { 3258c2ecf20Sopenharmony_ci .driver = { 3268c2ecf20Sopenharmony_ci .name = "rtc-rx8581", 3278c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rx8581_of_match), 3288c2ecf20Sopenharmony_ci }, 3298c2ecf20Sopenharmony_ci .probe = rx8581_probe, 3308c2ecf20Sopenharmony_ci .id_table = rx8581_id, 3318c2ecf20Sopenharmony_ci}; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cimodule_i2c_driver(rx8581_driver); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ciMODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); 3368c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Epson RX-8571/RX-8581 RTC driver"); 3378c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 338