From patchwork Fri Mar 8 07:38:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dongsheng Wang X-Patchwork-Id: 226036 X-Patchwork-Delegate: galak@kernel.crashing.org Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 1E5A42C076A for ; Fri, 8 Mar 2013 19:13:24 +1100 (EST) Received: from co1outboundpool.messaging.microsoft.com (co1ehsobe006.messaging.microsoft.com [216.32.180.189]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (Client CN "mail.global.frontbridge.com", Issuer "Microsoft Secure Server Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id DFECD2C053E for ; Fri, 8 Mar 2013 19:12:03 +1100 (EST) Received: from mail63-co1-R.bigfish.com (10.243.78.254) by CO1EHSOBE003.bigfish.com (10.243.66.66) with Microsoft SMTP Server id 14.1.225.23; Fri, 8 Mar 2013 08:12:00 +0000 Received: from mail63-co1 (localhost [127.0.0.1]) by mail63-co1-R.bigfish.com (Postfix) with ESMTP id 0CDEC380191 for ; Fri, 8 Mar 2013 08:12:00 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 3 X-BigFish: VS3(zzc8kzz1f42h1ee6h1de0h1202h1e76h1d1ah1d2ahzz8275bhz2dh2a8h668h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1155h) Received: from mail63-co1 (localhost.localdomain [127.0.0.1]) by mail63-co1 (MessageSwitch) id 1362730318215628_8444; Fri, 8 Mar 2013 08:11:58 +0000 (UTC) Received: from CO1EHSMHS032.bigfish.com (unknown [10.243.78.230]) by mail63-co1.bigfish.com (Postfix) with ESMTP id 275E99E0053 for ; Fri, 8 Mar 2013 08:11:58 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CO1EHSMHS032.bigfish.com (10.243.66.42) with Microsoft SMTP Server (TLS) id 14.1.225.23; Fri, 8 Mar 2013 08:11:54 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server (TLS) id 14.2.328.11; Fri, 8 Mar 2013 08:11:54 +0000 Received: from rock.am.freescale.net (rock.ap.freescale.net [10.193.20.106]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id r288BS3p004421; Fri, 8 Mar 2013 01:11:50 -0700 From: Wang Dongsheng To: , Subject: [PATCH 3/3] powerpc/fsl: add MPIC timer wakeup support Date: Fri, 8 Mar 2013 15:38:47 +0800 Message-ID: <1362728327-21013-3-git-send-email-dongsheng.wang@freescale.com> X-Mailer: git-send-email 1.7.5.1 In-Reply-To: <1362728327-21013-1-git-send-email-dongsheng.wang@freescale.com> References: <1362728327-21013-1-git-send-email-dongsheng.wang@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Cc: linuxppc-dev@lists.ozlabs.org, Wang Dongsheng , Zhao Chenhui X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The driver provides a way to wake up the system by the MPIC timer. For example, echo 5 > /sys/devices/system/mpic/timer_wakeup echo standby > /sys/power/state After 5 seconds the MPIC timer will generate an interrupt to wake up the system. Signed-off-by: Wang Dongsheng Signed-off-by: Zhao Chenhui Signed-off-by: Li Yang --- arch/powerpc/platforms/Kconfig | 9 ++ arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c | 185 +++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 5af04fa..487c37f 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -99,6 +99,15 @@ config MPIC_TIMER only tested on fsl chip, but it can potentially support other global timers complying to Open-PIC standard. +config FSL_MPIC_TIMER_WAKEUP + tristate "Freescale MPIC global timer wakeup driver" + depends on FSL_SOC && MPIC_TIMER + default n + help + This is only for freescale powerpc platform. The driver + provides a way to wake up the system by MPIC timer, + e.g. "echo 5 > /sys/devices/system/mpic/timer_wakeup" + config PPC_EPAPR_HV_PIC bool default n diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index ff6184a..e1b8a80 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_PPC64) := -mno-minimal-toc mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o +obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y) obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o diff --git a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c new file mode 100644 index 0000000..e94ba65 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c @@ -0,0 +1,185 @@ +/* + * MPIC timer wakeup driver + * + * Copyright 2013 Freescale Semiconductor, Inc. + * + * 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 + +struct fsl_mpic_timer_wakeup { + struct mpic_timer *timer; + struct work_struct free_work; +}; + +static struct fsl_mpic_timer_wakeup *fsl_wakeup; +static DEFINE_MUTEX(sysfs_lock); + +static void fsl_free_resource(struct work_struct *ws) +{ + struct fsl_mpic_timer_wakeup *wakeup = + container_of(ws, struct fsl_mpic_timer_wakeup, free_work); + + mutex_lock(&sysfs_lock); + + if (wakeup->timer) { + disable_irq_wake(wakeup->timer->irq); + mpic_free_timer(wakeup->timer); + } + + wakeup->timer = NULL; + mutex_unlock(&sysfs_lock); +} + +static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id) +{ + struct fsl_mpic_timer_wakeup *wakeup = dev_id; + + schedule_work(&wakeup->free_work); + return IRQ_HANDLED; +} + +static ssize_t fsl_timer_wakeup_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct timeval interval; + int val = 0; + + mutex_lock(&sysfs_lock); + if (fsl_wakeup->timer) { + mpic_get_remain_time(fsl_wakeup->timer, &interval); + val = interval.tv_sec + 1; + } + mutex_unlock(&sysfs_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t fsl_timer_wakeup_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct timeval interval; + int ret; + + interval.tv_usec = 0; + if (kstrtol(buf, 0, &interval.tv_sec)) + return -EINVAL; + + mutex_lock(&sysfs_lock); + + if (fsl_wakeup->timer && !interval.tv_sec) { + disable_irq_wake(fsl_wakeup->timer->irq); + mpic_free_timer(fsl_wakeup->timer); + fsl_wakeup->timer = NULL; + mutex_unlock(&sysfs_lock); + + return count; + } + + if (fsl_wakeup->timer) { + mutex_unlock(&sysfs_lock); + return -EBUSY; + } + + fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq, + fsl_wakeup, &interval); + if (!fsl_wakeup->timer) { + mutex_unlock(&sysfs_lock); + return -EINVAL; + } + + ret = enable_irq_wake(fsl_wakeup->timer->irq); + if (ret) { + mpic_free_timer(fsl_wakeup->timer); + fsl_wakeup->timer = NULL; + mutex_unlock(&sysfs_lock); + + return ret; + } + mpic_start_timer(fsl_wakeup->timer); + + mutex_unlock(&sysfs_lock); + + return count; +} + +static struct bus_type mpic_subsys = { + .name = "mpic", + .dev_name = "mpic", +}; + +static DEVICE_ATTR(timer_wakeup, 0644, + fsl_timer_wakeup_show, fsl_timer_wakeup_store); + +static struct device_attribute *mpic_attributes[] = { + &dev_attr_timer_wakeup, + NULL +}; + +static int __init fsl_wakeup_sys_init(void) +{ + int ret; + int i; + + fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL); + if (!fsl_wakeup) + return -ENOMEM; + + INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource); + + ret = subsys_system_register(&mpic_subsys, NULL); + if (ret) + goto err; + + for (i = 0; mpic_attributes[i]; i++) { + ret = device_create_file(mpic_subsys.dev_root, + mpic_attributes[i]); + if (ret) + goto err2; + } + + return ret; + +err2: + while (--i >= 0) + device_remove_file(mpic_subsys.dev_root, mpic_attributes[i]); + + bus_unregister(&mpic_subsys); + +err: + kfree(fsl_wakeup); + + return ret; +} + +static void __exit fsl_wakeup_sys_exit(void) +{ + int i; + + for (i = 0; mpic_attributes[i]; i++) + device_remove_file(mpic_subsys.dev_root, + mpic_attributes[i]); + bus_unregister(&mpic_subsys); + kfree(fsl_wakeup); +} + +module_init(fsl_wakeup_sys_init); +module_exit(fsl_wakeup_sys_exit); + +MODULE_DESCRIPTION("Freescale MPIC global timer wakeup driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Wang Dongsheng ");