From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Lezcano Subject: Re: [PATCH v2 08/10] qcom: cpuidle: Add cpuidle driver for QCOM cpus Date: Wed, 13 Aug 2014 13:22:09 +0200 Message-ID: <53EB4A61.2040609@linaro.org> References: <1407872640-6732-1-git-send-email-lina.iyer@linaro.org> <1407872640-6732-9-git-send-email-lina.iyer@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: Received: from mail-wi0-f182.google.com ([209.85.212.182]:57458 "EHLO mail-wi0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750751AbaHMLWM (ORCPT ); Wed, 13 Aug 2014 07:22:12 -0400 Received: by mail-wi0-f182.google.com with SMTP id d1so619649wiv.9 for ; Wed, 13 Aug 2014 04:22:11 -0700 (PDT) In-Reply-To: <1407872640-6732-9-git-send-email-lina.iyer@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org List-Id: linux-arm-msm@vger.kernel.org To: Lina Iyer , 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, Lorenzo Pieralisi On 08/12/2014 09:43 PM, Lina Iyer wrote: > Add cpuidle driver interface to allow cpus to go into C-States. > > Signed-off-by: Lina Iyer Hi Lina, I think you should based this driver on top of Lorenzo's work. Cc Lorenzo. > --- > .../devicetree/bindings/arm/msm/qcom,cpuidle.txt | 73 ++++++++++= + > drivers/cpuidle/Makefile | 1 + > drivers/cpuidle/cpuidle-qcom.c | 140 ++++++++++= +++++++++++ > 3 files changed, 214 insertions(+) > create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,c= puidle.txt > create mode 100644 drivers/cpuidle/cpuidle-qcom.c > > diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,cpuidle.t= xt b/Documentation/devicetree/bindings/arm/msm/qcom,cpuidle.txt > new file mode 100644 > index 0000000..b094baf > --- /dev/null > +++ b/Documentation/devicetree/bindings/arm/msm/qcom,cpuidle.txt > @@ -0,0 +1,73 @@ > +Qualcomm CPUIdle driver > + > +The Qualcomm cpuidle driver enables the processor to enter low power= modes > +when idle. The processors support 4 low power modes. > + wfi - also known as clock gating > + retention - processor clock gated and processor power is reduced. > + standalone-pc - processor is powered down and when reset, the core > + boots into secure mode and trampolines back to the kernel. > + Every core can individually enter this low power mode without > + affecting the state of the other cores. > + pc - essentially standalone power collapse, but indicates that the > + latency to put SoC into a low power state is tolerable. > + > +The cpuidle node is comprised of nodes, each of which represent a C-= State the > +processor can achieve. Each node provides the latency and residency = which > +helps the cpuidle governor to choose the appropriate low power mode = based on > +the time available. Not all SoCs may support all the above low power= modes. > + > +PROPERTIES > + > +- compatible: > + Usage: required > + Value type: > + Definition: Should be "qcom,cpuidle" > + > +- qcom,cpu-level: > + Usage: required > + Value type: { Node } > + Definition: Describes a C-State of the processor > + > + PROPERTIES of qcom,cpu-level > + > + - reg: > + Usage: required > + Value type: > + Definition: Index of the C-State > + > + - qcom,state-name: > + Usage: required > + Value type: > + Definition: C-State moniker > + > + - qcom,spm-cpu-mode: > + Usage: required > + Value type: > + Definition: The description of the h/w mode that will be > + achieved in this C-State. > + > + - qcom,latency-us: > + Usage: required > + Value type: > + Defintion: Time taken to exit from the C-State > + > + - qcom,residency-us: > + Usage: required > + Value type: > + Defintion: Time to be spent in this C-State for the power > + saving to be beneficial. > + > +Example: > + > + qcom,cpuidle { > + compatible =3D "qcom,cpuidle"; > + #address-cells =3D <1>; > + #size-cells =3D <0>; > + qcom,cpu-level@0 { > + reg =3D <0x0>; > + qcom,state-name =3D "C1"; > + qcom,spm-cpu-mode =3D "wfi"; > + qcom,latency-us =3D <1>; > + qcom,residency-us =3D <1>; > + }; > + }; > diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile > index 11edb31..4a2c446 100644 > --- a/drivers/cpuidle/Makefile > +++ b/drivers/cpuidle/Makefile > @@ -16,6 +16,7 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) +=3D cpuidle-zynq.o > obj-$(CONFIG_ARM_U8500_CPUIDLE) +=3D cpuidle-ux500.o > obj-$(CONFIG_ARM_AT91_CPUIDLE) +=3D cpuidle-at91.o > obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) +=3D cpuidle-exynos.o > +obj-$(CONFIG_ARM_QCOM_CPUIDLE) +=3D cpuidle-qcom.o > > ###################################################################= ############ > # MIPS drivers > diff --git a/drivers/cpuidle/cpuidle-qcom.c b/drivers/cpuidle/cpuidle= -qcom.c > new file mode 100644 > index 0000000..8e70a88 > --- /dev/null > +++ b/drivers/cpuidle/cpuidle-qcom.c > @@ -0,0 +1,140 @@ > +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. > + * Copyright (c) 2014 Linaro. > + * > + * This program is free software; you can redistribute it and/or mod= ify > + * it under the terms of the GNU General Public License version 2 an= d > + * 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 > + > +struct lookup { > + enum msm_pm_sleep_mode mode; > + char *name; > +}; > + > +static enum msm_pm_sleep_mode spm_sleep_modes[MSM_PM_SLEEP_MODE_NR]; > + > +static int qcom_lpm_enter(struct cpuidle_device *dev, > + struct cpuidle_driver *drv, > + int index) > +{ > + return msm_cpu_pm_enter_sleep(spm_sleep_modes[index], true); > +} > + > +static struct cpuidle_driver qcom_cpuidle_driver =3D { > + .name =3D "qcom_cpuidle", > + .owner =3D THIS_MODULE, > +}; > + > +static int qcom_cpuidle_probe(struct platform_device *pdev) > +{ > + int ret; > + struct device_node *top =3D pdev->dev.of_node; > + struct device_node *n; > + char *key; > + const char *val; > + int index =3D 0; > + int i; > + struct cpuidle_state *state; > + static const struct lookup pm_sm_lookup[] =3D { > + {MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT, > + "wfi"}, > + {MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE, > + "standalone_pc"}, > + {MSM_PM_SLEEP_MODE_POWER_COLLAPSE, > + "pc"}, > + {MSM_PM_SLEEP_MODE_RETENTION, > + "retention"}, > + }; > + > + if (!top) > + return -ENODEV; > + > + for_each_child_of_node(top, n) { > + key =3D "qcom,cpu-level"; > + if (of_node_cmp(n->name, key)) > + continue; > + > + state =3D &qcom_cpuidle_driver.states[index]; > + > + key =3D "qcom,spm-cpu-mode"; > + ret =3D of_property_read_string(n, key, &val); > + if (ret) > + goto failed; > + for (i =3D 0; i < ARRAY_SIZE(pm_sm_lookup); i++) { > + if (!strcmp(val, pm_sm_lookup[i].name)) { > + spm_sleep_modes[index] =3D pm_sm_lookup[i].mode; > + break; > + } > + } > + if (i =3D=3D ARRAY_SIZE(pm_sm_lookup)) { > + ret =3D -EFAULT; > + goto failed; > + } > + > + strncpy(state->desc, val, CPUIDLE_DESC_LEN); > + > + key =3D "qcom,state-name"; > + ret =3D of_property_read_string(n, key, &val); > + if (ret) > + goto failed; > + strncpy(state->name, val, CPUIDLE_NAME_LEN); > + > + key =3D "qcom,latency-us"; > + ret =3D of_property_read_u32(n, key, &state->exit_latency); > + if (ret) > + goto failed; > + > + key =3D "qcom,residency-us"; > + ret =3D of_property_read_u32(n, key, &state->target_residency); > + if (ret) > + goto failed; > + > + state->flags =3D CPUIDLE_FLAG_TIME_VALID; > + state->enter =3D qcom_lpm_enter; > + index++; > + } > + > + qcom_cpuidle_driver.state_count =3D index; > + qcom_cpuidle_driver.safe_state_index =3D 0; > + > + ret =3D cpuidle_register(&qcom_cpuidle_driver, NULL); > + if (ret) { > + dev_err(&pdev->dev, "failed to register cpuidle driver\n"); > + return ret; > + } > + > + return 0; > + > +failed: > + dev_err(&pdev->dev, "error parsing key: %s\n", key); > + return ret; > +} > + > +static struct of_device_id qcom_cpuidle_match_tbl[] =3D { > + {.compatible =3D "qcom,cpuidle"}, > + {}, > +}; > + > +static struct platform_driver qcom_cpuidle_platform_driver =3D { > + .probe =3D qcom_cpuidle_probe, > + .driver =3D { > + .name =3D "qcom,cpuidle", > + .owner =3D THIS_MODULE, > + .of_match_table =3D qcom_cpuidle_match_tbl, > + }, > +}; > + > +module_platform_driver(qcom_cpuidle_platform_driver); > --=20 Linaro.org =E2=94=82 Open source software fo= r ARM SoCs =46ollow Linaro: Facebook | Twitter | Blog