From patchwork Fri Mar 8 09:01:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Trumtrar X-Patchwork-Id: 226057 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-we0-x23c.google.com (mail-we0-x23c.google.com [IPv6:2a00:1450:400c:c03::23c]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 1AF712C0395 for ; Fri, 8 Mar 2013 20:02:21 +1100 (EST) Received: by mail-we0-f188.google.com with SMTP id t44sf245211wey.5 for ; Fri, 08 Mar 2013 01:02:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=x-received:mime-version:x-beenthere:x-received:received-spf:from:to :cc:subject:date:message-id:x-mailer:in-reply-to:references :x-sa-exim-connect-ip:x-sa-exim-mail-from:x-sa-exim-scanned :x-ptx-original-recipient:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:x-google-group-id:list-post:list-help:list-archive:sender :list-subscribe:list-unsubscribe:content-type; bh=5IRBEU2pmXwSmChoULaD0dpDUqwljUzDF3Y1fYhE39s=; b=ZJdTIuAoINTxPkGpzPoLMXyLOSepAy6npINtSE09wujkb5PEg3WGoIqlmQuUyqq3Lw rCX1DLoYh7YHDsMEmyhAbrAb03TomocBcu3RJUEx3ybJj7etYMdDkuLzkN+8bVpONMvW SptXFJeJt07vVbuNA2WB57p+gfEx9s4x2POeC0VmwZicDzyS9HeZwaISoSUZLy+YNnm1 H3WmC6/yC8q19O4kol+Kfv3MspR8TajoBJfuAPBux/eAvkyyyB1/nwbq485ypDx01Yk5 EXYb0nIo2xCwHjtrCSacgrXE2fFkvuFY62tghLeD8ZOKFWQ2i5d5/UxvEHGs3p8RN7kp f/8Q== X-Received: by 10.180.19.105 with SMTP id d9mr110038wie.10.1362733337175; Fri, 08 Mar 2013 01:02:17 -0800 (PST) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.180.19.99 with SMTP id d3ls945118wie.5.canary; Fri, 08 Mar 2013 01:02:16 -0800 (PST) X-Received: by 10.14.215.69 with SMTP id d45mr1392263eep.6.1362733336798; Fri, 08 Mar 2013 01:02:16 -0800 (PST) Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de. [2001:6f8:1178:4:290:27ff:fe1d:cc33]) by gmr-mx.google.com with ESMTPS id 6si1436730eej.0.2013.03.08.01.02.16 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 08 Mar 2013 01:02:16 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of str@pengutronix.de designates 2001:6f8:1178:4:290:27ff:fe1d:cc33 as permitted sender) client-ip=2001:6f8:1178:4:290:27ff:fe1d:cc33; Received: from dude.hi.pengutronix.de ([2001:6f8:1178:2:21e:67ff:fe11:9c5c]) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1UDtBv-0000lN-Ej; Fri, 08 Mar 2013 10:02:15 +0100 Received: from str by dude.hi.pengutronix.de with local (Exim 4.80) (envelope-from ) id 1UDtBt-0006d9-CF; Fri, 08 Mar 2013 10:02:13 +0100 From: Steffen Trumtrar To: rtc-linux@googlegroups.com, devicetree-discuss@lists.ozlabs.org Cc: Shawn Guo , Alessandro Zummo , Steffen Trumtrar , Juergen Beisert Subject: [rtc-linux] [PATCH v2 4/9] rtc: stmp3xxx: allow different oscillators Date: Fri, 8 Mar 2013 10:01:39 +0100 Message-Id: <1362733304-23037-5-git-send-email-s.trumtrar@pengutronix.de> X-Mailer: git-send-email 1.8.2.rc2 In-Reply-To: <1362733304-23037-1-git-send-email-s.trumtrar@pengutronix.de> References: <1362733304-23037-1-git-send-email-s.trumtrar@pengutronix.de> X-SA-Exim-Connect-IP: 2001:6f8:1178:2:21e:67ff:fe11:9c5c X-SA-Exim-Mail-From: str@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-Sender: s.trumtrar@pengutronix.de X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: best guess record for domain of str@pengutronix.de designates 2001:6f8:1178:4:290:27ff:fe1d:cc33 as permitted sender) smtp.mail=str@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: X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , The RTC can have different input clockrates. Configure the RTC accordingly and leave only the one used running. Signed-off-by: Juergen Beisert Signed-off-by: Steffen Trumtrar --- drivers/rtc/rtc-stmp3xxx.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 98f0d3c..d2283c5 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -53,18 +54,31 @@ #define STMP3XXX_RTC_PERSISTENT0 0x60 #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 +#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 +#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ (1 << 6) + #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 #define STMP3XXX_RTC_PERSISTENT1 0x70 /* missing bitmask in headers */ #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000 +enum clock_source { + MXS_UNKNOWN, + MXS_OSC_24M, + MXS_OSC_32K, + MXS_OSC_32K768 +}; + struct stmp3xxx_rtc_data { struct rtc_device *rtc; void __iomem *io; int irq_alarm; + enum clock_source clk_src; }; #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG) @@ -168,11 +182,55 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) return IRQ_NONE; } +/* + * To keep the energy consumption low, keep only + * the really used oscillator running when the power is down + */ +static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_data) +{ + switch (rtc_data->clk_src) { + case MXS_OSC_24M: + /* keep the 24 MHz oscillator running even in power down */ + writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 24 MHz / 750 */ + STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + break; + case MXS_OSC_32K: + /* keep the 32 kHz oscillator running even in power down */ + writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32 kHz */ + STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + break; + case MXS_OSC_32K768: + /* keep the 32 kHz oscillator running even in power down */ + writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32.768 kHz */ + STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP, + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + break; + case MXS_UNKNOWN: + default: + break; + } +} + static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); + stmp3xxx_alarm_keep_oscillator(rtc_data); + if (enabled) { + writel(STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, /* to be able to sleep */ + rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); @@ -240,6 +298,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) { struct stmp3xxx_rtc_data *rtc_data; struct resource *r; + struct clk *clk; + unsigned long rate; int err; rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL); @@ -272,6 +332,35 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc_data); mxs_reset_block(rtc_data->io); + + /* + * configure the RTC to provide the correct time + */ + clk = devm_clk_get(&pdev->dev, "32k"); + if (IS_ERR(clk)) { + /* just a fall back */ + dev_warn(&pdev->dev, "RTC's input clock undefined\n"); + rtc_data->clk_src = MXS_OSC_24M; + } else { + rate = clk_get_rate(clk); + if (rate == 0) { + /* no dedicated external crystal */ + rtc_data->clk_src = MXS_OSC_24M; + dev_info(&pdev->dev, "Using 24 MHz as RTC's clock\n"); + } else if (rate == 32000) { + rtc_data->clk_src = MXS_OSC_32K; + dev_info(&pdev->dev, "Using 32.0 kHz as RTC's clock\n"); + } else if (rate == 32768) { + rtc_data->clk_src = MXS_OSC_32K768; + dev_info(&pdev->dev, "Using 32.768 kHz as RTC's clock\n"); + } else + dev_warn(&pdev->dev, + "Cannot init the RTC's clock source\n"); + } + + /* basically configure the RTC's input clock */ + stmp3xxx_alarm_keep_oscillator(rtc_data); + writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,