18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MOXA ART RTC driver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Jonas Jensen 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Jonas Jensen <jonas.jensen@gmail.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based on code from 108c2ecf20Sopenharmony_ci * Moxa Technology Co., Ltd. <www.moxa.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/rtc.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/gpio.h> 208c2ecf20Sopenharmony_ci#include <linux/of_gpio.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define GPIO_RTC_RESERVED 0x0C 238c2ecf20Sopenharmony_ci#define GPIO_RTC_DATA_SET 0x10 248c2ecf20Sopenharmony_ci#define GPIO_RTC_DATA_CLEAR 0x14 258c2ecf20Sopenharmony_ci#define GPIO_RTC_PIN_PULL_ENABLE 0x18 268c2ecf20Sopenharmony_ci#define GPIO_RTC_PIN_PULL_TYPE 0x1C 278c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_ENABLE 0x20 288c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_RAW_STATE 0x24 298c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_MASKED_STATE 0x28 308c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_MASK 0x2C 318c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_CLEAR 0x30 328c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_TRIGGER 0x34 338c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_BOTH 0x38 348c2ecf20Sopenharmony_ci#define GPIO_RTC_INT_RISE_NEG 0x3C 358c2ecf20Sopenharmony_ci#define GPIO_RTC_BOUNCE_ENABLE 0x40 368c2ecf20Sopenharmony_ci#define GPIO_RTC_BOUNCE_PRE_SCALE 0x44 378c2ecf20Sopenharmony_ci#define GPIO_RTC_PROTECT_W 0x8E 388c2ecf20Sopenharmony_ci#define GPIO_RTC_PROTECT_R 0x8F 398c2ecf20Sopenharmony_ci#define GPIO_RTC_YEAR_W 0x8C 408c2ecf20Sopenharmony_ci#define GPIO_RTC_YEAR_R 0x8D 418c2ecf20Sopenharmony_ci#define GPIO_RTC_DAY_W 0x8A 428c2ecf20Sopenharmony_ci#define GPIO_RTC_DAY_R 0x8B 438c2ecf20Sopenharmony_ci#define GPIO_RTC_MONTH_W 0x88 448c2ecf20Sopenharmony_ci#define GPIO_RTC_MONTH_R 0x89 458c2ecf20Sopenharmony_ci#define GPIO_RTC_DATE_W 0x86 468c2ecf20Sopenharmony_ci#define GPIO_RTC_DATE_R 0x87 478c2ecf20Sopenharmony_ci#define GPIO_RTC_HOURS_W 0x84 488c2ecf20Sopenharmony_ci#define GPIO_RTC_HOURS_R 0x85 498c2ecf20Sopenharmony_ci#define GPIO_RTC_MINUTES_W 0x82 508c2ecf20Sopenharmony_ci#define GPIO_RTC_MINUTES_R 0x83 518c2ecf20Sopenharmony_ci#define GPIO_RTC_SECONDS_W 0x80 528c2ecf20Sopenharmony_ci#define GPIO_RTC_SECONDS_R 0x81 538c2ecf20Sopenharmony_ci#define GPIO_RTC_DELAY_TIME 8 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct moxart_rtc { 568c2ecf20Sopenharmony_ci struct rtc_device *rtc; 578c2ecf20Sopenharmony_ci spinlock_t rtc_lock; 588c2ecf20Sopenharmony_ci int gpio_data, gpio_sclk, gpio_reset; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int day_of_year[12] = { 0, 31, 59, 90, 120, 151, 181, 628c2ecf20Sopenharmony_ci 212, 243, 273, 304, 334 }; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic void moxart_rtc_write_byte(struct device *dev, u8 data) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 678c2ecf20Sopenharmony_ci int i; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++, data >>= 1) { 708c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 0); 718c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1)); 728c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 738c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 1); 748c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic u8 moxart_rtc_read_byte(struct device *dev) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 818c2ecf20Sopenharmony_ci int i; 828c2ecf20Sopenharmony_ci u8 data = 0; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 858c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 0); 868c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 878c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 1); 888c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 898c2ecf20Sopenharmony_ci if (gpio_get_value(moxart_rtc->gpio_data)) 908c2ecf20Sopenharmony_ci data |= (1 << i); 918c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci return data; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic u8 moxart_rtc_read_register(struct device *dev, u8 cmd) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 998c2ecf20Sopenharmony_ci u8 data; 1008c2ecf20Sopenharmony_ci unsigned long flags; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci local_irq_save(flags); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci gpio_direction_output(moxart_rtc->gpio_data, 0); 1058c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_reset, 1); 1068c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 1078c2ecf20Sopenharmony_ci moxart_rtc_write_byte(dev, cmd); 1088c2ecf20Sopenharmony_ci gpio_direction_input(moxart_rtc->gpio_data); 1098c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 1108c2ecf20Sopenharmony_ci data = moxart_rtc_read_byte(dev); 1118c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 0); 1128c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_reset, 0); 1138c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci local_irq_restore(flags); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return data; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 1238c2ecf20Sopenharmony_ci unsigned long flags; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci local_irq_save(flags); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci gpio_direction_output(moxart_rtc->gpio_data, 0); 1288c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_reset, 1); 1298c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 1308c2ecf20Sopenharmony_ci moxart_rtc_write_byte(dev, cmd); 1318c2ecf20Sopenharmony_ci moxart_rtc_write_byte(dev, data); 1328c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_sclk, 0); 1338c2ecf20Sopenharmony_ci gpio_set_value(moxart_rtc->gpio_reset, 0); 1348c2ecf20Sopenharmony_ci udelay(GPIO_RTC_DELAY_TIME); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci local_irq_restore(flags); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci spin_lock_irq(&moxart_rtc->rtc_lock); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0); 1468c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W, 1478c2ecf20Sopenharmony_ci (((tm->tm_year - 100) / 10) << 4) | 1488c2ecf20Sopenharmony_ci ((tm->tm_year - 100) % 10)); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W, 1518c2ecf20Sopenharmony_ci (((tm->tm_mon + 1) / 10) << 4) | 1528c2ecf20Sopenharmony_ci ((tm->tm_mon + 1) % 10)); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_DATE_W, 1558c2ecf20Sopenharmony_ci ((tm->tm_mday / 10) << 4) | 1568c2ecf20Sopenharmony_ci (tm->tm_mday % 10)); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W, 1598c2ecf20Sopenharmony_ci ((tm->tm_hour / 10) << 4) | 1608c2ecf20Sopenharmony_ci (tm->tm_hour % 10)); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W, 1638c2ecf20Sopenharmony_ci ((tm->tm_min / 10) << 4) | 1648c2ecf20Sopenharmony_ci (tm->tm_min % 10)); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W, 1678c2ecf20Sopenharmony_ci ((tm->tm_sec / 10) << 4) | 1688c2ecf20Sopenharmony_ci (tm->tm_sec % 10)); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci spin_unlock_irq(&moxart_rtc->rtc_lock); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n" 1758c2ecf20Sopenharmony_ci "tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n", 1768c2ecf20Sopenharmony_ci __func__, tm->tm_year, tm->tm_mon, tm->tm_mday, 1778c2ecf20Sopenharmony_ci tm->tm_hour, tm->tm_min, tm->tm_sec); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 1858c2ecf20Sopenharmony_ci unsigned char v; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci spin_lock_irq(&moxart_rtc->rtc_lock); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R); 1908c2ecf20Sopenharmony_ci tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R); 1938c2ecf20Sopenharmony_ci tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R); 1968c2ecf20Sopenharmony_ci if (v & 0x80) { /* 12-hour mode */ 1978c2ecf20Sopenharmony_ci tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F); 1988c2ecf20Sopenharmony_ci if (v & 0x20) { /* PM mode */ 1998c2ecf20Sopenharmony_ci tm->tm_hour += 12; 2008c2ecf20Sopenharmony_ci if (tm->tm_hour >= 24) 2018c2ecf20Sopenharmony_ci tm->tm_hour = 0; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci } else { /* 24-hour mode */ 2048c2ecf20Sopenharmony_ci tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F); 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R); 2088c2ecf20Sopenharmony_ci tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R); 2118c2ecf20Sopenharmony_ci tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F); 2128c2ecf20Sopenharmony_ci tm->tm_mon--; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R); 2158c2ecf20Sopenharmony_ci tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F); 2168c2ecf20Sopenharmony_ci tm->tm_year += 100; 2178c2ecf20Sopenharmony_ci if (tm->tm_year <= 69) 2188c2ecf20Sopenharmony_ci tm->tm_year += 100; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R); 2218c2ecf20Sopenharmony_ci tm->tm_wday = (v & 0x0f) - 1; 2228c2ecf20Sopenharmony_ci tm->tm_yday = day_of_year[tm->tm_mon]; 2238c2ecf20Sopenharmony_ci tm->tm_yday += (tm->tm_mday - 1); 2248c2ecf20Sopenharmony_ci if (tm->tm_mon >= 2) { 2258c2ecf20Sopenharmony_ci if (!(tm->tm_year % 4) && (tm->tm_year % 100)) 2268c2ecf20Sopenharmony_ci tm->tm_yday++; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci tm->tm_isdst = 0; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci spin_unlock_irq(&moxart_rtc->rtc_lock); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return 0; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic const struct rtc_class_ops moxart_rtc_ops = { 2378c2ecf20Sopenharmony_ci .read_time = moxart_rtc_read_time, 2388c2ecf20Sopenharmony_ci .set_time = moxart_rtc_set_time, 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic int moxart_rtc_probe(struct platform_device *pdev) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci struct moxart_rtc *moxart_rtc; 2448c2ecf20Sopenharmony_ci int ret = 0; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL); 2478c2ecf20Sopenharmony_ci if (!moxart_rtc) 2488c2ecf20Sopenharmony_ci return -ENOMEM; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node, 2518c2ecf20Sopenharmony_ci "gpio-rtc-data", 0); 2528c2ecf20Sopenharmony_ci if (!gpio_is_valid(moxart_rtc->gpio_data)) { 2538c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "invalid gpio (data): %d\n", 2548c2ecf20Sopenharmony_ci moxart_rtc->gpio_data); 2558c2ecf20Sopenharmony_ci return moxart_rtc->gpio_data; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node, 2598c2ecf20Sopenharmony_ci "gpio-rtc-sclk", 0); 2608c2ecf20Sopenharmony_ci if (!gpio_is_valid(moxart_rtc->gpio_sclk)) { 2618c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "invalid gpio (sclk): %d\n", 2628c2ecf20Sopenharmony_ci moxart_rtc->gpio_sclk); 2638c2ecf20Sopenharmony_ci return moxart_rtc->gpio_sclk; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node, 2678c2ecf20Sopenharmony_ci "gpio-rtc-reset", 0); 2688c2ecf20Sopenharmony_ci if (!gpio_is_valid(moxart_rtc->gpio_reset)) { 2698c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "invalid gpio (reset): %d\n", 2708c2ecf20Sopenharmony_ci moxart_rtc->gpio_reset); 2718c2ecf20Sopenharmony_ci return moxart_rtc->gpio_reset; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci spin_lock_init(&moxart_rtc->rtc_lock); 2758c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, moxart_rtc); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data"); 2788c2ecf20Sopenharmony_ci if (ret) { 2798c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "can't get rtc_data gpio\n"); 2808c2ecf20Sopenharmony_ci return ret; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk, 2848c2ecf20Sopenharmony_ci GPIOF_DIR_OUT, "rtc_sclk"); 2858c2ecf20Sopenharmony_ci if (ret) { 2868c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "can't get rtc_sclk gpio\n"); 2878c2ecf20Sopenharmony_ci return ret; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset, 2918c2ecf20Sopenharmony_ci GPIOF_DIR_OUT, "rtc_reset"); 2928c2ecf20Sopenharmony_ci if (ret) { 2938c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "can't get rtc_reset gpio\n"); 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 2988c2ecf20Sopenharmony_ci &moxart_rtc_ops, 2998c2ecf20Sopenharmony_ci THIS_MODULE); 3008c2ecf20Sopenharmony_ci if (IS_ERR(moxart_rtc->rtc)) { 3018c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "devm_rtc_device_register failed\n"); 3028c2ecf20Sopenharmony_ci return PTR_ERR(moxart_rtc->rtc); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic const struct of_device_id moxart_rtc_match[] = { 3098c2ecf20Sopenharmony_ci { .compatible = "moxa,moxart-rtc" }, 3108c2ecf20Sopenharmony_ci { }, 3118c2ecf20Sopenharmony_ci}; 3128c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, moxart_rtc_match); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic struct platform_driver moxart_rtc_driver = { 3158c2ecf20Sopenharmony_ci .probe = moxart_rtc_probe, 3168c2ecf20Sopenharmony_ci .driver = { 3178c2ecf20Sopenharmony_ci .name = "moxart-rtc", 3188c2ecf20Sopenharmony_ci .of_match_table = moxart_rtc_match, 3198c2ecf20Sopenharmony_ci }, 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_cimodule_platform_driver(moxart_rtc_driver); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MOXART RTC driver"); 3248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3258c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>"); 326