linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/14] Mediatek MT8183 scpsys support
@ 2019-03-19  8:01 Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 01/14] dt-bindings: mediatek: Add property to mt8183 smi-common Weiyi Lu
                   ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Resend scpsys patches from v4[1].
Based on v5.1-rc1 with MT8183 dts v9 patch[2] and
MT8183 SMI dt-binding v6 patch[3].

[1] https://patchwork.kernel.org/patch/10792071/
[2] https://patchwork.kernel.org/patch/10856987/
[3] https://patchwork.kernel.org/patch/10816827/

changes since v4:
- add property to mt8183 smi-common
- seperate refactor patches and new add function
- add power controller device node

Weiyi Lu (14):
  dt-bindings: mediatek: Add property to mt8183 smi-common
  dt-bindings: soc: Add MT8183 power dt-bindings
  soc: mediatek: Switch to SPDX license identifier
  soc: mediatek: Refactor polling timeout and documentation
  soc: mediatek: Refactor regulator control
  soc: mediatek: Refactor clock control
  soc: mediatek: Refactor sram control
  soc: mediatek: Refactor bus protection control
  soc: mediatek: Add basic_clk_name to scp_power_data
  soc: mediatek: Add multiple step bus protection control
  soc: mediatek: Add subsys clock control for bus protection
  soc: mediatek: Add extra sram control
  soc: mediatek: Add MT8183 scpsys support
  arm64: dts: Add power controller device node of MT8183

 .../mediatek,smi-common.txt                   |   2 +-
 .../bindings/soc/mediatek/scpsys.txt          |  14 +
 arch/arm64/boot/dts/mediatek/mt8183.dtsi      |  62 ++
 drivers/soc/mediatek/Makefile                 |   2 +-
 drivers/soc/mediatek/mtk-scpsys-ext.c         |  99 +++
 drivers/soc/mediatek/mtk-scpsys.c             | 603 +++++++++++++++---
 include/dt-bindings/power/mt8183-power.h      |  26 +
 include/linux/soc/mediatek/scpsys-ext.h       |  39 ++
 8 files changed, 757 insertions(+), 90 deletions(-)
 create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
 create mode 100644 include/dt-bindings/power/mt8183-power.h
 create mode 100644 include/linux/soc/mediatek/scpsys-ext.h



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v5 01/14] dt-bindings: mediatek: Add property to mt8183 smi-common
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 02/14] dt-bindings: soc: Add MT8183 power dt-bindings Weiyi Lu
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

For scpsys driver using regmap based syscon driver API.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 .../bindings/memory-controllers/mediatek,smi-common.txt         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index b478ade4da65..01744ec6a75b 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -20,7 +20,7 @@ Required properties:
 	"mediatek,mt2712-smi-common"
 	"mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common"
 	"mediatek,mt8173-smi-common"
-	"mediatek,mt8183-smi-common"
+	"mediatek,mt8183-smi-common", "syscon"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 02/14] dt-bindings: soc: Add MT8183 power dt-bindings
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 01/14] dt-bindings: mediatek: Add property to mt8183 smi-common Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 03/14] soc: mediatek: Switch to SPDX license identifier Weiyi Lu
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Add power dt-bindings of MT8183 and introduces "BASIC" and
"SUBSYS" clock types in binding document.
The "BASIC" type is compatible to the original power control with
clock name [a-z]+[0-9]*, e.g. mm, vpu1.
The "SUBSYS" type is used for bus protection control with clock
name [a-z]+-[0-9]+, e.g. isp-0, cam-1.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 .../bindings/soc/mediatek/scpsys.txt          | 14 ++++++++++
 include/dt-bindings/power/mt8183-power.h      | 26 +++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 include/dt-bindings/power/mt8183-power.h

diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index d6fe16f094af..b4728ce81c43 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -14,6 +14,7 @@ power/power_domain.txt. It provides the power domains defined in
 - include/dt-bindings/power/mt2701-power.h
 - include/dt-bindings/power/mt2712-power.h
 - include/dt-bindings/power/mt7622-power.h
+- include/dt-bindings/power/mt8183-power.h
 
 Required properties:
 - compatible: Should be one of:
@@ -24,18 +25,31 @@ Required properties:
 	- "mediatek,mt7623-scpsys", "mediatek,mt2701-scpsys": For MT7623 SoC
 	- "mediatek,mt7623a-scpsys": For MT7623A SoC
 	- "mediatek,mt8173-scpsys"
+	- "mediatek,mt8183-scpsys"
 - #power-domain-cells: Must be 1
 - reg: Address range of the SCPSYS unit
 - infracfg: must contain a phandle to the infracfg controller
 - clock, clock-names: clocks according to the common clock binding.
                       These are clocks which hardware needs to be
                       enabled before enabling certain power domains.
+                      The new clock type "BASIC" belongs to the type above.
+                      As to the new clock type "SUBSYS" needs to be
+                      enabled before releasing bus protection.
 	Required clocks for MT2701 or MT7623: "mm", "mfg", "ethif"
 	Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec"
 	Required clocks for MT6797: "mm", "mfg", "vdec"
 	Required clocks for MT7622: "hif_sel"
 	Required clocks for MT7622A: "ethif"
 	Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
+	Required clocks for MT8183: BASIC: "audio", "mfg", "mm", "cam", "isp",
+					   "vpu", "vpu1", "vpu2", "vpu3"
+				    SUBSYS: "mm-0", "mm-1", "mm-2", "mm-3",
+					    "mm-4", "mm-5", "mm-6", "mm-7",
+					    "mm-8", "mm-9", "isp-0", "isp-1",
+					    "cam-0", "cam-1", "cam-2", "cam-3",
+					    "cam-4", "cam-5", "cam-6", "vpu-0",
+					    "vpu-1", "vpu-2", "vpu-3", "vpu-4",
+					    "vpu-5"
 
 Optional properties:
 - vdec-supply: Power supply for the vdec power domain
diff --git a/include/dt-bindings/power/mt8183-power.h b/include/dt-bindings/power/mt8183-power.h
new file mode 100644
index 000000000000..5c0c8c7e3cd0
--- /dev/null
+++ b/include/dt-bindings/power/mt8183-power.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
+#define _DT_BINDINGS_POWER_MT8183_POWER_H
+
+#define MT8183_POWER_DOMAIN_AUDIO	0
+#define MT8183_POWER_DOMAIN_CONN	1
+#define MT8183_POWER_DOMAIN_MFG_ASYNC	2
+#define MT8183_POWER_DOMAIN_MFG		3
+#define MT8183_POWER_DOMAIN_MFG_CORE0	4
+#define MT8183_POWER_DOMAIN_MFG_CORE1	5
+#define MT8183_POWER_DOMAIN_MFG_2D	6
+#define MT8183_POWER_DOMAIN_DISP	7
+#define MT8183_POWER_DOMAIN_CAM		8
+#define MT8183_POWER_DOMAIN_ISP		9
+#define MT8183_POWER_DOMAIN_VDEC	10
+#define MT8183_POWER_DOMAIN_VENC	11
+#define MT8183_POWER_DOMAIN_VPU_TOP	12
+#define MT8183_POWER_DOMAIN_VPU_CORE0	13
+#define MT8183_POWER_DOMAIN_VPU_CORE1	14
+
+#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 03/14] soc: mediatek: Switch to SPDX license identifier
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 01/14] dt-bindings: mediatek: Add property to mt8183 smi-common Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 02/14] dt-bindings: soc: Add MT8183 power dt-bindings Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation Weiyi Lu
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 5b24bb4bfbf6..9f52f501178b 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -1,15 +1,7 @@
-/*
- * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
+
 #include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/io.h>
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (2 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 03/14] soc: mediatek: Switch to SPDX license identifier Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19 11:45   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 05/14] soc: mediatek: Refactor regulator control Weiyi Lu
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Use USEC_PER_SEC to indicate the polling timeout directly.
And add documentation of scp_domain_data.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 9f52f501178b..2855111b221a 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -21,7 +21,7 @@
 #include <dt-bindings/power/mt8173-power.h>
 
 #define MTK_POLL_DELAY_US   10
-#define MTK_POLL_TIMEOUT    (jiffies_to_usecs(HZ))
+#define MTK_POLL_TIMEOUT    USEC_PER_SEC
 
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
@@ -108,6 +108,18 @@ static const char * const clk_names[] = {
 
 #define MAX_CLKS	3
 
+/**
+ * struct scp_domain_data - scp domain data for power on/off flow
+ * @name: The domain name.
+ * @sta_mask: The mask for power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @bus_prot_mask: The mask for single step bus protection.
+ * @clk_id: The basic clock needs to be enabled before enabling certain
+ *          power domains.
+ * @caps: The flag for active wake-up action.
+ */
 struct scp_domain_data {
 	const char *name;
 	u32 sta_mask;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 05/14] soc: mediatek: Refactor regulator control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (3 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 06/14] soc: mediatek: Refactor clock control Weiyi Lu
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Put regulator enable and disable control in separate functions.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 32 ++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 2855111b221a..765ad4a5e5df 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -192,6 +192,22 @@ static int scpsys_domain_is_on(struct scp_domain *scpd)
 	return -EINVAL;
 }
 
+static int scpsys_regulator_enable(struct scp_domain *scpd)
+{
+	if (!scpd->supply)
+		return 0;
+
+	return regulator_enable(scpd->supply);
+}
+
+static int scpsys_regulator_disable(struct scp_domain *scpd)
+{
+	if (!scpd->supply)
+		return 0;
+
+	return regulator_disable(scpd->supply);
+}
+
 static int scpsys_power_on(struct generic_pm_domain *genpd)
 {
 	struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
@@ -202,11 +218,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	int ret, tmp;
 	int i;
 
-	if (scpd->supply) {
-		ret = regulator_enable(scpd->supply);
-		if (ret)
-			return ret;
-	}
+	ret = scpsys_regulator_enable(scpd);
+	if (ret < 0)
+		return ret;
 
 	for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
 		ret = clk_prepare_enable(scpd->clk[i]);
@@ -274,8 +288,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 			clk_disable_unprepare(scpd->clk[i]);
 	}
 err_clk:
-	if (scpd->supply)
-		regulator_disable(scpd->supply);
+	scpsys_regulator_disable(scpd);
 
 	dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
 
@@ -334,8 +347,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
 		clk_disable_unprepare(scpd->clk[i]);
 
-	if (scpd->supply)
-		regulator_disable(scpd->supply);
+	ret = scpsys_regulator_disable(scpd);
+	if (ret < 0)
+		goto out;
 
 	return 0;
 
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 06/14] soc: mediatek: Refactor clock control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (4 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 05/14] soc: mediatek: Refactor regulator control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19 12:02   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 07/14] soc: mediatek: Refactor sram control Weiyi Lu
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Put clock enable and disable control in separate function.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 49 ++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 765ad4a5e5df..3e9be07a2627 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -208,6 +208,33 @@ static int scpsys_regulator_disable(struct scp_domain *scpd)
 	return regulator_disable(scpd->supply);
 }
 
+static int scpsys_clk_enable(struct clk *clk[], int max_num)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < max_num && clk[i]; i++) {
+		ret = clk_prepare_enable(clk[i]);
+		if (ret) {
+			for (--i; i >= 0; i--)
+				clk_disable_unprepare(clk[i]);
+
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void scpsys_clk_disable(struct clk *clk[], int max_num)
+{
+	int i;
+
+	for (i = max_num - 1; i >= 0; i--) {
+		if (clk[i])
+			clk_disable_unprepare(clk[i]);
+	}
+}
+
 static int scpsys_power_on(struct generic_pm_domain *genpd)
 {
 	struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
@@ -216,21 +243,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	u32 val;
 	int ret, tmp;
-	int i;
 
 	ret = scpsys_regulator_enable(scpd);
 	if (ret < 0)
 		return ret;
 
-	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;
-		}
-	}
+	ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
+	if (ret)
+		goto err_clk;
 
 	val = readl(ctl_addr);
 	val |= PWR_ON_BIT;
@@ -283,10 +303,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	return 0;
 
 err_pwr_ack:
-	for (i = MAX_CLKS - 1; i >= 0; i--) {
-		if (scpd->clk[i])
-			clk_disable_unprepare(scpd->clk[i]);
-	}
+	scpsys_clk_disable(scpd->clk, MAX_CLKS);
 err_clk:
 	scpsys_regulator_disable(scpd);
 
@@ -303,7 +320,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	u32 val;
 	int ret, tmp;
-	int i;
 
 	if (scpd->data->bus_prot_mask) {
 		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
@@ -344,8 +360,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	if (ret < 0)
 		goto out;
 
-	for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
-		clk_disable_unprepare(scpd->clk[i]);
+	scpsys_clk_disable(scpd->clk, MAX_CLKS);
 
 	ret = scpsys_regulator_disable(scpd);
 	if (ret < 0)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 07/14] soc: mediatek: Refactor sram control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (5 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 06/14] soc: mediatek: Refactor clock control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19 12:07   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 08/14] soc: mediatek: Refactor bus protection control Weiyi Lu
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Put sram enable and disable control in separate functions.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 79 ++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 3e9be07a2627..65b734b40098 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -235,12 +235,55 @@ static void scpsys_clk_disable(struct clk *clk[], int max_num)
 	}
 }
 
