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