Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755376AbbHNPdy (ORCPT ); Fri, 14 Aug 2015 11:33:54 -0400 Received: from mail-bn1bon0080.outbound.protection.outlook.com ([157.56.111.80]:42858 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754153AbbHNPdw (ORCPT ); Fri, 14 Aug 2015 11:33:52 -0400 X-Greylist: delayed 1036 seconds by postgrey-1.27 at vger.kernel.org; Fri, 14 Aug 2015 11:33:52 EDT Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; towertech.it; dkim=none (message not signed) header.d=none; From: Suneel Garapati To: , , CC: Alexandre Belloni , , , Alessandro Zummo , Suneel Garapati Subject: [PATCH v3 2/3] drivers: rtc: add xilinx zynqmp rtc driver Date: Fri, 14 Aug 2015 20:31:02 +0530 Message-ID: <1439564462-21252-2-git-send-email-suneel.garapati@xilinx.com> X-Mailer: git-send-email 2.1.2 In-Reply-To: <1439564462-21252-1-git-send-email-suneel.garapati@xilinx.com> References: <1439564462-21252-1-git-send-email-suneel.garapati@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21744.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD049;1:/RefO2kMV01SNXRm3vbqxzoW5y5GS2vpVzTGAT4f0hVsINnQHJctDoUI7hweXY9FWPxbWcUKi4F8334RX2NjnLyB7SojKRBDV5iqBOGhu5XTYYl8LpdUaWwuVsBYB/fHnyFPr7jPLCA1og/tz2yBQYGwj/6FYbElKhsE8ngXT/HlLeU54Kl6GlIOJteNKdwF0MtXDIN9olnEetaS61z3yD+Kz7+0nH5IVuzzPlNKu3PVOE3GyypOP5xvL1qKCRVG/RuYJm+zluAIDszpnTjk3NaIOL12amChZwrURZZ2Nm3WlS1wA/wg3+8LsW9gnju3S5E8XX4/dt7Tr1n2rOjCv4CUI3oBRxsDW5ZYWMCovrJyjsrUy/BCSd8OOaIOaS5q X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(3050300001)(199003)(189002)(87936001)(50466002)(5001960100002)(5001860100001)(36386004)(5003940100001)(62966003)(81156007)(86362001)(107886002)(36756003)(5001830100001)(5001770100001)(77156002)(106466001)(2201001)(5003600100002)(189998001)(575784001)(63266004)(47776003)(19580395003)(48376002)(229853001)(4001540100001)(46102003)(50986999)(64706001)(6806004)(76176999)(33646002)(19580405001)(50226001)(15975445007)(2950100001)(77096005)(92566002)(107986001)(2004002)(4001430100001)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:BY2FFO11HUB002;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB002;2:25ve083jYvw+OAEFPDhoWxqZPSm9FgMlI2zv77Geg+tY70F6hTEbAZPZ8pckqjGxyzPvbN18ySIkspEPQmxaycnPuGc3N7Cdklyt5Ao5v5lTWBccXd0kBnCq1PfNcQ15SN2hUsk6i0l6hSDOGIJo21QKxIftBxCMz1IXq50i4x8=;3:sm1E2zU3l1FbTj2F5hRJYNFIcbtkKm5Y6okbafTFa4tZfShjHbY5illxItD8UwU/jfaiYWvfBHopPwq8heA20QsEJws/g+nmDUZsORCXvbSG2R2wMQDVe3Ys9ngu2FMqPEp4iRsxSH+7Fagz3bwQojYAEmcoEBlI70r/QpbnDudDfoURUcdT+RODGaaD6KQziMWDQHv5vr6YnJ7l/uOI1mMty0b9CRyp9OLkhW7yCkE=;25:stC0FSslpY6KoIe4a1PBK169I8csdepqJIWOg+6lX9mAQG1N8I0EUn+6/68I/YPVrk5h4ojOErqgktUNbnCbRgAZ+zz9e10ixwRUa6Brnbt0qqNqkg2Q7ziTgBcxk4mfjzp0XNXwyzEx/869da5WJXVi9ZyfKFgnFnqG2LclB6RPKFB64JbDEXul49zxJ9QbmnqunK6PMPuSTq+WNHF5mjPh+aFwrBEP7E8Fc7RwXrVpHHyax3WrWOVuIlYdKTEm6rKxdZPDrPaizb/RNjY8aw== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB002; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB002;20:fVRHuOaILVaZNdrghYOhSWGKltzSwDHe8izRrEixhEwM8KpS1L91VHYUo/A/Gb1FvxqH/TjdWJGn/J45GsdCMGCOMf0cWx8e11anuH4W1aUekZF6iDLopXG+RIetZRcSNCbr0GtRQa/urVqq+YyCTYdr6AicZFU7omk97YdiC/RoZYdMBR9rYmcaYSudV1uYy4UEFpnvXmHoUmIIBeRzKaNwQSkb83BnKhcI3JOFYZFj/C+wI3EhUByzEVBnmHSV37f9JDoqu2cw3VLFBBOoK8jiy7vz4fj0QaQ1E/yzMRuqlR8s1uZbmjKkHb7npFO5+K23rpEZZc50frhIMuGN4UyYoEIoRm1I3A4xCzjHHrVV2eoXeG7kRi7qzVgw/GJxiUXXD8ZbBO96SEOVU/y+ZPvGFmkABrfFEUGic10i5zSVhSMo4RSRFI7oUnXEsdVTL+O4FYo13SkbQ8QW660PTlFxmjHxdTCcqG8WmQW1RT4KPPLgt02lPe/u4anrW1lo;4:wUJ8iZiJ/M66n6yYUjHkHigwyNufapVtaS8Uzmk+r+aKjyrMq3rpKkjAar7GSzCE9YC/BjkRW8hkJYIKSlxuyKL9V8dYgm8rj5XCu3MaKHrEYvTbS+hz6GGDHx3voJs61AIzqvNDn/aS73sw1PTQzwU78q1sDQmw8Fyg4ZowQPQm7TUPjagYa/JLfobvQP+y/pE+kxMLlgnNGwHbCLBcGJtKwE66huxsjWW5yYTlmMFaFmc6acRxM+IgUfxiaeca3ywGQ2aLjC6F4jzEoUILsSG/RZihsHhkwLdPwtiEIpS/BSBEgzd8VCpqHg9q1KaL X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(8121501024)(3002001);SRVR:BY2FFO11HUB002;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB002; X-Forefront-PRVS: 066898046A X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY2FFO11HUB002;23:CfEniulvyqVBc/cbzSut5zfLvwxFp2JcXQk7llMg?= =?us-ascii?Q?JJabaabI6/CAmG5j3+xmVKqLdqMOJmonjr7PIdgaAB50y33UVbv4JkWd/bAT?= =?us-ascii?Q?TbQ2PMQzVzVL5qcG3NM/itnnOOgJX35CTDcbXyDb+0OLpXnGbtHkkGcYueEn?= =?us-ascii?Q?OYFTHJo0OZv9bcnIFQwXxZECCimzucPEMyGX/4ff3kSfa9hM8g1u0iYl1YKr?= =?us-ascii?Q?lnCbgD8bJQcyzZiK8IKzP/jv8wBglGOIVEGogq5Aq8WPEug+7RUBLWK+e5zF?= =?us-ascii?Q?5ZXwKqrVyNC5IynVUQodAtGI0MR676O8AvVrzBB1bVWysXsEj4T1CMEgBPhi?= =?us-ascii?Q?BlG3zmLhCikIv6j0vciU1ozMfytwK18G7v1T9XxtipP90mZIpf9MA+C56XzN?= =?us-ascii?Q?5itKkuD6pqj0iQvMyIYljH+gtry8SBjKwYri7HB/KlkfBgtMPMtcqW16aldg?= =?us-ascii?Q?GEEfSfPMoEor5ucV9jCaRkl7SRe09zaXNqk51wrXosaBy4m3SytQOxT7gseY?= =?us-ascii?Q?ZkWJ6BWLZbO3uAvC/HPrGuRH75L+3S5ydRLNqgC6V9pSFBEuycTG8Ie3pJNd?= =?us-ascii?Q?IAWSLJY2+RxdJUn3icaUdmtGmVvaOQ03dM5E0xjb0c+IXTHpv4VEzG1suMfB?= =?us-ascii?Q?pV8cNCqGCp0emdAeM1qK6XVFnfoEFOmwEj61Br0iNtFn0D2WHudXW8MO4tIn?= =?us-ascii?Q?VtiNiifYV451a37jei+cqgrpx2OB25fJ4W3qFo54Mql4sYbQZAmZePg8lrs8?= =?us-ascii?Q?8rBIMuzR0qKd8hJyQC8Cv7ZNG54z/9yySx4RVk4/blGvmMVxT4+XmpN+8lnd?= =?us-ascii?Q?xFGS/ODBj27PFCTJ8iYWUsYV/7w/E0j2BWlq86tX3RMHLPuNoCuhup8LS3pZ?= =?us-ascii?Q?5CF6K/Vu5Pw9o+cBeMrnqheHRUhkC9IXr+/76ufKX6IKlqr/GIDtaLLGaVjh?= =?us-ascii?Q?HxXnLhRSDvUE2/dXRy43ve/Kln0iOPNGfFdYyJXE+LA3uY+YH2baRZZbPOB6?= =?us-ascii?Q?hNJNc6mWJTD2Mg6gDwZhF1Y3RvXSwCS1dNWII7D8UYxiXCQV2ObH9LgzkvLt?= =?us-ascii?Q?1Zv+VFbSg2cdXV7/MYE7XEdVlRVZrsb8IRtEXyrWlvvtdY6LGvvyl40gn23T?= =?us-ascii?Q?2u4mmDh++0R+UbxR0Tx617PJenpq5ibyV0FG9cYHuhW3QxIfEwy0iMxMajJZ?= =?us-ascii?Q?n1x7lIerfwkoyWAcBoyzRDAxG9JLXUS3lG+4KDNz1Kly2/3mYp4xY3ePWvEf?= =?us-ascii?Q?bzYI6PTm8yBWtk+iXAyYagzoC0KmTPK05FH5TnD6?= X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB002;5:ic89Yy0GUsqp0xnvldsXrNEruxjLiNaNzC2l1NGuDH0oGGGpoTX/Hc/EU51mOn+FveiOMgaJI9jOQIrJ6lXigGCK6mcLTTa+QJxmt++uIKaiAULyOZTno2X1RCk7kcSWpI/tvtOr/3fG+IdFv/V7+Q==;24:TmDEm84ww7iR6VRoRWK3yH0v+dby7aFy4FEvRpdAxxH/0LxKHqrNV3hx122IN9vYkBcOkQ480u8/IW00ez2Z5F72wQvA7Za1Fz96ugq2s40= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Aug 2015 15:01:16.9866 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2FFO11HUB002 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9383 Lines: 340 adds support for RTC controller found on Xilinx Zynq Ultrascale+ MPSoC platform. Signed-off-by: Suneel Garapati --- Changes v3 - fix checkpatch errors - check time in secs arg against max sec val - order header files - use ptr_err_or_zero macro - use time64 variants Changes v2 - change alm to alarm --- drivers/rtc/Kconfig | 7 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-zynqmp.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/rtc/rtc-zynqmp.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 35ea04c..bc96277 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1116,6 +1116,13 @@ config RTC_DRV_OPAL This driver can also be built as a module. If so, the module will be called rtc-opal. +config RTC_DRV_ZYNQMP + tristate "Xilinx Zynq Ultrascale+ MPSoC RTC" + depends on OF + help + If you say yes here you get support for the RTC controller found on + Xilinx Zynq Ultrascale+ MPSoC. + comment "on-CPU RTC drivers" config RTC_DRV_DAVINCI diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 2797384..e491eb5 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -159,3 +159,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o +obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c new file mode 100644 index 0000000..8b28762 --- /dev/null +++ b/drivers/rtc/rtc-zynqmp.c @@ -0,0 +1,279 @@ +/* + * Xilinx Zynq Ultrascale+ MPSoC Real Time Clock Driver + * + * Copyright (C) 2015 Xilinx, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* RTC Registers */ +#define RTC_SET_TM_WR 0x00 +#define RTC_SET_TM_RD 0x04 +#define RTC_CALIB_WR 0x08 +#define RTC_CALIB_RD 0x0C +#define RTC_CUR_TM 0x10 +#define RTC_CUR_TICK 0x14 +#define RTC_ALRM 0x18 +#define RTC_INT_STS 0x20 +#define RTC_INT_MASK 0x24 +#define RTC_INT_EN 0x28 +#define RTC_INT_DIS 0x2C +#define RTC_CTRL 0x40 + +#define RTC_FR_EN BIT(20) +#define RTC_FR_DATSHIFT 16 +#define RTC_TICK_MASK 0xFFFF +#define RTC_INT_SEC BIT(0) +#define RTC_INT_ALRM BIT(1) +#define RTC_OSC_EN BIT(24) + +#define RTC_CALIB_DEF 0x198233 +#define RTC_CALIB_MASK 0x1FFFFF +#define RTC_SEC_MAX_VAL 0xFFFFFFFF + +struct xlnx_rtc_dev { + struct rtc_device *rtc; + void __iomem *reg_base; + int alarm_irq; + int sec_irq; +}; + +static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + unsigned long new_time; + + new_time = rtc_tm_to_time64(tm); + + if (new_time > RTC_SEC_MAX_VAL) + return -EINVAL; + + writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR); + + return 0; +} + +static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + + rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm); + + return rtc_valid_tm(tm); +} + +static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + + rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_ALRM), &alrm->time); + alrm->enabled = readl(xrtcdev->reg_base + RTC_INT_MASK) & RTC_INT_ALRM; + + return 0; +} + +static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled) +{ + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + + if (enabled) + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN); + else + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); + + return 0; +} + +static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + unsigned long alarm_time; + + alarm_time = rtc_tm_to_time64(&alrm->time); + + if (alarm_time > RTC_SEC_MAX_VAL) + return -EINVAL; + + writel((u32)alarm_time, (xrtcdev->reg_base + RTC_ALRM)); + + xlnx_rtc_alarm_irq_enable(dev, alrm->enabled); + + return 0; +} + +static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval) +{ + /* + * Based on crystal freq of 33.330 KHz + * set the seconds counter and enable, set fractions counter + * to default value suggested as per design spec + * to correct RTC delay in frequency over period of time. + */ + calibval &= RTC_CALIB_MASK; + writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR)); +} + +static const struct rtc_class_ops xlnx_rtc_ops = { + .set_time = xlnx_rtc_set_time, + .read_time = xlnx_rtc_read_time, + .read_alarm = xlnx_rtc_read_alarm, + .set_alarm = xlnx_rtc_set_alarm, + .alarm_irq_enable = xlnx_rtc_alarm_irq_enable, +}; + +static irqreturn_t xlnx_rtc_interrupt(int irq, void *id) +{ + struct xlnx_rtc_dev *xrtcdev = (struct xlnx_rtc_dev *)id; + unsigned int status; + + status = readl(xrtcdev->reg_base + RTC_INT_STS); + /* Check if interrupt asserted */ + if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) + return IRQ_NONE; + + /* Clear interrupt */ + writel(status, xrtcdev->reg_base + RTC_INT_STS); + + if (status & RTC_INT_SEC) + rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_UF); + if (status & RTC_INT_ALRM) + rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF); + + return IRQ_HANDLED; +} + +static int xlnx_rtc_probe(struct platform_device *pdev) +{ + struct xlnx_rtc_dev *xrtcdev; + struct resource *res; + int ret; + unsigned int calibvalue; + + xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL); + if (!xrtcdev) + return -ENOMEM; + + platform_set_drvdata(pdev, xrtcdev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + xrtcdev->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(xrtcdev->reg_base)) + return PTR_ERR(xrtcdev->reg_base); + + xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm"); + if (xrtcdev->alarm_irq < 0) { + dev_err(&pdev->dev, "no irq resource\n"); + return xrtcdev->alarm_irq; + } + ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq, + xlnx_rtc_interrupt, 0, + dev_name(&pdev->dev), xrtcdev); + if (ret) { + dev_err(&pdev->dev, "request irq failed\n"); + return ret; + } + + xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec"); + if (xrtcdev->sec_irq < 0) { + dev_err(&pdev->dev, "no irq resource\n"); + return xrtcdev->sec_irq; + } + ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq, + xlnx_rtc_interrupt, 0, + dev_name(&pdev->dev), xrtcdev); + if (ret) { + dev_err(&pdev->dev, "request irq failed\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, "calibration", + &calibvalue); + if (ret) + calibvalue = RTC_CALIB_DEF; + + xlnx_init_rtc(xrtcdev, calibvalue); + + device_init_wakeup(&pdev->dev, 1); + + xrtcdev->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &xlnx_rtc_ops, THIS_MODULE); + return PTR_ERR_OR_ZERO(xrtcdev->rtc); +} + +static int xlnx_rtc_remove(struct platform_device *pdev) +{ + xlnx_rtc_alarm_irq_enable(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, 0); + + return 0; +} + +static int __maybe_unused xlnx_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(xrtcdev->alarm_irq); + else + xlnx_rtc_alarm_irq_enable(dev, 0); + + return 0; +} + +static int __maybe_unused xlnx_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev); + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(xrtcdev->alarm_irq); + else + xlnx_rtc_alarm_irq_enable(dev, 1); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(xlnx_rtc_pm_ops, xlnx_rtc_suspend, xlnx_rtc_resume); + +static const struct of_device_id xlnx_rtc_of_match[] = { + {.compatible = "xlnx,zynqmp-rtc" }, + { } +}; +MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match); + +static struct platform_driver xlnx_rtc_driver = { + .probe = xlnx_rtc_probe, + .remove = xlnx_rtc_remove, + .driver = { + .name = KBUILD_MODNAME, + .pm = &xlnx_rtc_pm_ops, + .of_match_table = xlnx_rtc_of_match, + }, +}; + +module_platform_driver(xlnx_rtc_driver); + +MODULE_DESCRIPTION("Xilinx Zynq MPSoC RTC driver"); +MODULE_AUTHOR("Xilinx Inc."); +MODULE_LICENSE("GPL v2"); -- 2.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/