+static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+	u32 val;
+	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+	int tmp;
+
+	val = readl(ctl_addr) & ~scpd->data->sram_pdn_bits;
+	writel(val, ctl_addr);
+
+	/* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
+		/*
+		 * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
+		 * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
+		 * is applied here.
+		 */
+		usleep_range(12000, 12100);
+	} else {
+		/* Either wait until SRAM_PDN_ACK all 1 or 0 */
+		int ret = readl_poll_timeout(ctl_addr, tmp,
+				(tmp & pdn_ack) == 0,
+				MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+	u32 val;
+	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+	int tmp;
+
+	val = readl(ctl_addr) | scpd->data->sram_pdn_bits;
+	writel(val, ctl_addr);
+
+	/* Either wait until SRAM_PDN_ACK all 1 or 0 */
+	return readl_poll_timeout(ctl_addr, tmp,
+			(tmp & pdn_ack) == pdn_ack,
+			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
 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;
 	void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
-	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	u32 val;
 	int ret, tmp;
 
@@ -252,6 +295,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	if (ret)
 		goto err_clk;
 
+	/* subsys power on */
 	val = readl(ctl_addr);
 	val |= PWR_ON_BIT;
 	writel(val, ctl_addr);
@@ -273,24 +317,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	val |= PWR_RST_B_BIT;
 	writel(val, ctl_addr);
 
-	val &= ~scpd->data->sram_pdn_bits;
-	writel(val, ctl_addr);
-
-	/* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
-	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
-		/*
-		 * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
-		 * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is
-		 * applied here.
-		 */
-		usleep_range(12000, 12100);
-
-	} else {
-		ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
-					 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-		if (ret < 0)
-			goto err_pwr_ack;
-	}
+	ret = scpsys_sram_enable(scpd, ctl_addr);
+	if (ret < 0)
+		goto err_pwr_ack;
 
 	if (scpd->data->bus_prot_mask) {
 		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
@@ -317,7 +346,6 @@ 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;
 	void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
-	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	u32 val;
 	int ret, tmp;
 
@@ -329,17 +357,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 			goto out;
 	}
 
-	val = readl(ctl_addr);
-	val |= scpd->data->sram_pdn_bits;
-	writel(val, ctl_addr);
-
-	/* wait until SRAM_PDN_ACK all 1 */
-	ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
-				 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	ret = scpsys_sram_disable(scpd, ctl_addr);
 	if (ret < 0)
 		goto out;
 
-	val |= PWR_ISO_BIT;
+	/* subsys power off */
+	val = readl(ctl_addr) | PWR_ISO_BIT;
 	writel(val, ctl_addr);
 
 	val &= ~PWR_RST_B_BIT;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 08/14] soc: mediatek: Refactor bus protection control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (6 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 07/14] soc: mediatek: Refactor sram control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19 12:09   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data Weiyi Lu
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Put bus protection enable and disable control in separate functions.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 48 ++++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 65b734b40098..6bf846cb1893 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -279,6 +279,34 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 }
 
+static int scpsys_bus_protect_enable(struct scp_domain *scpd)
+{
+	struct scp *scp = scpd->scp;
+	int ret = 0;
+
+	if (scpd->data->bus_prot_mask) {
+		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
+				scpd->data->bus_prot_mask,
+				scp->bus_prot_reg_update);
+	}
+
+	return ret;
+}
+
+static int scpsys_bus_protect_disable(struct scp_domain *scpd)
+{
+	struct scp *scp = scpd->scp;
+	int ret = 0;
+
+	if (scpd->data->bus_prot_mask) {
+		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
+				scpd->data->bus_prot_mask,
+				scp->bus_prot_reg_update);
+	}
+
+	return ret;
+}
+
 static int scpsys_power_on(struct generic_pm_domain *genpd)
 {
 	struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
@@ -321,13 +349,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	if (ret < 0)
 		goto err_pwr_ack;
 
-	if (scpd->data->bus_prot_mask) {
-		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
-				scpd->data->bus_prot_mask,
-				scp->bus_prot_reg_update);
-		if (ret)
-			goto err_pwr_ack;
-	}
+	ret = scpsys_bus_protect_disable(scpd);
+	if (ret < 0)
+		goto err_pwr_ack;
 
 	return 0;
 
@@ -349,13 +373,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	u32 val;
 	int ret, tmp;
 
