From patchwork Mon Mar 1 10:53:45 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 46538 Return-Path: <3xJyLSwAACTglnW-fchoraiiafYaliojm.Wig@groups.bounces.google.com> X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-yw0-f148.google.com (mail-yw0-f148.google.com [209.85.211.148]) by ozlabs.org (Postfix) with ESMTP id 8B58BB7D2F for ; Mon, 1 Mar 2010 22:04:18 +1100 (EST) Received: by ywh12 with SMTP id 12sf4255980ywh.11 for ; Mon, 01 Mar 2010 03:04:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=beta; h=domainkey-signature:received:x-beenthere:received:received:received :received:received-spf:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references:mime-version:to :x-sa-exim-connect-ip:x-sa-exim-mail-from:x-sa-exim-scanned :x-ptx-original-recipient:x-original-authentication-results :x-original-sender:reply-to:precedence:mailing-list:list-id :list-post:list-help:list-archive:x-thread-url:x-message-url:sender :list-subscribe:list-unsubscribe:content-type :content-transfer-encoding; bh=9HkDVY7TyA7HPl4WEeSQqDMoW58BlDwymegEfple57Q=; b=7DaSudUaOkLgsSY3VlXMp50608O+e69sOER6npC+JexSiVZLh+gtigonbT324VbwqP bWKflfIIo/8ei6/J9Omsit0ClamlS4Vv2BgsFMgBlVlE18FtbTkjVHaqAAVfBxms6Jr/ pW1qJiJqrjWV4Tq2W9BzerT6JMpoX4XIwXK9Y= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlegroups.com; s=beta; h=x-beenthere:received-spf:from:to:cc:subject:date:message-id :x-mailer:in-reply-to:references:mime-version:x-sa-exim-connect-ip :x-sa-exim-mail-from:x-sa-exim-scanned:x-ptx-original-recipient :x-original-authentication-results:x-original-sender:reply-to :precedence:mailing-list:list-id:list-post:list-help:list-archive :x-thread-url:x-message-url:sender:list-subscribe:list-unsubscribe :content-type:content-transfer-encoding; b=hNgBj5kJq1wcieEgXhROWbYvYPdP7/l1P3sbu8veF8Nq3xjGJ9pYE5Xxc1N01cAzyk IQ+7JLm+W+V5FpTG8V0y2bQWpLw0l+KKiPk0IQuWciSedvRw7YXyiMSw0EQevWuPVqCW pPS+FIMo1iBLUWMbNPVTN2IS9HS6eIk2pN23g= Received: by 10.91.25.9 with SMTP id c9mr552953agj.21.1267440836112; Mon, 01 Mar 2010 02:53:56 -0800 (PST) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.87.45.23 with SMTP id x23ls769008fgj.0.p; Mon, 01 Mar 2010 02:53:55 -0800 (PST) Received: by 10.87.50.37 with SMTP id c37mr143851fgk.27.1267440835014; Mon, 01 Mar 2010 02:53:55 -0800 (PST) Received: by 10.87.50.37 with SMTP id c37mr143850fgk.27.1267440834990; Mon, 01 Mar 2010 02:53:54 -0800 (PST) Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [92.198.50.35]) by gmr-mx.google.com with ESMTP id 12si397158fxm.0.2010.03.01.02.53.54; Mon, 01 Mar 2010 02:53:54 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of ukl@pengutronix.de designates 92.198.50.35 as permitted sender) client-ip=92.198.50.35; Received: from octopus.hi.pengutronix.de ([2001:6f8:1178:2:215:17ff:fe12:23b0]) by metis.ext.pengutronix.de with esmtp (Exim 4.69) (envelope-from ) id 1Nm3G6-0005Gi-FK; Mon, 01 Mar 2010 11:53:54 +0100 Received: from ukl by octopus.hi.pengutronix.de with local (Exim 4.69) (envelope-from ) id 1Nm3G6-0004gv-B9; Mon, 01 Mar 2010 11:53:54 +0100 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= To: linux-kernel@vger.kernel.org, rtc-linux@googlegroups.com Cc: Alessandro Zummo , Paul Gortmaker , Andrew Morton , Valentin Longchamp , Sascha Hauer Subject: [rtc-linux] [PATCH 6/6] rtc/mc13783: implement alarm Date: Mon, 1 Mar 2010 11:53:45 +0100 Message-Id: <1267440825-14694-6-git-send-email-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 1.7.0 In-Reply-To: <1267440825-14694-1-git-send-email-u.kleine-koenig@pengutronix.de> References: <1267440825-14694-1-git-send-email-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 To: rtc-linux@googlegroups.com X-SA-Exim-Connect-IP: 2001:6f8:1178:2:215:17ff:fe12:23b0 X-SA-Exim-Mail-From: ukl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: rtc-linux@googlegroups.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: best guess record for domain of ukl@pengutronix.de designates 92.198.50.35 as permitted sender) smtp.mail=ukl@pengutronix.de X-Original-Sender: u.kleine-koenig@pengutronix.de Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: List-Post: , List-Help: , List-Archive: X-Thread-Url: http://groups.google.com/group/rtc-linux/t/27422cec32a1b315 X-Message-Url: http://groups.google.com/group/rtc-linux/msg/96d9a851b4495ce6 Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , Signed-off-by: Uwe Kleine-König --- Hello, for now this just ignores the possible race to trigger an alarm when setting the time. Should I resolve that, if so, what is the prefered way to do that? Best regards Uwe drivers/rtc/rtc-mc13783.c | 159 +++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 147 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c index 6a36201..ae01217 100644 --- a/drivers/rtc/rtc-mc13783.c +++ b/drivers/rtc/rtc-mc13783.c @@ -28,6 +28,34 @@ struct mc13783_rtc { int valid; }; +static int mc13783_rtc_irq_enable_unlocked(struct device *dev, + unsigned int enabled, int irq) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + int (*func)(struct mc13783 *mc13783, int irq); + + if (!priv->valid) + return -ENODATA; + + func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; + return func(priv->mc13783, irq); +} + +static int mc13783_rtc_irq_enable(struct device *dev, + unsigned int enabled, int irq) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + int ret; + + mc13783_lock(priv->mc13783); + + ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); + + mc13783_unlock(priv->mc13783); + + return ret; +} + static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct mc13783_rtc *priv = dev_get_drvdata(dev); @@ -114,6 +142,107 @@ out: return ret; } +static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + unsigned seconds, days; + unsigned long s1970; + int enabled, pending; + int ret; + + mc13783_lock(priv->mc13783); + + ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); + if (unlikely(ret)) + goto out; + if (seconds >= 86400) { + ret = -ENODATA; + goto out; + } + + ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); + if (unlikely(ret)) + goto out; + + ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, + &enabled, &pending); + +out: + mc13783_unlock(priv->mc13783); + + if (ret) + return ret; + + alarm->enabled = enabled; + alarm->pending = pending; + + s1970 = days * 86400 + seconds; + + rtc_time_to_tm(s1970, &alarm->time); + dev_dbg(dev, "%s: %lu\n", __func__, s1970); + + return 0; +} + +static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct mc13783_rtc *priv = dev_get_drvdata(dev); + unsigned long s1970; + unsigned seconds, days; + int ret; + + mc13783_lock(priv->mc13783); + + /* disable alarm to prevent false triggering */ + ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); + if (unlikely(ret)) + goto out; + + ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); + if (unlikely(ret)) + goto out; + + ret = rtc_tm_to_time(&alarm->time, &s1970); + if (unlikely(ret)) + goto out; + + dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", + s1970); + + ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, + MC13783_IRQ_TODA); + if (unlikely(ret)) + goto out; + + seconds = s1970 % 86400; + days = s1970 / 86400; + + ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); + if (unlikely(ret)) + goto out; + + ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); + +out: + mc13783_unlock(priv->mc13783); + + return ret; +} + +static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) +{ + struct mc13783_rtc *priv = dev; + struct mc13783 *mc13783 = priv->mc13783; + + dev_dbg(&priv->rtc->dev, "Alarm\n"); + + rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); + + mc13783_irq_ack(mc13783, irq); + + return IRQ_HANDLED; +} + static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) { struct mc13783_rtc *priv = dev; @@ -131,24 +260,21 @@ static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) static int mc13783_rtc_update_irq_enable(struct device *dev, unsigned int enabled) { - struct mc13783_rtc *priv = dev_get_drvdata(dev); - int ret = -ENODATA; - - mc13783_lock(priv->mc13783); - if (!priv->valid) - goto out; - - ret = (enabled ? mc13783_irq_unmask : mc13783_irq_mask)(priv->mc13783, - MC13783_IRQ_1HZ); -out: - mc13783_unlock(priv->mc13783); + return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); +} - return ret; +static int mc13783_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); } static const struct rtc_class_ops mc13783_rtc_ops = { .read_time = mc13783_rtc_read_time, .set_mmss = mc13783_rtc_set_mmss, + .read_alarm = mc13783_rtc_read_alarm, + .set_alarm = mc13783_rtc_set_alarm, + .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, .update_irq_enable = mc13783_rtc_update_irq_enable, }; @@ -197,11 +323,19 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) if (ret) goto err_update_irq_request; + ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA, + mc13783_rtc_alarm_handler, DRIVER_NAME, priv); + if (ret) + goto err_alarm_irq_request; + priv->rtc = rtc_device_register(pdev->name, &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); if (IS_ERR(priv->rtc)) { ret = PTR_ERR(priv->rtc); + mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); +err_alarm_irq_request: + mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); err_update_irq_request: @@ -227,6 +361,7 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev) rtc_device_unregister(priv->rtc); + mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);