From patchwork Fri Aug 8 04:05:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 35091 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f198.google.com (mail-ob0-f198.google.com [209.85.214.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8BA4221457 for ; Fri, 8 Aug 2014 04:05:48 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wp18sf20134507obc.9 for ; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=KDoIIVB8JY3qwiEbJQmgybQd2sxe6jBGxx5xgUp2WWk=; b=d5hVyM7P2VpstIYaeeJo9Dr7uSrNpsmpJ4Hm8aPJ6YpQCxjZBtZfkE4PXIk+rLwcnx bFU9vuBonGND75oaNcwNJfdVcY3al2wUA2Qq6ofesNPGMSu5NC/h2g3t1NJfqvKz0aFn UNUNzz/C9s+IjtWee8oy2SlTRcAE8GMFSr1T7ksMp9KaY41J07CGbHCScU2mKoV5pROG fKdOTMNHWvvjUz141nqTd+bOtrKN3vG084rMJn9MMu7knuqkxbqq8xNgB0a5kuarJp+T ZU7Jin/TYJjIYwABtL0zvJ7cHFQFu1jLgOgTpQz6nDjLDhz3knZ4WNqMAQD96V1VWMby nDkA== X-Gm-Message-State: ALoCoQkw+C2ySzBql5NOqUkE6BL+rCa43n9k70okN0qFBqblzgg7Cwq1qKtHryy+LyukidWPTXUO X-Received: by 10.50.126.9 with SMTP id mu9mr712413igb.6.1407470748185; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.98.212 with SMTP id o78ls412776qge.55.gmail; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) X-Received: by 10.52.34.209 with SMTP id b17mr100406vdj.49.1407470748096; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) Received: from mail-vc0-f170.google.com (mail-vc0-f170.google.com [209.85.220.170]) by mx.google.com with ESMTPS id ai1si2499569vdd.1.2014.08.07.21.05.48 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 07 Aug 2014 21:05:48 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.170 as permitted sender) client-ip=209.85.220.170; Received: by mail-vc0-f170.google.com with SMTP id lf12so7578137vcb.15 for ; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) X-Received: by 10.52.61.136 with SMTP id p8mr5031688vdr.15.1407470748013; Thu, 07 Aug 2014 21:05:48 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp87286vcb; Thu, 7 Aug 2014 21:05:47 -0700 (PDT) X-Received: by 10.70.132.38 with SMTP id or6mr21928919pdb.24.1407470747061; Thu, 07 Aug 2014 21:05:47 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b11si1450465pdj.25.2014.08.07.21.05.46 for ; Thu, 07 Aug 2014 21:05:47 -0700 (PDT) Received-SPF: none (google.com: linux-arm-msm-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752831AbaHHEFq (ORCPT + 4 others); Fri, 8 Aug 2014 00:05:46 -0400 Received: from mail-pa0-f50.google.com ([209.85.220.50]:57435 "EHLO mail-pa0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752761AbaHHEFp (ORCPT ); Fri, 8 Aug 2014 00:05:45 -0400 Received: by mail-pa0-f50.google.com with SMTP id et14so6482540pad.23 for ; Thu, 07 Aug 2014 21:05:45 -0700 (PDT) X-Received: by 10.70.108.194 with SMTP id hm2mr21923727pdb.115.1407470745154; Thu, 07 Aug 2014 21:05:45 -0700 (PDT) Received: from localhost.localdomain (c-24-8-37-141.hsd1.co.comcast.net. [24.8.37.141]) by mx.google.com with ESMTPSA id n8sm2163342pdm.22.2014.08.07.21.05.43 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Aug 2014 21:05:44 -0700 (PDT) From: Lina Iyer To: daniel.lezcano@linaro.org, khilman@linaro.org, amit.kucheria@linaro.org, sboyd@codeaurora.org, davidb@codeaurora.org, galak@codeaurora.org, linux-arm-msm@vger.kernel.org Cc: msivasub@codeaurora.org, bryanh@codeaurora.org, Lina Iyer Subject: [RFC] [PATCH 07/13] qcom: sleep-status: Add ability to recognize cpu power down state Date: Thu, 7 Aug 2014 22:05:16 -0600 Message-Id: <1407470722-23015-8-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1407470722-23015-1-git-send-email-lina.iyer@linaro.org> References: <1407470722-23015-1-git-send-email-lina.iyer@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lina.iyer@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , QCOM processors get notified by the processor subsystem logic that recognizes when a processor has entered the low power state. This is used by PM to guarantee that the processor is indeed in its low power state, before powering down the associated resources. Signed-off-by: Mahesh Sivasubramanian Signed-off-by: Lina Iyer --- .../bindings/arm/msm/qcom,cpu-sleep-status.txt | 41 +++++ drivers/soc/qcom/Makefile | 2 +- drivers/soc/qcom/sleep-status.c | 178 +++++++++++++++++++++ include/soc/qcom/pm.h | 2 + 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,cpu-sleep-status.txt create mode 100644 drivers/soc/qcom/sleep-status.c diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,cpu-sleep-status.txt b/Documentation/devicetree/bindings/arm/msm/qcom,cpu-sleep-status.txt new file mode 100644 index 0000000..3d2974e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/qcom,cpu-sleep-status.txt @@ -0,0 +1,41 @@ +* MSM Sleep Status + +MSM Sleep status device is used to check the power collapsed status of a +offlined core. The core that initiates the hotplug would wait on the +sleep status device before CPU_DEAD notifications are sent out. Some hardware +devices require that the offlined core is power collapsed before turning off +the resources that are used by the offlined core. + + +PROPERTIES + +- compatible: + Usage: required + Value type: + Definition: Should be "qcom,cpu-sleep-status" + +- reg: + Usage: required + Value type: + Definition: The physical address of the sleep status register for + core0, the second element is the size of the register. + +- qcom,cpu-alias-addr: + Usage: required + Value type: + Definition: On MSM chipset, the each cores registers are at a + fixed offset each other. + +- qcom,cpu-sleep-status-mask: + Usage: required + Value type: + Definition: The bit mask within the status register that + indicates the Core's sleep state. + +Example: + qcom,cpu-sleep-status@f9088008 { + compatible = "qcom,cpu-sleep-status"; + reg = <0xf9088008 0x4>; + qcom,cpu-alias-addr = <0x10000>; + qcom,sleep-status-mask = <0x80000>; + }; diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 87c3b9704..d2cc9c0 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o -obj-$(CONFIG_QCOM_PM) += spm_devices.o spm.o msm-pm.o +obj-$(CONFIG_QCOM_PM) += spm_devices.o spm.o msm-pm.o sleep-status.o CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o diff --git a/drivers/soc/qcom/sleep-status.c b/drivers/soc/qcom/sleep-status.c new file mode 100644 index 0000000..aa6340c --- /dev/null +++ b/drivers/soc/qcom/sleep-status.c @@ -0,0 +1,178 @@ +/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct msm_pm_sleep_status_data { + void *base_addr; + uint32_t cpu_offset; + uint32_t mask; +}; + +static struct msm_pm_sleep_status_data *msm_pm_slp_sts; + +/** + * msm_pm_wait_cpu_shutdown() - Wait for a core to be power collapsed during + * hotplug + * + * @ cpu - cpu to wait on. + * + * Blocking function call that waits on the core to be power collapsed. This + * function is called from platform_cpu_die to ensure that a core is power + * collapsed before sending the CPU_DEAD notification so the drivers could + * remove the resource votes for this CPU(regulator and clock) + */ +int msm_pm_wait_cpu_shutdown(unsigned int cpu) +{ + int timeout = 0; + + if (!msm_pm_slp_sts) + return 0; + + if (!msm_pm_slp_sts[cpu].base_addr) + return 0; + + while (1) { + /* + * Check for the SPM of the core being hotplugged to set + * its sleep state.The SPM sleep state indicates that the + * core has been power collapsed. + */ + int acc_sts = __raw_readl(msm_pm_slp_sts[cpu].base_addr); + + if (acc_sts & msm_pm_slp_sts[cpu].mask) + return 0; + + udelay(100); + /* + * Dump spm registers for debugging + */ + if (++timeout == 20) { + msm_spm_dump_regs(cpu); + __WARN_printf( + "CPU%u didn't collapse in 2ms, sleep status: 0x%x\n", + cpu, acc_sts); + } + } + + return -EBUSY; +} + +static int msm_cpu_status_probe(struct platform_device *pdev) +{ + struct msm_pm_sleep_status_data *pdata; + char *key; + u32 cpu; + + if (!pdev) + return -EFAULT; + + msm_pm_slp_sts = devm_kcalloc(&pdev->dev, num_possible_cpus(), + sizeof(*msm_pm_slp_sts), GFP_KERNEL); + + if (!msm_pm_slp_sts) + return -ENOMEM; + + if (pdev->dev.of_node) { + struct resource *res; + u32 offset; + int rc; + u32 mask; + bool offset_available = true; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + key = "qcom,cpu-alias-addr"; + rc = of_property_read_u32(pdev->dev.of_node, key, &offset); + + if (rc) + offset_available = false; + + key = "qcom,sleep-status-mask"; + rc = of_property_read_u32(pdev->dev.of_node, key, &mask); + + if (rc) + return -ENODEV; + + for_each_possible_cpu(cpu) { + phys_addr_t base_c; + + if (offset_available) + base_c = res->start + cpu * offset; + else { + res = platform_get_resource(pdev, + IORESOURCE_MEM, cpu); + if (!res) + return -ENODEV; + base_c = res->start; + } + + msm_pm_slp_sts[cpu].base_addr = + devm_ioremap(&pdev->dev, base_c, + resource_size(res)); + msm_pm_slp_sts[cpu].mask = mask; + + if (!msm_pm_slp_sts[cpu].base_addr) + return -ENOMEM; + } + } else { + pdata = pdev->dev.platform_data; + if (!pdev->dev.platform_data) + return -EINVAL; + + for_each_possible_cpu(cpu) { + msm_pm_slp_sts[cpu].base_addr = + pdata->base_addr + cpu * pdata->cpu_offset; + msm_pm_slp_sts[cpu].mask = pdata->mask; + } + } + + return 0; +}; + +static struct of_device_id msm_slp_sts_match_tbl[] = { + {.compatible = "qcom,cpu-sleep-status"}, + {}, +}; + +static struct platform_driver msm_cpu_status_driver = { + .probe = msm_cpu_status_probe, + .driver = { + .name = "qcom,cpu-sleep-status", + .owner = THIS_MODULE, + .of_match_table = msm_slp_sts_match_tbl, + }, +}; + +int __init msm_pm_sleep_status_init(void) +{ + static bool registered; + + if (registered) + return 0; + registered = true; + + return platform_driver_register(&msm_cpu_status_driver); +} +arch_initcall(msm_pm_sleep_status_init); diff --git a/include/soc/qcom/pm.h b/include/soc/qcom/pm.h index ed6124a..3de04b8 100644 --- a/include/soc/qcom/pm.h +++ b/include/soc/qcom/pm.h @@ -32,12 +32,14 @@ enum msm_pm_l2_scm_flag { bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle); int msm_pm_cpu_hotplug_enter(unsigned int cpu); int msm_pm_secondary_startup(unsigned int cpu); +int msm_pm_wait_cpu_shutdown(unsigned int cpu); #else static inline bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle) { return true; } static inline int msm_pm_cpu_hotplug_enter(unsigned int cpu) { return 0; } static inline int msm_pm_secondary_startup(unsigned int cpu) { return 0; } +static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; } #endif #endif /* __QCOM_PM_H */