* [PATCH 1/4] soc: Mediatek: Create Mediatek SIP call
2015-12-18 2:42 [PATCH 0/4] mediatek: Add cpuidle cluster sleep support for MT8173 Fan Chen
@ 2015-12-18 2:42 ` Fan Chen
2015-12-18 2:42 ` [PATCH 2/4] soc: mediatek: To move power control logic to ARM TF Fan Chen
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Fan Chen @ 2015-12-18 2:42 UTC (permalink / raw)
To: linux-arm-kernel
Create a generic interface for issuing SIP Service calls
which are specified in ARM SMC CALLING CONVENTION.
Signed-off-by: Fan Chen <fan.chen@mediatek.com>
---
drivers/soc/mediatek/Kconfig | 8 ++++++++
drivers/soc/mediatek/Makefile | 1 +
drivers/soc/mediatek/mtk-sip.c | 28 ++++++++++++++++++++++++++++
include/linux/soc/mediatek/mtk-sip.h | 17 +++++++++++++++++
4 files changed, 54 insertions(+)
create mode 100644 drivers/soc/mediatek/mtk-sip.c
create mode 100644 include/linux/soc/mediatek/mtk-sip.h
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 9d50682..65c1323 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -29,3 +29,11 @@ config MTK_SCPSYS
help
Say yes here to add support for the MediaTek SCPSYS power domain
driver.
+
+config MTK_SIP
+ bool "Mediatek SIP Support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on HAVE_SMCCC
+ help
+ Say yes here to add support for the MediaTek SIP call.
+
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..67077dc 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
+obj-$(CONFIG_MTK_SIP) += mtk-sip.o
diff --git a/drivers/soc/mediatek/mtk-sip.c b/drivers/soc/mediatek/mtk-sip.c
new file mode 100644
index 0000000..882617f
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-sip.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/arm-smccc.h>
+#include <linux/soc/mediatek/mtk-sip.h>
+
+int mtk_sip_simple_call(unsigned long func_id,
+ unsigned long a1,
+ unsigned long a2,
+ unsigned long a3)
+{
+ struct smccc_res res;
+
+ smccc_smc(func_id, a1, a2, a3, 0, 0, 0, 0, &res);
+
+ return res.a0;
+}
+
diff --git a/include/linux/soc/mediatek/mtk-sip.h b/include/linux/soc/mediatek/mtk-sip.h
new file mode 100644
index 0000000..dce1818
--- /dev/null
+++ b/include/linux/soc/mediatek/mtk-sip.h
@@ -0,0 +1,17 @@
+#ifndef __SOC_MEDIATEK_MTKSIP_H
+#define __SOC_MEDIATEK_MTKSIP_H
+
+#ifdef CONFIG_MTK_SIP
+int mtk_sip_simple_call(unsigned long func_id,
+ unsigned long a1,
+ unsigned long a2,
+ unsigned long a3);
+#else
+static inline int mtk_sip_simple_call(unsigned long func_id,
+ unsigned long a1,
+ unsigned long a2,
+ unsigned long a3)
+{ return -EOPNOTSUPP; }
+#endif
+
+#endif /*__SOC_MEDIATEK_MTKSIP_H*/
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] soc: mediatek: To move power control logic to ARM TF
2015-12-18 2:42 [PATCH 0/4] mediatek: Add cpuidle cluster sleep support for MT8173 Fan Chen
2015-12-18 2:42 ` [PATCH 1/4] soc: Mediatek: Create Mediatek SIP call Fan Chen
@ 2015-12-18 2:42 ` Fan Chen
2015-12-18 2:42 ` [PATCH 3/4] arm64: dts: mediatek: Add cluster sleep support on MT8173 Fan Chen
2015-12-18 2:42 ` [PATCH 4/4] arm64: dts: mediatek: Improve cpuidle latency " Fan Chen
3 siblings, 0 replies; 5+ messages in thread
From: Fan Chen @ 2015-12-18 2:42 UTC (permalink / raw)
To: linux-arm-kernel
From: "yt.lee" <yt.lee@mediatek.com>
Add an option to test if ARM TF supports non-cpus power
control and do it in firmware. Otherwise, fallback to
legecy way handling it in kernel driver.
Regarding time consumption of sip call for the power control.
In 52051 times of sip calls with power_LoadTest,
the maximum cost is 433us and the average cost is 118us.
Signed-off-by: yt.lee <yt.lee@mediatek.com>
Signed-off-by: Fan Chen <fan.chen@mediatek.com>
---
drivers/soc/mediatek/mtk-scpsys.c | 122 ++++++++++++++++++++++------------
include/linux/soc/mediatek/mtk-sip.h | 4 ++
2 files changed, 82 insertions(+), 44 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 4d4203c..cc8d0c8 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -21,6 +21,7 @@
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/soc/mediatek/infracfg.h>
+#include <linux/soc/mediatek/mtk-sip.h>
#include <dt-bindings/power/mt8173-power.h>
#define SPM_VDE_PWR_CON 0x0210
@@ -187,6 +188,7 @@ struct scp {
struct device *dev;
void __iomem *base;
struct regmap *infracfg;
+ bool sip_support;
};
static int scpsys_domain_is_on(struct scp_domain *scpd)
@@ -209,9 +211,8 @@ static int scpsys_domain_is_on(struct scp_domain *scpd)
return -EINVAL;
}
-static int scpsys_power_on(struct generic_pm_domain *genpd)
+static int scpsys_power_on_mtcmos(struct scp_domain *scpd)
{
- struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
struct scp *scp = scpd->scp;
unsigned long timeout;
bool expired;
@@ -219,17 +220,6 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
int ret;
- int i;
-
- for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
- ret = clk_prepare_enable(scpd->clk[i]);
- if (ret) {
- for (--i; i >= 0; i--)
- clk_disable_unprepare(scpd->clk[i]);
-
- goto err_clk;
- }
- }
val = readl(ctl_addr);
val |= PWR_ON_BIT;
@@ -245,10 +235,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (ret > 0)
break;
- if (expired) {
- ret = -ETIMEDOUT;
- goto err_pwr_ack;
- }
+ if (expired)
+ return -ETIMEDOUT;
cpu_relax();
@@ -273,10 +261,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
expired = false;
while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
- if (expired) {
- ret = -ETIMEDOUT;
- goto err_pwr_ack;
- }
+ if (expired)
+ return -ETIMEDOUT;
cpu_relax();
@@ -288,25 +274,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
scpd->bus_prot_mask);
if (ret)
- goto err_pwr_ack;
+ return ret;
}
return 0;
-
-err_pwr_ack:
- for (i = MAX_CLKS - 1; i >= 0; i--) {
- if (scpd->clk[i])
- clk_disable_unprepare(scpd->clk[i]);
- }
-err_clk:
- dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
-
- return ret;
}
-static int scpsys_power_off(struct generic_pm_domain *genpd)
+static int scpsys_power_off_mtcmos(struct scp_domain *scpd)
{
- struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
struct scp *scp = scpd->scp;
unsigned long timeout;
bool expired;
@@ -314,13 +289,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
u32 pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
int ret;
- int i;
if (scpd->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
scpd->bus_prot_mask);
if (ret)
- goto out;
+ return ret;
}
val = readl(ctl_addr);
@@ -331,10 +305,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
timeout = jiffies + HZ;
expired = false;
while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
- if (expired) {
- ret = -ETIMEDOUT;
- goto out;
- }
+
+ if (expired)
+ return -ETIMEDOUT;
cpu_relax();
@@ -365,10 +338,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
if (ret == 0)
break;
- if (expired) {
- ret = -ETIMEDOUT;
- goto out;
- }
+ if (expired)
+ return -ETIMEDOUT;
cpu_relax();
@@ -376,6 +347,62 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
expired = true;
}
+ return 0;
+}
+
+static int scpsys_power_on(struct generic_pm_domain *genpd)
+{
+ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+ struct scp *scp = scpd->scp;
+ int ret;
+ int i;
+
+ for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
+ ret = clk_prepare_enable(scpd->clk[i]);
+ if (ret) {
+ for (--i; i >= 0; i--)
+ clk_disable_unprepare(scpd->clk[i]);
+
+ goto err_clk;
+ }
+ }
+
+ if (!scp->sip_support)
+ ret = scpsys_power_on_mtcmos(scpd);
+ else
+ ret = mtk_sip_simple_call(MTK_SIP_PWR_ON_MTCMOS,
+ scpd->ctl_addr - scp->base, 0, 0);
+ if (ret)
+ goto err_pwr_ack;
+
+ return 0;
+
+err_pwr_ack:
+ for (i = MAX_CLKS - 1; i >= 0; i--) {
+ if (scpd->clk[i])
+ clk_disable_unprepare(scpd->clk[i]);
+ }
+err_clk:
+ dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
+
+ return ret;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+ struct scp *scp = scpd->scp;
+ int ret;
+ int i;
+
+ if (!scp->sip_support)
+ ret = scpsys_power_off_mtcmos(scpd);
+ else
+ ret = mtk_sip_simple_call(MTK_SIP_PWR_OFF_MTCMOS,
+ scpd->ctl_addr - scp->base, 0, 0);
+ if (ret)
+ goto out;
+
for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
clk_disable_unprepare(scpd->clk[i]);
@@ -503,6 +530,13 @@ static int __init scpsys_probe(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
+ ret = mtk_sip_simple_call(MTK_SIP_PWR_MTCMOS_SUPPORT, 0, 0, 0);
+ if (ret) {
+ scp->sip_support = false;
+ dev_info(&pdev->dev, "SIP call is not supported: %d\n", ret);
+ } else
+ scp->sip_support = true;
+
return 0;
}
diff --git a/include/linux/soc/mediatek/mtk-sip.h b/include/linux/soc/mediatek/mtk-sip.h
index dce1818..c803490 100644
--- a/include/linux/soc/mediatek/mtk-sip.h
+++ b/include/linux/soc/mediatek/mtk-sip.h
@@ -1,6 +1,10 @@
#ifndef __SOC_MEDIATEK_MTKSIP_H
#define __SOC_MEDIATEK_MTKSIP_H
+#define MTK_SIP_PWR_ON_MTCMOS 0x82000402
+#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403
+#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404
+
#ifdef CONFIG_MTK_SIP
int mtk_sip_simple_call(unsigned long func_id,
unsigned long a1,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] arm64: dts: mediatek: Add cluster sleep support on MT8173
2015-12-18 2:42 [PATCH 0/4] mediatek: Add cpuidle cluster sleep support for MT8173 Fan Chen
2015-12-18 2:42 ` [PATCH 1/4] soc: Mediatek: Create Mediatek SIP call Fan Chen
2015-12-18 2:42 ` [PATCH 2/4] soc: mediatek: To move power control logic to ARM TF Fan Chen
@ 2015-12-18 2:42 ` Fan Chen
2015-12-18 2:42 ` [PATCH 4/4] arm64: dts: mediatek: Improve cpuidle latency " Fan Chen
3 siblings, 0 replies; 5+ messages in thread
From: Fan Chen @ 2015-12-18 2:42 UTC (permalink / raw)
To: linux-arm-kernel
From: Weiyi Lu <weiyi.lu@mediatek.com>
Enable cluster sleep state by adding cluster-sleep node to mt8173.dtsi
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 880dacb..77c1f84 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -53,7 +53,7 @@
compatible = "arm,cortex-a53";
reg = <0x000>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
};
cpu1: cpu at 1 {
@@ -61,7 +61,7 @@
compatible = "arm,cortex-a53";
reg = <0x001>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
};
cpu2: cpu at 100 {
@@ -69,7 +69,7 @@
compatible = "arm,cortex-a57";
reg = <0x100>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
};
cpu3: cpu at 101 {
@@ -77,7 +77,7 @@
compatible = "arm,cortex-a57";
reg = <0x101>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
};
idle-states {
@@ -91,6 +91,15 @@
min-residency-us = <1088>;
arm,psci-suspend-param = <0x0010000>;
};
+
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "arm,idle-state";
+ local-timer-stop;
+ entry-latency-us = <800>;
+ exit-latency-us = <1000>;
+ min-residency-us = <2000>;
+ arm,psci-suspend-param = <0x1010000>;
+ };
};
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] arm64: dts: mediatek: Improve cpuidle latency on MT8173
2015-12-18 2:42 [PATCH 0/4] mediatek: Add cpuidle cluster sleep support for MT8173 Fan Chen
` (2 preceding siblings ...)
2015-12-18 2:42 ` [PATCH 3/4] arm64: dts: mediatek: Add cluster sleep support on MT8173 Fan Chen
@ 2015-12-18 2:42 ` Fan Chen
3 siblings, 0 replies; 5+ messages in thread
From: Fan Chen @ 2015-12-18 2:42 UTC (permalink / raw)
To: linux-arm-kernel
From: Weiyi Lu <weiyi.lu@mediatek.com>
All according to the exact profiling result:
First, each CPU cluster needs its own nodes due to the latency gap
between each other.
Second, tune the parameters to enter the lowest idle state as much time
as possible without disturbing the system performance for
power-saving demand.
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 34 +++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 77c1f84..0ae3983 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -69,7 +69,7 @@
compatible = "arm,cortex-a57";
reg = <0x100>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
};
cpu3: cpu at 101 {
@@ -77,7 +77,7 @@
compatible = "arm,cortex-a57";
reg = <0x101>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
};
idle-states {
@@ -86,18 +86,36 @@
CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state";
local-timer-stop;
- entry-latency-us = <639>;
- exit-latency-us = <680>;
- min-residency-us = <1088>;
+ entry-latency-us = <72>;
+ exit-latency-us = <66>;
+ min-residency-us = <458>;
arm,psci-suspend-param = <0x0010000>;
};
CLUSTER_SLEEP_0: cluster-sleep-0 {
compatible = "arm,idle-state";
local-timer-stop;
- entry-latency-us = <800>;
- exit-latency-us = <1000>;
- min-residency-us = <2000>;
+ entry-latency-us = <145>;
+ exit-latency-us = <60>;
+ min-residency-us = <331>;
+ arm,psci-suspend-param = <0x1010000>;
+ };
+
+ CPU_SLEEP_1: cpu-sleep-1 {
+ compatible = "arm,idle-state";
+ local-timer-stop;
+ entry-latency-us = <72>;
+ exit-latency-us = <66>;
+ min-residency-us = <516>;
+ arm,psci-suspend-param = <0x0010000>;
+ };
+
+ CLUSTER_SLEEP_1: cluster-sleep-1 {
+ compatible = "arm,idle-state";
+ local-timer-stop;
+ entry-latency-us = <287>;
+ exit-latency-us = <62>;
+ min-residency-us = <1423>;
arm,psci-suspend-param = <0x1010000>;
};
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread