From patchwork Sat Jun 27 03:02:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 6684631 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 018569F380 for ; Sat, 27 Jun 2015 03:10:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0379D2060D for ; Sat, 27 Jun 2015 03:10:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 006B620609 for ; Sat, 27 Jun 2015 03:10:11 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z8gS9-0001Tw-BZ; Sat, 27 Jun 2015 03:06:49 +0000 Received: from mail-pd0-f176.google.com ([209.85.192.176]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z8gOo-0006w0-An for linux-arm-kernel@lists.infradead.org; Sat, 27 Jun 2015 03:03:24 +0000 Received: by pdcu2 with SMTP id u2so84847472pdc.3 for ; Fri, 26 Jun 2015 20:03:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=pUH+H3yG9PGzzIJkh5W3tlQIWcZTkPOWh0Brr7g1gq4=; b=HSZDm0o3BLI07tFc96Hh+roynKnlTZzVN6uK8HMSldxskZscL4qXA+OV1iVVYbBEYj ywYMleRGK+U0yBP4TwmCrW8wnd4TdlzIKI8+YOnucdwuzbYgYBiLgYSJyBp1Sayp/rus vCGpv3TdyVAdWbQIrAvnudqvbI/lV/SHG90rlbUC86p16dJBZFjalxYO0veBKaR7d54c nPrmave0N5OCpnrnsoQxWyo0rFSx3mQ/D67mIR3szXAxa5hbqba05xp1ORFwP2WaK20U CNKsLqc/feRZ3RTW6lzQkw7oQOYpc4Cqi6gcsS3JbpufSLCgBFjCaoaQKHPgQvGB/C2V KiJw== X-Gm-Message-State: ALoCoQmpKthc52Z48TbCNFL5zM1BZ4RyN09HaP6dT562zCzLWrdSAG0GGzXmkBHSxTKZbnyb0+SD X-Received: by 10.66.250.12 with SMTP id yy12mr9217993pac.43.1435374181141; Fri, 26 Jun 2015 20:03:01 -0700 (PDT) Received: from ubuntu.localdomain (c-24-8-37-141.hsd1.co.comcast.net. [24.8.37.141]) by mx.google.com with ESMTPSA id j7sm34787756pdp.83.2015.06.26.20.02.59 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jun 2015 20:03:00 -0700 (PDT) From: Lina Iyer To: rjw@rjwysocki.net, ulf.hansson@linaro.org, khilman@linaro.org Subject: [PATCH RFC v2 11/16] drivers: qcom: spm: Support cache and coherency SPMs Date: Fri, 26 Jun 2015 21:02:31 -0600 Message-Id: <1435374156-19214-12-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1435374156-19214-1-git-send-email-lina.iyer@linaro.org> References: <1435374156-19214-1-git-send-email-lina.iyer@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150626_200322_454211_6B67DA42 X-CRM114-Status: GOOD ( 18.26 ) X-Spam-Score: -2.6 (--) Cc: k.kozlowski@samsung.com, linux-pm@vger.kernel.org, msivasub@codeaurora.org, geert@linux-m68k.org, Lina Iyer , agross@codeaurora.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Recognize non-CPU SPM devices defined in the DT and configure the corresponding SPM hardware. SPM controllers for L2 controls the cache's idle low power state and may also be used to turn off the cluster's power rail. On multi-cluster SoCs, each cluster would have an SPM for the cache and an additional coherency level SPM. The coherency SPM turns off or puts the coherency hardware in idle and any caches present at that level. Signed-off-by: Lina Iyer --- drivers/soc/qcom/spm.c | 75 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index b04b05a..bef2dfe1 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -68,9 +68,17 @@ struct spm_reg_data { u8 start_index[PM_SLEEP_MODE_NR]; }; +struct cluster; + struct spm_driver_data { void __iomem *reg_base; const struct spm_reg_data *reg_data; + struct cluster *domain; +}; + +/* Group for domain entities */ +struct cluster { + struct spm_driver_data *domain_spm; }; static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = { @@ -116,6 +124,9 @@ static const struct spm_reg_data spm_reg_8064_cpu = { static DEFINE_PER_CPU(struct spm_driver_data *, cpu_spm_drv); +/* 3 instances: little, big and coherency (cluster of clusters) */ +static struct cluster cpu_domain[3]; + typedef int (*idle_fn)(int); static DEFINE_PER_CPU(idle_fn*, qcom_idle_ops); @@ -282,14 +293,26 @@ static struct cpuidle_ops qcom_cpuidle_ops __initdata = { CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v1, "qcom,kpss-acc-v1", &qcom_cpuidle_ops); CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v2, "qcom,kpss-acc-v2", &qcom_cpuidle_ops); +/* Match L2 SPM with their affinity level */ +static const struct of_device_id cache_spm_table[] = { + { }, +}; + static struct spm_driver_data *spm_get_drv(struct platform_device *pdev, - int *spm_cpu) + int *index, bool *is_domain_spm) { struct spm_driver_data *drv = NULL; - struct device_node *cpu_node, *saw_node; + struct device_node *cpu_node, *saw_node, *cache_node; int cpu; bool found; + const struct of_device_id *match_id; + int idx; + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return ERR_PTR(-ENOMEM); + + /* Check for a CPU SPM, if found we are done */ for_each_possible_cpu(cpu) { cpu_node = of_cpu_device_node_get(cpu); if (!cpu_node) @@ -302,10 +325,37 @@ static struct spm_driver_data *spm_get_drv(struct platform_device *pdev, break; } + /* + * If found, we have a CPU SPM, if not, + * check if we have a cache SPM + */ if (found) { - drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); - if (drv) - *spm_cpu = cpu; + /* + * Now that we have our CPU, find the associated L2 + * SAW and bind the CPU with the domain that contains + * the L2 SAW. + */ + cache_node = of_parse_phandle(cpu_node, + "next-level-cache", 0); + saw_node = of_parse_phandle(cache_node, "qcom,saw", 0); + match_id = of_match_node(cache_spm_table, saw_node); + if (match_id) { + idx = (int) match_id->data; + drv->domain = &cpu_domain[idx]; + } + of_node_put(saw_node); + of_node_put(cache_node); + *index = cpu; + *is_domain_spm = false; + } else { + /* Check if this is a cache SPM */ + match_id = of_match_node(cache_spm_table, pdev->dev.of_node); + if (!match_id) { + devm_kfree(&pdev->dev, drv); + return ERR_PTR(-ENODEV); + } + *index = (int) match_id->data; + *is_domain_spm = true; } return drv; @@ -327,11 +377,12 @@ static int spm_dev_probe(struct platform_device *pdev) struct resource *res; const struct of_device_id *match_id; void __iomem *addr; - int cpu; + int index; + bool is_domain_spm; - drv = spm_get_drv(pdev, &cpu); - if (!drv) - return -EINVAL; + drv = spm_get_drv(pdev, &index, &is_domain_spm); + if (IS_ERR(drv)) + return PTR_ERR(drv); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); drv->reg_base = devm_ioremap_resource(&pdev->dev, res); @@ -366,7 +417,11 @@ static int spm_dev_probe(struct platform_device *pdev) /* Set up Standby as the default low power mode */ spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); - per_cpu(cpu_spm_drv, cpu) = drv; + /* We are ready to use the CPU/Cache SPM. */ + if (is_domain_spm) + cpu_domain[index].domain_spm = drv; + else + per_cpu(cpu_spm_drv, index) = drv; return 0; }