diff mbox

rtc: Driver for Marvell's SoCs 88F6281 and 88F6192

Message ID 20081209095708.21516.98999.stgit@i1501.lan.towertech.it
State Accepted, archived
Headers show

Commit Message

Alessandro Zummo Dec. 9, 2008, 9:57 a.m. UTC
From: Saeed Bishara <saeed@marvell.com>

Driver for the on-chip RTC found in some of Marvell's SoCs
such as the Kirkwood 88F6281 and 88F6192 devices.

Signed-off-by: Saeed Bishara <saeed@marvell.com>
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
---

 drivers/rtc/Kconfig  |   11 +++
 drivers/rtc/Makefile |    1 
 drivers/rtc/rtc-mv.c |  163 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-mv.c



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---

Comments

Andrew Morton Dec. 9, 2008, 7:42 p.m. UTC | #1
On Tue, 09 Dec 2008 10:57:08 +0100
Alessandro Zummo <a.zummo@towertech.it> wrote:

> From: Saeed Bishara <saeed@marvell.com>
> 
> Driver for the on-chip RTC found in some of Marvell's SoCs
> such as the Kirkwood 88F6281 and 88F6192 devices.
> 
> Signed-off-by: Saeed Bishara <saeed@marvell.com>
> Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
> Signed-off-by: Nicolas Pitre <nico@marvell.com>
> Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
> ---
> 
>  drivers/rtc/Kconfig  |   11 +++
>  drivers/rtc/Makefile |    1 
>  drivers/rtc/rtc-mv.c |  163 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 175 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/rtc/rtc-mv.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 5caa82d..b2cf166 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -704,4 +704,15 @@ config RTC_DRV_STARFIRE
>  	  If you say Y here you will get support for the RTC found on
>  	  Starfire systems.
>  
> +config RTC_DRV_MV
> +	tristate "Marvell SoC RTC"
> +	depends on ARCH_KIRKWOOD
> +	help
> +	  If you say yes here you will get support for the in-chip RTC
> +	  that can be found in some of Marvell's SoC devices, such as
> +	  the Kirkwood 88F6281 and 88F6192.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called rtc-mv.

hm, I wonder if "rtc-mv" is a good name.  It implies that this is the
only RTC device which Marvell will ever make.

