From 864becce0496368f8da1363857d7d0a8ef566c3d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Aug 2009 05:05:30 +0000 Subject: Add Freescale MC13783 RTC driver This driver provides support for the RTC part integrated into the Freescale MC13783 PMIC. changes since v1: - use set_mmss instead of set_time - fix __devinit / __devexit usage - use platform_driver_probe instead of platform_driver_register - add MODULE_ALIAS Signed-off-by: Sascha Hauer Cc: Paul Gortmaker Cc: Alessandro Zummo Cc: rtc-linux@googlegroups.com --- drivers/rtc/Kconfig | 6 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-mc13783.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 drivers/rtc/rtc-mc13783.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 14d5f9c49cc3..4e1095727b60 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -770,4 +770,10 @@ config RTC_DRV_PS3 This driver can also be built as a module. If so, the module will be called rtc-ps3. +config RTC_DRV_MC13783 + depends on MFD_MC13783 + tristate "Freescale MC13783 RTC" + help + This enables support for the Freescale MC13783 PMIC RTC + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 91422db12ec6..74eeeefc8780 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -51,6 +51,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_MC13783) += rtc-mc13783.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 diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c new file mode 100644 index 000000000000..dfa470224c41 --- /dev/null +++ b/drivers/rtc/rtc-mc13783.c @@ -0,0 +1,135 @@ +/* + * Real Time Clock driver for Freescale MC13783 PMIC + * + * (C) 2009 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +struct mc13783_rtc { + struct rtc_device *rtc; + struct mc13783 *mc13783; +}; + +static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + unsigned int seconds, days; + + seconds = secs % 86400; + days = secs / 86400; + + mc13783_reg_write(priv->mc13783, MC13783_REG_RTC_TIME, seconds); + mc13783_reg_write(priv->mc13783, MC13783_REG_RTC_DAY, days); + + return 0; +} + +static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + unsigned int seconds, days1, days2; + unsigned long s1970; + + rtc_tm_to_time(tm, &s1970); + + do { + mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_TIME, &seconds); + mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_DAY, &days1); + mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_DAY, &days2); + } while (days1 != days2); + + s1970 = days1 * 86400 + seconds; + + rtc_time_to_tm(s1970, tm); + + return rtc_valid_tm(tm); +} + +static const struct rtc_class_ops mc13783_rtc_ops = { + .read_time = mc13783_rtc_read_time, + .set_mmss = mc13783_rtc_set_mmss, +}; + +static int __devinit mc13783_rtc_probe(struct platform_device *pdev) +{ + int err; + struct mc13783_rtc *priv; + + priv = kzalloc(sizeof *priv, GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->mc13783 = dev_get_drvdata(pdev->dev.parent); + platform_set_drvdata(pdev, priv); + + priv->rtc = rtc_device_register(pdev->name, + &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); + + if (IS_ERR(priv->rtc)) { + err = PTR_ERR(priv->rtc); + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(priv); + return err; +} + +static int __devexit mc13783_rtc_remove(struct platform_device *pdev) +{ + struct mc13783_rtc *priv = platform_get_drvdata(pdev); + + rtc_device_unregister(priv->rtc); + platform_set_drvdata(pdev, NULL); + + kfree(priv); + + return 0; +} + +static struct platform_driver mc13783_rtc_driver = { + .remove = __devexit_p(mc13783_rtc_remove), + .driver = { + .name = "mc13783-rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init mc13783_rtc_init(void) +{ + return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe); +} +module_init(mc13783_rtc_init); + +static void __exit mc13783_rtc_exit(void) +{ + platform_driver_unregister(&mc13783_rtc_driver); +} +module_exit(mc13783_rtc_exit); + + +MODULE_AUTHOR("Sascha Hauer "); +MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mc13783-rtc"); -- cgit v1.2.3