-	if (scpd->data->bus_prot_mask) {
-		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
-				scpd->data->bus_prot_mask,
-				scp->bus_prot_reg_update);
-		if (ret)
-			goto out;
-	}
+	ret = scpsys_bus_protect_enable(scpd);
+	if (ret < 0)
+		goto out;
 
 	ret = scpsys_sram_disable(scpd, ctl_addr);
 	if (ret < 0)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (7 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 08/14] soc: mediatek: Refactor bus protection control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-21  6:02   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control Weiyi Lu
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Try to stop extending the clk_id or clk_names if there are
more and more new BASIC clocks. To get its own clocks by the
basic_clk_name of each power domain.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 6bf846cb1893..c6360de4e41e 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -118,6 +118,8 @@ static const char * const clk_names[] = {
  * @bus_prot_mask: The mask for single step bus protection.
  * @clk_id: The basic clock needs to be enabled before enabling certain
  *          power domains.
+ * @basic_clk_name: provide the same purpose with field "clk_id"
+ *                  by declaring basic clock prefix name rather than clk_id.
  * @caps: The flag for active wake-up action.
  */
 struct scp_domain_data {
@@ -128,6 +130,7 @@ struct scp_domain_data {
 	u32 sram_pdn_ack_bits;
 	u32 bus_prot_mask;
 	enum clk_id clk_id[MAX_CLKS];
+	const char *basic_clk_name[MAX_CLKS];
 	u8 caps;
 };
 
@@ -499,16 +502,24 @@ static struct scp *init_scp(struct platform_device *pdev,
 
 		scpd->data = data;
 
-		for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
-			struct clk *c = clk[data->clk_id[j]];
+		if (data->clk_id[0]) {
+			for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
+				struct clk *c = clk[data->clk_id[j]];
 
-			if (IS_ERR(c)) {
-				dev_err(&pdev->dev, "%s: clk unavailable\n",
-					data->name);
-				return ERR_CAST(c);
-			}
+				if (IS_ERR(c)) {
+					dev_err(&pdev->dev,
+						"%s: clk unavailable\n",
+						data->name);
+					return ERR_CAST(c);
+				}
 
-			scpd->clk[j] = c;
+				scpd->clk[j] = c;
+			}
+		} else if (data->basic_clk_name[0]) {
+			for (j = 0; j < MAX_CLKS &&
+					data->basic_clk_name[j]; j++)
+				scpd->clk[j] = devm_clk_get(&pdev->dev,
+						data->basic_clk_name[j]);
 		}
 
 		genpd->name = data->name;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (8 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-21  5:57   ` Nicolas Boichat
  2019-03-19  8:01 ` [PATCH v5 11/14] soc: mediatek: Add subsys clock control for bus protection Weiyi Lu
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Both MT8183 & MT6765 have more control steps of bus protection
than previous project. And there add more bus protection registers
reside at infracfg & smi-common. Also add new APIs for multiple
step bus protection control with more customize arguments.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/Makefile           |  2 +-
 drivers/soc/mediatek/mtk-scpsys-ext.c   | 99 +++++++++++++++++++++++++
 drivers/soc/mediatek/mtk-scpsys.c       | 24 ++++++
 include/linux/soc/mediatek/scpsys-ext.h | 39 ++++++++++
 4 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
 create mode 100644 include/linux/soc/mediatek/scpsys-ext.h

diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 64ce5eeaba32..b9dbad6b12f9 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
-obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
new file mode 100644
index 000000000000..f630edb2f65d
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <Owen.Chen@mediatek.com>
+ */
+#include <linux/ktime.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/mediatek/scpsys-ext.h>
+
+#define MTK_POLL_DELAY_US   10
+#define MTK_POLL_TIMEOUT    USEC_PER_SEC
+
+static int set_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
+		u32 reg_set, u32 reg_sta, u32 reg_en)
+{
+	u32 val;
+
+	if (reg_set)
+		regmap_write(map, reg_set, mask);
+	else
+		regmap_update_bits(map, reg_en, mask, mask);
+
+	return regmap_read_poll_timeout(map, reg_sta,
+			val, (val & ack_mask) == ack_mask,
+			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static int clear_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
+		u32 reg_clr, u32 reg_sta, u32 reg_en)
+{
+	u32 val;
+
+	if (reg_clr)
+		regmap_write(map, reg_clr, mask);
+	else
+		regmap_update_bits(map, reg_en, mask, 0);
+
+	return regmap_read_poll_timeout(map, reg_sta,
+			val, !(val & ack_mask),
+			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
+	struct regmap *infracfg, struct regmap *smi_common)
+{
+	int i;
+
+	for (i = 0; i < MAX_STEPS && bp_table[i].mask; i++) {
+		struct regmap *map;
+		int ret;
+
+		if (bp_table[i].type == IFR_TYPE)
+			map = infracfg;
+		else if (bp_table[i].type == SMI_TYPE)
+			map = smi_common;
+		else
+			return -EINVAL;
+
+		ret = set_bus_protection(map,
+				bp_table[i].mask, bp_table[i].mask,
+				bp_table[i].set_ofs, bp_table[i].sta_ofs,
+				bp_table[i].en_ofs);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
+	struct regmap *infracfg, struct regmap *smi_common)
+{
+	int i;
+
+	for (i = MAX_STEPS - 1; i >= 0; i--) {
+		struct regmap *map;
+		int ret;
+
+		if (bp_table[i].type == IFR_TYPE)
+			map = infracfg;
+		else if (bp_table[i].type == SMI_TYPE)
+			map = smi_common;
+		else
+			return -EINVAL;
+
+		ret = clear_bus_protection(map,
+				bp_table[i].mask, bp_table[i].clr_ack_mask,
+				bp_table[i].clr_ofs, bp_table[i].sta_ofs,
+				bp_table[i].en_ofs);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index c6360de4e41e..181bf7bce591 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -12,6 +12,7 @@
 #include <linux/pm_domain.h>
 #include <linux/regulator/consumer.h>
 #include <linux/soc/mediatek/infracfg.h>
+#include <linux/soc/mediatek/scpsys-ext.h>
 
 #include <dt-bindings/power/mt2701-power.h>
 #include <dt-bindings/power/mt2712-power.h>
@@ -121,6 +122,7 @@ static const char * const clk_names[] = {
  * @basic_clk_name: provide the same purpose with field "clk_id"
  *                  by declaring basic clock prefix name rather than clk_id.
  * @caps: The flag for active wake-up action.
+ * @bp_table: The mask table for multiple step bus protection.
  */
 struct scp_domain_data {
 	const char *name;
@@ -132,6 +134,7 @@ struct scp_domain_data {
 	enum clk_id clk_id[MAX_CLKS];
 	const char *basic_clk_name[MAX_CLKS];
 	u8 caps;
+	struct bus_prot bp_table[MAX_STEPS];
 };
 
 struct scp;
@@ -155,6 +158,7 @@ struct scp {
 	struct device *dev;
 	void __iomem *base;
 	struct regmap *infracfg;
+	struct regmap *smi_common;
 	struct scp_ctrl_reg ctrl_reg;
 	bool bus_prot_reg_update;
 };
@@ -291,6 +295,10 @@ static int scpsys_bus_protect_enable(struct scp_domain *scpd)
 		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
 				scpd->data->bus_prot_mask,
 				scp->bus_prot_reg_update);
+	} else if (scpd->data->bp_table[0].mask) {
+		ret = mtk_scpsys_ext_set_bus_protection(scpd->data->bp_table,
+				scp->infracfg,
+				scp->smi_common);
 	}
 
 	return ret;
@@ -305,6 +313,11 @@ static int scpsys_bus_protect_disable(struct scp_domain *scpd)
 		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
 				scpd->data->bus_prot_mask,
 				scp->bus_prot_reg_update);
+	} else if (scpd->data->bp_table[0].mask) {
+		ret = mtk_scpsys_ext_clear_bus_protection(
+				scpd->data->bp_table,
+				scp->infracfg,
+				scp->smi_common);
 	}
 
 	return ret;
@@ -475,6 +488,17 @@ static struct scp *init_scp(struct platform_device *pdev,
 		return ERR_CAST(scp->infracfg);
 	}
 
+	scp->smi_common = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+			"smi_comm");
+
+	if (scp->smi_common == ERR_PTR(-ENODEV)) {
+		scp->smi_common = NULL;
+	} else if (IS_ERR(scp->smi_common)) {
+		dev_err(&pdev->dev, "Cannot find smi_common controller: %ld\n",
+				PTR_ERR(scp->smi_common));
+		return ERR_CAST(scp->smi_common);
+	}
+
 	for (i = 0; i < num; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		const struct scp_domain_data *data = &scp_domain_data[i];
diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
new file mode 100644
index 000000000000..d0ed295c88a7
--- /dev/null
+++ b/include/linux/soc/mediatek/scpsys-ext.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
+#define __SOC_MEDIATEK_SCPSYS_EXT_H
+
+#define MAX_STEPS	4
+
+#define BUS_PROT(_type, _set_ofs, _clr_ofs,			\
+		_en_ofs, _sta_ofs, _mask, _clr_ack_mask) {	\
+		.type = _type,					\
+		.set_ofs = _set_ofs,				\
+		.clr_ofs = _clr_ofs,				\
+		.en_ofs = _en_ofs,				\
+		.sta_ofs = _sta_ofs,				\
+		.mask = _mask,					\
+		.clr_ack_mask = _clr_ack_mask,			\
+	}
+
+enum regmap_type {
+	IFR_TYPE,
+	SMI_TYPE,
+	MAX_REGMAP_TYPE,
+};
+
+struct bus_prot {
+	enum regmap_type type;
+	u32 set_ofs;
+	u32 clr_ofs;
+	u32 en_ofs;
+	u32 sta_ofs;
+	u32 mask;
+	u32 clr_ack_mask;
+};
+
+int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
+	struct regmap *infracfg, struct regmap *smi_common);
+int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
+	struct regmap *infracfg, struct regmap *smi_common);
+
+#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 11/14] soc: mediatek: Add subsys clock control for bus protection
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (9 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 12/14] soc: mediatek: Add extra sram control Weiyi Lu
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Add subsys CG control flow before/after the bus protect control
due to bus protection need SMI bus relative CGs enabled to feedback
its ack.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 72 ++++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 181bf7bce591..356ca2626b36 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -108,6 +108,7 @@ static const char * const clk_names[] = {
 };
 
 #define MAX_CLKS	3
+#define MAX_SUBSYS_CLKS 10
 
 /**
  * struct scp_domain_data - scp domain data for power on/off flow
@@ -121,6 +122,8 @@ static const char * const clk_names[] = {
  *          power domains.
  * @basic_clk_name: provide the same purpose with field "clk_id"
  *                  by declaring basic clock prefix name rather than clk_id.
+ * @subsys_clk_prefix: The prefix name of the clocks need to be enabled
+ *                     before releasing bus protection.
  * @caps: The flag for active wake-up action.
  * @bp_table: The mask table for multiple step bus protection.
  */
@@ -133,6 +136,7 @@ struct scp_domain_data {
 	u32 bus_prot_mask;
 	enum clk_id clk_id[MAX_CLKS];
 	const char *basic_clk_name[MAX_CLKS];
+	const char *subsys_clk_prefix;
 	u8 caps;
 	struct bus_prot bp_table[MAX_STEPS];
 };
@@ -143,6 +147,7 @@ struct scp_domain {
 	struct generic_pm_domain genpd;
 	struct scp *scp;
 	struct clk *clk[MAX_CLKS];
+	struct clk *subsys_clk[MAX_SUBSYS_CLKS];
 	const struct scp_domain_data *data;
 	struct regulator *supply;
 };
@@ -361,16 +366,22 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	val |= PWR_RST_B_BIT;
 	writel(val, ctl_addr);
 
-	ret = scpsys_sram_enable(scpd, ctl_addr);
+	ret = scpsys_clk_enable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
 	if (ret < 0)
 		goto err_pwr_ack;
 
+	ret = scpsys_sram_enable(scpd, ctl_addr);
+	if (ret < 0)
+		goto err_sram;
+
 	ret = scpsys_bus_protect_disable(scpd);
 	if (ret < 0)
-		goto err_pwr_ack;
+		goto err_sram;
 
 	return 0;
 
+err_sram:
+	scpsys_clk_disable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
 err_pwr_ack:
 	scpsys_clk_disable(scpd->clk, MAX_CLKS);
 err_clk:
@@ -397,6 +408,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	if (ret < 0)
 		goto out;
 
+	scpsys_clk_disable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
+
 	/* subsys power off */
 	val = readl(ctl_addr) | PWR_ISO_BIT;
 	writel(val, ctl_addr);
@@ -433,6 +446,48 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	return ret;
 }
 
+static int init_subsys_clks(struct platform_device *pdev,
+		const char *prefix, struct clk **clk)
+{
+	struct device_node *node = pdev->dev.of_node;
+	u32 prefix_len, sub_clk_cnt = 0;
+	struct property *prop;
+	const char *clk_name;
+
+	if (!node) {
+		dev_err(&pdev->dev, "Cannot find scpsys node: %ld\n",
+			PTR_ERR(node));
+		return PTR_ERR(node);
+	}
+
+	prefix_len = strlen(prefix);
+
+	of_property_for_each_string(node, "clock-names", prop, clk_name) {
+		if (!strncmp(clk_name, prefix, prefix_len) &&
+				(clk_name[prefix_len] == '-')) {
+			if (sub_clk_cnt >= MAX_SUBSYS_CLKS) {
+				dev_err(&pdev->dev,
+					"subsys clk out of range %d\n",
+					sub_clk_cnt);
+				return -ENOMEM;
+			}
+
+			clk[sub_clk_cnt] = devm_clk_get(&pdev->dev,
+						clk_name);
+
+			if (IS_ERR(clk)) {
+				dev_err(&pdev->dev,
+					"Subsys clk read fail %ld\n",
+					PTR_ERR(clk));
+				return PTR_ERR(clk);
+			}
+			sub_clk_cnt++;
+		}
+	}
+
+	return sub_clk_cnt;
+}
+
 static void init_clks(struct platform_device *pdev, struct clk **clk)
 {
 	int i;
@@ -520,6 +575,7 @@ static struct scp *init_scp(struct platform_device *pdev,
 		struct scp_domain *scpd = &scp->domains[i];
 		struct generic_pm_domain *genpd = &scpd->genpd;
 		const struct scp_domain_data *data = &scp_domain_data[i];
+		int clk_cnt;
 
 		pd_data->domains[i] = genpd;
 		scpd->scp = scp;
@@ -546,6 +602,18 @@ static struct scp *init_scp(struct platform_device *pdev,
 						data->basic_clk_name[j]);
 		}
 
+		if (data->subsys_clk_prefix) {
+			clk_cnt = init_subsys_clks(pdev,
+					data->subsys_clk_prefix,
+					scpd->subsys_clk);
+			if (clk_cnt < 0) {
+				dev_err(&pdev->dev,
+					"%s: subsys clk unavailable\n",
+					data->name);
+				return ERR_PTR(clk_cnt);
+			}
+		}
+
 		genpd->name = data->name;
 		genpd->power_off = scpsys_power_off;
 		genpd->power_on = scpsys_power_on;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 12/14] soc: mediatek: Add extra sram control
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (10 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 11/14] soc: mediatek: Add subsys clock control for bus protection Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 13/14] soc: mediatek: Add MT8183 scpsys support Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 14/14] arm64: dts: Add power controller device node of MT8183 Weiyi Lu
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

For some power domains like vpu_core on MT8183 whose sram need to
do clock and internal isolation while power on/off sram.
We add a flag "sram_iso_ctrl" in scp_domain_data to judge if we
need to do the extra sram isolation control or not.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 356ca2626b36..94c10f69655d 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -57,6 +57,8 @@
 #define PWR_ON_BIT			BIT(2)
 #define PWR_ON_2ND_BIT			BIT(3)
 #define PWR_CLK_DIS_BIT			BIT(4)
+#define PWR_SRAM_CLKISO_BIT		BIT(5)
+#define PWR_SRAM_ISOINT_B_BIT		BIT(6)
 
 #define PWR_STATUS_CONN			BIT(1)
 #define PWR_STATUS_DISP			BIT(3)
@@ -115,6 +117,8 @@ static const char * const clk_names[] = {
  * @name: The domain name.
  * @sta_mask: The mask for power on/off status bit.
  * @ctl_offs: The offset for main power control register.
+ * @sram_iso_ctrl: The flag to judge if the power domain need to do
+ *                 the extra sram isolation control.
  * @sram_pdn_bits: The mask for sram power control bits.
  * @sram_pdn_ack_bits: The mask for sram power control acked bits.
  * @bus_prot_mask: The mask for single step bus protection.
@@ -131,6 +135,7 @@ struct scp_domain_data {
 	const char *name;
 	u32 sta_mask;
 	int ctl_offs;
+	bool sram_iso_ctrl;
 	u32 sram_pdn_bits;
 	u32 sram_pdn_ack_bits;
 	u32 bus_prot_mask;
@@ -273,6 +278,14 @@ static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
 			return ret;
 	}
 
+	if (scpd->data->sram_iso_ctrl)	{
+		val = readl(ctl_addr) | PWR_SRAM_ISOINT_B_BIT;
+		writel(val, ctl_addr);
+		udelay(1);
+		val &= ~PWR_SRAM_CLKISO_BIT;
+		writel(val, ctl_addr);
+	}
+
 	return 0;
 }
 
@@ -282,6 +295,15 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	int tmp;
 
