linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: Lina Iyer <lina.iyer@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,
	Venkat Devarasetty <vdevaras@codeaurora.org>,
	Nicolas Pitre <nicolas.pitre@linaro.org>
Subject: Re: [PATCH v2 07/10] qcom: msm-pm: Add cpu low power mode functions
Date: Wed, 13 Aug 2014 13:18:01 +0200	[thread overview]
Message-ID: <53EB4969.3030204@linaro.org> (raw)
In-Reply-To: <1407872640-6732-8-git-send-email-lina.iyer@linaro.org>

On 08/12/2014 09:43 PM, Lina Iyer wrote:
> Add interface layer to abstract and handle hardware specific
> functionality for executing various cpu low power modes in QCOM
> chipsets.
>
> Signed-off-by: Venkat Devarasetty <vdevaras@codeaurora.org>
> Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> ---
>   drivers/soc/qcom/Makefile |   2 +-
>   drivers/soc/qcom/msm-pm.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++
>   include/soc/qcom/pm.h     |  39 +++++++++
>   3 files changed, 259 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/soc/qcom/msm-pm.c
>   create mode 100644 include/soc/qcom/pm.h
>
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index d7ae93b..7925f83 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
> +obj-$(CONFIG_QCOM_PM) +=	spm-devices.o spm.o msm-pm.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/msm-pm.c b/drivers/soc/qcom/msm-pm.c
> new file mode 100644
> index 0000000..f2f15b8
> --- /dev/null
> +++ b/drivers/soc/qcom/msm-pm.c
> @@ -0,0 +1,219 @@
> +/* 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 <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/smp.h>
> +#include <linux/tick.h>
> +#include <linux/platform_device.h>
> +#include <linux/cpu_pm.h>
> +#include <linux/uaccess.h>
> +
> +#include <soc/qcom/spm.h>
> +#include <soc/qcom/pm.h>
> +#include <soc/qcom/scm.h>
> +#include <soc/qcom/scm-boot.h>
> +
> +#include <asm/suspend.h>
> +#include <asm/cacheflush.h>
> +#include <asm/cputype.h>
> +#include <asm/system_misc.h>
> +
> +#define SCM_CMD_TERMINATE_PC	(0x2)
> +#define SCM_CMD_CORE_HOTPLUGGED (0x10)
> +#define SCM_FLUSH_FLAG_MASK	(0x3)
> +
> +static bool msm_pm_is_L1_writeback(void)
> +{
> +	u32 cache_id = 0;
> +
> +#if defined(CONFIG_CPU_V7)
> +	u32 sel = 0;
> +
> +	asm volatile ("mcr p15, 2, %[ccselr], c0, c0, 0\n\t"
> +		      "isb\n\t"
> +		      "mrc p15, 1, %[ccsidr], c0, c0, 0\n\t"
> +		      :[ccsidr]"=r" (cache_id)
> +		      :[ccselr]"r" (sel)
> +		     );
> +	return cache_id & BIT(30);
> +#elif defined(CONFIG_ARM64)
> +	u32 sel = 0;
> +	asm volatile("msr csselr_el1, %[ccselr]\n\t"
> +		     "isb\n\t"
> +		     "mrs %[ccsidr],ccsidr_el1\n\t"
> +		     :[ccsidr]"=r" (cache_id)
> +		     :[ccselr]"r" (sel)
> +		    );
> +	return cache_id & BIT(30);
> +#else
> +#error No valid CPU arch selected
> +#endif
> +}
> +
> +static inline void msm_arch_idle(void)
> +{
> +	/* Flush and clock-gate */
> +	mb();

Why is needed this memory barrier ?

> +	wfi();
> +}
> +
> +static bool msm_pm_swfi(bool from_idle)
> +{
> +	msm_arch_idle();
> +	return true;
> +}
> +
> +static bool msm_pm_retention(bool from_idle)
> +{
> +	int ret = 0;
> +
> +	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_RETENTION, false);
> +	WARN_ON(ret);
> +
> +	msm_arch_idle();
> +
> +	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
> +	WARN_ON(ret);

Why do you need to set the clock gating mode each time you exit the 
retention mode ?

