diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/rtc/rtc-tile.c | 162 | 
3 files changed, 170 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e1878877399..d2c615fcaa1 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -995,4 +995,11 @@ config RTC_DRV_TEGRA  	  This drive can also be built as a module. If so, the module  	  will be called rtc-tegra. +config RTC_DRV_TILE +	tristate "Tilera hypervisor RTC support" +	depends on TILE +	help +	  Enable support for the Linux driver side of the Tilera +	  hypervisor's real-time clock interface. +  endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ca91c3c42e9..9574748d1c7 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_RTC_DRV_STMP)	+= rtc-stmp3xxx.o  obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o  obj-$(CONFIG_RTC_DRV_TEGRA)	+= rtc-tegra.o  obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o +obj-$(CONFIG_RTC_DRV_TILE)	+= rtc-tile.o  obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o  obj-$(CONFIG_RTC_DRV_TX4939)	+= rtc-tx4939.o  obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c new file mode 100644 index 00000000000..eb65dafee66 --- /dev/null +++ b/drivers/rtc/rtc-tile.c @@ -0,0 +1,162 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + *   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, version 2. + * + *   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, GOOD TITLE or + *   NON INFRINGEMENT.  See the GNU General Public License for + *   more details. + * + * Tilera-specific RTC driver. + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> + +/* Platform device pointer. */ +static struct platform_device *tile_rtc_platform_device; + +/* + * RTC read routine.  Gets time info from RTC chip via hypervisor syscall. + */ +static int read_rtc_time(struct device *dev, struct rtc_time *tm) +{ +	HV_RTCTime hvtm = hv_get_rtc(); + +	tm->tm_sec = hvtm.tm_sec; +	tm->tm_min = hvtm.tm_min; +	tm->tm_hour = hvtm.tm_hour; +	tm->tm_mday = hvtm.tm_mday; +	tm->tm_mon = hvtm.tm_mon; +	tm->tm_year = hvtm.tm_year; +	tm->tm_wday = 0; +	tm->tm_yday = 0; +	tm->tm_isdst = 0; + +	if (rtc_valid_tm(tm) < 0) +		dev_warn(dev, "Read invalid date/time from RTC\n"); + +	return 0; +} + +/* + * RTC write routine.  Sends time info to hypervisor via syscall, to be + * written to RTC chip. + */ +static int set_rtc_time(struct device *dev, struct rtc_time *tm) +{ +	HV_RTCTime hvtm; + +	hvtm.tm_sec = tm->tm_sec; +	hvtm.tm_min = tm->tm_min; +	hvtm.tm_hour = tm->tm_hour; +	hvtm.tm_mday = tm->tm_mday; +	hvtm.tm_mon = tm->tm_mon; +	hvtm.tm_year = tm->tm_year; + +	hv_set_rtc(hvtm); + +	return 0; +} + +/* + * RTC read/write ops. + */ +static const struct rtc_class_ops tile_rtc_ops = { +	.read_time	= read_rtc_time, +	.set_time	= set_rtc_time, +}; + +/* + * Device probe routine. + */ +static int __devinit tile_rtc_probe(struct platform_device *dev) +{ +	struct rtc_device *rtc; + +	rtc = rtc_device_register("tile", +				  &dev->dev, &tile_rtc_ops, THIS_MODULE); + +	if (IS_ERR(rtc)) +		return PTR_ERR(rtc); + +	platform_set_drvdata(dev, rtc); + +	return 0; +} + +/* + * Device cleanup routine. + */ +static int __devexit tile_rtc_remove(struct platform_device *dev) +{ +	struct rtc_device *rtc = platform_get_drvdata(dev); + +	if (rtc) +		rtc_device_unregister(rtc); + +	platform_set_drvdata(dev, NULL); + +	return 0; +} + +static struct platform_driver tile_rtc_platform_driver = { +	.driver		= { +		.name	= "rtc-tile", +		.owner	= THIS_MODULE, +	}, +	.probe		= tile_rtc_probe, +	.remove		= __devexit_p(tile_rtc_remove), +}; + +/* + * Driver init routine. + */ +static int __init tile_rtc_driver_init(void) +{ +	int err; + +	err = platform_driver_register(&tile_rtc_platform_driver); +	if (err) +		return err; + +	tile_rtc_platform_device = platform_device_alloc("rtc-tile", 0); +	if (tile_rtc_platform_device == NULL) { +		err = -ENOMEM; +		goto exit_driver_unregister; +	} + +	err = platform_device_add(tile_rtc_platform_device); +	if (err) +		goto exit_device_put; + +	return 0; + +exit_device_put: +	platform_device_put(tile_rtc_platform_device); + +exit_driver_unregister: +	platform_driver_unregister(&tile_rtc_platform_driver); +	return err; +} + +/* + * Driver cleanup routine. + */ +static void __exit tile_rtc_driver_exit(void) +{ +	platform_driver_unregister(&tile_rtc_platform_driver); +} + +module_init(tile_rtc_driver_init); +module_exit(tile_rtc_driver_exit); + +MODULE_DESCRIPTION("Tilera-specific Real Time Clock Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rtc-tile");  |