+	if (scpd->data->sram_iso_ctrl)	{
+		val = readl(ctl_addr);
+		val |= PWR_SRAM_CLKISO_BIT;
+		writel(val, ctl_addr);
+		val &= ~PWR_SRAM_ISOINT_B_BIT;
+		writel(val, ctl_addr);
+		udelay(1);
+	}
+
 	val = readl(ctl_addr) | scpd->data->sram_pdn_bits;
 	writel(val, ctl_addr);
 
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 13/14] soc: mediatek: Add MT8183 scpsys support
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (11 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 12/14] soc: mediatek: Add extra sram control Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  2019-03-19  8:01 ` [PATCH v5 14/14] arm64: dts: Add power controller device node of MT8183 Weiyi Lu
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Add scpsys driver for MT8183

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 226 ++++++++++++++++++++++++++++++
 1 file changed, 226 insertions(+)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 94c10f69655d..f1d82cdb219e 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -20,6 +20,7 @@
 #include <dt-bindings/power/mt7622-power.h>
 #include <dt-bindings/power/mt7623a-power.h>
 #include <dt-bindings/power/mt8173-power.h>
+#include <dt-bindings/power/mt8183-power.h>
 
 #define MTK_POLL_DELAY_US   10
 #define MTK_POLL_TIMEOUT    USEC_PER_SEC
@@ -1141,6 +1142,217 @@ static const struct scp_subdomain scp_subdomain_mt8173[] = {
 	{MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
 };
 
+/*
+ * MT8183 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt8183[] = {
+	[MT8183_POWER_DOMAIN_AUDIO] = {
+		.name = "audio",
+		.sta_mask = PWR_STATUS_AUDIO,
+		.ctl_offs = 0x0314,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.basic_clk_name = {"audio", "audio1", "audio2"},
+	},
+	[MT8183_POWER_DOMAIN_CONN] = {
+		.name = "conn",
+		.sta_mask = PWR_STATUS_CONN,
+		.ctl_offs = 0x032c,
+		.sram_pdn_bits = 0,
+		.sram_pdn_ack_bits = 0,
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2a0, 0x2a4, 0, 0x228,
+				BIT(13) | BIT(14), BIT(13) | BIT(14)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_MFG_ASYNC] = {
+		.name = "mfg_async",
+		.sta_mask = PWR_STATUS_MFG_ASYNC,
+		.ctl_offs = 0x0334,
+		.sram_pdn_bits = 0,
+		.sram_pdn_ack_bits = 0,
+		.basic_clk_name = {"mfg"},
+	},
+	[MT8183_POWER_DOMAIN_MFG] = {
+		.name = "mfg",
+		.sta_mask = PWR_STATUS_MFG,
+		.ctl_offs = 0x0338,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+	},
+	[MT8183_POWER_DOMAIN_MFG_CORE0] = {
+		.name = "mfg_core0",
+		.sta_mask = BIT(7),
+		.ctl_offs = 0x034c,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+	},
+	[MT8183_POWER_DOMAIN_MFG_CORE1] = {
+		.name = "mfg_core1",
+		.sta_mask = BIT(20),
+		.ctl_offs = 0x0310,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+	},
+	[MT8183_POWER_DOMAIN_MFG_2D] = {
+		.name = "mfg_2d",
+		.sta_mask = PWR_STATUS_MFG_2D,
+		.ctl_offs = 0x0348,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2a8, 0x2ac, 0, 0x258,
+				BIT(19) | BIT(20) | BIT(21),
+				BIT(19) | BIT(20) | BIT(21)),
+			BUS_PROT(IFR_TYPE, 0x2a0, 0x2a4, 0, 0x228,
+				BIT(21) | BIT(22), BIT(21) | BIT(22)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_DISP] = {
+		.name = "disp",
+		.sta_mask = PWR_STATUS_DISP,
+		.ctl_offs = 0x030c,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.basic_clk_name = {"mm"},
+		.subsys_clk_prefix = "mm",
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2a8, 0x2ac, 0, 0x258,
+				BIT(16) | BIT(17), BIT(16) | BIT(17)),
+			BUS_PROT(IFR_TYPE, 0x2a0, 0x2a4, 0, 0x228,
+				BIT(10) | BIT(11), BIT(10) | BIT(11)),
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				GENMASK(7, 0), GENMASK(7, 0)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_CAM] = {
+		.name = "cam",
+		.sta_mask = BIT(25),
+		.ctl_offs = 0x0344,
+		.sram_pdn_bits = GENMASK(9, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.basic_clk_name = {"cam"},
+		.subsys_clk_prefix = "cam",
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				BIT(4) | BIT(5) | BIT(9) | BIT(13),
+				BIT(4) | BIT(5) | BIT(9) | BIT(13)),
+			BUS_PROT(IFR_TYPE, 0x2a0, 0x2a4, 0, 0x228,
+				BIT(28), BIT(28)),
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				BIT(11), 0),
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				BIT(3) | BIT(4), BIT(3) | BIT(4)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_ISP] = {
+		.name = "isp",
+		.sta_mask = PWR_STATUS_ISP,
+		.ctl_offs = 0x0308,
+		.sram_pdn_bits = GENMASK(9, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.basic_clk_name = {"isp"},
+		.subsys_clk_prefix = "isp",
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				BIT(3) | BIT(8), BIT(3) | BIT(8)),
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				BIT(10), 0),
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				BIT(2), BIT(2)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_VDEC] = {
+		.name = "vdec",
+		.sta_mask = BIT(31),
+		.ctl_offs = 0x0300,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				BIT(7), BIT(7)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_VENC] = {
+		.name = "venc",
+		.sta_mask = PWR_STATUS_VENC,
+		.ctl_offs = 0x0304,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.bp_table = {
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				BIT(1), BIT(1)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_VPU_TOP] = {
+		.name = "vpu_top",
+		.sta_mask = BIT(26),
+		.ctl_offs = 0x0324,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.basic_clk_name = {"vpu", "vpu1"},
+		.subsys_clk_prefix = "vpu",
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				GENMASK(9, 6) | BIT(12),
+				GENMASK(9, 6) | BIT(12)),
+			BUS_PROT(IFR_TYPE, 0x2a0, 0x2a4, 0, 0x228,
+				BIT(27), BIT(27)),
+			BUS_PROT(IFR_TYPE, 0x2d4, 0x2d8, 0, 0x2ec,
+				BIT(10) | BIT(11), BIT(10) | BIT(11)),
+			BUS_PROT(SMI_TYPE, 0x3c4, 0x3c8, 0, 0x3c0,
+				BIT(5) | BIT(6), BIT(5) | BIT(6)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_VPU_CORE0] = {
+		.name = "vpu_core0",
+		.sta_mask = BIT(27),
+		.ctl_offs = 0x33c,
+		.sram_iso_ctrl = true,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.basic_clk_name = {"vpu2"},
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2c4, 0x2c8, 0, 0x2e4,
+				BIT(6), BIT(6)),
+			BUS_PROT(IFR_TYPE, 0x2c4, 0x2c8, 0, 0x2e4,
+				BIT(0) | BIT(2) | BIT(4),
+				BIT(0) | BIT(2) | BIT(4)),
+		},
+	},
+	[MT8183_POWER_DOMAIN_VPU_CORE1] = {
+		.name = "vpu_core1",
+		.sta_mask = BIT(28),
+		.ctl_offs = 0x0340,
+		.sram_iso_ctrl = true,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.basic_clk_name = {"vpu3"},
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x2c4, 0x2c8, 0, 0x2e4,
+				BIT(7), BIT(7)),
+			BUS_PROT(IFR_TYPE, 0x2c4, 0x2c8, 0, 0x2e4,
+				BIT(1) | BIT(3) | BIT(5),
+				BIT(1) | BIT(3) | BIT(5)),
+		},
+	},
+};
+
+static const struct scp_subdomain scp_subdomain_mt8183[] = {
+	{MT8183_POWER_DOMAIN_MFG_ASYNC, MT8183_POWER_DOMAIN_MFG},
+	{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_2D},
+	{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_CORE0},
+	{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_CORE1},
+	{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_CAM},
+	{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_ISP},
+	{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VDEC},
+	{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VENC},
+	{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VPU_TOP},
+	{MT8183_POWER_DOMAIN_VPU_TOP, MT8183_POWER_DOMAIN_VPU_CORE0},
+	{MT8183_POWER_DOMAIN_VPU_TOP, MT8183_POWER_DOMAIN_VPU_CORE1},
+};
+
 static const struct scp_soc_data mt2701_data = {
 	.domains = scp_domain_data_mt2701,
 	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
@@ -1207,6 +1419,17 @@ static const struct scp_soc_data mt8173_data = {
 	.bus_prot_reg_update = true,
 };
 
+static const struct scp_soc_data mt8183_data = {
+	.domains = scp_domain_data_mt8183,
+	.num_domains = ARRAY_SIZE(scp_domain_data_mt8183),
+	.subdomains = scp_subdomain_mt8183,
+	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8183),
+	.regs = {
+		.pwr_sta_offs = 0x0180,
+		.pwr_sta2nd_offs = 0x0184
+	}
+};
+
 /*
  * scpsys driver init
  */
@@ -1230,6 +1453,9 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
 	}, {
 		.compatible = "mediatek,mt8173-scpsys",
 		.data = &mt8173_data,
+	}, {
+		.compatible = "mediatek,mt8183-scpsys",
+		.data = &mt8183_data,
 	}, {
 		/* sentinel */
 	}
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 14/14] arm64: dts: Add power controller device node of MT8183
  2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
                   ` (12 preceding siblings ...)
  2019-03-19  8:01 ` [PATCH v5 13/14] soc: mediatek: Add MT8183 scpsys support Weiyi Lu
@ 2019-03-19  8:01 ` Weiyi Lu
  13 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-03-19  8:01 UTC (permalink / raw)
  To: Nicolas Boichat, Matthias Brugger, Rob Herring
  Cc: James Liao, Fan Chen, linux-arm-kernel, linux-kernel,
	linux-mediatek, srv_heupstream, Weiyi Lu

Add power controller node and smi-common node for MT8183
In scpsys node, it contains clocks and regmapping of
infracfg and smi-common for bus protection.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi | 62 ++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 08274bfcebd8..75c4881bbe5e 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -8,6 +8,7 @@
 #include <dt-bindings/clock/mt8183-clk.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/mt8183-power.h>
 
 / {
 	compatible = "mediatek,mt8183";
@@ -196,6 +197,62 @@
 			#clock-cells = <1>;
 		};
 
+		scpsys: syscon@10006000 {
+			compatible = "mediatek,mt8183-scpsys", "syscon";
+			#power-domain-cells = <1>;
+			reg = <0 0x10006000 0 0x1000>;
+			clocks = <&topckgen CLK_TOP_MUX_AUD_INTBUS>,
+				 <&infracfg CLK_INFRA_AUDIO>,
+				 <&infracfg CLK_INFRA_AUDIO_26M_BCLK>,
+				 <&topckgen CLK_TOP_MUX_MFG>,
+				 <&topckgen CLK_TOP_MUX_MM>,
+				 <&topckgen CLK_TOP_MUX_CAM>,
+				 <&topckgen CLK_TOP_MUX_IMG>,
+				 <&topckgen CLK_TOP_MUX_IPU_IF>,
+				 <&topckgen CLK_TOP_MUX_DSP>,
+				 <&topckgen CLK_TOP_MUX_DSP1>,
+				 <&topckgen CLK_TOP_MUX_DSP2>,
+				 <&mmsys CLK_MM_SMI_COMMON>,
+				 <&mmsys CLK_MM_SMI_LARB0>,
+				 <&mmsys CLK_MM_SMI_LARB1>,
+				 <&mmsys CLK_MM_GALS_COMM0>,
+				 <&mmsys CLK_MM_GALS_COMM1>,
+				 <&mmsys CLK_MM_GALS_CCU2MM>,
+				 <&mmsys CLK_MM_GALS_IPU12MM>,
+				 <&mmsys CLK_MM_GALS_IMG2MM>,
+				 <&mmsys CLK_MM_GALS_CAM2MM>,
+				 <&mmsys CLK_MM_GALS_IPU2MM>,
+				 <&imgsys CLK_IMG_LARB5>,
+				 <&imgsys CLK_IMG_LARB2>,
+				 <&camsys CLK_CAM_LARB6>,
+				 <&camsys CLK_CAM_LARB3>,
+				 <&camsys CLK_CAM_SENINF>,
+				 <&camsys CLK_CAM_CAMSV0>,
+				 <&camsys CLK_CAM_CAMSV1>,
+				 <&camsys CLK_CAM_CAMSV2>,
+				 <&camsys CLK_CAM_CCU>,
+				 <&ipu_conn CLK_IPU_CONN_IPU>,
+				 <&ipu_conn CLK_IPU_CONN_AHB>,
+				 <&ipu_conn CLK_IPU_CONN_AXI>,
+				 <&ipu_conn CLK_IPU_CONN_ISP>,
+				 <&ipu_conn CLK_IPU_CONN_CAM_ADL>,
+				 <&ipu_conn CLK_IPU_CONN_IMG_ADL>;
+			clock-names = "audio", "audio1", "audio2",
+				      "mfg", "mm", "cam",
+				      "isp", "vpu", "vpu1",
+				      "vpu2", "vpu3", "mm-0",
+				      "mm-1", "mm-2", "mm-3",
+				      "mm-4", "mm-5", "mm-6",
+				      "mm-7", "mm-8", "mm-9",
+				      "isp-0", "isp-1", "cam-0",
+				      "cam-1", "cam-2", "cam-3",
+				      "cam-4", "cam-5", "cam-6",
+				      "vpu-0", "vpu-1", "vpu-2",
+				      "vpu-3", "vpu-4", "vpu-5";
+			infracfg = <&infracfg>;
+			smi_comm = <&smi_common>;
+		};
+
 		apmixedsys: syscon@1000c000 {
 			compatible = "mediatek,mt8183-apmixedsys", "syscon";
 			reg = <0 0x1000c000 0 0x1000>;
@@ -260,6 +317,11 @@
 			#clock-cells = <1>;
 		};
 
