[PATCH 0/2] RTC updates - Kernel

This is a discussion on [PATCH 0/2] RTC updates - Kernel ; This patch series fixes a bug in the RTC core and adds support for the WM8350 RTC. The bug fix is required for the WM8350 driver since it does not support configuration of the year for alarms, triggering the need ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: [PATCH 0/2] RTC updates

  1. [PATCH 0/2] RTC updates

    This patch series fixes a bug in the RTC core and adds support for the
    WM8350 RTC. The bug fix is required for the WM8350 driver since it does
    not support configuration of the year for alarms, triggering the need to
    handle year wraparound when reporting the alarm status.
    --
    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/

  2. [PATCH 1/2] rtc: Fix handling of missing tm_year data when reading alarms

    When fixing up invalid years rtc_read_alarm() was calling rtc_valid_tm()
    as a boolean but rtc_valid_tm() returns zero on success or a negative
    number if the time is not valid so the test was inverted.

    Signed-off-by: Mark Brown
    ---
    drivers/rtc/interface.c | 2 +-
    1 files changed, 1 insertions(+), 1 deletions(-)

    diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
    index 7af60b9..a04c1b6 100644
    --- a/drivers/rtc/interface.c
    +++ b/drivers/rtc/interface.c
    @@ -271,7 +271,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
    dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
    do {
    alarm->time.tm_year++;
    - } while (!rtc_valid_tm(&alarm->time));
    + } while (rtc_valid_tm(&alarm->time) != 0);
    break;

    default:
    --
    1.5.6.5

    --
    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/

  3. [PATCH 2/2] rtc: rtc-wm8350: Add support for WM8350 RTC

    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
    ---
    drivers/rtc/Kconfig | 10 +
    drivers/rtc/Makefile | 1 +
    drivers/rtc/rtc-wm8350.c | 515 ++++++++++++++++++++++++++++++++++++++++
    include/linux/mfd/wm8350/rtc.h | 2 +
    4 files changed, 528 insertions(+), 0 deletions(-)
    create mode 100644 drivers/rtc/rtc-wm8350.c

    diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
    index f660ef3..86e8a1b 100644
    --- a/drivers/rtc/Kconfig
    +++ b/drivers/rtc/Kconfig
    @@ -458,6 +458,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 d05928b..3501d86 100644
    --- a/drivers/rtc/Makefile
    +++ b/drivers/rtc/Makefile
    @@ -64,4 +64,5 @@ obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
    obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.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..862588c
    --- /dev/null
    +++ b/drivers/rtc/rtc-wm8350.c
    @@ -0,0 +1,515 @@
    +/*
    + * Real Time Clock driver for Wolfson Microelectronics WM8350
    + *
    + * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
    + *
    + * Author: Liam Girdwood
    + * linux@wolfsonmicro.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
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +#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_interruptible(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_interruptible(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_interruptible(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 __exit 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,
    + .suspend = wm8350_rtc_suspend,
    + .resume = wm8350_rtc_resume,
    + .driver = {
    + .name = "wm8350-rtc",
    + },
    +};
    +
    +static int __init wm8350_rtc_init(void)
    +{
    + return platform_driver_register(&wm8350_rtc_driver);
    +}
    +
    +static void __exit wm8350_rtc_exit(void)
    +{
    + platform_driver_unregister(&wm8350_rtc_driver);
    +}
    +
    +module_init(wm8350_rtc_init);
    +module_exit(wm8350_rtc_exit);
    +
    +MODULE_AUTHOR("Liam Girdwood");
    +MODULE_DESCRIPTION("RTC driver WM8350");
    +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

    --
    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/

  4. Re: [PATCH 2/2] rtc: rtc-wm8350: Add support for WM8350 RTC

    On Mon, 20 Oct 2008 20:35:18 +0100 Mark Brown wrote:

    > +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_interruptible(msecs_to_jiffies(1) );


    If the calling process has signal_pending() (eg: someone typed ^C) then
    schedule_timeout_interruptible() will return immediately.

    > + } while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS));
    > +
    > + if (!(rtc_ctrl & WM8350_RTC_ALMSTS))
    > + return -ETIMEDOUT;


    And the driver will incorrectly 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_interruptible(msecs_to_jiffies(1) );
    > + } while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS);
    > +
    > + if (rtc_ctrl & WM8350_RTC_ALMSTS)
    > + return -ETIMEDOUT;


    ditto.

    > + return 0;
    > +}


    I'll switch those to schedule_timeout_uninterruptible(), OK?
    --
    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/

  5. Re: [PATCH 2/2] rtc: rtc-wm8350: Add support for WM8350 RTC

    On Sun, Oct 26, 2008 at 10:14:31PM -0700, Andrew Morton wrote:

    > I'll switch those to schedule_timeout_uninterruptible(), OK?


    OK.
    --
    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/

+ Reply to Thread