Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752954AbbHSJxo (ORCPT ); Wed, 19 Aug 2015 05:53:44 -0400 Received: from mail-by2on0057.outbound.protection.outlook.com ([207.46.100.57]:34000 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751165AbbHSJxm (ORCPT ); Wed, 19 Aug 2015 05:53:42 -0400 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/2] drivers: rtc: add xilinx zynqmp rtc driver Date: Wed, 19 Aug 2015 15:23:22 +0530 Message-ID: <1439978002-12157-2-git-send-email-suneel.garapati@xilinx.com> X-Mailer: git-send-email 2.1.2 In-Reply-To: <1439978002-12157-1-git-send-email-suneel.garapati@xilinx.com> References: <1439978002-12157-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-21756.000 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD052;1:usr6T6w3mHH4dnwc4y2p/wB1pi1GHESOvppKON9iQ00z04ppsbyxg0tf7TPQS99nOtuVreXre309VmoDkJtJ/q69AYdrd/VPNO17+w6lrL7KrgF/y0PPsM09r8/4xVNuqnD89uzOQ6PRRSZZRRYtxVhQhO2P8sBCEhlLD9czc+8HknJLOrPbyqhx4pkSHc0ejq9ivh0Dewe/Zd23Abt5nIGQS90xWr98+KYKfoaOXYYwBm46Lvs2Qlbw5ayZSDbF0yLhKWvIkBZCfIorjh+Ff4G//N+bOIpYGIegrUjKPqr/AS7kNBPegFM5JaSszpHT7t6iShYFoJlj2ZQP3kKstWjTNdkF2rUeW9MbLNjibpYpN1nmaplqpxgVnAb3oDIi 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)(5001830100001)(5001860100001)(19580405001)(2950100001)(48376002)(47776003)(15975445007)(19580395003)(2201001)(87936001)(63266004)(50466002)(50986999)(46102003)(106466001)(4001540100001)(107886002)(5001770100001)(76176999)(64706001)(33646002)(5001960100002)(189998001)(86362001)(92566002)(6806004)(81156007)(36756003)(77156002)(50226001)(229853001)(77096005)(36386004)(5003600100002)(5003940100001)(575784001)(62966003)(107986001)(2004002)(4001430100001)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:BY2FFO11HUB046;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;BY2FFO11HUB046;2:CC/ZGW8fLbB3D7RguD2kFvZaaWwK9/DCgK+eULtHFe6/EFNRvZ211vG0S9nPO9OAaaUXJaq5o6NpKR3FnF32DemIAnoif7Bk5BAkE3kKmOCDM4IXJTfP4gxXKVFAWR68ltcVwtj6XuMl4VYNNwQPR5gUQ20dyqgMLJsNhCvC/Yo=;3:8/gzcMzCiHxt5ZX7n+O2pcaF0YNJuVISeBWNEfOREk3yImjIjTA5r3iqA1EJuN0DDOjJhOdeNfU0syG8EIDqwTRAC6H0kkYD4MDvYXoDI0zjiEqfwAnS9JPgRyfLtO+kktA03cVO+DA8O+9uTQJ0vrWg+smo/3iy9ztQv3jqh1gV/ehpzH6EZecDV/qE8V/yw8GTpCu05P3L5QzWVdzkWv79t7Bv4PA49O+ETShuRAY=;25:rdQn7UiUhong3yVUWzopcgt388D9xA34bEs9WVAEy0zZE2pMZUZM1SGwhQe9nfwozNnJ6JhgM+RNF7v+TUtHy2TLVY3ytEIpBmHnXi6iaIRa9zSQzuD5MRxfP16LngkFyyuFF/AwHTZNAraeREbIR7u6viJ0l4s+tH8PUN6HWirYGRuVv+cgRG75z3I1Uho1brVBQlghcdSyBoqmKzlSl4HsVenFwSfL7wl57heRnhwIaFMwm6+gjItEL/hQxcACnVjODlf6W0Un2MnE1JYt1w== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB046; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB046;20:qw33PQTudSUsT/RgmOvQ3b7cXlP5cp4bwHwOTaApY8qwaqNarA1kNaYoRDjsAw5KO96CmyoUEUzucPgclh92IFBUuxrHke+EfDMCYG84N7x3/cJKqV/FjMIKxIW8QKXPDHOlYKPis2UQ8HH0mbPZkRUm9jmpOYBRGP8pfLEERRxyDC5QmS01/90A83M6p6puT/TxZ0chLTEYkwnMiM3mdjTXJRthN8awPbJCO0Vsy+GvNjkLAEZNRhZd6M4yADJICvLtZfIAFFOP88FhU5Bx98ZVBVfndV5tKbtbvK/8zaWuQQGy9GLNs30yRKuwpbswcderXEAR5aOlvbrOdlgStdobOYf/o4ph1CpOJmX6CjHRwCnbbec6eS03jJ5XrTjDNwc5AwbJZxBP27y7Sb/d6uURoLYyrX29kow2qaPH/53MrCfCBrw8Z0Y0NF2r2WGLd5WjxU9//+aPmuIPFQfos7bPifqVyer/vJWopyOEcW3x8NnWapEFLVioc9yd/WcK;4:5mIrb13NbZQXCgNLFMqaqFuYiD8jY2x2DYOeTcn3khZHI788E2x81BcAaEY2SvZNXB1WMB5LTu/VMA58mZOhlxRNMzN36SwKOR7c4vZDgrcfKZ36JAx3t5p5AsmrSsgD6fPB/LnExMy39lxrhZ4oaWXdAs0uRG1qM0mvpk3/HhlBXW35xdwHsXyUauTLVFBxODjNWBKDb7u/iSDwKD4fgCDRecpGBKivhjrHC4o0u7/zURi8POb1DYtB+M/ncL/bwK6V3oR11zd0aVCNDKXzEou29aWMdnstmAHjVG4Ej5VJhK30XhjT/Tl5SWWrYuPvuuqodto1azV8EeOXhjkIhf/TnQXbRpngoX4teKjCVOfqJE6jl5wbDgXf0RkdxYNf X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(8121501046)(8121501016)(8121501027)(3002001);SRVR:BY2FFO11HUB046;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB046; X-Forefront-PRVS: 0673F5BE31 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY2FFO11HUB046;23:NZRfJO6Y5uqKTtsd6g2/C3RZTd92J44MMB3BDqLa?= =?us-ascii?Q?OfciM/oLXZAjSzFRVITe14VeWi3QNJYDGhbB3b9RCZ5VHYNvNCl+IEhrubwM?= =?us-ascii?Q?AvqO0LVUbX6VZCr/zITsS4FBajSPCG13NaqwE4Ab6jCLpveXacTfLoYbjiMW?= =?us-ascii?Q?XNr1SVu3QXp+wCBZdDmJwdz2eo9gNtergMD1dX54qRf5zfdeZyce/KEmq7l2?= =?us-ascii?Q?fGaJ5ByU5FtqPlIdjtruvSAPFLp4VUbL0hobGXQaa3Q93YfKtJZlYAxEJMwN?= =?us-ascii?Q?CDgJKox4itEAvngrrhaw2hY8WmhP/9IqyFVXV6g+oglodLmxPwDbcZNACKh4?= =?us-ascii?Q?l/tWscG64iaOLNshSNod0ZQePuk4ROVrWdQ6uEsAK1qRcKn3D2qs1hUOS8Jf?= =?us-ascii?Q?fXBr7FsbyKP769QOmVF/Xj8znCMXrOhg5755gVRIYsb+C3zCHU20u9cYhj6V?= =?us-ascii?Q?RJ49leg4cAautMEtSS94pvyMJkIfq52jBwLHmS0iyO0QZVBg+ZoduJGJUQ60?= =?us-ascii?Q?OFPIiELBlP4Kx5iZ+9dif3z+juOaxI1IVq0rlWuDNumBF8FWyD3OWQ1G4ufo?= =?us-ascii?Q?3Hc7j43VyIFSBBC+3YAy/2yFDRiCmGBExclLGL+WPzFBI+YKsg/Dvk4aYv3C?= =?us-ascii?Q?SYyL+pjKNOAxchLcArAklmeRj3eSv9wAJOpW5306gEAnDJoATsBp1qF5ILIs?= =?us-ascii?Q?mZuOiI4h0Rs+ihdBjo1+7IIMh9sZx9B0h0osxrxL9dqKMBln49AaqWKT3NZO?= =?us-ascii?Q?BS61SnKEQx3/2cjoifAzwKJP0VseUxrGRX3E8Rqm0zS6c9b4roV54yPGIswH?= =?us-ascii?Q?9b5NTEE8VvfCgTiAisoYCZurs/XaP7HvYB2EeFSJrwkrFe/qz4O90eAmLrww?= =?us-ascii?Q?jkEOgemyfHhSR17ZaxgWPlOb1Ny9R1muHucKxCc772+2tvdIzXStwGtRjaNK?= =?us-ascii?Q?77YHH4YuxIEpLuFf1iTiJ+73mGbI5UaKmJJ6Bj4EvOa9QQgQEtTjwQ85Nsiw?= =?us-ascii?Q?nthGjf3R+ngteNkYYShFqmNQu0llzNbzZvp7+5S3XMT94lX2MCCHrWK+i6Xc?= =?us-ascii?Q?1zOKExCyp1iGbQaYDJJ3MscMAXXosehQpAt5V26hykcdGVq4mJJgZ7yIw/p7?= =?us-ascii?Q?f2aPg5eMv40QzYyfHJTlQc0UhRrwXSJwq3y4lDf3yUVU6Zi7n+tP5cNPxxcP?= =?us-ascii?Q?+G0OpcbXR+b6LU9yV6p08FVq2YXuvYGNobgr6cay2wEtrAsuIxt4U34O2NQK?= =?us-ascii?Q?2B9xXc0cjVNPvJUZLrh+8xA1RZe6BKRBSevN4WfW?= X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB046;5:OlWQAOSENvI45VstAG0tAABpQGPlQtS8poVMIuaTUfx9kU8LMrHtBkSJUmkyZHSB7viKqESQVA8/gpe0QzaOIsGqTE5Y9T0NvqDllxI4E/XG7ZKfNND7g/D6oa3cq5XWf6qmX4TV2xiCPRlwlio9Dw==;24:ffGDiDbkdE8UNDWe9sQb4FaQUErcs3RhcuNOi9RSwbOuCixP/M+9NcnEbL2eu5HHsBLTnKjWpfLKNfwpsbtM8x5pOgLIfEvhCMKhPxSvLTI= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2015 09:53:38.6647 (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: BY2FFO11HUB046 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9390 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/