+		smi_common: smi@14019000 {
+			compatible = "mediatek,mt8183-smi-common", "syscon";
+			reg = <0 0x14019000 0 0x1000>;
+		};
+
 		imgsys: syscon@15020000 {
 			compatible = "mediatek,mt8183-imgsys", "syscon";
 			reg = <0 0x15020000 0 0x1000>;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation
  2019-03-19  8:01 ` [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation Weiyi Lu
@ 2019-03-19 11:45   ` Nicolas Boichat
  2019-06-19  9:11     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-19 11:45 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Use USEC_PER_SEC to indicate the polling timeout directly.
> And add documentation of scp_domain_data.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>  drivers/soc/mediatek/mtk-scpsys.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 9f52f501178b..2855111b221a 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -21,7 +21,7 @@
>  #include <dt-bindings/power/mt8173-power.h>
>
>  #define MTK_POLL_DELAY_US   10
> -#define MTK_POLL_TIMEOUT    (jiffies_to_usecs(HZ))
> +#define MTK_POLL_TIMEOUT    USEC_PER_SEC
>
>  #define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
>  #define MTK_SCPD_FWAIT_SRAM            BIT(1)
> @@ -108,6 +108,18 @@ static const char * const clk_names[] = {
>
>  #define MAX_CLKS       3
>
> +/**
> + * struct scp_domain_data - scp domain data for power on/off flow
> + * @name: The domain name.
> + * @sta_mask: The mask for power on/off status bit.
> + * @ctl_offs: The offset for main power control register.
> + * @sram_pdn_bits: The mask for sram power control bits.
> + * @sram_pdn_ack_bits: The mask for sram power control acked bits.
> + * @bus_prot_mask: The mask for single step bus protection.
> + * @clk_id: The basic clock needs to be enabled before enabling certain
> + *          power domains.

I assume these are the clock*s* that *this* scp_domain requires?

So maybe just: "The basic clocks required by this power domain." ?

> + * @caps: The flag for active wake-up action.
> + */
>  struct scp_domain_data {
>         const char *name;
>         u32 sta_mask;
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 06/14] soc: mediatek: Refactor clock control
  2019-03-19  8:01 ` [PATCH v5 06/14] soc: mediatek: Refactor clock control Weiyi Lu
@ 2019-03-19 12:02   ` Nicolas Boichat
  2019-06-19  9:19     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-19 12:02 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Put clock enable and disable control in separate function.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>  drivers/soc/mediatek/mtk-scpsys.c | 49 ++++++++++++++++++++-----------
>  1 file changed, 32 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 765ad4a5e5df..3e9be07a2627 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -208,6 +208,33 @@ static int scpsys_regulator_disable(struct scp_domain *scpd)
>         return regulator_disable(scpd->supply);
>  }
>
> +static int scpsys_clk_enable(struct clk *clk[], int max_num)
> +{
> +       int i, ret = 0;
> +
> +       for (i = 0; i < max_num && clk[i]; i++) {
> +               ret = clk_prepare_enable(clk[i]);
> +               if (ret) {
> +                       for (--i; i >= 0; i--)
> +                               clk_disable_unprepare(clk[i]);

Would it be simpler to just call scpsys_clk_disable(clk, i) ?

> +
> +                       break;
> +               }
> +       }
> +
> +       return ret;
> +}

Maybe not for this series, but could you use clk_bulk_prepare_enable
instead? The only issue is that it'd still call clk_prepare_enable on
NULL clocks, but that does nothing, so it's just a little less
efficient...

> +
> +static void scpsys_clk_disable(struct clk *clk[], int max_num)
> +{
> +       int i;
> +
> +       for (i = max_num - 1; i >= 0; i--) {
> +               if (clk[i])

if test not needed, clk_disable_unprepare ignores NULL parameters.

> +                       clk_disable_unprepare(clk[i]);
> +       }
> +}

ditto: clk_bulk_disable_unprepare

> +
>  static int scpsys_power_on(struct generic_pm_domain *genpd)
>  {
>         struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
> @@ -216,21 +243,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>         u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
>         u32 val;
>         int ret, tmp;
> -       int i;
>
>         ret = scpsys_regulator_enable(scpd);
>         if (ret < 0)
>                 return ret;
>
> -       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;
> -               }
> -       }
> +       ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
> +       if (ret)
> +               goto err_clk;
>
>         val = readl(ctl_addr);
>         val |= PWR_ON_BIT;
> @@ -283,10 +303,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>         return 0;
>
>  err_pwr_ack:
> -       for (i = MAX_CLKS - 1; i >= 0; i--) {
> -               if (scpd->clk[i])
> -                       clk_disable_unprepare(scpd->clk[i]);
> -       }
> +       scpsys_clk_disable(scpd->clk, MAX_CLKS);
>  err_clk:
>         scpsys_regulator_disable(scpd);
>
> @@ -303,7 +320,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>         u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
>         u32 val;
>         int ret, tmp;
> -       int i;
>
>         if (scpd->data->bus_prot_mask) {
>                 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> @@ -344,8 +360,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>         if (ret < 0)
>                 goto out;
>
> -       for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
> -               clk_disable_unprepare(scpd->clk[i]);
> +       scpsys_clk_disable(scpd->clk, MAX_CLKS);
>
>         ret = scpsys_regulator_disable(scpd);
>         if (ret < 0)
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 07/14] soc: mediatek: Refactor sram control
  2019-03-19  8:01 ` [PATCH v5 07/14] soc: mediatek: Refactor sram control Weiyi Lu
@ 2019-03-19 12:07   ` Nicolas Boichat
  2019-06-19  9:30     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-19 12:07 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Put sram enable and disable control in separate functions.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>

Refactoring looks ok, just a small comment.

Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>

> ---
>  drivers/soc/mediatek/mtk-scpsys.c | 79 ++++++++++++++++++++-----------
>  1 file changed, 51 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 3e9be07a2627..65b734b40098 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -235,12 +235,55 @@ static void scpsys_clk_disable(struct clk *clk[], int max_num)
>         }
>  }
>
> +static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
> +{
> +       u32 val;
> +       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> +       int tmp;
> +
> +       val = readl(ctl_addr) & ~scpd->data->sram_pdn_bits;
> +       writel(val, ctl_addr);
> +
> +       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
> +       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
> +               /*
> +                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
> +                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
> +                * is applied here.
> +                */
> +               usleep_range(12000, 12100);

Does the range really need to be so tight? Would 12000, 13000 also be ok?

> +       } else {
> +               /* Either wait until SRAM_PDN_ACK all 1 or 0 */
> +               int ret = readl_poll_timeout(ctl_addr, tmp,
> +                               (tmp & pdn_ack) == 0,
> +                               MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> +               if (ret < 0)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
> +{
> +       u32 val;
> +       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> +       int tmp;
> +
> +       val = readl(ctl_addr) | scpd->data->sram_pdn_bits;
> +       writel(val, ctl_addr);
> +
> +       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
> +       return readl_poll_timeout(ctl_addr, tmp,
> +                       (tmp & pdn_ack) == pdn_ack,
> +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> +}
> +
>  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;
>         void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
> -       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
>         u32 val;
>         int ret, tmp;
>
> @@ -252,6 +295,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>         if (ret)
>                 goto err_clk;
>
> +       /* subsys power on */
>         val = readl(ctl_addr);
>         val |= PWR_ON_BIT;
>         writel(val, ctl_addr);
> @@ -273,24 +317,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>         val |= PWR_RST_B_BIT;
>         writel(val, ctl_addr);
>
> -       val &= ~scpd->data->sram_pdn_bits;
> -       writel(val, ctl_addr);
> -
> -       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
> -       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
> -               /*
> -                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
> -                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is
> -                * applied here.
> -                */
> -               usleep_range(12000, 12100);
> -
> -       } else {
> -               ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
> -                                        MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> -               if (ret < 0)
> -                       goto err_pwr_ack;
> -       }
> +       ret = scpsys_sram_enable(scpd, ctl_addr);
> +       if (ret < 0)
> +               goto err_pwr_ack;
>
>         if (scpd->data->bus_prot_mask) {
>                 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> @@ -317,7 +346,6 @@ 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;
>         void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
> -       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
>         u32 val;
>         int ret, tmp;
>
> @@ -329,17 +357,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>                         goto out;
>         }
>
> -       val = readl(ctl_addr);
> -       val |= scpd->data->sram_pdn_bits;
> -       writel(val, ctl_addr);
> -
> -       /* wait until SRAM_PDN_ACK all 1 */
> -       ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
> -                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> +       ret = scpsys_sram_disable(scpd, ctl_addr);
>         if (ret < 0)
>                 goto out;
>
> -       val |= PWR_ISO_BIT;
> +       /* subsys power off */
> +       val = readl(ctl_addr) | PWR_ISO_BIT;
>         writel(val, ctl_addr);
>
>         val &= ~PWR_RST_B_BIT;
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 08/14] soc: mediatek: Refactor bus protection control
  2019-03-19  8:01 ` [PATCH v5 08/14] soc: mediatek: Refactor bus protection control Weiyi Lu
@ 2019-03-19 12:09   ` Nicolas Boichat
  2019-06-19  9:31     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-19 12:09 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Put bus protection enable and disable control in separate functions.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>  drivers/soc/mediatek/mtk-scpsys.c | 48 ++++++++++++++++++++++---------
>  1 file changed, 34 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 65b734b40098..6bf846cb1893 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -279,6 +279,34 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
>                         MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
>  }
>
> +static int scpsys_bus_protect_enable(struct scp_domain *scpd)
> +{
> +       struct scp *scp = scpd->scp;
> +       int ret = 0;
> +
> +       if (scpd->data->bus_prot_mask) {
> +               ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> +                               scpd->data->bus_prot_mask,
> +                               scp->bus_prot_reg_update);
> +       }
> +
> +       return ret;

Maybe other people have different opinions, but I prefer:

if (!scpd->data->bus_prot_mask)
    return 0;

return mtk_infracfg_set_bus_protection(...);

> +}
> +
> +static int scpsys_bus_protect_disable(struct scp_domain *scpd)
> +{
> +       struct scp *scp = scpd->scp;
> +       int ret = 0;
> +
> +       if (scpd->data->bus_prot_mask) {
> +               ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> +                               scpd->data->bus_prot_mask,
> +                               scp->bus_prot_reg_update);
> +       }
> +
> +       return ret;
> +}
> +
>  static int scpsys_power_on(struct generic_pm_domain *genpd)
>  {
>         struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
> @@ -321,13 +349,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>         if (ret < 0)
>                 goto err_pwr_ack;
>
> -       if (scpd->data->bus_prot_mask) {
> -               ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> -                               scpd->data->bus_prot_mask,
> -                               scp->bus_prot_reg_update);
> -               if (ret)
> -                       goto err_pwr_ack;
> -       }
> +       ret = scpsys_bus_protect_disable(scpd);
> +       if (ret < 0)
> +               goto err_pwr_ack;
>
>         return 0;
>
> @@ -349,13 +373,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>         u32 val;
>         int ret, tmp;
>
> -       if (scpd->data->bus_prot_mask) {
> -               ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> -                               scpd->data->bus_prot_mask,
> -                               scp->bus_prot_reg_update);
> -               if (ret)
> -                       goto out;
> -       }
> +       ret = scpsys_bus_protect_enable(scpd);
> +       if (ret < 0)
> +               goto out;
>
>         ret = scpsys_sram_disable(scpd, ctl_addr);
>         if (ret < 0)
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control
  2019-03-19  8:01 ` [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control Weiyi Lu
@ 2019-03-21  5:57   ` Nicolas Boichat
  2019-06-19  9:43     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-21  5:57 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Both MT8183 & MT6765 have more control steps of bus protection