>  endif # RTC_CLASS
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index fca0c9b..87a3adc 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
>  obj-$(CONFIG_RTC_DRV_STARFIRE)	+= rtc-starfire.o
>  obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o
>  obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
> +obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
>  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
>  obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
>  obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
> diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
> new file mode 100644
> index 0000000..45f12dc
> --- /dev/null
> +++ b/drivers/rtc/rtc-mv.c
> @@ -0,0 +1,163 @@
> +/*
> + * Driver for the RTC in Marvell SoCs.
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/rtc.h>
> +#include <linux/bcd.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +
> +#define RTC_TIME_REG_OFFS	0
> +#define RTC_SECONDS_OFFS	0
> +#define RTC_MINUTES_OFFS	8
> +#define RTC_HOURS_OFFS		16
> +#define RTC_WDAY_OFFS		24
> +#define RTC_HOURS_12H_MODE		(1 << 22) /* 12 hours mode */
> +
> +#define RTC_DATE_REG_OFFS	4
> +#define RTC_MDAY_OFFS		0
> +#define RTC_MONTH_OFFS		8
> +#define RTC_YEAR_OFFS		16
> +
> +
> +struct rtc_plat_data {
> +	struct rtc_device *rtc;
> +	void __iomem *ioaddr;
> +};
> +
> +static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +	u32	rtc_reg;
> +
> +	rtc_reg = (bin2bcd(tm->tm_sec) << RTC_SECONDS_OFFS) |
> +		(bin2bcd(tm->tm_min) << RTC_MINUTES_OFFS) |
> +		(bin2bcd(tm->tm_hour) << RTC_HOURS_OFFS) |
> +		(bin2bcd(tm->tm_wday) << RTC_WDAY_OFFS);
> +	writel(rtc_reg, ioaddr + RTC_TIME_REG_OFFS);
> +
> +	rtc_reg = (bin2bcd(tm->tm_mday) << RTC_MDAY_OFFS) |
> +		(bin2bcd(tm->tm_mon + 1) << RTC_MONTH_OFFS) |
> +		(bin2bcd(tm->tm_year % 100) << RTC_YEAR_OFFS);
> +	writel(rtc_reg, ioaddr + RTC_DATE_REG_OFFS);
> +
> +	return 0;
> +}
> +
> +static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +	u32	rtc_time, rtc_date;
> +	unsigned int year, month, day, hour, minute, second, wday;
> +
> +	rtc_time = readl(ioaddr + RTC_TIME_REG_OFFS);
> +	rtc_date = readl(ioaddr + RTC_DATE_REG_OFFS);
> +
> +	second = rtc_time & 0x7f;
> +	minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
> +	hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
> +	wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
> +
> +	day = rtc_date & 0x3f;
> +	month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f;
> +	year = (rtc_date >> RTC_YEAR_OFFS) & 0xff;
> +
> +	tm->tm_sec = bcd2bin(second);
> +	tm->tm_min = bcd2bin(minute);
> +	tm->tm_hour = bcd2bin(hour);
> +	tm->tm_mday = bcd2bin(day);
> +	tm->tm_wday = bcd2bin(wday);
> +	tm->tm_mon = bcd2bin(month) - 1;
> +	/* hw counts from year 2000, but tm_year is relative to 1900 */
> +	tm->tm_year = bcd2bin(year) + 100;
> +
> +	return rtc_valid_tm(tm);
> +}
> +
> +static const struct rtc_class_ops mv_rtc_ops = {
> +	.read_time	= mv_rtc_read_time,
> +	.set_time	= mv_rtc_set_time,
> +};
> +
> +static int __init mv_rtc_probe(struct platform_device *pdev)
> +{
> +	struct resource *res;
> +	struct rtc_plat_data *pdata;
> +	resource_size_t size;
> +	u32 rtc_time;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return -ENOMEM;
> +
> +	size = resource_size(res);
> +	if (!devm_request_mem_region(&pdev->dev, res->start, size,
> +				     pdev->name))
> +		return -EBUSY;

leak.
		
> +	pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
> +	if (!pdata->ioaddr)
> +		return -ENOMEM;

double leak.

> +	/* make sure the 24 hours mode is enabled */
> +	rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
> +	if (rtc_time & RTC_HOURS_12H_MODE) {
> +		dev_err(&pdev->dev, "24 Hours mode not supported.\n");
> +		return -EINVAL;

triple leak.

> +	}
> +
> +	platform_set_drvdata(pdev, pdata);
> +	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
> +					 &mv_rtc_ops, THIS_MODULE);
> +	if (IS_ERR(pdata->rtc))
> +		return PTR_ERR(pdata->rtc);
> +
> +	return 0;
> +}
> +
> +static int __exit mv_rtc_remove(struct platform_device *pdev)
> +{
> +	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
> +
> +	rtc_device_unregister(pdata->rtc);
> +	return 0;
> +}
> +
> +static struct platform_driver mv_rtc_driver = {
> +	.remove		= __exit_p(mv_rtc_remove),
> +	.driver		= {
> +		.name	= "rtc-mv",
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +static __init int mv_init(void)
> +{
> +	return platform_driver_probe(&mv_rtc_driver, mv_rtc_probe);
> +}
> +
> +static __exit void mv_exit(void)
> +{
> +	platform_driver_unregister(&mv_rtc_driver);
> +}
> +
> +module_init(mv_init);
> +module_exit(mv_exit);
> +
> +MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
> +MODULE_DESCRIPTION("Marvell RTC driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:rtc-mv");

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---
Nicolas Pitre Dec. 9, 2008, 7:56 p.m. UTC | #2
On Tue, 9 Dec 2008, Andrew Morton wrote:

> > +config RTC_DRV_MV
> > +	tristate "Marvell SoC RTC"
> > +	depends on ARCH_KIRKWOOD
> > +	help
> > +	  If you say yes here you will get support for the in-chip RTC
> > +	  that can be found in some of Marvell's SoC devices, such as
> > +	  the Kirkwood 88F6281 and 88F6192.
> > +
> > +	  This driver can also be built as a module. If so, the module
> > +	  will be called rtc-mv.
> 
> hm, I wonder if "rtc-mv" is a good name.  It implies that this is the
> only RTC device which Marvell will ever make.

Heh.  This is the best name that came out internally within Marvell.  So 
if we ever produce another RTC variant then maybe we'll have ground to 
rename things appropriately.

> > +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> > +	if (!pdata)
> > +		return -ENOMEM;
> > +
> > +	size = resource_size(res);
> > +	if (!devm_request_mem_region(&pdev->dev, res->start, size,
> > +				     pdev->name))
> > +		return -EBUSY;
> 
> leak.

Isn't "devm_" in devm_kzalloc() supposed to mean there is no leak?

> > +	pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
> > +	if (!pdata->ioaddr)
> > +		return -ENOMEM;
> 
> double leak.

Ditto.

> > +	/* make sure the 24 hours mode is enabled */
> > +	rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
> > +	if (rtc_time & RTC_HOURS_12H_MODE) {
> > +		dev_err(&pdev->dev, "24 Hours mode not supported.\n");
> > +		return -EINVAL;
> 
> triple leak.

Double ditto.


Nicolas

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---
Andrew Morton Dec. 9, 2008, 8:03 p.m. UTC | #3
On Tue, 9 Dec 2008 14:56:59 -0500 (EST)
Nicolas Pitre <nico@marvell.com> wrote:

> > leak.
> 
> Isn't "devm_" in devm_kzalloc() supposed to mean there is no leak?

Oh.  That shows how much atention I paid when that stuff went it.

wtf did we do that for?  Sigh.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---
Nicolas Pitre Dec. 9, 2008, 8:25 p.m. UTC | #4
On Tue, 9 Dec 2008, Andrew Morton wrote:

> On Tue, 9 Dec 2008 14:56:59 -0500 (EST)
> Nicolas Pitre <nico@marvell.com> wrote:
> 
> > > leak.
> > 
> > Isn't "devm_" in devm_kzalloc() supposed to mean there is no leak?
> 
> Oh.  That shows how much atention I paid when that stuff went it.

It's been in mainline for nearly 2 years now.  Amazing you didn't come 
across it since then.

> wtf did we do that for?  Sigh.

	http://lwn.net/Articles/215996/
	http://lwn.net/Articles/222860/


Nicolas

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---
Andrew Morton Dec. 9, 2008, 8:44 p.m. UTC | #5
On Tue, 9 Dec 2008 15:25:18 -0500 (EST)
Nicolas Pitre <nico@marvell.com> wrote:

> On Tue, 9 Dec 2008, Andrew Morton wrote:
> 
> > On Tue, 9 Dec 2008 14:56:59 -0500 (EST)
> > Nicolas Pitre <nico@marvell.com> wrote:
> > 
> > > > leak.
> > > 
> > > Isn't "devm_" in devm_kzalloc() supposed to mean there is no leak?
> > 
> > Oh.  That shows how much atention I paid when that stuff went it.
> 
> It's been in mainline for nearly 2 years now.  Amazing you didn't come 
> across it since then.

Oh, I saw it go past, but I didn't notice this aspect of it.  I would
have objected had I done so.

> > wtf did we do that for?  Sigh.
> 
> 	http://lwn.net/Articles/215996/
> 	http://lwn.net/Articles/222860/

Yeah.  We add permanent cost to every machine running this code, for
all time.  Just to save programmers and reviewers a once-off five minute
effort.

That is a stupid, stupid tradeoff decision.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
-~----------~----~----~----~------~----~------~--~---
diff mbox

Patch

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 5caa82d..b2cf166 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -704,4 +704,15 @@  config RTC_DRV_STARFIRE
 	  If you say Y here you will get support for the RTC found on
 	  Starfire systems.
 
+config RTC_DRV_MV
+	tristate "Marvell SoC RTC"
+	depends on ARCH_KIRKWOOD
+	help
+	  If you say yes here you will get support for the in-chip RTC
+	  that can be found in some of Marvell's SoC devices, such as
+	  the Kirkwood 88F6281 and 88F6192.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-mv.
+
 endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index fca0c9b..87a3adc 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -48,6 +48,7 @@  obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
 obj-$(CONFIG_RTC_DRV_STARFIRE)	+= rtc-starfire.o
 obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
new file mode 100644
index 0000000..45f12dc
--- /dev/null
+++ b/drivers/rtc/rtc-mv.c
@@ -0,0 +1,163 @@ 
+/*
+ * Driver for the RTC in Marvell SoCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+
+#define RTC_TIME_REG_OFFS	0
+#define RTC_SECONDS_OFFS	0
+#define RTC_MINUTES_OFFS	8
+#define RTC_HOURS_OFFS		16
+#define RTC_WDAY_OFFS		24
+#define RTC_HOURS_12H_MODE		(1 << 22) /* 12 hours mode */
+
+#define RTC_DATE_REG_OFFS	4
+#define RTC_MDAY_OFFS		0
+#define RTC_MONTH_OFFS		8
+#define RTC_YEAR_OFFS		16
+
+
+struct rtc_plat_data {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+};
+
+static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u32	rtc_reg;
+
+	rtc_reg = (bin2bcd(tm->tm_sec) << RTC_SECONDS_OFFS) |
+		(bin2bcd(tm->tm_min) << RTC_MINUTES_OFFS) |
+		(bin2bcd(tm->tm_hour) << RTC_HOURS_OFFS) |
+		(bin2bcd(tm->tm_wday) << RTC_WDAY_OFFS);
+	writel(rtc_reg, ioaddr + RTC_TIME_REG_OFFS);
+
+	rtc_reg = (bin2bcd(tm->tm_mday) << RTC_MDAY_OFFS) |
+		(bin2bcd(tm->tm_mon + 1) << RTC_MONTH_OFFS) |
+		(bin2bcd(tm->tm_year % 100) << RTC_YEAR_OFFS);
+	writel(rtc_reg, ioaddr + RTC_DATE_REG_OFFS);
+
+	return 0;
+}
+
+static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u32	rtc_time, rtc_date;
+	unsigned int year, month, day, hour, minute, second, wday;
+
+	rtc_time = readl(ioaddr + RTC_TIME_REG_OFFS);
+	rtc_date = readl(ioaddr + RTC_DATE_REG_OFFS);
+
+	second = rtc_time & 0x7f;
+	minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
+	hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
+	wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
+
+	day = rtc_date & 0x3f;
+	month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f;
+	year = (rtc_date >> RTC_YEAR_OFFS) & 0xff;
+
+	tm->tm_sec = bcd2bin(second);
+	tm->tm_min = bcd2bin(minute);
+	tm->tm_hour = bcd2bin(hour);
+	tm->tm_mday = bcd2bin(day);
+	tm->tm_wday = bcd2bin(wday);
+	tm->tm_mon = bcd2bin(month) - 1;
+	/* hw counts from year 2000, but tm_year is relative to 1900 */
+	tm->tm_year = bcd2bin(year) + 100;
+
+	return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops mv_rtc_ops = {
+	.read_time	= mv_rtc_read_time,
+	.set_time	= mv_rtc_set_time,
+};
+
+static int __init mv_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct rtc_plat_data *pdata;
+	resource_size_t size;
+	u32 rtc_time;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	size = resource_size(res);
+	if (!devm_request_mem_region(&pdev->dev, res->start, size,
+				     pdev->name))
+		return -EBUSY;
+
+	pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
+	if (!pdata->ioaddr)
+		return -ENOMEM;
+
+	/* make sure the 24 hours mode is enabled */
+	rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
+	if (rtc_time & RTC_HOURS_12H_MODE) {
+		dev_err(&pdev->dev, "24 Hours mode not supported.\n");
+		return -EINVAL;
+	}
+
+	platform_set_drvdata(pdev, pdata);
+	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+					 &mv_rtc_ops, THIS_MODULE);
+	if (IS_ERR(pdata->rtc))
+		return PTR_ERR(pdata->rtc);
+
+	return 0;
+}
+
+static int __exit mv_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(pdata->rtc);
+	return 0;
+}
+
+static struct platform_driver mv_rtc_driver = {
+	.remove		= __exit_p(mv_rtc_remove),
+	.driver		= {
+		.name	= "rtc-mv",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int mv_init(void)
+{
+	return platform_driver_probe(&mv_rtc_driver, mv_rtc_probe);
+}
+
+static __exit void mv_exit(void)
+{
+	platform_driver_unregister(&mv_rtc_driver);
+}
+
+module_init(mv_init);
+module_exit(mv_exit);
+
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_DESCRIPTION("Marvell RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rtc-mv");