> +	return true;
> +}
> +
> +static int msm_pm_collapse(unsigned long from_idle)
> +{
> +	enum msm_pm_l2_scm_flag flag = MSM_SCM_L2_ON;
> +
> +	/**
> +	 * Single core processors need to have L2
> +	 * flushed when powering down the core.
> +	 * Notify SCM to flush secure L2 lines.
> +	 */
> +	if (num_possible_cpus() == 1)
> +		flag = MSM_SCM_L2_OFF;

I am wondering if this shouldn't be handle by a mcpm driver.

Cc nico.

> +	if (flag == MSM_SCM_L2_OFF)
> +		flush_cache_all();
> +	else if (msm_pm_is_L1_writeback())
> +		flush_cache_louis();
> +
> +	flag &= SCM_FLUSH_FLAG_MASK;
> +	if (!from_idle)
> +		flag |= SCM_CMD_CORE_HOTPLUGGED;
> +
> +	scm_call_atomic1(SCM_SVC_BOOT, SCM_CMD_TERMINATE_PC, flag);
> +
> +	return 0;
> +}
> +
> +static void set_up_boot_address(void *entry, int cpu)
> +{
> +	static int flags[NR_CPUS] = {
> +		SCM_FLAG_WARMBOOT_CPU0,
> +		SCM_FLAG_WARMBOOT_CPU1,
> +		SCM_FLAG_WARMBOOT_CPU2,
> +		SCM_FLAG_WARMBOOT_CPU3,
> +	};
> +	static DEFINE_PER_CPU(void *, last_known_entry);
> +
> +	if (entry == per_cpu(last_known_entry, cpu))
> +		return;
> +
> +	per_cpu(last_known_entry, cpu) = entry;
> +	scm_set_boot_addr(virt_to_phys(entry), flags[cpu]);
> +}
> +
> +static bool __ref msm_pm_spm_power_collapse(unsigned int cpu, bool from_idle)
> +{
> +	void *entry;
> +	bool collapsed = 0;
> +	int ret;
> +	bool save_cpu_regs = (cpu_online(cpu) || from_idle);
> +
> +	if (from_idle)
> +		cpu_pm_enter();
> +
> +	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE, false);
> +	WARN_ON(ret);
> +
> +	entry = save_cpu_regs ? cpu_resume : secondary_startup;
> +	set_up_boot_address(entry, cpu);
> +
> +#ifdef CONFIG_CPU_V7
> +	collapsed = !cpu_suspend(from_idle, msm_pm_collapse);
> +#else
> +	collapsed = !cpu_suspend(0);
> +#endif
> +
> +	if (collapsed)
> +		local_fiq_enable();
> +
> +	if (from_idle)
> +		cpu_pm_exit();
> +
> +	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
> +	WARN_ON(ret);
> +
> +	return collapsed;
> +}
> +
> +static bool msm_pm_power_collapse_standalone(bool from_idle)
> +{
> +	unsigned int cpu = smp_processor_id();
> +	bool collapsed;
> +
> +	collapsed = msm_pm_spm_power_collapse(cpu, from_idle);
> +
> +	return collapsed;
> +}
> +
> +static bool msm_pm_power_collapse(bool from_idle)
> +{
> +	unsigned int cpu = smp_processor_id();
> +	bool collapsed;
> +
> +	collapsed = msm_pm_spm_power_collapse(cpu, from_idle);
> +
> +	return collapsed;
> +}
> +
> +static bool (*execute[MSM_PM_SLEEP_MODE_NR])(bool idle) = {
> +	[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = msm_pm_swfi,
> +	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] =
> +		msm_pm_power_collapse_standalone,
> +	[MSM_PM_SLEEP_MODE_RETENTION] = msm_pm_retention,
> +	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = msm_pm_power_collapse,
> +};
> +
> +/**
> + * msm_cpu_pm_enter_sleep(): Enter a low power mode on current cpu
> + *
> + * @mode - sleep mode to enter
> + * @from_idle - bool to indicate that the mode is exercised during idle/suspend
> + *
> + * The code should be with interrupts disabled and on the core on which the
> + * low power is to be executed.
> + *
> + */
> +bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle)
> +{
> +	bool exit_stat = false;
> +
> +	if (execute[mode])
> +		exit_stat = execute[mode](from_idle);
> +
> +	local_irq_enable();
> +	return exit_stat;
> +}
> +EXPORT_SYMBOL(msm_cpu_pm_enter_sleep);
> diff --git a/include/soc/qcom/pm.h b/include/soc/qcom/pm.h
> new file mode 100644
> index 0000000..01872ad
> --- /dev/null
> +++ b/include/soc/qcom/pm.h
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef __QCOM_PM_H
> +#define __QCOM_PM_H
> +
> +enum msm_pm_sleep_mode {
> +	MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
> +	MSM_PM_SLEEP_MODE_RETENTION,
> +	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
> +	MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
> +	MSM_PM_SLEEP_MODE_NR,
> +};
> +
> +enum msm_pm_l2_scm_flag {
> +	MSM_SCM_L2_ON = 0,
> +	MSM_SCM_L2_OFF = 1,
> +};
> +
> +#ifdef CONFIG_QCOM_PM
> +bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle);
> +#else
> +static inline bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode,
> +						bool from_idle)
> +{ return true; }
> +#endif
> +
> +#endif  /* __QCOM_PM_H */
>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

  reply	other threads:[~2014-08-13 11:18 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-12 19:43 [PATCH v2 00/10] QCOM 8074 cpuidle driver Lina Iyer
2014-08-12 19:43 ` [PATCH v2 01/10] msm: scm: Move scm-boot files to drivers/soc and include/soc Lina Iyer
2014-08-12 19:43 ` [PATCH v2 02/10] msm: scm: Add SCM warmboot flags for quad core targets Lina Iyer
2014-08-14 10:20   ` Pramod Gurav
2014-08-12 19:43 ` [PATCH v2 03/10] qcom: spm: Add Subsystem Power Manager (SPM) driver for QCOM chipsets Lina Iyer
2014-08-13 10:49   ` Daniel Lezcano
2014-08-13 14:00     ` Lina Iyer
2014-08-14 13:01   ` Pramod Gurav
2014-08-14 15:18     ` Lina Iyer
2014-08-14 15:16   ` Kumar Gala
2014-08-14 15:27     ` Lina Iyer
2014-08-14 15:33       ` Kumar Gala
2014-08-14 16:09   ` Kumar Gala
2014-08-14 16:18     ` Lina Iyer
2014-08-14 16:41       ` Kumar Gala
2014-08-15  4:18         ` Lina Iyer
2014-08-15 13:42           ` Kumar Gala
2014-08-16  3:41             ` Lina Iyer
2014-08-12 19:43 ` [PATCH v2 04/10] soc: qcom: Add QCOM Power management config Lina Iyer
2014-08-13  9:36   ` Daniel Lezcano
2014-08-12 19:43 ` [PATCH v2 05/10] arm: qcom-msm8974: Add CPU phandles to CPU definitions Lina Iyer
2014-08-12 21:09   ` Kumar Gala
2014-08-14 10:04   ` Pramod Gurav
2014-08-12 19:43 ` [PATCH v2 06/10] arm: dts: qcom: Add SPM device bindings for 8974 Lina Iyer
2014-08-12 21:10   ` Kumar Gala
2014-08-12 21:32     ` Lina Iyer
2014-08-13  7:39   ` Ivan T. Ivanov
2014-08-12 19:43 ` [PATCH v2 07/10] qcom: msm-pm: Add cpu low power mode functions Lina Iyer
2014-08-13 11:18   ` Daniel Lezcano [this message]
2014-08-13 14:16     ` Lina Iyer
2014-08-14 14:24       ` Daniel Lezcano
2014-08-14 14:53         ` Lina Iyer
2014-08-14 16:11       ` Daniel Lezcano
2014-08-14 19:22         ` Lina Iyer
2014-08-15  0:01           ` Daniel Lezcano
2014-08-15  1:02             ` Lina Iyer
2014-08-14 13:38   ` Pramod Gurav
2014-08-14 14:43     ` Lina Iyer
2014-08-12 19:43 ` [PATCH v2 08/10] qcom: cpuidle: Add cpuidle driver for QCOM cpus Lina Iyer
2014-08-13 11:22   ` Daniel Lezcano
2014-08-13 14:03     ` Lina Iyer
2014-08-12 19:43 ` [PATCH v2 09/10] qcom: cpuidle: Config option to enable QCOM cpuidle driver Lina Iyer
2014-08-13 11:18   ` Daniel Lezcano
2014-08-12 19:44 ` [PATCH v2 10/10] qcom: cpuidle: Add cpuidle device nodes for 8974 chipset Lina Iyer
2014-08-13  1:52 ` [PATCH v2 00/10] QCOM 8074 cpuidle driver Stephen Boyd
2014-08-13  2:17   ` Lina Iyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53EB4969.3030204@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=amit.kucheria@linaro.org \
    --cc=davidb@codeaurora.org \
    --cc=galak@codeaurora.org \
    --cc=khilman@linaro.org \
    --cc=lina.iyer@linaro.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=msivasub@codeaurora.org \
    --cc=nicolas.pitre@linaro.org \
    --cc=sboyd@codeaurora.org \
    --cc=vdevaras@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).