> than previous project. And there add more bus protection registers
> reside at infracfg & smi-common. Also add new APIs for multiple
> step bus protection control with more customize arguments.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>  drivers/soc/mediatek/Makefile           |  2 +-
>  drivers/soc/mediatek/mtk-scpsys-ext.c   | 99 +++++++++++++++++++++++++
>  drivers/soc/mediatek/mtk-scpsys.c       | 24 ++++++
>  include/linux/soc/mediatek/scpsys-ext.h | 39 ++++++++++
>  4 files changed, 163 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
>  create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
>
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index 64ce5eeaba32..b9dbad6b12f9 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,4 +1,4 @@
>  obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
> -obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> +obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
>  obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
>  obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
> new file mode 100644
> index 000000000000..f630edb2f65d
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
> @@ -0,0 +1,99 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + * Author: Owen Chen <Owen.Chen@mediatek.com>
> + */
> +#include <linux/ktime.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +#include <linux/soc/mediatek/scpsys-ext.h>
> +
> +#define MTK_POLL_DELAY_US   10
> +#define MTK_POLL_TIMEOUT    USEC_PER_SEC
> +
> +static int set_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
> +               u32 reg_set, u32 reg_sta, u32 reg_en)
> +{
> +       u32 val;
> +
> +       if (reg_set)
> +               regmap_write(map, reg_set, mask);
> +       else
> +               regmap_update_bits(map, reg_en, mask, mask);
> +
> +       return regmap_read_poll_timeout(map, reg_sta,
> +                       val, (val & ack_mask) == ack_mask,
> +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> +}
> +
> +static int clear_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
> +               u32 reg_clr, u32 reg_sta, u32 reg_en)
> +{
> +       u32 val;
> +
> +       if (reg_clr)
> +               regmap_write(map, reg_clr, mask);
> +       else
> +               regmap_update_bits(map, reg_en, mask, 0);
> +
> +       return regmap_read_poll_timeout(map, reg_sta,
> +                       val, !(val & ack_mask),
> +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> +}
> +
> +int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
> +       struct regmap *infracfg, struct regmap *smi_common)
> +{
> +       int i;
> +
> +       for (i = 0; i < MAX_STEPS && bp_table[i].mask; i++) {
> +               struct regmap *map;
> +               int ret;
> +
> +               if (bp_table[i].type == IFR_TYPE)
> +                       map = infracfg;
> +               else if (bp_table[i].type == SMI_TYPE)
> +                       map = smi_common;
> +               else
> +                       return -EINVAL;
> +
> +               ret = set_bus_protection(map,
> +                               bp_table[i].mask, bp_table[i].mask,
> +                               bp_table[i].set_ofs, bp_table[i].sta_ofs,
> +                               bp_table[i].en_ofs);
> +
> +               if (ret)
> +                       return ret;

Should you undo the rest of the operations and clear bus protection on
the ones that were already enabled?

> +       }
> +
> +       return 0;
> +}
> +
> +int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
> +       struct regmap *infracfg, struct regmap *smi_common)
> +{
> +       int i;
> +
> +       for (i = MAX_STEPS - 1; i >= 0; i--) {

So when you set protection, you stop at the first bp_table[i].mask ==
0, but when you clear it, you call clear_bus_protection for those, as
well. You should just skip over the ones when bp_table[i].mask == 0?

e.g.
if (!bp_table[i].mask)
   continue;

> +               struct regmap *map;
> +               int ret;
> +
> +               if (bp_table[i].type == IFR_TYPE)
> +                       map = infracfg;
> +               else if (bp_table[i].type == SMI_TYPE)
> +                       map = smi_common;
> +               else
> +                       return -EINVAL;
> +
> +               ret = clear_bus_protection(map,
> +                               bp_table[i].mask, bp_table[i].clr_ack_mask,
> +                               bp_table[i].clr_ofs, bp_table[i].sta_ofs,
> +                               bp_table[i].en_ofs);
> +
> +               if (ret)
> +                       return ret;

Similar question, is it ok to just abort? Or should you try to clear
the protection on all others, too?

> +       }
> +
> +       return 0;
> +}
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index c6360de4e41e..181bf7bce591 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -12,6 +12,7 @@
>  #include <linux/pm_domain.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/soc/mediatek/infracfg.h>
> +#include <linux/soc/mediatek/scpsys-ext.h>
>
>  #include <dt-bindings/power/mt2701-power.h>
>  #include <dt-bindings/power/mt2712-power.h>
> @@ -121,6 +122,7 @@ static const char * const clk_names[] = {
>   * @basic_clk_name: provide the same purpose with field "clk_id"
>   *                  by declaring basic clock prefix name rather than clk_id.
>   * @caps: The flag for active wake-up action.
> + * @bp_table: The mask table for multiple step bus protection.
>   */
>  struct scp_domain_data {
>         const char *name;
> @@ -132,6 +134,7 @@ struct scp_domain_data {
>         enum clk_id clk_id[MAX_CLKS];
>         const char *basic_clk_name[MAX_CLKS];
>         u8 caps;
> +       struct bus_prot bp_table[MAX_STEPS];
>  };
>
>  struct scp;
> @@ -155,6 +158,7 @@ struct scp {
>         struct device *dev;
>         void __iomem *base;
>         struct regmap *infracfg;
> +       struct regmap *smi_common;
>         struct scp_ctrl_reg ctrl_reg;
>         bool bus_prot_reg_update;
>  };
> @@ -291,6 +295,10 @@ static int scpsys_bus_protect_enable(struct scp_domain *scpd)
>                 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
>                                 scpd->data->bus_prot_mask,
>                                 scp->bus_prot_reg_update);
> +       } else if (scpd->data->bp_table[0].mask) {
> +               ret = mtk_scpsys_ext_set_bus_protection(scpd->data->bp_table,
> +                               scp->infracfg,
> +                               scp->smi_common);
>         }
>
>         return ret;
> @@ -305,6 +313,11 @@ static int scpsys_bus_protect_disable(struct scp_domain *scpd)
>                 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
>                                 scpd->data->bus_prot_mask,
>                                 scp->bus_prot_reg_update);
> +       } else if (scpd->data->bp_table[0].mask) {
> +               ret = mtk_scpsys_ext_clear_bus_protection(
> +                               scpd->data->bp_table,
> +                               scp->infracfg,
> +                               scp->smi_common);
>         }
>
>         return ret;
> @@ -475,6 +488,17 @@ static struct scp *init_scp(struct platform_device *pdev,
>                 return ERR_CAST(scp->infracfg);
>         }
>
> +       scp->smi_common = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> +                       "smi_comm");
> +
> +       if (scp->smi_common == ERR_PTR(-ENODEV)) {
> +               scp->smi_common = NULL;
> +       } else if (IS_ERR(scp->smi_common)) {
> +               dev_err(&pdev->dev, "Cannot find smi_common controller: %ld\n",
> +                               PTR_ERR(scp->smi_common));
> +               return ERR_CAST(scp->smi_common);
> +       }
> +
>         for (i = 0; i < num; i++) {
>                 struct scp_domain *scpd = &scp->domains[i];
>                 const struct scp_domain_data *data = &scp_domain_data[i];
> diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
> new file mode 100644
> index 000000000000..d0ed295c88a7
> --- /dev/null
> +++ b/include/linux/soc/mediatek/scpsys-ext.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
> +#define __SOC_MEDIATEK_SCPSYS_EXT_H
> +
> +#define MAX_STEPS      4
> +
> +#define BUS_PROT(_type, _set_ofs, _clr_ofs,                    \
> +               _en_ofs, _sta_ofs, _mask, _clr_ack_mask) {      \
> +               .type = _type,                                  \
> +               .set_ofs = _set_ofs,                            \
> +               .clr_ofs = _clr_ofs,                            \
> +               .en_ofs = _en_ofs,                              \
> +               .sta_ofs = _sta_ofs,                            \
> +               .mask = _mask,                                  \
> +               .clr_ack_mask = _clr_ack_mask,                  \
> +       }
> +
> +enum regmap_type {

Maybe add INVALID_TYPE = 0, so that you can skip over those when
looping over them, instead of checking if mask is 0?

> +       IFR_TYPE,
> +       SMI_TYPE,
> +       MAX_REGMAP_TYPE,

This is not used, right? Do you really need it?

> +};
> +
> +struct bus_prot {
> +       enum regmap_type type;
> +       u32 set_ofs;
> +       u32 clr_ofs;
> +       u32 en_ofs;
> +       u32 sta_ofs;
> +       u32 mask;
> +       u32 clr_ack_mask;
> +};
> +
> +int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
> +       struct regmap *infracfg, struct regmap *smi_common);
> +int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
> +       struct regmap *infracfg, struct regmap *smi_common);
> +
> +#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data
  2019-03-19  8:01 ` [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data Weiyi Lu
@ 2019-03-21  6:02   ` Nicolas Boichat
  2019-06-19  9:36     ` Weiyi Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas Boichat @ 2019-03-21  6:02 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Try to stop extending the clk_id or clk_names if there are
> more and more new BASIC clocks. To get its own clocks by the
> basic_clk_name of each power domain.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>  drivers/soc/mediatek/mtk-scpsys.c | 27 +++++++++++++++++++--------
>  1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 6bf846cb1893..c6360de4e41e 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -118,6 +118,8 @@ static const char * const clk_names[] = {
>   * @bus_prot_mask: The mask for single step bus protection.
>   * @clk_id: The basic clock needs to be enabled before enabling certain
>   *          power domains.
> + * @basic_clk_name: provide the same purpose with field "clk_id"
> + *                  by declaring basic clock prefix name rather than clk_id.
>   * @caps: The flag for active wake-up action.
>   */
>  struct scp_domain_data {
> @@ -128,6 +130,7 @@ struct scp_domain_data {
>         u32 sram_pdn_ack_bits;
>         u32 bus_prot_mask;
>         enum clk_id clk_id[MAX_CLKS];
> +       const char *basic_clk_name[MAX_CLKS];

Either call them basic_clk_id/basic_clk_name, or clk_id/clk_name.

>         u8 caps;
>  };
>
> @@ -499,16 +502,24 @@ static struct scp *init_scp(struct platform_device *pdev,
>
>                 scpd->data = data;
>
> -               for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
> -                       struct clk *c = clk[data->clk_id[j]];
> +               if (data->clk_id[0]) {

Since it's either clk_id or basic_clk_name, I wonder if it'd be good
to add a WARN_ON here, e.g.

WARN_ON(data->basic_clk_name[0]);

> +                       for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
> +                               struct clk *c = clk[data->clk_id[j]];
>
> -                       if (IS_ERR(c)) {
> -                               dev_err(&pdev->dev, "%s: clk unavailable\n",
> -                                       data->name);
> -                               return ERR_CAST(c);
> -                       }
> +                               if (IS_ERR(c)) {
> +                                       dev_err(&pdev->dev,
> +                                               "%s: clk unavailable\n",
> +                                               data->name);
> +                                       return ERR_CAST(c);
> +                               }
>
> -                       scpd->clk[j] = c;
> +                               scpd->clk[j] = c;
> +                       }
> +               } else if (data->basic_clk_name[0]) {
> +                       for (j = 0; j < MAX_CLKS &&
> +                                       data->basic_clk_name[j]; j++)
> +                               scpd->clk[j] = devm_clk_get(&pdev->dev,
> +                                               data->basic_clk_name[j]);
>                 }
>
>                 genpd->name = data->name;
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation
  2019-03-19 11:45   ` Nicolas Boichat
@ 2019-06-19  9:11     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:11 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Rob Herring, srv_heupstream, James Liao, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	linux-arm Mailing List

