From patchwork Tue Nov 20 09:48:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AnilKumar Chimata X-Patchwork-Id: 200280 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-ye0-f184.google.com (mail-ye0-f184.google.com [209.85.213.184]) (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 458252C0098 for ; Tue, 20 Nov 2012 20:49:23 +1100 (EST) Received: by mail-ye0-f184.google.com with SMTP id q10sf3952622yen.11 for ; Tue, 20 Nov 2012 01:49:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=x-beenthere:received-spf:from:to:cc:subject:date:message-id :x-mailer:in-reply-to:references:mime-version: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=Qq4McO3gtwmz8RoMwavNSuui8EolwwveJDBcONPSuqU=; b=xh9GHwAwsqfkIoc2fEAzfdnigUS8CxG30EMRu0MIu4G1myR5BRX2L8FHR9ApFpDtCs eQfE069UDNjvi5/cPBtIaUDf7NiWibKAMdziodt/LsWrEyUzBusXqn2+xiabEsXTLQ/W qolQ3S7XuHgveSV4nXfrvUmR9P0X1NcbiG1PElayyOz6zj0FB+xnOflkJp9aX7+DvwLC TMCKadtQMelpARMSUrvZHt2VooxvlhEaEE6VU0hSvmfvigiMn09P1f5euOZFSu193d1y Ags+FLX0mJlCcHzlELLLY5pokXAUoGnCD2lrLlcmVC/EptqCZ+fPSGbgsXotpDyPfqDE +ouw== Received: by 10.50.0.204 with SMTP id 12mr3486439igg.9.1353404960468; Tue, 20 Nov 2012 01:49:20 -0800 (PST) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.50.188.170 with SMTP id gb10ls4044035igc.16.gmail; Tue, 20 Nov 2012 01:49:20 -0800 (PST) Received: by 10.50.0.148 with SMTP id 20mr8522844ige.3.1353404960074; Tue, 20 Nov 2012 01:49:20 -0800 (PST) Received: by 10.50.0.148 with SMTP id 20mr8522843ige.3.1353404960062; Tue, 20 Nov 2012 01:49:20 -0800 (PST) Received: from bear.ext.ti.com (bear.ext.ti.com. [192.94.94.41]) by gmr-mx.google.com with ESMTPS id s15si1553820igi.1.2012.11.20.01.49.19 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 20 Nov 2012 01:49:20 -0800 (PST) Received-SPF: pass (google.com: domain of anilkumar@ti.com designates 192.94.94.41 as permitted sender) client-ip=192.94.94.41; Received: from dbdp20.itg.ti.com ([172.24.170.38]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id qAK9nH9H004016; Tue, 20 Nov 2012 03:49:17 -0600 Received: from DBDE70.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id qAK9n8GD029316; Tue, 20 Nov 2012 15:19:15 +0530 (IST) Received: from dbdp32.itg.ti.com (172.24.170.251) by dbde70.ent.ti.com (172.24.170.148) with Microsoft SMTP Server id 14.1.323.3; Tue, 20 Nov 2012 15:19:09 +0530 Received: from localhost.localdomain (dbdp20.itg.ti.com [172.24.170.38]) by dbdp32.itg.ti.com (8.13.8/8.13.8) with ESMTP id qAK9n0cu017340; Tue, 20 Nov 2012 15:19:08 +0530 From: AnilKumar Ch To: , , CC: , , , , , , , Colin Foe-Parker , AnilKumar Ch Subject: [rtc-linux] [PATCH v3 1/5] rtc: OMAP: Add system pm_power_off to rtc driver Date: Tue, 20 Nov 2012 15:18:43 +0530 Message-ID: <1353404927-14412-2-git-send-email-anilkumar@ti.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1353404927-14412-1-git-send-email-anilkumar@ti.com> References: <1353404927-14412-1-git-send-email-anilkumar@ti.com> MIME-Version: 1.0 X-Original-Sender: anilkumar@ti.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of anilkumar@ti.com designates 192.94.94.41 as permitted sender) smtp.mail=anilkumar@ti.com 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: , From: Colin Foe-Parker Add system power off control to rtc driver which is the in-charge of controlling the BeagleBone system power. The power_off routine can be hooked up to "pm_power_off" system call. System power off sequence:- * Set PMIC STATUS_OFF when PMIC_POWER_EN is pulled low * Enable PMIC_POWER_EN in rtc module * Set rtc ALARM2 time * Enable ALARM2 interrupt Added while (1); after the above steps to make sure that no other process acquire cpu. Otherwise we might see an unexpected behaviour because we are shutting down all the power rails of SoC except RTC. Signed-off-by: Colin Foe-Parker [anilkumar@ti.com: move poweroff additions to rtc driver] Signed-off-by: AnilKumar Ch Reviewed-by: Vaibhav Bedia Acked-by: Grant Likely --- Documentation/devicetree/bindings/rtc/rtc-omap.txt | 5 ++ drivers/rtc/rtc-omap.c | 81 +++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt index b47aa41..8d9f4f9 100644 --- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt +++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt @@ -6,6 +6,10 @@ Required properties: - interrupts: rtc timer, alarm interrupts in order - interrupt-parent: phandle for the interrupt controller +Optional properties: +- ti,system-power-controller: Telling whether or not rtc is controlling + the system power. + Example: rtc@1c23000 { @@ -14,4 +18,5 @@ rtc@1c23000 { interrupts = <19 19>; interrupt-parent = <&intc>; + ti,system-power-controller; }; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 6009714..c31f93a 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -72,6 +72,14 @@ #define OMAP_RTC_KICK0_REG 0x6c #define OMAP_RTC_KICK1_REG 0x70 +#define OMAP_RTC_ALARM2_SECONDS_REG 0x80 +#define OMAP_RTC_ALARM2_MINUTES_REG 0x84 +#define OMAP_RTC_ALARM2_HOURS_REG 0x88 +#define OMAP_RTC_ALARM2_DAYS_REG 0x8c +#define OMAP_RTC_ALARM2_MONTHS_REG 0x90 +#define OMAP_RTC_ALARM2_YEARS_REG 0x94 +#define OMAP_RTC_PMIC_REG 0x98 + /* OMAP_RTC_CTRL_REG bit fields: */ #define OMAP_RTC_CTRL_SPLIT (1<<7) #define OMAP_RTC_CTRL_DISABLE (1<<6) @@ -93,15 +101,21 @@ #define OMAP_RTC_STATUS_BUSY (1<<0) /* OMAP_RTC_INTERRUPTS_REG bit fields: */ +#define OMAP_RTC_INTERRUPTS_IT_ALARM2 (1<<4) #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) +/* OMAP_RTC_PMIC_REG bit fields: */ +#define OMAP_RTC_PMIC_POWER_EN_EN (1<<16) + /* OMAP_RTC_KICKER values */ #define KICK0_VALUE 0x83e70b13 #define KICK1_VALUE 0x95a4f1e0 #define OMAP_RTC_HAS_KICKER 0x1 +#define SHUTDOWN_TIME_SEC 2 + static void __iomem *rtc_base; #define rtc_read(addr) readb(rtc_base + (addr)) @@ -290,6 +304,63 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) return 0; } +/* + * rtc_power_off: Set the pmic power off sequence. The RTC generates + * pmic_pwr_enable control, which can be used to control an external + * PMIC. + */ +static void rtc_power_off(void) +{ + u32 val; + struct rtc_time tm; + spinlock_t lock; + unsigned long flags, time; + + spin_lock_init(&lock); + + /* Set PMIC power enable */ + val = readl(rtc_base + OMAP_RTC_PMIC_REG); + writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG); + + /* Read rtc time */ + omap_rtc_read_time(NULL, &tm); + + /* Convert Gregorian date to seconds since 01-01-1970 00:00:00 */ + rtc_tm_to_time(&tm, &time); + + /* Add shutdown time to the current value */ + time += SHUTDOWN_TIME_SEC; + + /* Convert seconds since 01-01-1970 00:00:00 to Gregorian date */ + rtc_time_to_tm(time, &tm); + + if (tm2bcd(&tm) < 0) + return; + + pr_info("System will go to power_off state in approx. %d secs\n", + SHUTDOWN_TIME_SEC); + + /* + * pmic_pwr_enable is controlled by means of ALARM2 event. So here + * programming alarm2 expiry time and enabling alarm2 interrupt + */ + rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG); + rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG); + rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG); + rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG); + rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG); + rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG); + + /* Enable alarm2 interrupt */ + val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG); + writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2, + rtc_base + OMAP_RTC_INTERRUPTS_REG); + + /* Do not allow to execute any other task */ + spin_lock_irqsave(&lock, flags); + while (1); +} + static struct rtc_class_ops omap_rtc_ops = { .read_time = omap_rtc_read_time, .set_time = omap_rtc_set_time, @@ -327,12 +398,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev) struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; + bool pm_off = false; const struct platform_device_id *id_entry; const struct of_device_id *of_id; of_id = of_match_device(omap_rtc_of_match, &pdev->dev); - if (of_id) + if (of_id) { pdev->id_entry = of_id->data; + pm_off = of_property_read_bool(pdev->dev.of_node, + "ti,system-power-controller"); + } omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { @@ -385,6 +460,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); dev_set_drvdata(&rtc->dev, mem); + /* RTC power off */ + if (pm_off && !pm_power_off) + pm_power_off = rtc_power_off; + /* clear pending irqs, and set 1/second periodic, * which we'll use instead of update irqs */