lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 27 Oct 2008 18:04:32 +0100
From:	Alessandro Zummo <alessandro.zummo@...ertech.it>
To:	rtc-linux@...glegroups.com
Cc:	broonie@...nsource.wolfsonmicro.com,
	David Brownell <david-b@...bell.net>,
	Andrew Morton <akpm@...ux-foundation.org>,
	linux-kernel@...r.kernel.org
Subject: Re: [rtc-linux] [PATCH 2/2] rtc: rtc-wm8350: Add support for WM8350
 RTC

On Mon, 27 Oct 2008 15:38:25 +0000
Mark Brown <broonie@...nsource.wolfsonmicro.com> wrote:

> 
> This adds support for the RTC provided by the Wolfson Microelectronics
> WM8350.
> 
> This driver was originally written by Graeme Gregory and Liam Girdwood,
> though it has been modified since then to update it to current mainline
> coding standards and for API completeness.
> 
> Signed-off-by: Mark Brown <broonie@...nsource.wolfsonmicro.com>

 Hi Mark,

  a few notes below:


 (and a detailed checklist at http://groups.google.com/group/rtc-linux/web/checklist )

> ---
> Updated to use schedule_timeout_uninterruptible() as per Andrew's
> suggestion.
> 
>  drivers/rtc/Kconfig            |   10 +
>  drivers/rtc/Makefile           |    1 +
>  drivers/rtc/rtc-wm8350.c       |  514 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/wm8350/rtc.h |    2 +
>  4 files changed, 527 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/rtc/rtc-wm8350.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 8abbb20..7951ad2 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -468,6 +468,16 @@ config RTC_DRV_V3020
>  	  This driver can also be built as a module. If so, the module
>  	  will be called rtc-v3020.
>  
> +config RTC_DRV_WM8350
> +	tristate "Wolfson Microelectronics WM8350 RTC"
> +	depends on MFD_WM8350
> +	help
> +	  If you say yes here you will get support for the RTC subsystem
> +	  of the Wolfson Microelectronics WM8350.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called "rtc-wm8350".
> +
>  comment "on-CPU RTC drivers"
>  
>  config RTC_DRV_OMAP
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index e9e8474..7a41201 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -66,4 +66,5 @@ obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
>  obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl4030.o
>  obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o
>  obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o
> +obj-$(CONFIG_RTC_DRV_WM8350)	+= rtc-wm8350.o
>  obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
> diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
> new file mode 100644
> index 0000000..0a53652
> --- /dev/null
> +++ b/drivers/rtc/rtc-wm8350.c
> @@ -0,0 +1,514 @@
> +/*
> + *	Real Time Clock driver for Wolfson Microelectronics WM8350
> + *
> + *	Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
> + *
> + *  Author: Liam Girdwood
> + *          linux@...fsonmicro.com
> + *
> + *  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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/time.h>
> +#include <linux/rtc.h>
> +#include <linux/bcd.h>
> +#include <linux/interrupt.h>
> +#include <linux/ioctl.h>
> +#include <linux/completion.h>
> +#include <linux/mfd/wm8350/rtc.h>
> +#include <linux/mfd/wm8350/core.h>
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +
> +#define WM8350_SET_ALM_RETRIES	5
> +#define WM8350_SET_TIME_RETRIES	5
> +#define WM8350_GET_TIME_RETRIES	5
> +
> +#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev)
> +
> +/*
> + * Read current time and date in RTC
> + */
> +static int wm8350_rtc_readtime(struct device *dev, struct rtc_time *tm)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(dev);
> +	u16 time1[4], time2[4];
> +	int retries = WM8350_GET_TIME_RETRIES, ret;
> +
> +	/*
> +	 * Read the time twice and compare.
> +	 * If time1 == time2, then time is valid else retry.
> +	 */
> +	do {
> +		ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES,
> +					4, time1);
> +		if (ret < 0)
> +			return ret;
> +		ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES,
> +					4, time2);
> +		if (ret < 0)
> +			return ret;
> +
> +		if (memcmp(time1, time2, sizeof(time1)) == 0) {
> +			tm->tm_sec = time1[0] & WM8350_RTC_SECS_MASK;
> +
> +			tm->tm_min = (time1[0] & WM8350_RTC_MINS_MASK)
> +			    >> WM8350_RTC_MINS_SHIFT;
> +
> +			tm->tm_hour = time1[1] & WM8350_RTC_HRS_MASK;
> +
> +			tm->tm_wday = ((time1[1] >> WM8350_RTC_DAY_SHIFT)
> +				       & 0x7) - 1;
> +
> +			tm->tm_mon = ((time1[2] & WM8350_RTC_MTH_MASK)
> +				      >> WM8350_RTC_MTH_SHIFT) - 1;
> +
> +			tm->tm_mday = (time1[2] & WM8350_RTC_DATE_MASK);
> +
> +			tm->tm_year = ((time1[3] & WM8350_RTC_YHUNDREDS_MASK)
> +				       >> WM8350_RTC_YHUNDREDS_SHIFT) * 100;
> +			tm->tm_year += time1[3] & WM8350_RTC_YUNITS_MASK;
> +
> +			tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon,
> +						    tm->tm_year);
> +			tm->tm_year -= 1900;
> +
> +			dev_dbg(dev, "Read (%d left): %04x %04x %04x %04x\n",
> +				retries,
> +				time1[0], time1[1], time1[2], time1[3]);
> +
> +			return 0;
> +		}
> +	} while (retries--);
> +
> +	dev_err(dev, "timed out reading RTC time\n");
> +	return -EIO;
> +}
> +
> +/*
> + * Set current time and date in RTC
> + */
> +static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(dev);
> +	u16 time[4];
> +	u16 rtc_ctrl;
> +	int ret, retries = WM8350_SET_TIME_RETRIES;
> +
> +	time[0] = tm->tm_sec;
> +	time[0] |= tm->tm_min << WM8350_RTC_MINS_SHIFT;
> +	time[1] = tm->tm_hour;
> +	time[1] |= (tm->tm_wday + 1) << WM8350_RTC_DAY_SHIFT;
> +	time[2] = tm->tm_mday;
> +	time[2] |= (tm->tm_mon + 1) << WM8350_RTC_MTH_SHIFT;
> +	time[3] = ((tm->tm_year + 1900) / 100) << WM8350_RTC_YHUNDREDS_SHIFT;
> +	time[3] |= (tm->tm_year + 1900) % 100;
> +
> +	dev_dbg(dev, "Setting: %04x %04x %04x %04x\n",
> +		time[0], time[1], time[2], time[3]);
> +
> +	/* Set RTC_SET to stop the clock */
> +	ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Wait until confirmation of stopping */
> +	do {
> +		rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
> +		schedule_timeout_uninterruptible(msecs_to_jiffies(1));
> +	} while (retries-- && !(rtc_ctrl & WM8350_RTC_STS));
> +
> +	if (!retries) {
> +		dev_err(dev, "timed out on set confirmation\n");
> +		return -EIO;
> +	}
> +
> +	/* Write time to RTC */
> +	ret = wm8350_block_write(wm8350, WM8350_RTC_SECONDS_MINUTES, 4, time);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Clear RTC_SET to start the clock */
> +	ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
> +				WM8350_RTC_SET);
> +	return ret;
> +}
> +
> +/*
> + * Read alarm time and date in RTC
> + */
> +static int wm8350_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time;
> +	u16 time[4];
> +	int ret;
> +
> +	ret = wm8350_block_read(wm8350, WM8350_ALARM_SECONDS_MINUTES, 4, time);
> +	if (ret < 0)
> +		return ret;
> +
> +	tm->tm_sec = time[0] & WM8350_RTC_ALMSECS_MASK;
> +	if (tm->tm_sec == WM8350_RTC_ALMSECS_MASK)
> +		tm->tm_sec = -1;
> +
> +	tm->tm_min = time[0] & WM8350_RTC_ALMMINS_MASK;
> +	if (tm->tm_min == WM8350_RTC_ALMMINS_MASK)
> +		tm->tm_min = -1;
> +	else
> +		tm->tm_min >>= WM8350_RTC_ALMMINS_SHIFT;
> +
> +	tm->tm_hour = time[1] & WM8350_RTC_ALMHRS_MASK;
> +	if (tm->tm_hour == WM8350_RTC_ALMHRS_MASK)
> +		tm->tm_hour = -1;
> +
> +	tm->tm_wday = ((time[1] >> WM8350_RTC_ALMDAY_SHIFT) & 0x7) - 1;
> +	if (tm->tm_wday > 7)
> +		tm->tm_wday = -1;
> +
> +	tm->tm_mon = time[2] & WM8350_RTC_ALMMTH_MASK;
> +	if (tm->tm_mon == WM8350_RTC_ALMMTH_MASK)
> +		tm->tm_mon = -1;
> +	else
> +		tm->tm_mon = (tm->tm_mon >> WM8350_RTC_ALMMTH_SHIFT) - 1;
> +
> +	tm->tm_mday = (time[2] & WM8350_RTC_ALMDATE_MASK);
> +	if (tm->tm_mday == WM8350_RTC_ALMDATE_MASK)
> +		tm->tm_mday = -1;
> +
> +	tm->tm_year = -1;
> +
> +	alrm->enabled = !(time[3] & WM8350_RTC_ALMSTS);
> +
> +	return 0;
> +}
> +
> +static int wm8350_rtc_stop_alarm(struct wm8350 *wm8350)
> +{
> +	int retries = WM8350_SET_ALM_RETRIES;
> +	u16 rtc_ctrl;
> +	int ret;
> +
> +	/* Set RTC_SET to stop the clock */
> +	ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL,
> +			      WM8350_RTC_ALMSET);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Wait until confirmation of stopping */
> +	do {
> +		rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
> +		schedule_timeout_uninterruptible(msecs_to_jiffies(1));
> +	} while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS));
> +
> +	if (!(rtc_ctrl & WM8350_RTC_ALMSTS))
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int wm8350_rtc_start_alarm(struct wm8350 *wm8350)
> +{
> +	int ret;
> +	int retries = WM8350_SET_ALM_RETRIES;
> +	u16 rtc_ctrl;
> +
> +	ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
> +				WM8350_RTC_ALMSET);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Wait until confirmation */
> +	do {
> +		rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
> +		schedule_timeout_uninterruptible(msecs_to_jiffies(1));
> +	} while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS);
> +
> +	if (rtc_ctrl & WM8350_RTC_ALMSTS)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time;
> +	u16 time[3];
> +	int ret;
> +
> +	memset(time, 0, sizeof(time));
> +
> +	if (tm->tm_sec != -1)
> +		time[0] |= tm->tm_sec;
> +	else
> +		time[0] |= WM8350_RTC_ALMSECS_MASK;
> +
> +	if (tm->tm_min != -1)
> +		time[0] |= tm->tm_min << WM8350_RTC_ALMMINS_SHIFT;
> +	else
> +		time[0] |= WM8350_RTC_ALMMINS_MASK;
> +
> +	if (tm->tm_hour != -1)
> +		time[1] |= tm->tm_hour;
> +	else
> +		time[1] |= WM8350_RTC_ALMHRS_MASK;
> +
> +	if (tm->tm_wday != -1)
> +		time[1] |= (tm->tm_wday + 1) << WM8350_RTC_ALMDAY_SHIFT;
> +	else
> +		time[1] |= WM8350_RTC_ALMDAY_MASK;
> +
> +	if (tm->tm_mday != -1)
> +		time[2] |= tm->tm_mday;
> +	else
> +		time[2] |= WM8350_RTC_ALMDATE_MASK;
> +
> +	if (tm->tm_mon != -1)
> +		time[2] |= (tm->tm_mon + 1) << WM8350_RTC_ALMMTH_SHIFT;
> +	else
> +		time[2] |= WM8350_RTC_ALMMTH_MASK;
> +
> +	ret = wm8350_rtc_stop_alarm(wm8350);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Write time to RTC */
> +	ret = wm8350_block_write(wm8350, WM8350_ALARM_SECONDS_MINUTES,
> +				 3, time);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (alrm->enabled)
> +		ret = wm8350_rtc_start_alarm(wm8350);
> +
> +	return ret;
> +}
> +
> +/*
> + * Handle commands from user-space
> + */
> +static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd,
> +			    unsigned long arg)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(dev);
> +
> +	switch (cmd) {
> +	case RTC_AIE_OFF:
> +		return wm8350_rtc_stop_alarm(wm8350);
> +	case RTC_AIE_ON:
> +		return wm8350_rtc_start_alarm(wm8350);
> +
> +	case RTC_UIE_OFF:
> +		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
> +		break;
> +	case RTC_UIE_ON:
> +		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
> +		break;
> +
> +	default:
> +		return -ENOIOCTLCMD;
> +	}
> +
> +	return 0;
> +}
> +
> +static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq,
> +				     void *data)
> +{
> +	struct rtc_device *rtc = wm8350->rtc.rtc;
> +	int ret;
> +
> +	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
> +
> +	/* Make it one shot */
> +	ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL,
> +			      WM8350_RTC_ALMSET);
> +	if (ret != 0) {
> +		dev_err(&(wm8350->rtc.pdev->dev),
> +			"Failed to disable alarm: %d\n", ret);
> +	}
> +}
> +
> +static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq,
> +				      void *data)
> +{
> +	struct rtc_device *rtc = wm8350->rtc.rtc;
> +
> +	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF);
> +}
> +
> +static const struct rtc_class_ops wm8350_rtc_ops = {
> +	.ioctl = wm8350_rtc_ioctl,
> +	.read_time = wm8350_rtc_readtime,
> +	.set_time = wm8350_rtc_settime,
> +	.read_alarm = wm8350_rtc_readalarm,
> +	.set_alarm = wm8350_rtc_setalarm,
> +};
> +
> +#ifdef CONFIG_PM
> +static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
> +	int ret = 0;
> +	u16 reg;
> +
> +	reg = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
> +
> +	if (device_may_wakeup(&wm8350->rtc.pdev->dev) &&
> +	    reg & WM8350_RTC_ALMSTS) {
> +		ret = wm8350_rtc_stop_alarm(wm8350);
> +		if (ret != 0)
> +			dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n",
> +				ret);
> +	}
> +
> +	return ret;
> +}
> +
> +static int wm8350_rtc_resume(struct platform_device *pdev)
> +{
> +	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
> +	int ret;
> +
> +	if (wm8350->rtc.alarm_enabled) {
> +		ret = wm8350_rtc_start_alarm(wm8350);
> +		if (ret != 0)
> +			dev_err(&pdev->dev,
> +				"Failed to restart RTC alarm: %d\n", ret);
> +	}
> +
> +	return 0;
> +}
> +
> +#else
> +#define wm8350_rtc_suspend NULL
> +#define wm8350_rtc_resume NULL
> +#endif
> +
> +static int wm8350_rtc_probe(struct platform_device *pdev)
> +{
> +	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
> +	struct wm8350_rtc *wm_rtc = &wm8350->rtc;
> +	int ret = 0;
> +	u16 timectl, power5;
> +
> +	timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
> +	if (timectl & WM8350_RTC_BCD) {
> +		dev_err(&pdev->dev, "RTC BCD mode not supported\n");
> +		return -EINVAL;
> +	}
> +	if (timectl & WM8350_RTC_12HR) {
> +		dev_err(&pdev->dev, "RTC 12 hour mode not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	/* enable the RTC if it's not already enabled */
> +	power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
> +	if (!(power5 &  WM8350_RTC_TICK_ENA)) {
> +		dev_info(wm8350->dev, "Starting RTC\n");
> +
> +		wm8350_reg_unlock(wm8350);
> +
> +		ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5,
> +				      WM8350_RTC_TICK_ENA);
> +		if (ret < 0) {
> +			dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret);
> +			return ret;
> +		}
> +
> +		wm8350_reg_lock(wm8350);
> +	}
> +
> +	if (timectl & WM8350_RTC_STS) {
> +		int retries;
> +
> +		ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
> +					WM8350_RTC_SET);
> +		if (ret < 0) {
> +			dev_err(&pdev->dev, "failed to start: %d\n", ret);
> +			return ret;
> +		}
> +
> +		retries = WM8350_SET_TIME_RETRIES;
> +		do {
> +			timectl = wm8350_reg_read(wm8350,
> +						  WM8350_RTC_TIME_CONTROL);
> +		} while (timectl & WM8350_RTC_STS && retries--);
> +
> +		if (retries == 0) {
> +			dev_err(&pdev->dev, "failed to start: timeout\n");
> +			return -ENODEV;
> +		}
> +	}
> +
> +	device_init_wakeup(&pdev->dev, 1);
> +
> +	wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev,
> +					  &wm8350_rtc_ops, THIS_MODULE);
> +	if (IS_ERR(wm_rtc->rtc)) {
> +		ret = PTR_ERR(wm_rtc->rtc);
> +		dev_err(&pdev->dev, "failed to register RTC: %d\n", ret);
> +		return ret;
> +	}
> +
> +	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
> +	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER);
> +
> +	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
> +			    wm8350_rtc_update_handler, NULL);
> +
> +	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
> +			    wm8350_rtc_alarm_handler, NULL);
> +	wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM);
> +
> +	return 0;
> +}
> +
> +static int __devexit wm8350_rtc_remove(struct platform_device *pdev)
> +{
> +	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
> +	struct wm8350_rtc *wm_rtc = &wm8350->rtc;
> +
> +	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
> +
> +	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC);
> +	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM);
> +
> +	rtc_device_unregister(wm_rtc->rtc);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver wm8350_rtc_driver = {
> +	.probe = wm8350_rtc_probe,
> +	.remove = wm8350_rtc_remove,

 mark with __devexit_p


> +	.suspend = wm8350_rtc_suspend,
> +	.resume = wm8350_rtc_resume,
> +	.driver = {
> +		.name = "wm8350-rtc",

 I'd like rtc-wm8350 here, if it doesn't hurt anything else.


> +	},
> +};
> +
> +static int __init wm8350_rtc_init(void)
> +{
> +	return platform_driver_register(&wm8350_rtc_driver);
> +}
> +module_init(wm8350_rtc_init);
> +
> +static void __exit wm8350_rtc_exit(void)
> +{
> +	platform_driver_unregister(&wm8350_rtc_driver);
> +}
> +module_exit(wm8350_rtc_exit);
> +
> +MODULE_AUTHOR("Mark Brown <broonie@...nsource.wolfsonmicro.com>");
> +MODULE_DESCRIPTION("RTC driver WM8350");

 driver _for_ 

> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:wm8350-rtc");
> diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
> index dfda69e..24add2b 100644
> --- a/include/linux/mfd/wm8350/rtc.h
> +++ b/include/linux/mfd/wm8350/rtc.h
> @@ -261,6 +261,8 @@
>  
>  struct wm8350_rtc {
>  	struct platform_device *pdev;
> +	struct rtc_device *rtc;
> +	int alarm_enabled;      /* used over suspend/resume */
>  };
>  
>  #endif
> -- 
> 1.5.6.5


-- 

 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