On Tue, 2019-03-19 at 19:45 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Use USEC_PER_SEC to indicate the polling timeout directly.
> > And add documentation of scp_domain_data.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >  drivers/soc/mediatek/mtk-scpsys.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 9f52f501178b..2855111b221a 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -21,7 +21,7 @@
> >  #include <dt-bindings/power/mt8173-power.h>
> >
> >  #define MTK_POLL_DELAY_US   10
> > -#define MTK_POLL_TIMEOUT    (jiffies_to_usecs(HZ))
> > +#define MTK_POLL_TIMEOUT    USEC_PER_SEC
> >
> >  #define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
> >  #define MTK_SCPD_FWAIT_SRAM            BIT(1)
> > @@ -108,6 +108,18 @@ static const char * const clk_names[] = {
> >
> >  #define MAX_CLKS       3
> >
> > +/**
> > + * struct scp_domain_data - scp domain data for power on/off flow
> > + * @name: The domain name.
> > + * @sta_mask: The mask for power on/off status bit.
> > + * @ctl_offs: The offset for main power control register.
> > + * @sram_pdn_bits: The mask for sram power control bits.
> > + * @sram_pdn_ack_bits: The mask for sram power control acked bits.
> > + * @bus_prot_mask: The mask for single step bus protection.
> > + * @clk_id: The basic clock needs to be enabled before enabling certain
> > + *          power domains.
> 
> I assume these are the clock*s* that *this* scp_domain requires?
> 
> So maybe just: "The basic clocks required by this power domain." ?
> 
Thanks for revision. I'll update in next version.
> > + * @caps: The flag for active wake-up action.
> > + */
> >  struct scp_domain_data {
> >         const char *name;
> >         u32 sta_mask;
> > --
> > 2.18.0
> >
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 06/14] soc: mediatek: Refactor clock control
  2019-03-19 12:02   ` Nicolas Boichat
@ 2019-06-19  9:19     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:19 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, 2019-03-19 at 20:02 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Put clock enable and disable control in separate function.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >  drivers/soc/mediatek/mtk-scpsys.c | 49 ++++++++++++++++++++-----------
> >  1 file changed, 32 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 765ad4a5e5df..3e9be07a2627 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -208,6 +208,33 @@ static int scpsys_regulator_disable(struct scp_domain *scpd)
> >         return regulator_disable(scpd->supply);
> >  }
> >
> > +static int scpsys_clk_enable(struct clk *clk[], int max_num)
> > +{
> > +       int i, ret = 0;
> > +
> > +       for (i = 0; i < max_num && clk[i]; i++) {
> > +               ret = clk_prepare_enable(clk[i]);
> > +               if (ret) {
> > +                       for (--i; i >= 0; i--)
> > +                               clk_disable_unprepare(clk[i]);
> 
> Would it be simpler to just call scpsys_clk_disable(clk, i) ?
> 

OK, I'll try.

> > +
> > +                       break;
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> 
> Maybe not for this series, but could you use clk_bulk_prepare_enable
> instead? The only issue is that it'd still call clk_prepare_enable on
> NULL clocks, but that does nothing, so it's just a little less
> efficient...
> 

OK, I'll try after this series.

> > +
> > +static void scpsys_clk_disable(struct clk *clk[], int max_num)
> > +{
> > +       int i;
> > +
> > +       for (i = max_num - 1; i >= 0; i--) {
> > +               if (clk[i])
> 
> if test not needed, clk_disable_unprepare ignores NULL parameters.
> 

You're right. Supposed it's not needed, I'll test.

> > +                       clk_disable_unprepare(clk[i]);
> > +       }
> > +}
> 
> ditto: clk_bulk_disable_unprepare
> 
> > +
> >  static int scpsys_power_on(struct generic_pm_domain *genpd)
> >  {
> >         struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
> > @@ -216,21 +243,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >         u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> >         u32 val;
> >         int ret, tmp;
> > -       int i;
> >
> >         ret = scpsys_regulator_enable(scpd);
> >         if (ret < 0)
> >                 return ret;
> >
> > -       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;
> > -               }
> > -       }
> > +       ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
> > +       if (ret)
> > +               goto err_clk;
> >
> >         val = readl(ctl_addr);
> >         val |= PWR_ON_BIT;
> > @@ -283,10 +303,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >         return 0;
> >
> >  err_pwr_ack:
> > -       for (i = MAX_CLKS - 1; i >= 0; i--) {
> > -               if (scpd->clk[i])
> > -                       clk_disable_unprepare(scpd->clk[i]);
> > -       }
> > +       scpsys_clk_disable(scpd->clk, MAX_CLKS);
> >  err_clk:
> >         scpsys_regulator_disable(scpd);
> >
> > @@ -303,7 +320,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> >         u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> >         u32 val;
> >         int ret, tmp;
> > -       int i;
> >
> >         if (scpd->data->bus_prot_mask) {
> >                 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> > @@ -344,8 +360,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> >         if (ret < 0)
> >                 goto out;
> >
> > -       for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
> > -               clk_disable_unprepare(scpd->clk[i]);
> > +       scpsys_clk_disable(scpd->clk, MAX_CLKS);
> >
> >         ret = scpsys_regulator_disable(scpd);
> >         if (ret < 0)
> > --
> > 2.18.0
> >



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 07/14] soc: mediatek: Refactor sram control
  2019-03-19 12:07   ` Nicolas Boichat
@ 2019-06-19  9:30     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:30 UTC (permalink / raw)
  To: Nicolas Boichat, Sean Wang
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Tue, 2019-03-19 at 20:07 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Put sram enable and disable control in separate functions.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> 
> Refactoring looks ok, just a small comment.
> 
> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
> 
> > ---
> >  drivers/soc/mediatek/mtk-scpsys.c | 79 ++++++++++++++++++++-----------
> >  1 file changed, 51 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 3e9be07a2627..65b734b40098 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -235,12 +235,55 @@ static void scpsys_clk_disable(struct clk *clk[], int max_num)
> >         }
> >  }
> >
> > +static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
> > +{
> > +       u32 val;
> > +       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> > +       int tmp;
> > +
> > +       val = readl(ctl_addr) & ~scpd->data->sram_pdn_bits;
> > +       writel(val, ctl_addr);
> > +
> > +       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
> > +       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
> > +               /*
> > +                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
> > +                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
> > +                * is applied here.
> > +                */
> > +               usleep_range(12000, 12100);
> 
> Does the range really need to be so tight? Would 12000, 13000 also be ok?
> 

I think Sean could give you a more accurate answer.

Hi Sean, would you mind answering this question?

> > +       } else {
> > +               /* Either wait until SRAM_PDN_ACK all 1 or 0 */
> > +               int ret = readl_poll_timeout(ctl_addr, tmp,
> > +                               (tmp & pdn_ack) == 0,
> > +                               MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > +               if (ret < 0)
> > +                       return ret;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
> > +{
> > +       u32 val;
> > +       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> > +       int tmp;
> > +
> > +       val = readl(ctl_addr) | scpd->data->sram_pdn_bits;
> > +       writel(val, ctl_addr);
> > +
> > +       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
> > +       return readl_poll_timeout(ctl_addr, tmp,
> > +                       (tmp & pdn_ack) == pdn_ack,
> > +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > +}
> > +
> >  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;
> >         void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
> > -       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> >         u32 val;
> >         int ret, tmp;
> >
> > @@ -252,6 +295,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >         if (ret)
> >                 goto err_clk;
> >
> > +       /* subsys power on */
> >         val = readl(ctl_addr);
> >         val |= PWR_ON_BIT;
> >         writel(val, ctl_addr);
> > @@ -273,24 +317,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >         val |= PWR_RST_B_BIT;
> >         writel(val, ctl_addr);
> >
> > -       val &= ~scpd->data->sram_pdn_bits;
> > -       writel(val, ctl_addr);
> > -
> > -       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
> > -       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
> > -               /*
> > -                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
> > -                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is
> > -                * applied here.
> > -                */
> > -               usleep_range(12000, 12100);
> > -
> > -       } else {
> > -               ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
> > -                                        MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > -               if (ret < 0)
> > -                       goto err_pwr_ack;
> > -       }
> > +       ret = scpsys_sram_enable(scpd, ctl_addr);
> > +       if (ret < 0)
> > +               goto err_pwr_ack;
> >
> >         if (scpd->data->bus_prot_mask) {
> >                 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> > @@ -317,7 +346,6 @@ 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;
> >         void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
> > -       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
> >         u32 val;
> >         int ret, tmp;
> >
> > @@ -329,17 +357,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> >                         goto out;
> >         }
> >
> > -       val = readl(ctl_addr);
> > -       val |= scpd->data->sram_pdn_bits;
> > -       writel(val, ctl_addr);
> > -
> > -       /* wait until SRAM_PDN_ACK all 1 */
> > -       ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
> > -                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > +       ret = scpsys_sram_disable(scpd, ctl_addr);
> >         if (ret < 0)
> >                 goto out;
> >
> > -       val |= PWR_ISO_BIT;
> > +       /* subsys power off */
> > +       val = readl(ctl_addr) | PWR_ISO_BIT;
> >         writel(val, ctl_addr);
> >
> >         val &= ~PWR_RST_B_BIT;
> > --
> > 2.18.0
> >



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 08/14] soc: mediatek: Refactor bus protection control
  2019-03-19 12:09   ` Nicolas Boichat
@ 2019-06-19  9:31     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:31 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Rob Herring, srv_heupstream, James Liao, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	linux-arm Mailing List

On Tue, 2019-03-19 at 20:09 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Put bus protection enable and disable control in separate functions.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >  drivers/soc/mediatek/mtk-scpsys.c | 48 ++++++++++++++++++++++---------
> >  1 file changed, 34 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 65b734b40098..6bf846cb1893 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -279,6 +279,34 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
> >                         MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> >  }
> >
> > +static int scpsys_bus_protect_enable(struct scp_domain *scpd)
> > +{
> > +       struct scp *scp = scpd->scp;
> > +       int ret = 0;
> > +
> > +       if (scpd->data->bus_prot_mask) {
> > +               ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> > +                               scpd->data->bus_prot_mask,
> > +                               scp->bus_prot_reg_update);
> > +       }
> > +
> > +       return ret;
> 
> Maybe other people have different opinions, but I prefer:
> 
> if (!scpd->data->bus_prot_mask)
>     return 0;
> 
> return mtk_infracfg_set_bus_protection(...);
> 

ok, I'll update in next version.

> > +}
> > +
> > +static int scpsys_bus_protect_disable(struct scp_domain *scpd)
> > +{
> > +       struct scp *scp = scpd->scp;
> > +       int ret = 0;
> > +
> > +       if (scpd->data->bus_prot_mask) {
> > +               ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> > +                               scpd->data->bus_prot_mask,
> > +                               scp->bus_prot_reg_update);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> >  static int scpsys_power_on(struct generic_pm_domain *genpd)
> >  {
> >         struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
> > @@ -321,13 +349,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >         if (ret < 0)
> >                 goto err_pwr_ack;
> >
> > -       if (scpd->data->bus_prot_mask) {
> > -               ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> > -                               scpd->data->bus_prot_mask,
> > -                               scp->bus_prot_reg_update);
> > -               if (ret)
> > -                       goto err_pwr_ack;
> > -       }
> > +       ret = scpsys_bus_protect_disable(scpd);
> > +       if (ret < 0)
> > +               goto err_pwr_ack;
> >
> >         return 0;
> >
> > @@ -349,13 +373,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> >         u32 val;
> >         int ret, tmp;
> >
> > -       if (scpd->data->bus_prot_mask) {
> > -               ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> > -                               scpd->data->bus_prot_mask,
> > -                               scp->bus_prot_reg_update);
> > -               if (ret)
> > -                       goto out;
> > -       }
> > +       ret = scpsys_bus_protect_enable(scpd);
> > +       if (ret < 0)
> > +               goto out;
> >
> >         ret = scpsys_sram_disable(scpd, ctl_addr);
> >         if (ret < 0)
> > --
> > 2.18.0
> >
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data
  2019-03-21  6:02   ` Nicolas Boichat
@ 2019-06-19  9:36     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:36 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Thu, 2019-03-21 at 14:02 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Try to stop extending the clk_id or clk_names if there are
> > more and more new BASIC clocks. To get its own clocks by the
> > basic_clk_name of each power domain.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >  drivers/soc/mediatek/mtk-scpsys.c | 27 +++++++++++++++++++--------
> >  1 file changed, 19 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 6bf846cb1893..c6360de4e41e 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -118,6 +118,8 @@ static const char * const clk_names[] = {
> >   * @bus_prot_mask: The mask for single step bus protection.
> >   * @clk_id: The basic clock needs to be enabled before enabling certain
> >   *          power domains.
> > + * @basic_clk_name: provide the same purpose with field "clk_id"
> > + *                  by declaring basic clock prefix name rather than clk_id.
> >   * @caps: The flag for active wake-up action.
> >   */
> >  struct scp_domain_data {
> > @@ -128,6 +130,7 @@ struct scp_domain_data {
> >         u32 sram_pdn_ack_bits;
> >         u32 bus_prot_mask;
> >         enum clk_id clk_id[MAX_CLKS];
> > +       const char *basic_clk_name[MAX_CLKS];
> 
> Either call them basic_clk_id/basic_clk_name, or clk_id/clk_name.
> 

OK.

> >         u8 caps;
> >  };
> >
> > @@ -499,16 +502,24 @@ static struct scp *init_scp(struct platform_device *pdev,
> >
> >                 scpd->data = data;
> >
> > -               for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
> > -                       struct clk *c = clk[data->clk_id[j]];
> > +               if (data->clk_id[0]) {
> 
> Since it's either clk_id or basic_clk_name, I wonder if it'd be good
> to add a WARN_ON here, e.g.
> 
> WARN_ON(data->basic_clk_name[0]);
> 

Thanks for the advise. I'll add it.

> > +                       for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
> > +                               struct clk *c = clk[data->clk_id[j]];
> >
> > -                       if (IS_ERR(c)) {
> > -                               dev_err(&pdev->dev, "%s: clk unavailable\n",
> > -                                       data->name);
> > -                               return ERR_CAST(c);
> > -                       }
> > +                               if (IS_ERR(c)) {
> > +                                       dev_err(&pdev->dev,
> > +                                               "%s: clk unavailable\n",
> > +                                               data->name);
> > +                                       return ERR_CAST(c);
> > +                               }
> >
> > -                       scpd->clk[j] = c;
> > +                               scpd->clk[j] = c;
> > +                       }
> > +               } else if (data->basic_clk_name[0]) {
> > +                       for (j = 0; j < MAX_CLKS &&
> > +                                       data->basic_clk_name[j]; j++)
> > +                               scpd->clk[j] = devm_clk_get(&pdev->dev,
> > +                                               data->basic_clk_name[j]);
> >                 }
> >
> >                 genpd->name = data->name;
> > --
> > 2.18.0
> >



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control
  2019-03-21  5:57   ` Nicolas Boichat
@ 2019-06-19  9:43     ` Weiyi Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Weiyi Lu @ 2019-06-19  9:43 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Matthias Brugger, Rob Herring, James Liao, Fan Chen,
	linux-arm Mailing List, lkml,
	moderated list:ARM/Mediatek SoC support, srv_heupstream

On Thu, 2019-03-21 at 13:57 +0800, Nicolas Boichat wrote:
> On Tue, Mar 19, 2019 at 4:02 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Both MT8183 & MT6765 have more control steps of bus protection
> > than previous project. And there add more bus protection registers
> > reside at infracfg & smi-common. Also add new APIs for multiple
> > step bus protection control with more customize arguments.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >  drivers/soc/mediatek/Makefile           |  2 +-
> >  drivers/soc/mediatek/mtk-scpsys-ext.c   | 99 +++++++++++++++++++++++++
> >  drivers/soc/mediatek/mtk-scpsys.c       | 24 ++++++
> >  include/linux/soc/mediatek/scpsys-ext.h | 39 ++++++++++
> >  4 files changed, 163 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
> >  create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
> >
> > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> > index 64ce5eeaba32..b9dbad6b12f9 100644
> > --- a/drivers/soc/mediatek/Makefile
> > +++ b/drivers/soc/mediatek/Makefile
> > @@ -1,4 +1,4 @@
> >  obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
> > -obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> > +obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
> >  obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
> >  obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> > diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
> > new file mode 100644
> > index 000000000000..f630edb2f65d
> > --- /dev/null
> > +++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
> > @@ -0,0 +1,99 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 MediaTek Inc.
> > + * Author: Owen Chen <Owen.Chen@mediatek.com>
> > + */
> > +#include <linux/ktime.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/soc/mediatek/scpsys-ext.h>
> > +
> > +#define MTK_POLL_DELAY_US   10
> > +#define MTK_POLL_TIMEOUT    USEC_PER_SEC
> > +
> > +static int set_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
> > +               u32 reg_set, u32 reg_sta, u32 reg_en)
> > +{
> > +       u32 val;
> > +
> > +       if (reg_set)
> > +               regmap_write(map, reg_set, mask);
> > +       else
> > +               regmap_update_bits(map, reg_en, mask, mask);
> > +
> > +       return regmap_read_poll_timeout(map, reg_sta,
> > +                       val, (val & ack_mask) == ack_mask,
> > +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > +}
> > +
> > +static int clear_bus_protection(struct regmap *map, u32 mask, u32 ack_mask,
> > +               u32 reg_clr, u32 reg_sta, u32 reg_en)
> > +{
> > +       u32 val;
> > +
> > +       if (reg_clr)
> > +               regmap_write(map, reg_clr, mask);
> > +       else
> > +               regmap_update_bits(map, reg_en, mask, 0);
> > +
> > +       return regmap_read_poll_timeout(map, reg_sta,
> > +                       val, !(val & ack_mask),
> > +                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > +}
> > +
> > +int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
> > +       struct regmap *infracfg, struct regmap *smi_common)
> > +{
> > +       int i;
> > +
> > +       for (i = 0; i < MAX_STEPS && bp_table[i].mask; i++) {
> > +               struct regmap *map;
> > +               int ret;
> > +
> > +               if (bp_table[i].type == IFR_TYPE)
> > +                       map = infracfg;
> > +               else if (bp_table[i].type == SMI_TYPE)
> > +                       map = smi_common;
> > +               else
> > +                       return -EINVAL;
> > +
> > +               ret = set_bus_protection(map,
> > +                               bp_table[i].mask, bp_table[i].mask,
> > +                               bp_table[i].set_ofs, bp_table[i].sta_ofs,
> > +                               bp_table[i].en_ofs);
> > +
> > +               if (ret)
> > +                       return ret;
> 
> Should you undo the rest of the operations and clear bus protection on
> the ones that were already enabled?
> 

Actually we assume all bus protection operations need to be done
successfully, undo might not be a very useful error handling here. But
I'll consider it carefully.


> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
> > +       struct regmap *infracfg, struct regmap *smi_common)
> > +{
> > +       int i;
> > +
> > +       for (i = MAX_STEPS - 1; i >= 0; i--) {
> 
> So when you set protection, you stop at the first bp_table[i].mask ==
> 0, but when you clear it, you call clear_bus_protection for those, as
> well. You should just skip over the ones when bp_table[i].mask == 0?
> 
> e.g.
> if (!bp_table[i].mask)
>    continue;
> 

I'll use the idea of INVALID_TYPE = 0 to fix.

> > +               struct regmap *map;
> > +               int ret;
> > +
> > +               if (bp_table[i].type == IFR_TYPE)
> > +                       map = infracfg;
> > +               else if (bp_table[i].type == SMI_TYPE)
> > +                       map = smi_common;
> > +               else
> > +                       return -EINVAL;
> > +
> > +               ret = clear_bus_protection(map,
> > +                               bp_table[i].mask, bp_table[i].clr_ack_mask,
> > +                               bp_table[i].clr_ofs, bp_table[i].sta_ofs,
> > +                               bp_table[i].en_ofs);
> > +
> > +               if (ret)
> > +                       return ret;
> 
> Similar question, is it ok to just abort? Or should you try to clear
> the protection on all others, too?
> 
> > +       }
> > +
> > +       return 0;
> > +}
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index c6360de4e41e..181bf7bce591 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/pm_domain.h>
> >  #include <linux/regulator/consumer.h>
> >  #include <linux/soc/mediatek/infracfg.h>
> > +#include <linux/soc/mediatek/scpsys-ext.h>
> >
> >  #include <dt-bindings/power/mt2701-power.h>
> >  #include <dt-bindings/power/mt2712-power.h>
> > @@ -121,6 +122,7 @@ static const char * const clk_names[] = {
> >   * @basic_clk_name: provide the same purpose with field "clk_id"
> >   *                  by declaring basic clock prefix name rather than clk_id.
> >   * @caps: The flag for active wake-up action.
> > + * @bp_table: The mask table for multiple step bus protection.
> >   */
> >  struct scp_domain_data {
> >         const char *name;
> > @@ -132,6 +134,7 @@ struct scp_domain_data {
> >         enum clk_id clk_id[MAX_CLKS];
> >         const char *basic_clk_name[MAX_CLKS];
> >         u8 caps;
> > +       struct bus_prot bp_table[MAX_STEPS];
> >  };
> >
> >  struct scp;
> > @@ -155,6 +158,7 @@ struct scp {
> >         struct device *dev;
> >         void __iomem *base;
> >         struct regmap *infracfg;
> > +       struct regmap *smi_common;
> >         struct scp_ctrl_reg ctrl_reg;
> >         bool bus_prot_reg_update;
> >  };
> > @@ -291,6 +295,10 @@ static int scpsys_bus_protect_enable(struct scp_domain *scpd)
> >                 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> >                                 scpd->data->bus_prot_mask,
> >                                 scp->bus_prot_reg_update);
> > +       } else if (scpd->data->bp_table[0].mask) {
> > +               ret = mtk_scpsys_ext_set_bus_protection(scpd->data->bp_table,
> > +                               scp->infracfg,
> > +                               scp->smi_common);
> >         }
> >
> >         return ret;
> > @@ -305,6 +313,11 @@ static int scpsys_bus_protect_disable(struct scp_domain *scpd)
> >                 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> >                                 scpd->data->bus_prot_mask,
> >                                 scp->bus_prot_reg_update);
> > +       } else if (scpd->data->bp_table[0].mask) {
> > +               ret = mtk_scpsys_ext_clear_bus_protection(
> > +                               scpd->data->bp_table,
> > +                               scp->infracfg,
> > +                               scp->smi_common);
> >         }
> >
> >         return ret;
> > @@ -475,6 +488,17 @@ static struct scp *init_scp(struct platform_device *pdev,
> >                 return ERR_CAST(scp->infracfg);
> >         }
> >
> > +       scp->smi_common = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> > +                       "smi_comm");
> > +
> > +       if (scp->smi_common == ERR_PTR(-ENODEV)) {
> > +               scp->smi_common = NULL;
> > +       } else if (IS_ERR(scp->smi_common)) {
> > +               dev_err(&pdev->dev, "Cannot find smi_common controller: %ld\n",
> > +                               PTR_ERR(scp->smi_common));
> > +               return ERR_CAST(scp->smi_common);
> > +       }
> > +
> >         for (i = 0; i < num; i++) {
> >                 struct scp_domain *scpd = &scp->domains[i];
> >                 const struct scp_domain_data *data = &scp_domain_data[i];
> > diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
> > new file mode 100644
> > index 000000000000..d0ed295c88a7
> > --- /dev/null
> > +++ b/include/linux/soc/mediatek/scpsys-ext.h
> > @@ -0,0 +1,39 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
> > +#define __SOC_MEDIATEK_SCPSYS_EXT_H
> > +
> > +#define MAX_STEPS      4
> > +
> > +#define BUS_PROT(_type, _set_ofs, _clr_ofs,                    \
> > +               _en_ofs, _sta_ofs, _mask, _clr_ack_mask) {      \
> > +               .type = _type,                                  \
> > +               .set_ofs = _set_ofs,                            \
> > +               .clr_ofs = _clr_ofs,                            \
> > +               .en_ofs = _en_ofs,                              \
> > +               .sta_ofs = _sta_ofs,                            \
> > +               .mask = _mask,                                  \
> > +               .clr_ack_mask = _clr_ack_mask,                  \
> > +       }
> > +
> > +enum regmap_type {
> 
> Maybe add INVALID_TYPE = 0, so that you can skip over those when
> looping over them, instead of checking if mask is 0?
> 

Thanks for advise. I'll use it in next version.

> > +       IFR_TYPE,
> > +       SMI_TYPE,
> > +       MAX_REGMAP_TYPE,
> 
> This is not used, right? Do you really need it?
> 

I'll remove it.

> > +};
> > +
> > +struct bus_prot {
> > +       enum regmap_type type;
> > +       u32 set_ofs;
> > +       u32 clr_ofs;
> > +       u32 en_ofs;
> > +       u32 sta_ofs;
> > +       u32 mask;
> > +       u32 clr_ack_mask;
> > +};
> > +
> > +int mtk_scpsys_ext_set_bus_protection(const struct bus_prot *bp_table,
> > +       struct regmap *infracfg, struct regmap *smi_common);
> > +int mtk_scpsys_ext_clear_bus_protection(const struct bus_prot *bp_table,
> > +       struct regmap *infracfg, struct regmap *smi_common);
> > +
> > +#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
> > --
> > 2.18.0
> >



^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2019-06-19  9:43 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-19  8:01 [PATCH v5 00/14] Mediatek MT8183 scpsys support Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 01/14] dt-bindings: mediatek: Add property to mt8183 smi-common Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 02/14] dt-bindings: soc: Add MT8183 power dt-bindings Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 03/14] soc: mediatek: Switch to SPDX license identifier Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 04/14] soc: mediatek: Refactor polling timeout and documentation Weiyi Lu
2019-03-19 11:45   ` Nicolas Boichat
2019-06-19  9:11     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 05/14] soc: mediatek: Refactor regulator control Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 06/14] soc: mediatek: Refactor clock control Weiyi Lu
2019-03-19 12:02   ` Nicolas Boichat
2019-06-19  9:19     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 07/14] soc: mediatek: Refactor sram control Weiyi Lu
2019-03-19 12:07   ` Nicolas Boichat
2019-06-19  9:30     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 08/14] soc: mediatek: Refactor bus protection control Weiyi Lu
2019-03-19 12:09   ` Nicolas Boichat
2019-06-19  9:31     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 09/14] soc: mediatek: Add basic_clk_name to scp_power_data Weiyi Lu
2019-03-21  6:02   ` Nicolas Boichat
2019-06-19  9:36     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 10/14] soc: mediatek: Add multiple step bus protection control Weiyi Lu
2019-03-21  5:57   ` Nicolas Boichat
2019-06-19  9:43     ` Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 11/14] soc: mediatek: Add subsys clock control for bus protection Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 12/14] soc: mediatek: Add extra sram control Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 13/14] soc: mediatek: Add MT8183 scpsys support Weiyi Lu
2019-03-19  8:01 ` [PATCH v5 14/14] arm64: dts: Add power controller device node of MT8183 Weiyi Lu

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).