18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * RTC driver for NXP LPC178x/18xx/43xx Real-Time Clock (RTC) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2011 NXP Semiconductors 68c2ecf20Sopenharmony_ci * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/io.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/of_device.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/rtc.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* LPC24xx RTC register offsets and bits */ 198c2ecf20Sopenharmony_ci#define LPC24XX_ILR 0x00 208c2ecf20Sopenharmony_ci#define LPC24XX_RTCCIF BIT(0) 218c2ecf20Sopenharmony_ci#define LPC24XX_RTCALF BIT(1) 228c2ecf20Sopenharmony_ci#define LPC24XX_CTC 0x04 238c2ecf20Sopenharmony_ci#define LPC24XX_CCR 0x08 248c2ecf20Sopenharmony_ci#define LPC24XX_CLKEN BIT(0) 258c2ecf20Sopenharmony_ci#define LPC178X_CCALEN BIT(4) 268c2ecf20Sopenharmony_ci#define LPC24XX_CIIR 0x0c 278c2ecf20Sopenharmony_ci#define LPC24XX_AMR 0x10 288c2ecf20Sopenharmony_ci#define LPC24XX_ALARM_DISABLE 0xff 298c2ecf20Sopenharmony_ci#define LPC24XX_CTIME0 0x14 308c2ecf20Sopenharmony_ci#define LPC24XX_CTIME1 0x18 318c2ecf20Sopenharmony_ci#define LPC24XX_CTIME2 0x1c 328c2ecf20Sopenharmony_ci#define LPC24XX_SEC 0x20 338c2ecf20Sopenharmony_ci#define LPC24XX_MIN 0x24 348c2ecf20Sopenharmony_ci#define LPC24XX_HOUR 0x28 358c2ecf20Sopenharmony_ci#define LPC24XX_DOM 0x2c 368c2ecf20Sopenharmony_ci#define LPC24XX_DOW 0x30 378c2ecf20Sopenharmony_ci#define LPC24XX_DOY 0x34 388c2ecf20Sopenharmony_ci#define LPC24XX_MONTH 0x38 398c2ecf20Sopenharmony_ci#define LPC24XX_YEAR 0x3c 408c2ecf20Sopenharmony_ci#define LPC24XX_ALSEC 0x60 418c2ecf20Sopenharmony_ci#define LPC24XX_ALMIN 0x64 428c2ecf20Sopenharmony_ci#define LPC24XX_ALHOUR 0x68 438c2ecf20Sopenharmony_ci#define LPC24XX_ALDOM 0x6c 448c2ecf20Sopenharmony_ci#define LPC24XX_ALDOW 0x70 458c2ecf20Sopenharmony_ci#define LPC24XX_ALDOY 0x74 468c2ecf20Sopenharmony_ci#define LPC24XX_ALMON 0x78 478c2ecf20Sopenharmony_ci#define LPC24XX_ALYEAR 0x7c 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* Macros to read fields in consolidated time (CT) registers */ 508c2ecf20Sopenharmony_ci#define CT0_SECS(x) (((x) >> 0) & 0x3f) 518c2ecf20Sopenharmony_ci#define CT0_MINS(x) (((x) >> 8) & 0x3f) 528c2ecf20Sopenharmony_ci#define CT0_HOURS(x) (((x) >> 16) & 0x1f) 538c2ecf20Sopenharmony_ci#define CT0_DOW(x) (((x) >> 24) & 0x07) 548c2ecf20Sopenharmony_ci#define CT1_DOM(x) (((x) >> 0) & 0x1f) 558c2ecf20Sopenharmony_ci#define CT1_MONTH(x) (((x) >> 8) & 0x0f) 568c2ecf20Sopenharmony_ci#define CT1_YEAR(x) (((x) >> 16) & 0xfff) 578c2ecf20Sopenharmony_ci#define CT2_DOY(x) (((x) >> 0) & 0xfff) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define rtc_readl(dev, reg) readl((dev)->rtc_base + (reg)) 608c2ecf20Sopenharmony_ci#define rtc_writel(dev, reg, val) writel((val), (dev)->rtc_base + (reg)) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistruct lpc24xx_rtc { 638c2ecf20Sopenharmony_ci void __iomem *rtc_base; 648c2ecf20Sopenharmony_ci struct rtc_device *rtc; 658c2ecf20Sopenharmony_ci struct clk *clk_rtc; 668c2ecf20Sopenharmony_ci struct clk *clk_reg; 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_set_time(struct device *dev, struct rtc_time *tm) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = dev_get_drvdata(dev); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* Disable RTC during update */ 748c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_SEC, tm->tm_sec); 778c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_MIN, tm->tm_min); 788c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_HOUR, tm->tm_hour); 798c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_DOW, tm->tm_wday); 808c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_DOM, tm->tm_mday); 818c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_DOY, tm->tm_yday); 828c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_MONTH, tm->tm_mon); 838c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_YEAR, tm->tm_year); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = dev_get_drvdata(dev); 938c2ecf20Sopenharmony_ci u32 ct0, ct1, ct2; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci ct0 = rtc_readl(rtc, LPC24XX_CTIME0); 968c2ecf20Sopenharmony_ci ct1 = rtc_readl(rtc, LPC24XX_CTIME1); 978c2ecf20Sopenharmony_ci ct2 = rtc_readl(rtc, LPC24XX_CTIME2); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci tm->tm_sec = CT0_SECS(ct0); 1008c2ecf20Sopenharmony_ci tm->tm_min = CT0_MINS(ct0); 1018c2ecf20Sopenharmony_ci tm->tm_hour = CT0_HOURS(ct0); 1028c2ecf20Sopenharmony_ci tm->tm_wday = CT0_DOW(ct0); 1038c2ecf20Sopenharmony_ci tm->tm_mon = CT1_MONTH(ct1); 1048c2ecf20Sopenharmony_ci tm->tm_mday = CT1_DOM(ct1); 1058c2ecf20Sopenharmony_ci tm->tm_year = CT1_YEAR(ct1); 1068c2ecf20Sopenharmony_ci tm->tm_yday = CT2_DOY(ct2); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = dev_get_drvdata(dev); 1148c2ecf20Sopenharmony_ci struct rtc_time *tm = &wkalrm->time; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci tm->tm_sec = rtc_readl(rtc, LPC24XX_ALSEC); 1178c2ecf20Sopenharmony_ci tm->tm_min = rtc_readl(rtc, LPC24XX_ALMIN); 1188c2ecf20Sopenharmony_ci tm->tm_hour = rtc_readl(rtc, LPC24XX_ALHOUR); 1198c2ecf20Sopenharmony_ci tm->tm_mday = rtc_readl(rtc, LPC24XX_ALDOM); 1208c2ecf20Sopenharmony_ci tm->tm_wday = rtc_readl(rtc, LPC24XX_ALDOW); 1218c2ecf20Sopenharmony_ci tm->tm_yday = rtc_readl(rtc, LPC24XX_ALDOY); 1228c2ecf20Sopenharmony_ci tm->tm_mon = rtc_readl(rtc, LPC24XX_ALMON); 1238c2ecf20Sopenharmony_ci tm->tm_year = rtc_readl(rtc, LPC24XX_ALYEAR); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci wkalrm->enabled = rtc_readl(rtc, LPC24XX_AMR) == 0; 1268c2ecf20Sopenharmony_ci wkalrm->pending = !!(rtc_readl(rtc, LPC24XX_ILR) & LPC24XX_RTCCIF); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci return rtc_valid_tm(&wkalrm->time); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = dev_get_drvdata(dev); 1348c2ecf20Sopenharmony_ci struct rtc_time *tm = &wkalrm->time; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Disable alarm irq during update */ 1378c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALSEC, tm->tm_sec); 1408c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALMIN, tm->tm_min); 1418c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALHOUR, tm->tm_hour); 1428c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALDOM, tm->tm_mday); 1438c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALDOW, tm->tm_wday); 1448c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALDOY, tm->tm_yday); 1458c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALMON, tm->tm_mon); 1468c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ALYEAR, tm->tm_year); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (wkalrm->enabled) 1498c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, 0); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = dev_get_drvdata(dev); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (enable) 1598c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, 0); 1608c2ecf20Sopenharmony_ci else 1618c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic irqreturn_t lpc24xx_rtc_interrupt(int irq, void *data) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci unsigned long events = RTC_IRQF; 1698c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = data; 1708c2ecf20Sopenharmony_ci u32 rtc_iir; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* Check interrupt cause */ 1738c2ecf20Sopenharmony_ci rtc_iir = rtc_readl(rtc, LPC24XX_ILR); 1748c2ecf20Sopenharmony_ci if (rtc_iir & LPC24XX_RTCALF) { 1758c2ecf20Sopenharmony_ci events |= RTC_AF; 1768c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE); 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Clear interrupt status and report event */ 1808c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ILR, rtc_iir); 1818c2ecf20Sopenharmony_ci rtc_update_irq(rtc->rtc, 1, events); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic const struct rtc_class_ops lpc24xx_rtc_ops = { 1878c2ecf20Sopenharmony_ci .read_time = lpc24xx_rtc_read_time, 1888c2ecf20Sopenharmony_ci .set_time = lpc24xx_rtc_set_time, 1898c2ecf20Sopenharmony_ci .read_alarm = lpc24xx_rtc_read_alarm, 1908c2ecf20Sopenharmony_ci .set_alarm = lpc24xx_rtc_set_alarm, 1918c2ecf20Sopenharmony_ci .alarm_irq_enable = lpc24xx_rtc_alarm_irq_enable, 1928c2ecf20Sopenharmony_ci}; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_probe(struct platform_device *pdev) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc; 1978c2ecf20Sopenharmony_ci int irq, ret; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!rtc) 2018c2ecf20Sopenharmony_ci return -ENOMEM; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci rtc->rtc_base = devm_platform_ioremap_resource(pdev, 0); 2048c2ecf20Sopenharmony_ci if (IS_ERR(rtc->rtc_base)) 2058c2ecf20Sopenharmony_ci return PTR_ERR(rtc->rtc_base); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 2088c2ecf20Sopenharmony_ci if (irq < 0) 2098c2ecf20Sopenharmony_ci return irq; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc"); 2128c2ecf20Sopenharmony_ci if (IS_ERR(rtc->clk_rtc)) { 2138c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "error getting rtc clock\n"); 2148c2ecf20Sopenharmony_ci return PTR_ERR(rtc->clk_rtc); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci rtc->clk_reg = devm_clk_get(&pdev->dev, "reg"); 2188c2ecf20Sopenharmony_ci if (IS_ERR(rtc->clk_reg)) { 2198c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "error getting reg clock\n"); 2208c2ecf20Sopenharmony_ci return PTR_ERR(rtc->clk_reg); 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ret = clk_prepare_enable(rtc->clk_rtc); 2248c2ecf20Sopenharmony_ci if (ret) { 2258c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "unable to enable rtc clock\n"); 2268c2ecf20Sopenharmony_ci return ret; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci ret = clk_prepare_enable(rtc->clk_reg); 2308c2ecf20Sopenharmony_ci if (ret) { 2318c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "unable to enable reg clock\n"); 2328c2ecf20Sopenharmony_ci goto disable_rtc_clk; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, rtc); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Clear any pending interrupts */ 2388c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_ILR, LPC24XX_RTCCIF | LPC24XX_RTCALF); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Enable RTC count */ 2418c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci ret = devm_request_irq(&pdev->dev, irq, lpc24xx_rtc_interrupt, 0, 2448c2ecf20Sopenharmony_ci pdev->name, rtc); 2458c2ecf20Sopenharmony_ci if (ret < 0) { 2468c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, "can't request interrupt\n"); 2478c2ecf20Sopenharmony_ci goto disable_clks; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci rtc->rtc = devm_rtc_device_register(&pdev->dev, "lpc24xx-rtc", 2518c2ecf20Sopenharmony_ci &lpc24xx_rtc_ops, THIS_MODULE); 2528c2ecf20Sopenharmony_ci if (IS_ERR(rtc->rtc)) { 2538c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "can't register rtc device\n"); 2548c2ecf20Sopenharmony_ci ret = PTR_ERR(rtc->rtc); 2558c2ecf20Sopenharmony_ci goto disable_clks; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return 0; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cidisable_clks: 2618c2ecf20Sopenharmony_ci clk_disable_unprepare(rtc->clk_reg); 2628c2ecf20Sopenharmony_cidisable_rtc_clk: 2638c2ecf20Sopenharmony_ci clk_disable_unprepare(rtc->clk_rtc); 2648c2ecf20Sopenharmony_ci return ret; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic int lpc24xx_rtc_remove(struct platform_device *pdev) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci struct lpc24xx_rtc *rtc = platform_get_drvdata(pdev); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* Ensure all interrupt sources are masked */ 2728c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE); 2738c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_CIIR, 0); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci clk_disable_unprepare(rtc->clk_rtc); 2788c2ecf20Sopenharmony_ci clk_disable_unprepare(rtc->clk_reg); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic const struct of_device_id lpc24xx_rtc_match[] = { 2848c2ecf20Sopenharmony_ci { .compatible = "nxp,lpc1788-rtc" }, 2858c2ecf20Sopenharmony_ci { } 2868c2ecf20Sopenharmony_ci}; 2878c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, lpc24xx_rtc_match); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic struct platform_driver lpc24xx_rtc_driver = { 2908c2ecf20Sopenharmony_ci .probe = lpc24xx_rtc_probe, 2918c2ecf20Sopenharmony_ci .remove = lpc24xx_rtc_remove, 2928c2ecf20Sopenharmony_ci .driver = { 2938c2ecf20Sopenharmony_ci .name = "lpc24xx-rtc", 2948c2ecf20Sopenharmony_ci .of_match_table = lpc24xx_rtc_match, 2958c2ecf20Sopenharmony_ci }, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_cimodule_platform_driver(lpc24xx_rtc_driver); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com>"); 3008c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("RTC driver for the LPC178x/18xx/408x/43xx SoCs"); 3018c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 302