Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys
@ 2019-04-30  8:50 Henry Chen
  2019-04-30  8:50 ` [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings Henry Chen
                   ` (10 more replies)
  0 siblings, 11 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Fan Chen,
	devicetree, linux-mediatek, linux-arm-kernel

The patchsets add support for MediaTek hardware module named DVFSRC
(dynamic voltage and frequency scaling resource collector). The DVFSRC is
a HW module which is used to collect all the requests from both software
and hardware and turn into the decision of minimum operating voltage and
minimum DRAM frequency to fulfill those requests.

So, This series is to implement the dvfsrc driver to collect all the
requests of operating voltage or DRAM bandwidth from other device drivers
likes GPU/Camera through 2 frameworks basically:

1. interconnect framework: to aggregate the bandwidth
   requirements from different clients

[1] https://patchwork.kernel.org/cover/10766329/

Below is the emi bandwidth map of mt8183. There has a hw module "DRAM scheduler"
which used to control the throughput. The DVFSRC will collect forecast data
of dram bandwidth from SW consumers(camera/gpu...), and according the forecast
to change the DRAM frequency

           ICC provider         ICC Nodes
                            ----          ----
           ---------       |CPU |   |--->|VPU |
  -----   |         |-----> ----    |     ----
 |DRAM |--|DRAM     |       ----    |     ----
 |     |--|scheduler|----->|GPU |   |--->|DISP|
 |     |--|(EMI)    |       ----    |     ----
 |     |--|         |       -----   |     ----
  -----   |         |----->|MMSYS|--|--->|VDEC|
           ---------        -----   |     ----
             /|\                    |     ----
              |change DRAM freq     |--->|VENC|
           ----------               |     ----
          |  DVFSR   |              |
          |          |              |     ----
           ----------               |--->|IMG |
                                    |     ----
                                    |     ----
                                    |--->|CAM |
                                          ----

2. Active state management of power domains[1]: to handle the operating
   voltage opp requirement from different power domains

[2] https://lwn.net/Articles/744047/

Changes in RFC V2:
* Remove the DT property dram_type. (Rob)
* Used generic dts property 'opp-level' to get the performace state. (Stephen)
* Remove unecessary dependency config on Kconfig. (Stephen)
* Remove unused header file, fixed some coding style issue, typo,
error handling on dvfsrc driver. (Nicolas/Stephen)
* Remove irq handler on dvfsrc driver. (Stephen)
* Remove init table on dvfsrc driver, combine hw init on trustzone.
* Add interconnect support of mt8183 to aggregate the emi bandwidth.
(Georgi)

RFC V1: https://lore.kernel.org/patchwork/cover/1028535/

Henry Chen (11):
  dt-bindings: soc: Add dvfsrc driver bindings
  dt-bindings: soc: Add opp table on scpsys bindings
  soc: mediatek: add support for the performance state
  arm64: dts: mt8183: add performance state support of scpsys
  soc: mediatek: add header for mediatek SIP interface
  soc: mediatek: add MT8183 dvfsrc support
  arm64: dts: mt8183: add dvfsrc related nodes
  dt-bindings: interconnect: add MT8183 interconnect dt-bindings
  dt-bindings: interconnect: Add header for interconnect node
  interconnect: mediatek: Add mt8183 interconnect provider driver
  arm64: dts: mt8183: Add interconnect provider DT nodes

 .../bindings/interconnect/mtk,mt8183.txt           |  24 ++
 .../devicetree/bindings/soc/mediatek/dvfsrc.txt    |  23 ++
 .../devicetree/bindings/soc/mediatek/scpsys.txt    |  42 +++
 arch/arm64/boot/dts/mediatek/mt8183.dtsi           |  33 ++
 drivers/interconnect/Kconfig                       |   1 +
 drivers/interconnect/Makefile                      |   1 +
 drivers/interconnect/mediatek/Kconfig              |  13 +
 drivers/interconnect/mediatek/Makefile             |   5 +
 drivers/interconnect/mediatek/mt8183.c             | 223 +++++++++++++
 drivers/soc/mediatek/Kconfig                       |  15 +
 drivers/soc/mediatek/Makefile                      |   1 +
 drivers/soc/mediatek/mtk-dvfsrc.c                  | 347 +++++++++++++++++++++
 drivers/soc/mediatek/mtk-scpsys.c                  |  53 ++++
 drivers/soc/mediatek/mtk-scpsys.h                  |  22 ++
 include/dt-bindings/interconnect/mtk,mt8183.h      |  18 ++
 include/dt-bindings/soc/mtk,dvfsrc.h               |  14 +
 include/soc/mediatek/mtk_dvfsrc.h                  |  22 ++
 include/soc/mediatek/mtk_sip.h                     |  17 +
 18 files changed, 874 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt
 create mode 100644 drivers/interconnect/mediatek/Kconfig
 create mode 100644 drivers/interconnect/mediatek/Makefile
 create mode 100644 drivers/interconnect/mediatek/mt8183.c
 create mode 100644 drivers/soc/mediatek/mtk-dvfsrc.c
 create mode 100644 drivers/soc/mediatek/mtk-scpsys.h
 create mode 100644 include/dt-bindings/interconnect/mtk,mt8183.h
 create mode 100644 include/dt-bindings/soc/mtk,dvfsrc.h
 create mode 100644 include/soc/mediatek/mtk_dvfsrc.h
 create mode 100644 include/soc/mediatek/mtk_sip.h

-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
@ 2019-04-30  8:50 ` Henry Chen
  2019-05-01 20:25   ` Rob Herring
  2019-04-30  8:50 ` [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings Henry Chen
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Document the binding for enabling dvfsrc on MediaTek SoC.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/dvfsrc.txt    | 23 ++++++++++++++++++++++
 include/dt-bindings/soc/mtk,dvfsrc.h               | 14 +++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt
 create mode 100644 include/dt-bindings/soc/mtk,dvfsrc.h

diff --git a/Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt b/Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt
new file mode 100644
index 0000000..7f43499
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt
@@ -0,0 +1,23 @@
+MediaTek DVFSRC
+
+The Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC) is a
+HW module which is used to collect all the requests from both software and
+hardware and turn into the decision of minimum operating voltage and minimum
+DRAM frequency to fulfill those requests.
+
+Required Properties:
+- compatible: Should be one of the following
+	- "mediatek,mt8183-dvfsrc": For MT8183 SoC
+- reg: Address range of the DVFSRC unit
+- clock-names: Must include the following entries:
+	"dvfsrc": DVFSRC module clock
+- clocks: Must contain an entry for each entry in clock-names.
+
+Example:
+
+	dvfsrc@10012000 {
+		compatible = "mediatek,mt8183-dvfsrc";
+		reg = <0 0x10012000 0 0x1000>;
+		clocks = <&infracfg CLK_INFRA_DVFSRC>;
+		clock-names = "dvfsrc";
+	};
diff --git a/include/dt-bindings/soc/mtk,dvfsrc.h b/include/dt-bindings/soc/mtk,dvfsrc.h
new file mode 100644
index 0000000..a522488
--- /dev/null
+++ b/include/dt-bindings/soc/mtk,dvfsrc.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_POWER_MTK_DVFSRC_H
+#define _DT_BINDINGS_POWER_MTK_DVFSRC_H
+
+#define MT8183_DVFSRC_LEVEL_1	1
+#define MT8183_DVFSRC_LEVEL_2	2
+#define MT8183_DVFSRC_LEVEL_3	3
+#define MT8183_DVFSRC_LEVEL_4	4
+
+#endif /* _DT_BINDINGS_POWER_MTK_DVFSRC_H */
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
  2019-04-30  8:50 ` [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings Henry Chen
@ 2019-04-30  8:50 ` Henry Chen
  2019-05-01 20:26   ` Rob Herring
  2019-04-30  8:50 ` [RFC V2 03/11] soc: mediatek: add support for the performance state Henry Chen
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add opp table on scpsys dt-bindings for Mediatek SoC.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/scpsys.txt    | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index b4728ce..33df802 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -63,6 +63,10 @@ Optional properties:
 - mfg_2d-supply: Power supply for the mfg_2d power domain
 - mfg-supply: Power supply for the mfg power domain
 
+- operating-points-v2: Phandle to the OPP table for the Power domain.
+	Refer to Documentation/devicetree/bindings/power/power_domain.txt
+	and Documentation/devicetree/bindings/opp/opp.txt for more details
+
 Example:
 
 	scpsys: scpsys@10006000 {
@@ -75,6 +79,27 @@ Example:
 			 <&topckgen CLK_TOP_VENC_SEL>,
 			 <&topckgen CLK_TOP_VENC_LT_SEL>;
 		clock-names = "mfg", "mm", "venc", "venc_lt";
+		operating-points-v2 = <&dvfsrc_opp_table>;
+
+		dvfsrc_opp_table: opp-table {
+			compatible = "operating-points-v2-level";
+
+			dvfsrc_vol_min: opp1 {
+				opp,level = <MT8183_DVFSRC_LEVEL_1>;
+			};
+
+			dvfsrc_freq_medium: opp2 {
+				opp,level = <MT8183_DVFSRC_LEVEL_2>;
+			};
+
+			dvfsrc_freq_max: opp3 {
+				opp,level = <MT8183_DVFSRC_LEVEL_3>;
+			};
+
+			dvfsrc_vol_max: opp4 {
+				opp,level = <MT8183_DVFSRC_LEVEL_4>;
+			};
+		};
 	};
 
 Example consumer:
@@ -82,4 +107,21 @@ Example consumer:
 	afe: mt8173-afe-pcm@11220000 {
 		compatible = "mediatek,mt8173-afe-pcm";
 		power-domains = <&scpsys MT8173_POWER_DOMAIN_AUDIO>;
+		operating-points-v2 = <&aud_opp_table>;
+	};
+
+	aud_opp_table: aud-opp-table {
+		compatible = "operating-points-v2";
+		opp1 {
+			opp-hz = /bits/ 64 <793000000>;
+			required-opps = <&dvfsrc_vol_min>;
+		};
+		opp2 {
+			opp-hz = /bits/ 64 <910000000>;
+			required-opps = <&dvfsrc_vol_max>;
+		};
+		opp3 {
+			opp-hz = /bits/ 64 <1014000000>;
+			required-opps = <&dvfsrc_vol_max>;
+		};
 	};
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 03/11] soc: mediatek: add support for the performance state
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
  2019-04-30  8:50 ` [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings Henry Chen
  2019-04-30  8:50 ` [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings Henry Chen
@ 2019-04-30  8:50 ` Henry Chen
  2019-04-30  8:50 ` [RFC V2 04/11] arm64: dts: mt8183: add performance state support of scpsys Henry Chen
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Support power domain performance state, add header file for scp event.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 53 +++++++++++++++++++++++++++++++++++++++
 drivers/soc/mediatek/mtk-scpsys.h | 22 ++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-scpsys.h

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index f1d82cd..be8c948 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -10,7 +10,9 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_opp.h>
 #include <linux/regulator/consumer.h>
+#include <linux/slab.h>
 #include <linux/soc/mediatek/infracfg.h>
 #include <linux/soc/mediatek/scpsys-ext.h>
 
@@ -21,6 +23,7 @@
 #include <dt-bindings/power/mt7623a-power.h>
 #include <dt-bindings/power/mt8173-power.h>
 #include <dt-bindings/power/mt8183-power.h>
+#include "mtk-scpsys.h"
 
 #define MTK_POLL_DELAY_US   10
 #define MTK_POLL_TIMEOUT    USEC_PER_SEC
@@ -188,6 +191,18 @@ struct scp_soc_data {
 	bool bus_prot_reg_update;
 };
 
+static BLOCKING_NOTIFIER_HEAD(scpsys_notifier_list);
+
+int register_scpsys_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&scpsys_notifier_list, nb);
+}
+
+int unregister_scpsys_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&scpsys_notifier_list, nb);
+}
+
 static int scpsys_domain_is_on(struct scp_domain *scpd)
 {
 	struct scp *scp = scpd->scp;
@@ -519,6 +534,41 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
 		clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
 }
 
+static int mtk_pd_set_performance(struct generic_pm_domain *genpd,
+				  unsigned int state)
+{
+	int i;
+	struct scp_domain *scpd =
+		container_of(genpd, struct scp_domain, genpd);
+	struct scp_event_data scpe;
+	struct scp *scp = scpd->scp;
+	struct genpd_onecell_data *pd_data = &scp->pd_data;
+
+	for (i = 0; i < pd_data->num_domains; i++) {
+		if (genpd == pd_data->domains[i]) {
+			dev_dbg(scp->dev, "%d. %s = %d\n",
+				i, genpd->name, state);
+			break;
+		}
+	}
+
+	if (i == pd_data->num_domains)
+		return 0;
+
+	scpe.event_type = MTK_SCPSYS_PSTATE;
+	scpe.genpd = genpd;
+	scpe.domain_id = i;
+	blocking_notifier_call_chain(&scpsys_notifier_list, state, &scpe);
+
+	return 0;
+}
+
+static unsigned int mtk_pd_get_performance(struct generic_pm_domain *genpd,
+					   struct dev_pm_opp *opp)
+{
+	return dev_pm_opp_get_level(opp);
+}
+
 static struct scp *init_scp(struct platform_device *pdev,
 			const struct scp_domain_data *scp_domain_data, int num,
 			const struct scp_ctrl_reg *scp_ctrl_reg,
@@ -642,6 +692,9 @@ static struct scp *init_scp(struct platform_device *pdev,
 		genpd->power_on = scpsys_power_on;
 		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
 			genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+
+		genpd->set_performance_state = mtk_pd_set_performance;
+		genpd->opp_to_performance_state = mtk_pd_get_performance;
 	}
 
 	return scp;
diff --git a/drivers/soc/mediatek/mtk-scpsys.h b/drivers/soc/mediatek/mtk-scpsys.h
new file mode 100644
index 0000000..c1e8325
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-scpsys.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef __MTK_SCPSYS_H__
+#define __MTK_SCPSYS_H__
+
+struct scp_event_data {
+	int event_type;
+	int domain_id;
+	struct generic_pm_domain *genpd;
+};
+
+enum scp_event_type {
+	MTK_SCPSYS_PSTATE,
+};
+
+int register_scpsys_notifier(struct notifier_block *nb);
+int unregister_scpsys_notifier(struct notifier_block *nb);
+
+#endif /* __MTK_SCPSYS_H__ */
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 04/11] arm64: dts: mt8183: add performance state support of scpsys
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (2 preceding siblings ...)
  2019-04-30  8:50 ` [RFC V2 03/11] soc: mediatek: add support for the performance state Henry Chen
@ 2019-04-30  8:50 ` Henry Chen
  2019-04-30  8:50 ` [RFC V2 05/11] soc: mediatek: add header for mediatek SIP interface Henry Chen
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add support for performance state of scpsys on mt8183 platform.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 75c4881..665d561 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -9,6 +9,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/power/mt8183-power.h>
+#include <dt-bindings/soc/mtk,dvfsrc.h>
 
 / {
 	compatible = "mediatek,mt8183";
@@ -251,6 +252,26 @@
 				      "vpu-3", "vpu-4", "vpu-5";
 			infracfg = <&infracfg>;
 			smi_comm = <&smi_common>;
+			operating-points-v2 = <&dvfsrc_opp_table>;
+			dvfsrc_opp_table: opp-table {
+				compatible = "operating-points-v2-level";
+
+				dvfsrc_vol_min: opp1 {
+					opp,level = <MT8183_DVFSRC_LEVEL_1>;
+				};
+
+				dvfsrc_freq_medium: opp2 {
+					opp,level = <MT8183_DVFSRC_LEVEL_2>;
+				};
+
+				dvfsrc_freq_max: opp3 {
+					opp,level = <MT8183_DVFSRC_LEVEL_3>;
+				};
+
+				dvfsrc_vol_max: opp4 {
+					opp,level = <MT8183_DVFSRC_LEVEL_4>;
+				};
+			};
 		};
 
 		apmixedsys: syscon@1000c000 {
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 05/11] soc: mediatek: add header for mediatek SIP interface
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (3 preceding siblings ...)
  2019-04-30  8:50 ` [RFC V2 04/11] arm64: dts: mt8183: add performance state support of scpsys Henry Chen
@ 2019-04-30  8:50 ` Henry Chen
  2019-04-30  8:51 ` [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support Henry Chen
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:50 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add a header to collect SIPs and add one SIP call to initialize power
management hardware for the SIP interface defined to access the SPM
handling vcore voltage and ddr rate changes on mt8183 (and most likely
later socs).

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 include/soc/mediatek/mtk_sip.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 include/soc/mediatek/mtk_sip.h

diff --git a/include/soc/mediatek/mtk_sip.h b/include/soc/mediatek/mtk_sip.h
new file mode 100644
index 0000000..5394ff4
--- /dev/null
+++ b/include/soc/mediatek/mtk_sip.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+#ifndef __SOC_MTK_SIP_H
+#define __SOC_MTK_SIP_H
+
+#ifdef CONFIG_ARM64
+#define MTK_SIP_SMC_AARCH_BIT		0x40000000
+#else
+#define MTK_SIP_SMC_AARCH_BIT		0x00000000
+#endif
+
+#define MTK_SIP_SPM			(0x82000220 | MTK_SIP_SMC_AARCH_BIT)
+#define MTK_SIP_SPM_DVFSRC_INIT		0x00
+
+#endif
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (4 preceding siblings ...)
  2019-04-30  8:50 ` [RFC V2 05/11] soc: mediatek: add header for mediatek SIP interface Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  2019-06-10 21:00   ` Ryan Case
  2019-04-30  8:51 ` [RFC V2 07/11] arm64: dts: mt8183: add dvfsrc related nodes Henry Chen
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add dvfsrc driver for MT8183

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 drivers/soc/mediatek/Kconfig      |  15 ++
 drivers/soc/mediatek/Makefile     |   1 +
 drivers/soc/mediatek/mtk-dvfsrc.c | 347 ++++++++++++++++++++++++++++++++++++++
 include/soc/mediatek/mtk_dvfsrc.h |  22 +++
 4 files changed, 385 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-dvfsrc.c
 create mode 100644 include/soc/mediatek/mtk_dvfsrc.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 17bd759..2721fd6 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -24,6 +24,21 @@ config MTK_INFRACFG
 	  INFRACFG controller contains various infrastructure registers not
 	  directly associated to any device.
 
+config MTK_DVFSRC
+	bool "MediaTek DVFSRC Support"
+	depends on ARCH_MEDIATEK
+	default ARCH_MEDIATEK
+	select MTK_INFRACFG
+	select PM_GENERIC_DOMAINS if PM
+	depends on MTK_SCPSYS
+	help
+	  Say yes here to add support for the MediaTek DVFSRC (dynamic voltage
+	  and frequency scaling resource collector) found
+	  on different MediaTek SoCs. The DVFSRC is a proprietary
+	  hardware which is used to collect all the requests from
+	  system and turn into the decision of minimum Vcore voltage
+	  and minimum DRAM frequency to fulfill those requests.
+
 config MTK_PMIC_WRAP
 	tristate "MediaTek PMIC Wrapper Support"
 	depends on RESET_CONTROLLER
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index b9dbad6..cd9d63f 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
+obj-$(CONFIG_MTK_DVFSRC) += mtk-dvfsrc.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-dvfsrc.c b/drivers/soc/mediatek/mtk-dvfsrc.c
new file mode 100644
index 0000000..e54a654
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-dvfsrc.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <soc/mediatek/mtk_dvfsrc.h>
+#include <soc/mediatek/mtk_sip.h>
+#include <dt-bindings/power/mt8183-power.h>
+#include <dt-bindings/soc/mtk,dvfsrc.h>
+#include <dt-bindings/soc/mtk,dvfsrc.h>
+#include "mtk-scpsys.h"
+
+#define DVFSRC_IDLE		0x00
+#define DVFSRC_GET_TARGET_LEVEL(x)	(((x) >> 0) & 0x0000ffff)
+#define DVFSRC_GET_CURRENT_LEVEL(x)	(((x) >> 16) & 0x0000ffff)
+
+#define MT8183_DVFSRC_OPP_LP4	0
+#define MT8183_DVFSRC_OPP_LP4X	1
+#define MT8183_DVFSRC_OPP_LP3	2
+
+struct dvfsrc_opp {
+	u32 vcore_opp;
+	u32 dram_opp;
+};
+
+struct dvfsrc_domain {
+	u32 id;
+	u32 state;
+};
+
+struct mtk_dvfsrc;
+struct dvfsrc_soc_data {
+	const int *regs;
+	u32 num_opp;
+	u32 num_domains;
+	const struct dvfsrc_opp **opps;
+	struct dvfsrc_domain *domains;
+	int (*get_target_level)(struct mtk_dvfsrc *dvfsrc);
+	int (*get_current_level)(struct mtk_dvfsrc *dvfsrc);
+	void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
+	void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+};
+
+struct mtk_dvfsrc {
+	struct device *dev;
+	struct clk *clk_dvfsrc;
+	const struct dvfsrc_soc_data *dvd;
+	int dram_type;
+	void __iomem *regs;
+	struct mutex lock;
+	struct notifier_block scpsys_notifier;
+};
+
+static u32 dvfsrc_read(struct mtk_dvfsrc *dvfs, u32 offset)
+{
+	return readl(dvfs->regs + dvfs->dvd->regs[offset]);
+}
+
+static void dvfsrc_write(struct mtk_dvfsrc *dvfs, u32 offset, u32 val)
+{
+	writel(val, dvfs->regs + dvfs->dvd->regs[offset]);
+}
+
+enum dvfsrc_regs {
+	DVFSRC_SW_REQ,
+	DVFSRC_LEVEL,
+	DVFSRC_SW_BW_0,
+	DVFSRC_LAST,
+};
+
+static const int mt8183_regs[] = {
+	[DVFSRC_SW_REQ] =	0x4,
+	[DVFSRC_LEVEL] =	0xDC,
+	[DVFSRC_SW_BW_0] =	0x160,
+	[DVFSRC_LAST] =		0x308,
+};
+
+static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc)
+{
+	if (!dvfsrc->dvd->get_target_level)
+		return true;
+
+	return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_IDLE;
+}
+
+static int dvfsrc_wait_for_idle(struct mtk_dvfsrc *dvfsrc)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + usecs_to_jiffies(1000);
+
+	do {
+		if (dvfsrc_is_idle(dvfsrc))
+			return 0;
+	} while (!time_after(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+static int mt8183_get_target_level(struct mtk_dvfsrc *dvfsrc)
+{
+	return DVFSRC_GET_TARGET_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL));
+}
+
+static int mt8183_get_current_level(struct mtk_dvfsrc *dvfsrc)
+{
+	return ffs(DVFSRC_GET_CURRENT_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL)));
+}
+
+static void mt8183_set_dram_bw(struct mtk_dvfsrc *dvfsrc, u64 bw)
+{
+	dvfsrc_write(dvfsrc, DVFSRC_SW_BW_0, bw);
+}
+
+static void mt8183_set_opp_level(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+	int vcore_opp, dram_opp;
+	const struct dvfsrc_opp *opp;
+
+	/* translate pstate to dvfsrc level, and set it to DVFSRC HW */
+	opp = &dvfsrc->dvd->opps[dvfsrc->dram_type][level - 1];
+	vcore_opp = opp->vcore_opp;
+	dram_opp = opp->dram_opp;
+
+	dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n",
+		vcore_opp, dram_opp);
+	dvfsrc_write(dvfsrc, DVFSRC_SW_REQ, dram_opp | vcore_opp << 2);
+}
+
+void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data)
+{
+	struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev);
+
+	dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data);
+
+	mutex_lock(&dvfsrc->lock);
+
+	if (dvfsrc_wait_for_idle(dvfsrc)) {
+		dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
+			 __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
+		dvfsrc_read(dvfsrc, DVFSRC_LAST));
+		goto out;
+	}
+
+	switch (cmd) {
+	case MTK_DVFSRC_CMD_BW_REQUEST:
+		dvfsrc->dvd->set_dram_bw(dvfsrc, data);
+		goto out;
+	case MTK_DVFSRC_CMD_OPP_REQUEST:
+		dvfsrc->dvd->set_opp_level(dvfsrc, data);
+		break;
+	default:
+		dev_err(dvfsrc->dev, "unknown command: %d\n", cmd);
+		break;
+	}
+
+	if (dvfsrc_wait_for_idle(dvfsrc)) {
+		dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
+			 __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
+			 dvfsrc_read(dvfsrc, DVFSRC_LAST));
+		goto out;
+	}
+
+out:
+	mutex_unlock(&dvfsrc->lock);
+}
+EXPORT_SYMBOL(mtk_dvfsrc_send_request);
+
+static int dvfsrc_set_performance(struct notifier_block *b,
+				  unsigned long l, void *v)
+{
+	int i, val, highest;
+	struct mtk_dvfsrc *dvfsrc;
+	struct scp_event_data *sc = v;
+	struct dvfsrc_domain *d;
+
+	if (sc->event_type != MTK_SCPSYS_PSTATE)
+		return 0;
+
+	dvfsrc = container_of(b, struct mtk_dvfsrc, scpsys_notifier);
+
+	d = dvfsrc->dvd->domains;
+
+	if (l > dvfsrc->dvd->num_opp) {
+		dev_err(dvfsrc->dev, "pstate out of range = %ld\n", l);
+		goto out;
+	}
+
+	for (i = 0, highest = 0; i < dvfsrc->dvd->num_domains - 1; i++, d++) {
+		if (sc->domain_id == d->id)
+			d->state = l;
+		if (d->state > highest)
+			highest = d->state;
+	}
+
+	if (highest == 0) {
+		dev_err(dvfsrc->dev, "domain not match\n");
+		goto out;
+	}
+
+	mtk_dvfsrc_send_request(dvfsrc->dev, MTK_DVFSRC_CMD_OPP_REQUEST,
+				highest);
+
+	val = dvfsrc->dvd->get_current_level(dvfsrc);
+
+	dev_dbg(dvfsrc->dev, "DVFSRC_LEVEL: %x, val: %x, DVFSRC_SW_REQ: %x\n",
+		dvfsrc_read(dvfsrc, DVFSRC_LEVEL), val,
+		dvfsrc_read(dvfsrc, DVFSRC_SW_REQ));
+
+	if (val < highest) {
+		dev_err(dvfsrc->dev, "current: %d < highest: %x\n",
+			val, highest);
+		goto out;
+	}
+
+out:
+	return 0;
+}
+
+static void pstate_notifier_register(struct mtk_dvfsrc *dvfsrc)
+{
+	dvfsrc->scpsys_notifier.notifier_call = dvfsrc_set_performance;
+	register_scpsys_notifier(&dvfsrc->scpsys_notifier);
+}
+
+static int mtk_dvfsrc_probe(struct platform_device *pdev)
+{
+	struct arm_smccc_res ares;
+	struct resource *res;
+	struct mtk_dvfsrc *dvfsrc;
+	int ret;
+
+	dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL);
+	if (!dvfsrc)
+		return -ENOMEM;
+
+	dvfsrc->dvd = of_device_get_match_data(&pdev->dev);
+	dvfsrc->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dvfsrc->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dvfsrc->regs))
+		return PTR_ERR(dvfsrc->regs);
+
+	dvfsrc->clk_dvfsrc = devm_clk_get(dvfsrc->dev, "dvfsrc");
+	if (IS_ERR(dvfsrc->clk_dvfsrc)) {
+		dev_err(dvfsrc->dev, "failed to get clock: %ld\n",
+			PTR_ERR(dvfsrc->clk_dvfsrc));
+		return PTR_ERR(dvfsrc->clk_dvfsrc);
+	}
+
+	ret = clk_prepare_enable(dvfsrc->clk_dvfsrc);
+	if (ret)
+		return ret;
+
+	mutex_init(&dvfsrc->lock);
+
+	arm_smccc_smc(MTK_SIP_SPM, MTK_SIP_SPM_DVFSRC_INIT, 0, 0, 0, 0, 0, 0,
+		      &ares);
+
+	if (!ares.a0) {
+		dvfsrc->dram_type = ares.a1;
+	} else {
+		dev_err(dvfsrc->dev, "init fails: %lu\n", ares.a0);
+		clk_disable_unprepare(dvfsrc->clk_dvfsrc);
+		return ares.a0;
+	}
+
+	platform_set_drvdata(pdev, dvfsrc);
+	pstate_notifier_register(dvfsrc);
+
+	return devm_of_platform_populate(&pdev->dev);
+}
+
+static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = {
+	{0, 0}, {0, 1}, {0, 2}, {1, 2},
+};
+
+static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = {
+	{0, 0}, {0, 1}, {1, 1}, {1, 2},
+};
+
+static const struct dvfsrc_opp *dvfsrc_opp_mt8183[] = {
+	[MT8183_DVFSRC_OPP_LP4] = dvfsrc_opp_mt8183_lp4,
+	[MT8183_DVFSRC_OPP_LP4X] = dvfsrc_opp_mt8183_lp3,
+	[MT8183_DVFSRC_OPP_LP3] = dvfsrc_opp_mt8183_lp3,
+};
+
+static struct dvfsrc_domain dvfsrc_domains_mt8183[] = {
+	{ MT8183_POWER_DOMAIN_MFG_ASYNC, 0 },
+	{ MT8183_POWER_DOMAIN_MFG, 0 },
+	{ MT8183_POWER_DOMAIN_CAM, 0 },
+	{ MT8183_POWER_DOMAIN_DISP, 0 },
+	{ MT8183_POWER_DOMAIN_ISP, 0 },
+	{ MT8183_POWER_DOMAIN_VDEC, 0 },
+	{ MT8183_POWER_DOMAIN_VENC, 0 },
+};
+
+static const struct dvfsrc_soc_data mt8183_data = {
+	.opps = dvfsrc_opp_mt8183,
+	.num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4),
+	.regs = mt8183_regs,
+	.domains = dvfsrc_domains_mt8183,
+	.num_domains = ARRAY_SIZE(dvfsrc_domains_mt8183),
+	.get_target_level = mt8183_get_target_level,
+	.get_current_level = mt8183_get_current_level,
+	.set_dram_bw = mt8183_set_dram_bw,
+	.set_opp_level = mt8183_set_opp_level,
+};
+
+static int mtk_dvfsrc_remove(struct platform_device *pdev)
+{
+	struct mtk_dvfsrc *dvfsrc = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(dvfsrc->clk_dvfsrc);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_dvfsrc_of_match[] = {
+	{
+		.compatible = "mediatek,mt8183-dvfsrc",
+		.data = &mt8183_data,
+	}, {
+		/* sentinel */
+	},
+};
+
+static struct platform_driver mtk_dvfsrc_driver = {
+	.probe	= mtk_dvfsrc_probe,
+	.remove	= mtk_dvfsrc_remove,
+	.driver = {
+		.name = "mtk-dvfsrc",
+		.of_match_table = of_match_ptr(mtk_dvfsrc_of_match),
+	},
+};
+
+builtin_platform_driver(mtk_dvfsrc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MTK DVFSRC driver");
diff --git a/include/soc/mediatek/mtk_dvfsrc.h b/include/soc/mediatek/mtk_dvfsrc.h
new file mode 100644
index 0000000..e759a65
--- /dev/null
+++ b/include/soc/mediatek/mtk_dvfsrc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+#ifndef __SOC_MTK_DVFSRC_H
+#define __SOC_MTK_DVFSRC_H
+
+#define MTK_DVFSRC_CMD_BW_REQUEST	0
+#define MTK_DVFSRC_CMD_OPP_REQUEST	1
+
+#if IS_ENABLED(CONFIG_MTK_DVFSRC)
+void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data);
+
+#else
+
+static inline void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd,
+					   u64 data)
+{ return -ENODEV; }
+
+#endif /* CONFIG_MTK_DVFSRC */
+
+#endif
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 07/11] arm64: dts: mt8183: add dvfsrc related nodes
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (5 preceding siblings ...)
  2019-04-30  8:51 ` [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  2019-04-30  8:51 ` [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings Henry Chen
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Enable dvfsrc on mt8183 platform.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 665d561..d298013 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -134,6 +134,13 @@
 		clock-output-names = "clk26m";
 	};
 
+	dvfsrc@10012000 {
+		compatible = "mediatek,mt8183-dvfsrc";
+		reg = <0 0x10012000 0 0x1000>;
+		clocks = <&infracfg CLK_INFRA_DVFSRC>;
+		clock-names = "dvfsrc";
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (6 preceding siblings ...)
  2019-04-30  8:51 ` [RFC V2 07/11] arm64: dts: mt8183: add dvfsrc related nodes Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  2019-05-01 20:27   ` Rob Herring
  2019-04-30  8:51 ` [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node Henry Chen
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add interconnect provider dt-bindings for MT8183.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 .../bindings/interconnect/mtk,mt8183.txt           | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt

diff --git a/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
new file mode 100644
index 0000000..1cf1841
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
@@ -0,0 +1,24 @@
+Mediatek MT8183 interconnect binding
+
+MT8183 interconnect providers support dram bandwidth requirements. The provider
+is able to communicate with the DVFSRC and send the dram bandwidth to it.
+Provider nodes must reside within an DVFSRC device node.
+
+Required properties :
+- compatible : shall contain only one of the following:
+			"mediatek,mt8183-emi-icc"
+- #interconnect-cells : should contain 1
+
+Examples:
+
+dvfsrc@10012000 {
+	compatible = "mediatek,mt8183-dvfsrc";
+	reg = <0 0x10012000 0 0x1000>;
+	clocks = <&infracfg CLK_INFRA_DVFSRC>;
+	clock-names = "dvfsrc";
+	ddr_emi: interconnect {
+		compatible = "mediatek,mt8183-emi-icc";
+		#interconnect-cells = <1>;
+	};
+};
+
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (7 preceding siblings ...)
  2019-04-30  8:51 ` [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  2019-05-01 20:28   ` Rob Herring
  2019-04-30  8:51 ` [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver Henry Chen
  2019-04-30  8:51 ` [RFC V2 11/11] arm64: dts: mt8183: Add interconnect provider DT nodes Henry Chen
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add header file for mt8183 interconnect node that could be shared between
the interconeect provider driver and Device Tree source files.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 include/dt-bindings/interconnect/mtk,mt8183.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 include/dt-bindings/interconnect/mtk,mt8183.h

diff --git a/include/dt-bindings/interconnect/mtk,mt8183.h b/include/dt-bindings/interconnect/mtk,mt8183.h
new file mode 100644
index 0000000..34adbfa
--- /dev/null
+++ b/include/dt-bindings/interconnect/mtk,mt8183.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_MTK_MT8183_H
+#define __DT_BINDINGS_INTERCONNECT_MTK_MT8183_H
+
+#define SLAVE_DDR_EMI			0
+#define MASTER_MCUSYS			1
+#define MASTER_GPU			2
+#define MASTER_MMSYS			3
+#define MASTER_MM_VPU			4
+#define MASTER_MM_DISP			5
+#define MASTER_MM_VDEC			6
+#define MASTER_MM_VENC			7
+#define MASTER_MM_CAM			8
+#define MASTER_MM_IMG			9
+#define MASTER_MM_MDP			10
+
+#endif
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (8 preceding siblings ...)
  2019-04-30  8:51 ` [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  2019-05-14  6:43   ` Georgi Djakov
  2019-04-30  8:51 ` [RFC V2 11/11] arm64: dts: mt8183: Add interconnect provider DT nodes Henry Chen
  10 siblings, 1 reply; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Introduce Mediatek MT8183 specific provider driver using the
interconnect framework.

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 drivers/interconnect/Kconfig           |   1 +
 drivers/interconnect/Makefile          |   1 +
 drivers/interconnect/mediatek/Kconfig  |  13 ++
 drivers/interconnect/mediatek/Makefile |   5 +
 drivers/interconnect/mediatek/mt8183.c | 223 +++++++++++++++++++++++++++++++++
 5 files changed, 243 insertions(+)
 create mode 100644 drivers/interconnect/mediatek/Kconfig
 create mode 100644 drivers/interconnect/mediatek/Makefile
 create mode 100644 drivers/interconnect/mediatek/mt8183.c

diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
index 07a8276..ac41ea6 100644
--- a/drivers/interconnect/Kconfig
+++ b/drivers/interconnect/Kconfig
@@ -11,5 +11,6 @@ menuconfig INTERCONNECT
 if INTERCONNECT
 
 source "drivers/interconnect/qcom/Kconfig"
+source "drivers/interconnect/mediatek/Kconfig"
 
 endif
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
index 28f2ab0..253f24a3 100644
--- a/drivers/interconnect/Makefile
+++ b/drivers/interconnect/Makefile
@@ -4,3 +4,4 @@ icc-core-objs				:= core.o
 
 obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
 obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
+obj-$(CONFIG_INTERCONNECT_MTK)		+= mediatek/
diff --git a/drivers/interconnect/mediatek/Kconfig b/drivers/interconnect/mediatek/Kconfig
new file mode 100644
index 0000000..0686494
--- /dev/null
+++ b/drivers/interconnect/mediatek/Kconfig
@@ -0,0 +1,13 @@
+config INTERCONNECT_MTK
+	bool "Mediatek Network-on-Chip interconnect drivers"
+	depends on ARCH_MEDIATEK
+	help
+	  Support for Mediatek's Network-on-Chip interconnect hardware.
+
+config INTERCONNECT_MTK_MT8183
+	tristate "Mediatek MT8183 interconnect driver"
+	depends on INTERCONNECT_MTK
+	depends on (MTK_DVFSRC && OF)
+	help
+	  This is a driver for the Mediatek Network-on-Chip on mt8183-based
+	  platforms.
diff --git a/drivers/interconnect/mediatek/Makefile b/drivers/interconnect/mediatek/Makefile
new file mode 100644
index 0000000..a39ceee
--- /dev/null
+++ b/drivers/interconnect/mediatek/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+mtk-mt8183-objs			:= mt8183.o
+
+obj-$(CONFIG_INTERCONNECT_MTK_MT8183) += mtk-mt8183.o
\ No newline at end of file
diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
new file mode 100644
index 0000000..38ffe0b
--- /dev/null
+++ b/drivers/interconnect/mediatek/mt8183.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <dt-bindings/interconnect/mtk,mt8183.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <soc/mediatek/mtk_dvfsrc.h>
+
+#define MT8183_MAX_LINKS	6
+
+/**
+ * struct mtk_icc_node - Mediatek specific interconnect nodes
+ * @name: the node name used in debugfs
+ * @ep: true if the node is an end point.
+ * @id: a unique node identifier
+ * @links: an array of nodes where we can go next while traversing
+ * @num_links: the total number of @links
+ * @buswidth: width of the interconnect between a node and the bus
+ * @sum_avg: current sum aggregate value of all avg bw requests
+ * @max_peak: current max aggregate value of all peak bw requests
+ */
+struct mtk_icc_node {
+	unsigned char *name;
+	bool ep;
+	u16 id;
+	u16 links[MT8183_MAX_LINKS];
+	u16 num_links;
+	u16 buswidth;
+	u64 sum_avg;
+	u64 max_peak;
+};
+
+struct mtk_icc_desc {
+	struct mtk_icc_node **nodes;
+	size_t num_nodes;
+};
+
+#define DEFINE_MNODE(_name, _id, _buswidth, _ep, _numlinks, ...)	\
+		static struct mtk_icc_node _name = {			\
+		.name = #_name,						\
+		.id = _id,						\
+		.buswidth = _buswidth,					\
+		.ep = _ep,						\
+		.num_links = _numlinks,					\
+		.links = { __VA_ARGS__ },				\
+}
+
+DEFINE_MNODE(ddr_emi, SLAVE_DDR_EMI, 1024, 1, 0, 0);
+DEFINE_MNODE(mcusys, MASTER_MCUSYS, 256, 0, 1, SLAVE_DDR_EMI);
+DEFINE_MNODE(gpu, MASTER_GPU, 256, 0, 1, SLAVE_DDR_EMI);
+DEFINE_MNODE(mmsys, MASTER_MMSYS, 256, 0, 1, SLAVE_DDR_EMI);
+DEFINE_MNODE(mm_vpu, MASTER_MM_VPU, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_disp, MASTER_MM_DISP, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_vdec, MASTER_MM_VDEC, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_venc, MASTER_MM_VENC, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_cam, MASTER_MM_CAM, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_img, MASTER_MM_IMG, 128, 0, 1, MASTER_MMSYS);
+DEFINE_MNODE(mm_mdp, MASTER_MM_MDP, 128, 0, 1, MASTER_MMSYS);
+
+static struct mtk_icc_node *mt8183_icc_nodes[] = {
+	&ddr_emi,
+	&mcusys,
+	&gpu,
+	&mmsys,
+	&mm_vpu,
+	&mm_disp,
+	&mm_vdec,
+	&mm_venc,
+	&mm_cam,
+	&mm_img,
+	&mm_mdp,
+};
+
+static struct mtk_icc_desc mt8183_icc = {
+	.nodes = mt8183_icc_nodes,
+	.num_nodes = ARRAY_SIZE(mt8183_icc_nodes),
+};
+
+static int mt8183_icc_aggregate(struct icc_node *node, u32 avg_bw,
+			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+	struct mtk_icc_node *in;
+
+	in = node->data;
+
+	*agg_avg += avg_bw;
+	*agg_peak = max_t(u32, *agg_peak, peak_bw);
+
+	in->sum_avg = *agg_avg;
+	in->max_peak = *agg_peak;
+
+	return 0;
+}
+
+static int mt8183_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	int ret = 0;
+	struct mtk_icc_node *node;
+
+	node = dst->data;
+	if (node->ep) {
+		pr_debug("sum_avg (%llu), max_peak (%llu)\n",
+			node->sum_avg, node->max_peak);
+		mtk_dvfsrc_send_request(src->provider->dev->parent,
+					MTK_DVFSRC_CMD_BW_REQUEST,
+					node->max_peak);
+	}
+
+	return ret;
+}
+
+static int mt8183_icc_probe(struct platform_device *pdev)
+{
+	int ret;
+	const struct mtk_icc_desc *desc;
+	struct icc_node *node;
+	struct icc_onecell_data *data;
+	struct icc_provider *provider;
+	struct mtk_icc_node **mnodes;
+	size_t num_nodes, i, j;
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
+	mnodes = desc->nodes;
+	num_nodes = desc->num_nodes;
+
+	provider = devm_kzalloc(&pdev->dev, sizeof(*provider), GFP_KERNEL);
+	if (!provider)
+		return -ENOMEM;
+
+	data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	provider->dev = &pdev->dev;
+	provider->set = mt8183_icc_set;
+	provider->aggregate = mt8183_icc_aggregate;
+	provider->xlate = of_icc_xlate_onecell;
+	INIT_LIST_HEAD(&provider->nodes);
+	provider->data = data;
+
+	ret = icc_provider_add(provider);
+	if (ret) {
+		dev_err(&pdev->dev, "error adding interconnect provider\n");
+		return ret;
+	}
+
+	for (i = 0; i < num_nodes; i++) {
+		node = icc_node_create(mnodes[i]->id);
+		if (IS_ERR(node)) {
+			ret = PTR_ERR(node);
+			goto err;
+		}
+
+		node->name = mnodes[i]->name;
+		node->data = mnodes[i];
+		icc_node_add(node, provider);
+
+		dev_dbg(&pdev->dev, "registered node %s, num link: %d\n",
+			mnodes[i]->name, mnodes[i]->num_links);
+
+		/* populate links */
+		for (j = 0; j < mnodes[i]->num_links; j++)
+			icc_link_create(node, mnodes[i]->links[j]);
+
+		data->nodes[i] = node;
+	}
+	data->num_nodes = num_nodes;
+
+	platform_set_drvdata(pdev, provider);
+
+	return ret;
+err:
+	list_for_each_entry(node, &provider->nodes, node_list) {
+		icc_node_del(node);
+		icc_node_destroy(node->id);
+	}
+
+	icc_provider_del(provider);
+	return ret;
+}
+
+static int mt8183_icc_remove(struct platform_device *pdev)
+{
+	struct icc_provider *provider = platform_get_drvdata(pdev);
+	struct icc_node *n;
+
+	list_for_each_entry(n, &provider->nodes, node_list) {
+		icc_node_del(n);
+		icc_node_destroy(n->id);
+	}
+
+	return icc_provider_del(provider);
+}
+
+static const struct of_device_id mt8183_icc_of_match[] = {
+	{ .compatible = "mediatek,mt8183-emi-icc", .data = &mt8183_icc },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mt8183_icc_of_match);
+
+static struct platform_driver mt8183_icc_driver = {
+	.probe = mt8183_icc_probe,
+	.remove = mt8183_icc_remove,
+	.driver = {
+		.name = "mt8183-emi-icc",
+		.of_match_table = mt8183_icc_of_match,
+	},
+};
+module_platform_driver(mt8183_icc_driver);
+
+MODULE_AUTHOR("Henry Chen <henryc.chen@mediatek.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC V2 11/11] arm64: dts: mt8183: Add interconnect provider DT nodes
  2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
                   ` (9 preceding siblings ...)
  2019-04-30  8:51 ` [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver Henry Chen
@ 2019-04-30  8:51 ` Henry Chen
  10 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-04-30  8:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Matthias Brugger, Viresh Kumar, Stephen Boyd
  Cc: James Liao, Weiyi Lu, Nicolas Boichat, linux-kernel, Henry Chen,
	Fan Chen, devicetree, linux-mediatek, linux-arm-kernel

Add DDR EMI provider dictating dram interconnect bus performance
found on MT8183-based platforms

Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index d298013..ab98adb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/power/mt8183-power.h>
 #include <dt-bindings/soc/mtk,dvfsrc.h>
+#include <dt-bindings/interconnect/mtk,mt8183.h>
 
 / {
 	compatible = "mediatek,mt8183";
@@ -139,6 +140,10 @@
 		reg = <0 0x10012000 0 0x1000>;
 		clocks = <&infracfg CLK_INFRA_DVFSRC>;
 		clock-names = "dvfsrc";
+		ddr_emi: interconnect {
+			compatible = "mediatek,mt8183-emi-icc";
+			#interconnect-cells = <1>;
+		};
 	};
 
 	timer {
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings
  2019-04-30  8:50 ` [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings Henry Chen
@ 2019-05-01 20:25   ` Rob Herring
  0 siblings, 0 replies; 22+ messages in thread
From: Rob Herring @ 2019-05-01 20:25 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Henry Chen, Stephen Boyd, Fan Chen, devicetree,
	Rob Herring, linux-mediatek, Matthias Brugger, Georgi Djakov,
	linux-arm-kernel

On Tue, 30 Apr 2019 16:50:55 +0800, Henry Chen wrote:
> Document the binding for enabling dvfsrc on MediaTek SoC.
> 
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  .../devicetree/bindings/soc/mediatek/dvfsrc.txt    | 23 ++++++++++++++++++++++
>  include/dt-bindings/soc/mtk,dvfsrc.h               | 14 +++++++++++++
>  2 files changed, 37 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/mediatek/dvfsrc.txt
>  create mode 100644 include/dt-bindings/soc/mtk,dvfsrc.h
> 

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings
  2019-04-30  8:50 ` [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings Henry Chen
@ 2019-05-01 20:26   ` Rob Herring
  0 siblings, 0 replies; 22+ messages in thread
From: Rob Herring @ 2019-05-01 20:26 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Henry Chen, Stephen Boyd, Fan Chen, devicetree,
	Rob Herring, linux-mediatek, Matthias Brugger, Georgi Djakov,
	linux-arm-kernel

On Tue, 30 Apr 2019 16:50:56 +0800, Henry Chen wrote:
> Add opp table on scpsys dt-bindings for Mediatek SoC.
> 
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  .../devicetree/bindings/soc/mediatek/scpsys.txt    | 42 ++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings
  2019-04-30  8:51 ` [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings Henry Chen
@ 2019-05-01 20:27   ` Rob Herring
  2019-08-19  1:39     ` Henry Chen
  0 siblings, 1 reply; 22+ messages in thread
From: Rob Herring @ 2019-05-01 20:27 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, linux-mediatek,
	Matthias Brugger, Georgi Djakov, linux-arm-kernel

On Tue, Apr 30, 2019 at 04:51:02PM +0800, Henry Chen wrote:
> Add interconnect provider dt-bindings for MT8183.
> 
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  .../bindings/interconnect/mtk,mt8183.txt           | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> 
> diff --git a/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> new file mode 100644
> index 0000000..1cf1841
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> @@ -0,0 +1,24 @@
> +Mediatek MT8183 interconnect binding

This should be part of the dvfsrc binding.

> +
> +MT8183 interconnect providers support dram bandwidth requirements. The provider
> +is able to communicate with the DVFSRC and send the dram bandwidth to it.
> +Provider nodes must reside within an DVFSRC device node.
> +
> +Required properties :
> +- compatible : shall contain only one of the following:
> +			"mediatek,mt8183-emi-icc"
> +- #interconnect-cells : should contain 1
> +
> +Examples:
> +
> +dvfsrc@10012000 {
> +	compatible = "mediatek,mt8183-dvfsrc";
> +	reg = <0 0x10012000 0 0x1000>;
> +	clocks = <&infracfg CLK_INFRA_DVFSRC>;
> +	clock-names = "dvfsrc";
> +	ddr_emi: interconnect {
> +		compatible = "mediatek,mt8183-emi-icc";
> +		#interconnect-cells = <1>;

No need for a child node here. Just move #interconnect-cells to the 
parent.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node
  2019-04-30  8:51 ` [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node Henry Chen
@ 2019-05-01 20:28   ` Rob Herring
  2019-08-19  1:43     ` Henry Chen
  0 siblings, 1 reply; 22+ messages in thread
From: Rob Herring @ 2019-05-01 20:28 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, linux-mediatek,
	Matthias Brugger, Georgi Djakov, linux-arm-kernel

On Tue, Apr 30, 2019 at 04:51:03PM +0800, Henry Chen wrote:
> Add header file for mt8183 interconnect node that could be shared between
> the interconeect provider driver and Device Tree source files.
> 
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  include/dt-bindings/interconnect/mtk,mt8183.h | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>  create mode 100644 include/dt-bindings/interconnect/mtk,mt8183.h

This goes with the binding patch.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver
  2019-04-30  8:51 ` [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver Henry Chen
@ 2019-05-14  6:43   ` Georgi Djakov
  2019-08-19  1:53     ` Henry Chen
  0 siblings, 1 reply; 22+ messages in thread
From: Georgi Djakov @ 2019-05-14  6:43 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	Linux PM list, linux-kernel, Stephen Boyd, Fan Chen, devicetree,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel

Hi Henry,

On 4/30/19 11:51, Henry Chen wrote:
> Introduce Mediatek MT8183 specific provider driver using the
> interconnect framework.
> 
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  drivers/interconnect/Kconfig           |   1 +
>  drivers/interconnect/Makefile          |   1 +
>  drivers/interconnect/mediatek/Kconfig  |  13 ++
>  drivers/interconnect/mediatek/Makefile |   5 +
>  drivers/interconnect/mediatek/mt8183.c | 223 +++++++++++++++++++++++++++++++++
>  5 files changed, 243 insertions(+)
>  create mode 100644 drivers/interconnect/mediatek/Kconfig
>  create mode 100644 drivers/interconnect/mediatek/Makefile
>  create mode 100644 drivers/interconnect/mediatek/mt8183.c
> 
> diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
> index 07a8276..ac41ea6 100644
> --- a/drivers/interconnect/Kconfig
> +++ b/drivers/interconnect/Kconfig
> @@ -11,5 +11,6 @@ menuconfig INTERCONNECT
>  if INTERCONNECT
>  
>  source "drivers/interconnect/qcom/Kconfig"
> +source "drivers/interconnect/mediatek/Kconfig"
>  
>  endif
> diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
> index 28f2ab0..253f24a3 100644
> --- a/drivers/interconnect/Makefile
> +++ b/drivers/interconnect/Makefile
> @@ -4,3 +4,4 @@ icc-core-objs				:= core.o
>  
>  obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
>  obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
> +obj-$(CONFIG_INTERCONNECT_MTK)		+= mediatek/
> diff --git a/drivers/interconnect/mediatek/Kconfig b/drivers/interconnect/mediatek/Kconfig
> new file mode 100644
> index 0000000..0686494
> --- /dev/null
> +++ b/drivers/interconnect/mediatek/Kconfig
> @@ -0,0 +1,13 @@
> +config INTERCONNECT_MTK
> +	bool "Mediatek Network-on-Chip interconnect drivers"
> +	depends on ARCH_MEDIATEK
> +	help
> +	  Support for Mediatek's Network-on-Chip interconnect hardware.
> +
> +config INTERCONNECT_MTK_MT8183
> +	tristate "Mediatek MT8183 interconnect driver"
> +	depends on INTERCONNECT_MTK
> +	depends on (MTK_DVFSRC && OF)
> +	help
> +	  This is a driver for the Mediatek Network-on-Chip on mt8183-based
> +	  platforms.
> diff --git a/drivers/interconnect/mediatek/Makefile b/drivers/interconnect/mediatek/Makefile
> new file mode 100644
> index 0000000..a39ceee
> --- /dev/null
> +++ b/drivers/interconnect/mediatek/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +mtk-mt8183-objs			:= mt8183.o
> +
> +obj-$(CONFIG_INTERCONNECT_MTK_MT8183) += mtk-mt8183.o
> \ No newline at end of file
> diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
> new file mode 100644
> index 0000000..38ffe0b
> --- /dev/null
> +++ b/drivers/interconnect/mediatek/mt8183.c
> @@ -0,0 +1,223 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, The Linux Foundation. All rights reserved.
> + *
> + */
> +
> +#include <dt-bindings/interconnect/mtk,mt8183.h>
> +#include <linux/device.h>
> +#include <linux/interconnect.h>

This is not needed.

> +#include <linux/interconnect-provider.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <soc/mediatek/mtk_dvfsrc.h>
> +
> +#define MT8183_MAX_LINKS	6
> +
> +/**
> + * struct mtk_icc_node - Mediatek specific interconnect nodes
> + * @name: the node name used in debugfs
> + * @ep: true if the node is an end point.
> + * @id: a unique node identifier
> + * @links: an array of nodes where we can go next while traversing
> + * @num_links: the total number of @links
> + * @buswidth: width of the interconnect between a node and the bus

Maybe mention the units?

> + * @sum_avg: current sum aggregate value of all avg bw requests
> + * @max_peak: current max aggregate value of all peak bw requests

units?

> + */
> +struct mtk_icc_node {
> +	unsigned char *name;
> +	bool ep;
> +	u16 id;
> +	u16 links[MT8183_MAX_LINKS];
> +	u16 num_links;
> +	u16 buswidth;
> +	u64 sum_avg;
> +	u64 max_peak;
> +};
> +
> +struct mtk_icc_desc {
> +	struct mtk_icc_node **nodes;
> +	size_t num_nodes;
> +};
> +
> +#define DEFINE_MNODE(_name, _id, _buswidth, _ep, _numlinks, ...)	\

We can drop the _numlinks and..

> +		static struct mtk_icc_node _name = {			\
> +		.name = #_name,						\
> +		.id = _id,						\
> +		.buswidth = _buswidth,					\
> +		.ep = _ep,						\
> +		.num_links = _numlinks,					\

..just use 	.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ }))

> +		.links = { __VA_ARGS__ },				\
> +}
> +
> +DEFINE_MNODE(ddr_emi, SLAVE_DDR_EMI, 1024, 1, 0, 0);
> +DEFINE_MNODE(mcusys, MASTER_MCUSYS, 256, 0, 1, SLAVE_DDR_EMI);
> +DEFINE_MNODE(gpu, MASTER_GPU, 256, 0, 1, SLAVE_DDR_EMI);
> +DEFINE_MNODE(mmsys, MASTER_MMSYS, 256, 0, 1, SLAVE_DDR_EMI);
> +DEFINE_MNODE(mm_vpu, MASTER_MM_VPU, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_disp, MASTER_MM_DISP, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_vdec, MASTER_MM_VDEC, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_venc, MASTER_MM_VENC, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_cam, MASTER_MM_CAM, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_img, MASTER_MM_IMG, 128, 0, 1, MASTER_MMSYS);
> +DEFINE_MNODE(mm_mdp, MASTER_MM_MDP, 128, 0, 1, MASTER_MMSYS);
> +
> +static struct mtk_icc_node *mt8183_icc_nodes[] = {
> +	&ddr_emi,
> +	&mcusys,
> +	&gpu,
> +	&mmsys,
> +	&mm_vpu,
> +	&mm_disp,
> +	&mm_vdec,
> +	&mm_venc,
> +	&mm_cam,
> +	&mm_img,
> +	&mm_mdp,
> +};
> +
> +static struct mtk_icc_desc mt8183_icc = {
> +	.nodes = mt8183_icc_nodes,
> +	.num_nodes = ARRAY_SIZE(mt8183_icc_nodes),
> +};
> +
> +static int mt8183_icc_aggregate(struct icc_node *node, u32 avg_bw,
> +			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> +	struct mtk_icc_node *in;
> +
> +	in = node->data;
> +
> +	*agg_avg += avg_bw;
> +	*agg_peak = max_t(u32, *agg_peak, peak_bw);
> +
> +	in->sum_avg = *agg_avg;
> +	in->max_peak = *agg_peak;
> +
> +	return 0;
> +}
> +
> +static int mt8183_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	int ret = 0;
> +	struct mtk_icc_node *node;
> +
> +	node = dst->data;
> +	if (node->ep) {
> +		pr_debug("sum_avg (%llu), max_peak (%llu)\n",
> +			node->sum_avg, node->max_peak);
> +		mtk_dvfsrc_send_request(src->provider->dev->parent,
> +					MTK_DVFSRC_CMD_BW_REQUEST,
> +					node->max_peak);
> +	}
> +
> +	return ret;
> +}
> +
> +static int mt8183_icc_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	const struct mtk_icc_desc *desc;
> +	struct icc_node *node;
> +	struct icc_onecell_data *data;
> +	struct icc_provider *provider;
> +	struct mtk_icc_node **mnodes;
> +	size_t num_nodes, i, j;
> +
> +	desc = of_device_get_match_data(&pdev->dev);
> +	if (!desc)
> +		return -EINVAL;
> +
> +	mnodes = desc->nodes;
> +	num_nodes = desc->num_nodes;
> +
> +	provider = devm_kzalloc(&pdev->dev, sizeof(*provider), GFP_KERNEL);
> +	if (!provider)
> +		return -ENOMEM;
> +
> +	data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	provider->dev = &pdev->dev;
> +	provider->set = mt8183_icc_set;
> +	provider->aggregate = mt8183_icc_aggregate;
> +	provider->xlate = of_icc_xlate_onecell;
> +	INIT_LIST_HEAD(&provider->nodes);
> +	provider->data = data;
> +
> +	ret = icc_provider_add(provider);
> +	if (ret) {
> +		dev_err(&pdev->dev, "error adding interconnect provider\n");
> +		return ret;
> +	}
> +
> +	for (i = 0; i < num_nodes; i++) {
> +		node = icc_node_create(mnodes[i]->id);
> +		if (IS_ERR(node)) {
> +			ret = PTR_ERR(node);
> +			goto err;
> +		}
> +
> +		node->name = mnodes[i]->name;
> +		node->data = mnodes[i];
> +		icc_node_add(node, provider);
> +
> +		dev_dbg(&pdev->dev, "registered node %s, num link: %d\n",
> +			mnodes[i]->name, mnodes[i]->num_links);
> +
> +		/* populate links */
> +		for (j = 0; j < mnodes[i]->num_links; j++)
> +			icc_link_create(node, mnodes[i]->links[j]);
> +
> +		data->nodes[i] = node;
> +	}
> +	data->num_nodes = num_nodes;
> +
> +	platform_set_drvdata(pdev, provider);
> +
> +	return ret;

just return 0;

> +err:
> +	list_for_each_entry(node, &provider->nodes, node_list) {
> +		icc_node_del(node);
> +		icc_node_destroy(node->id);
> +	}
> +
> +	icc_provider_del(provider);
> +	return ret;
> +}
> +
> +static int mt8183_icc_remove(struct platform_device *pdev)
> +{
> +	struct icc_provider *provider = platform_get_drvdata(pdev);
> +	struct icc_node *n;
> +
> +	list_for_each_entry(n, &provider->nodes, node_list) {
> +		icc_node_del(n);
> +		icc_node_destroy(n->id);
> +	}
> +
> +	return icc_provider_del(provider);
> +}
> +
> +static const struct of_device_id mt8183_icc_of_match[] = {
> +	{ .compatible = "mediatek,mt8183-emi-icc", .data = &mt8183_icc },

A separate -icc compatible should not be needed.

Thanks,
Georgi

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support
  2019-04-30  8:51 ` [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support Henry Chen
@ 2019-06-10 21:00   ` Ryan Case
  2019-08-19  1:35     ` Henry Chen
  0 siblings, 1 reply; 22+ messages in thread
From: Ryan Case @ 2019-06-10 21:00 UTC (permalink / raw)
  To: Henry Chen
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, Rob Herring,
	linux-mediatek, Matthias Brugger, Georgi Djakov,
	linux-arm-kernel

Hi Henry,

On Tue, Apr 30, 2019 at 2:45 AM Henry Chen <henryc.chen@mediatek.com> wrote:
>
> Add dvfsrc driver for MT8183
>
> Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> ---
>  drivers/soc/mediatek/Kconfig      |  15 ++
>  drivers/soc/mediatek/Makefile     |   1 +
>  drivers/soc/mediatek/mtk-dvfsrc.c | 347 ++++++++++++++++++++++++++++++++++++++
>  include/soc/mediatek/mtk_dvfsrc.h |  22 +++
>  4 files changed, 385 insertions(+)
>  create mode 100644 drivers/soc/mediatek/mtk-dvfsrc.c
>  create mode 100644 include/soc/mediatek/mtk_dvfsrc.h
>
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 17bd759..2721fd6 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -24,6 +24,21 @@ config MTK_INFRACFG
>           INFRACFG controller contains various infrastructure registers not
>           directly associated to any device.
>
> +config MTK_DVFSRC
> +       bool "MediaTek DVFSRC Support"
> +       depends on ARCH_MEDIATEK
> +       default ARCH_MEDIATEK
> +       select MTK_INFRACFG
> +       select PM_GENERIC_DOMAINS if PM
> +       depends on MTK_SCPSYS
> +       help
> +         Say yes here to add support for the MediaTek DVFSRC (dynamic voltage
> +         and frequency scaling resource collector) found
> +         on different MediaTek SoCs. The DVFSRC is a proprietary
> +         hardware which is used to collect all the requests from
> +         system and turn into the decision of minimum Vcore voltage
> +         and minimum DRAM frequency to fulfill those requests.
> +
>  config MTK_PMIC_WRAP
>         tristate "MediaTek PMIC Wrapper Support"
>         depends on RESET_CONTROLLER
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index b9dbad6..cd9d63f 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,4 +1,5 @@
>  obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
> +obj-$(CONFIG_MTK_DVFSRC) += mtk-dvfsrc.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-dvfsrc.c b/drivers/soc/mediatek/mtk-dvfsrc.c
> new file mode 100644
> index 0000000..e54a654
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-dvfsrc.c
> @@ -0,0 +1,347 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + */
> +#include <linux/arm-smccc.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/notifier.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <soc/mediatek/mtk_dvfsrc.h>
> +#include <soc/mediatek/mtk_sip.h>
> +#include <dt-bindings/power/mt8183-power.h>
> +#include <dt-bindings/soc/mtk,dvfsrc.h>
> +#include <dt-bindings/soc/mtk,dvfsrc.h>
> +#include "mtk-scpsys.h"
> +
> +#define DVFSRC_IDLE            0x00
> +#define DVFSRC_GET_TARGET_LEVEL(x)     (((x) >> 0) & 0x0000ffff)
> +#define DVFSRC_GET_CURRENT_LEVEL(x)    (((x) >> 16) & 0x0000ffff)
> +
> +#define MT8183_DVFSRC_OPP_LP4  0
> +#define MT8183_DVFSRC_OPP_LP4X 1
> +#define MT8183_DVFSRC_OPP_LP3  2
> +
> +struct dvfsrc_opp {
> +       u32 vcore_opp;
> +       u32 dram_opp;
> +};
> +
> +struct dvfsrc_domain {
> +       u32 id;
> +       u32 state;
> +};
> +
> +struct mtk_dvfsrc;
> +struct dvfsrc_soc_data {
> +       const int *regs;
> +       u32 num_opp;
> +       u32 num_domains;
> +       const struct dvfsrc_opp **opps;
> +       struct dvfsrc_domain *domains;
> +       int (*get_target_level)(struct mtk_dvfsrc *dvfsrc);
> +       int (*get_current_level)(struct mtk_dvfsrc *dvfsrc);
> +       void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
> +       void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
> +};
> +
> +struct mtk_dvfsrc {
> +       struct device *dev;
> +       struct clk *clk_dvfsrc;
> +       const struct dvfsrc_soc_data *dvd;
> +       int dram_type;
> +       void __iomem *regs;
> +       struct mutex lock;
> +       struct notifier_block scpsys_notifier;
> +};
> +
> +static u32 dvfsrc_read(struct mtk_dvfsrc *dvfs, u32 offset)
> +{
> +       return readl(dvfs->regs + dvfs->dvd->regs[offset]);
> +}
> +
> +static void dvfsrc_write(struct mtk_dvfsrc *dvfs, u32 offset, u32 val)
> +{
> +       writel(val, dvfs->regs + dvfs->dvd->regs[offset]);
> +}
> +
> +enum dvfsrc_regs {
> +       DVFSRC_SW_REQ,
> +       DVFSRC_LEVEL,
> +       DVFSRC_SW_BW_0,
> +       DVFSRC_LAST,
> +};
> +
> +static const int mt8183_regs[] = {
> +       [DVFSRC_SW_REQ] =       0x4,
> +       [DVFSRC_LEVEL] =        0xDC,
> +       [DVFSRC_SW_BW_0] =      0x160,
> +       [DVFSRC_LAST] =         0x308,
> +};
> +
> +static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc)
> +{
> +       if (!dvfsrc->dvd->get_target_level)
> +               return true;
> +
> +       return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_IDLE;
> +}
> +
> +static int dvfsrc_wait_for_idle(struct mtk_dvfsrc *dvfsrc)
> +{
> +       unsigned long timeout;
> +
> +       timeout = jiffies + usecs_to_jiffies(1000);
> +
> +       do {
> +               if (dvfsrc_is_idle(dvfsrc))
> +                       return 0;
> +       } while (!time_after(jiffies, timeout));

This all seems like it would be better handled by readx_poll_timeout
rather than rolling your own.

> +
> +       return -ETIMEDOUT;
> +}
> +
> +static int mt8183_get_target_level(struct mtk_dvfsrc *dvfsrc)
> +{
> +       return DVFSRC_GET_TARGET_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL));
> +}
> +
> +static int mt8183_get_current_level(struct mtk_dvfsrc *dvfsrc)
> +{
> +       return ffs(DVFSRC_GET_CURRENT_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL)));
> +}
> +
> +static void mt8183_set_dram_bw(struct mtk_dvfsrc *dvfsrc, u64 bw)
> +{
> +       dvfsrc_write(dvfsrc, DVFSRC_SW_BW_0, bw);
> +}
> +
> +static void mt8183_set_opp_level(struct mtk_dvfsrc *dvfsrc, u32 level)
> +{
> +       int vcore_opp, dram_opp;
> +       const struct dvfsrc_opp *opp;
> +
> +       /* translate pstate to dvfsrc level, and set it to DVFSRC HW */
> +       opp = &dvfsrc->dvd->opps[dvfsrc->dram_type][level - 1];
> +       vcore_opp = opp->vcore_opp;
> +       dram_opp = opp->dram_opp;
> +
> +       dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n",
> +               vcore_opp, dram_opp);
> +       dvfsrc_write(dvfsrc, DVFSRC_SW_REQ, dram_opp | vcore_opp << 2);
> +}
> +
> +void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data)
> +{
> +       struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev);
> +
> +       dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data);
> +
> +       mutex_lock(&dvfsrc->lock);
> +
> +       if (dvfsrc_wait_for_idle(dvfsrc)) {
> +               dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
> +                        __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
> +               dvfsrc_read(dvfsrc, DVFSRC_LAST));
> +               goto out;
> +       }
> +
> +       switch (cmd) {
> +       case MTK_DVFSRC_CMD_BW_REQUEST:
> +               dvfsrc->dvd->set_dram_bw(dvfsrc, data);
> +               goto out;
> +       case MTK_DVFSRC_CMD_OPP_REQUEST:
> +               dvfsrc->dvd->set_opp_level(dvfsrc, data);
> +               break;
> +       default:
> +               dev_err(dvfsrc->dev, "unknown command: %d\n", cmd);
> +               break;
> +       }
> +
> +       if (dvfsrc_wait_for_idle(dvfsrc)) {
> +               dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
> +                        __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
> +                        dvfsrc_read(dvfsrc, DVFSRC_LAST));
> +               goto out;
> +       }
> +
> +out:
> +       mutex_unlock(&dvfsrc->lock);
> +}
> +EXPORT_SYMBOL(mtk_dvfsrc_send_request);
> +
> +static int dvfsrc_set_performance(struct notifier_block *b,
> +                                 unsigned long l, void *v)
> +{
> +       int i, val, highest;

Variable names could be improved. "val" is only ever used to store the
current level, would be nice to make the name more specific. Similarly
"l" looks like it would be better as something state related.

val and highest at least should be u32.

> +       struct mtk_dvfsrc *dvfsrc;
> +       struct scp_event_data *sc = v;
> +       struct dvfsrc_domain *d;
> +
> +       if (sc->event_type != MTK_SCPSYS_PSTATE)
> +               return 0;
> +
> +       dvfsrc = container_of(b, struct mtk_dvfsrc, scpsys_notifier);
> +
> +       d = dvfsrc->dvd->domains;
> +
> +       if (l > dvfsrc->dvd->num_opp) {
> +               dev_err(dvfsrc->dev, "pstate out of range = %ld\n", l);
> +               goto out;

Can just return 0;

> +       }
> +
> +       for (i = 0, highest = 0; i < dvfsrc->dvd->num_domains - 1; i++, d++) {

It's not immediately clear to me why a domain is skipped (the -1).
This is either worth a comment or it may be a bug?

> +               if (sc->domain_id == d->id)
> +                       d->state = l;
> +               if (d->state > highest)
> +                       highest = d->state;
> +       }
> +
> +       if (highest == 0) {
> +               dev_err(dvfsrc->dev, "domain not match\n");

This text is incorrect. You're checking whether all domains had a
state of zero, not whether you found a domain match. Is this check
actually needed?

> +               goto out;

return 0;

> +       }
> +
> +       mtk_dvfsrc_send_request(dvfsrc->dev, MTK_DVFSRC_CMD_OPP_REQUEST,
> +                               highest);
> +
> +       val = dvfsrc->dvd->get_current_level(dvfsrc);
> +
> +       dev_dbg(dvfsrc->dev, "DVFSRC_LEVEL: %x, val: %x, DVFSRC_SW_REQ: %x\n",
> +               dvfsrc_read(dvfsrc, DVFSRC_LEVEL), val,
> +               dvfsrc_read(dvfsrc, DVFSRC_SW_REQ));

"val:" to "current level:" or something similarly descriptive.

> +
> +       if (val < highest) {
> +               dev_err(dvfsrc->dev, "current: %d < highest: %x\n",
> +                       val, highest);

This message isn't clear and should be more explicit. Something like
"Current level %d < highest requested %d"

> +               goto out;

return 0;

> +       }
> +
> +out:

Out label no longer needed.

> +       return 0;
> +}
> +
> +static void pstate_notifier_register(struct mtk_dvfsrc *dvfsrc)
> +{
> +       dvfsrc->scpsys_notifier.notifier_call = dvfsrc_set_performance;
> +       register_scpsys_notifier(&dvfsrc->scpsys_notifier);
> +}
> +
> +static int mtk_dvfsrc_probe(struct platform_device *pdev)
> +{
> +       struct arm_smccc_res ares;
> +       struct resource *res;
> +       struct mtk_dvfsrc *dvfsrc;
> +       int ret;
> +
> +       dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL);
> +       if (!dvfsrc)
> +               return -ENOMEM;
> +
> +       dvfsrc->dvd = of_device_get_match_data(&pdev->dev);
> +       dvfsrc->dev = &pdev->dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       dvfsrc->regs = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(dvfsrc->regs))
> +               return PTR_ERR(dvfsrc->regs);
> +
> +       dvfsrc->clk_dvfsrc = devm_clk_get(dvfsrc->dev, "dvfsrc");
> +       if (IS_ERR(dvfsrc->clk_dvfsrc)) {
> +               dev_err(dvfsrc->dev, "failed to get clock: %ld\n",
> +                       PTR_ERR(dvfsrc->clk_dvfsrc));
> +               return PTR_ERR(dvfsrc->clk_dvfsrc);
> +       }
> +
> +       ret = clk_prepare_enable(dvfsrc->clk_dvfsrc);
> +       if (ret)
> +               return ret;
> +
> +       mutex_init(&dvfsrc->lock);
> +
> +       arm_smccc_smc(MTK_SIP_SPM, MTK_SIP_SPM_DVFSRC_INIT, 0, 0, 0, 0, 0, 0,
> +                     &ares);
> +
> +       if (!ares.a0) {
> +               dvfsrc->dram_type = ares.a1;
> +       } else {
> +               dev_err(dvfsrc->dev, "init fails: %lu\n", ares.a0);
> +               clk_disable_unprepare(dvfsrc->clk_dvfsrc);
> +               return ares.a0;
> +       }
> +
> +       platform_set_drvdata(pdev, dvfsrc);
> +       pstate_notifier_register(dvfsrc);
> +
> +       return devm_of_platform_populate(&pdev->dev);
> +}
> +
> +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = {
> +       {0, 0}, {0, 1}, {0, 2}, {1, 2},
> +};
> +
> +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = {
> +       {0, 0}, {0, 1}, {1, 1}, {1, 2},
> +};
> +
> +static const struct dvfsrc_opp *dvfsrc_opp_mt8183[] = {
> +       [MT8183_DVFSRC_OPP_LP4] = dvfsrc_opp_mt8183_lp4,
> +       [MT8183_DVFSRC_OPP_LP4X] = dvfsrc_opp_mt8183_lp3,
> +       [MT8183_DVFSRC_OPP_LP3] = dvfsrc_opp_mt8183_lp3,
> +};
> +
> +static struct dvfsrc_domain dvfsrc_domains_mt8183[] = {
> +       { MT8183_POWER_DOMAIN_MFG_ASYNC, 0 },
> +       { MT8183_POWER_DOMAIN_MFG, 0 },
> +       { MT8183_POWER_DOMAIN_CAM, 0 },
> +       { MT8183_POWER_DOMAIN_DISP, 0 },
> +       { MT8183_POWER_DOMAIN_ISP, 0 },
> +       { MT8183_POWER_DOMAIN_VDEC, 0 },
> +       { MT8183_POWER_DOMAIN_VENC, 0 },
> +};
> +
> +static const struct dvfsrc_soc_data mt8183_data = {
> +       .opps = dvfsrc_opp_mt8183,
> +       .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4),
> +       .regs = mt8183_regs,
> +       .domains = dvfsrc_domains_mt8183,
> +       .num_domains = ARRAY_SIZE(dvfsrc_domains_mt8183),
> +       .get_target_level = mt8183_get_target_level,
> +       .get_current_level = mt8183_get_current_level,
> +       .set_dram_bw = mt8183_set_dram_bw,
> +       .set_opp_level = mt8183_set_opp_level,
> +};
> +
> +static int mtk_dvfsrc_remove(struct platform_device *pdev)
> +{
> +       struct mtk_dvfsrc *dvfsrc = platform_get_drvdata(pdev);
> +
> +       clk_disable_unprepare(dvfsrc->clk_dvfsrc);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id mtk_dvfsrc_of_match[] = {
> +       {
> +               .compatible = "mediatek,mt8183-dvfsrc",
> +               .data = &mt8183_data,
> +       }, {
> +               /* sentinel */
> +       },
> +};
> +
> +static struct platform_driver mtk_dvfsrc_driver = {
> +       .probe  = mtk_dvfsrc_probe,
> +       .remove = mtk_dvfsrc_remove,
> +       .driver = {
> +               .name = "mtk-dvfsrc",
> +               .of_match_table = of_match_ptr(mtk_dvfsrc_of_match),
> +       },
> +};
> +
> +builtin_platform_driver(mtk_dvfsrc_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("MTK DVFSRC driver");
> diff --git a/include/soc/mediatek/mtk_dvfsrc.h b/include/soc/mediatek/mtk_dvfsrc.h
> new file mode 100644
> index 0000000..e759a65
> --- /dev/null
> +++ b/include/soc/mediatek/mtk_dvfsrc.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * Copyright (c) 2018 MediaTek Inc.
> + */
> +#ifndef __SOC_MTK_DVFSRC_H
> +#define __SOC_MTK_DVFSRC_H
> +
> +#define MTK_DVFSRC_CMD_BW_REQUEST      0
> +#define MTK_DVFSRC_CMD_OPP_REQUEST     1
> +
> +#if IS_ENABLED(CONFIG_MTK_DVFSRC)
> +void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data);
> +
> +#else
> +
> +static inline void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd,
> +                                          u64 data)
> +{ return -ENODEV; }
> +
> +#endif /* CONFIG_MTK_DVFSRC */
> +
> +#endif
> --
> 1.9.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support
  2019-06-10 21:00   ` Ryan Case
@ 2019-08-19  1:35     ` Henry Chen
  0 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-08-19  1:35 UTC (permalink / raw)
  To: Ryan Case
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, Rob Herring,
	linux-mediatek, Matthias Brugger, Georgi Djakov,
	linux-arm-kernel

On Mon, 2019-06-10 at 14:00 -0700, Ryan Case wrote:
Hi Ryan,

Sorry for late reply.

> Hi Henry,
> 
> On Tue, Apr 30, 2019 at 2:45 AM Henry Chen <henryc.chen@mediatek.com> wrote:
> >
> > Add dvfsrc driver for MT8183
> >
> > Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> > ---
> >  drivers/soc/mediatek/Kconfig      |  15 ++
> >  drivers/soc/mediatek/Makefile     |   1 +
> >  drivers/soc/mediatek/mtk-dvfsrc.c | 347 ++++++++++++++++++++++++++++++++++++++
> >  include/soc/mediatek/mtk_dvfsrc.h |  22 +++
> >  4 files changed, 385 insertions(+)
> >  create mode 100644 drivers/soc/mediatek/mtk-dvfsrc.c
> >  create mode 100644 include/soc/mediatek/mtk_dvfsrc.h
> >
> > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> > index 17bd759..2721fd6 100644
> > --- a/drivers/soc/mediatek/Kconfig
> > +++ b/drivers/soc/mediatek/Kconfig
> > @@ -24,6 +24,21 @@ config MTK_INFRACFG
> >           INFRACFG controller contains various infrastructure registers not
> >           directly associated to any device.
> >
> > +config MTK_DVFSRC
> > +       bool "MediaTek DVFSRC Support"
> > +       depends on ARCH_MEDIATEK
> > +       default ARCH_MEDIATEK
> > +       select MTK_INFRACFG
> > +       select PM_GENERIC_DOMAINS if PM
> > +       depends on MTK_SCPSYS
> > +       help
> > +         Say yes here to add support for the MediaTek DVFSRC (dynamic voltage
> > +         and frequency scaling resource collector) found
> > +         on different MediaTek SoCs. The DVFSRC is a proprietary
> > +         hardware which is used to collect all the requests from
> > +         system and turn into the decision of minimum Vcore voltage
> > +         and minimum DRAM frequency to fulfill those requests.
> > +
> >  config MTK_PMIC_WRAP
> >         tristate "MediaTek PMIC Wrapper Support"
> >         depends on RESET_CONTROLLER
> > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> > index b9dbad6..cd9d63f 100644
> > --- a/drivers/soc/mediatek/Makefile
> > +++ b/drivers/soc/mediatek/Makefile
> > @@ -1,4 +1,5 @@
> >  obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
> > +obj-$(CONFIG_MTK_DVFSRC) += mtk-dvfsrc.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-dvfsrc.c b/drivers/soc/mediatek/mtk-dvfsrc.c
> > new file mode 100644
> > index 0000000..e54a654
> > --- /dev/null
> > +++ b/drivers/soc/mediatek/mtk-dvfsrc.c
> > @@ -0,0 +1,347 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + */
> > +#include <linux/arm-smccc.h>
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/notifier.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <soc/mediatek/mtk_dvfsrc.h>
> > +#include <soc/mediatek/mtk_sip.h>
> > +#include <dt-bindings/power/mt8183-power.h>
> > +#include <dt-bindings/soc/mtk,dvfsrc.h>
> > +#include <dt-bindings/soc/mtk,dvfsrc.h>
> > +#include "mtk-scpsys.h"
> > +
> > +#define DVFSRC_IDLE            0x00
> > +#define DVFSRC_GET_TARGET_LEVEL(x)     (((x) >> 0) & 0x0000ffff)
> > +#define DVFSRC_GET_CURRENT_LEVEL(x)    (((x) >> 16) & 0x0000ffff)
> > +
> > +#define MT8183_DVFSRC_OPP_LP4  0
> > +#define MT8183_DVFSRC_OPP_LP4X 1
> > +#define MT8183_DVFSRC_OPP_LP3  2
> > +
> > +struct dvfsrc_opp {
> > +       u32 vcore_opp;
> > +       u32 dram_opp;
> > +};
> > +
> > +struct dvfsrc_domain {
> > +       u32 id;
> > +       u32 state;
> > +};
> > +
> > +struct mtk_dvfsrc;
> > +struct dvfsrc_soc_data {
> > +       const int *regs;
> > +       u32 num_opp;
> > +       u32 num_domains;
> > +       const struct dvfsrc_opp **opps;
> > +       struct dvfsrc_domain *domains;
> > +       int (*get_target_level)(struct mtk_dvfsrc *dvfsrc);
> > +       int (*get_current_level)(struct mtk_dvfsrc *dvfsrc);
> > +       void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
> > +       void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
> > +};
> > +
> > +struct mtk_dvfsrc {
> > +       struct device *dev;
> > +       struct clk *clk_dvfsrc;
> > +       const struct dvfsrc_soc_data *dvd;
> > +       int dram_type;
> > +       void __iomem *regs;
> > +       struct mutex lock;
> > +       struct notifier_block scpsys_notifier;
> > +};
> > +
> > +static u32 dvfsrc_read(struct mtk_dvfsrc *dvfs, u32 offset)
> > +{
> > +       return readl(dvfs->regs + dvfs->dvd->regs[offset]);
> > +}
> > +
> > +static void dvfsrc_write(struct mtk_dvfsrc *dvfs, u32 offset, u32 val)
> > +{
> > +       writel(val, dvfs->regs + dvfs->dvd->regs[offset]);
> > +}
> > +
> > +enum dvfsrc_regs {
> > +       DVFSRC_SW_REQ,
> > +       DVFSRC_LEVEL,
> > +       DVFSRC_SW_BW_0,
> > +       DVFSRC_LAST,
> > +};
> > +
> > +static const int mt8183_regs[] = {
> > +       [DVFSRC_SW_REQ] =       0x4,
> > +       [DVFSRC_LEVEL] =        0xDC,
> > +       [DVFSRC_SW_BW_0] =      0x160,
> > +       [DVFSRC_LAST] =         0x308,
> > +};
> > +
> > +static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc)
> > +{
> > +       if (!dvfsrc->dvd->get_target_level)
> > +               return true;
> > +
> > +       return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_IDLE;
> > +}
> > +
> > +static int dvfsrc_wait_for_idle(struct mtk_dvfsrc *dvfsrc)
> > +{
> > +       unsigned long timeout;
> > +
> > +       timeout = jiffies + usecs_to_jiffies(1000);
> > +
> > +       do {
> > +               if (dvfsrc_is_idle(dvfsrc))
> > +                       return 0;
> > +       } while (!time_after(jiffies, timeout));
> 
> This all seems like it would be better handled by readx_poll_timeout
> rather than rolling your own.
It's great suggestion, thanks.
> 
> > +
> > +       return -ETIMEDOUT;
> > +}
> > +
> > +static int mt8183_get_target_level(struct mtk_dvfsrc *dvfsrc)
> > +{
> > +       return DVFSRC_GET_TARGET_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL));
> > +}
> > +
> > +static int mt8183_get_current_level(struct mtk_dvfsrc *dvfsrc)
> > +{
> > +       return ffs(DVFSRC_GET_CURRENT_LEVEL(dvfsrc_read(dvfsrc, DVFSRC_LEVEL)));
> > +}
> > +
> > +static void mt8183_set_dram_bw(struct mtk_dvfsrc *dvfsrc, u64 bw)
> > +{
> > +       dvfsrc_write(dvfsrc, DVFSRC_SW_BW_0, bw);
> > +}
> > +
> > +static void mt8183_set_opp_level(struct mtk_dvfsrc *dvfsrc, u32 level)
> > +{
> > +       int vcore_opp, dram_opp;
> > +       const struct dvfsrc_opp *opp;
> > +
> > +       /* translate pstate to dvfsrc level, and set it to DVFSRC HW */
> > +       opp = &dvfsrc->dvd->opps[dvfsrc->dram_type][level - 1];
> > +       vcore_opp = opp->vcore_opp;
> > +       dram_opp = opp->dram_opp;
> > +
> > +       dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n",
> > +               vcore_opp, dram_opp);
> > +       dvfsrc_write(dvfsrc, DVFSRC_SW_REQ, dram_opp | vcore_opp << 2);
> > +}
> > +
> > +void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data)
> > +{
> > +       struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev);
> > +
> > +       dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data);
> > +
> > +       mutex_lock(&dvfsrc->lock);
> > +
> > +       if (dvfsrc_wait_for_idle(dvfsrc)) {
> > +               dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
> > +                        __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
> > +               dvfsrc_read(dvfsrc, DVFSRC_LAST));
> > +               goto out;
> > +       }
> > +
> > +       switch (cmd) {
> > +       case MTK_DVFSRC_CMD_BW_REQUEST:
> > +               dvfsrc->dvd->set_dram_bw(dvfsrc, data);
> > +               goto out;
> > +       case MTK_DVFSRC_CMD_OPP_REQUEST:
> > +               dvfsrc->dvd->set_opp_level(dvfsrc, data);
> > +               break;
> > +       default:
> > +               dev_err(dvfsrc->dev, "unknown command: %d\n", cmd);
> > +               break;
> > +       }
> > +
> > +       if (dvfsrc_wait_for_idle(dvfsrc)) {
> > +               dev_warn(dvfsrc->dev, "[%s] wait idle, last: %d -> %d\n",
> > +                        __func__, dvfsrc_read(dvfsrc, DVFSRC_LEVEL),
> > +                        dvfsrc_read(dvfsrc, DVFSRC_LAST));
> > +               goto out;
> > +       }
> > +
> > +out:
> > +       mutex_unlock(&dvfsrc->lock);
> > +}
> > +EXPORT_SYMBOL(mtk_dvfsrc_send_request);
> > +
> > +static int dvfsrc_set_performance(struct notifier_block *b,
> > +                                 unsigned long l, void *v)
> > +{
> > +       int i, val, highest;
> 
> Variable names could be improved. "val" is only ever used to store the
> current level, would be nice to make the name more specific. Similarly
> "l" looks like it would be better as something state related.
> 
> val and highest at least should be u32.
ok, about naming, I will correct and make it more clearly.
> 
> > +       struct mtk_dvfsrc *dvfsrc;
> > +       struct scp_event_data *sc = v;
> > +       struct dvfsrc_domain *d;
> > +
> > +       if (sc->event_type != MTK_SCPSYS_PSTATE)
> > +               return 0;
> > +
> > +       dvfsrc = container_of(b, struct mtk_dvfsrc, scpsys_notifier);
> > +
> > +       d = dvfsrc->dvd->domains;
> > +
> > +       if (l > dvfsrc->dvd->num_opp) {
> > +               dev_err(dvfsrc->dev, "pstate out of range = %ld\n", l);
> > +               goto out;
> 
> Can just return 0;
ok.
> 
> > +       }
> > +
> > +       for (i = 0, highest = 0; i < dvfsrc->dvd->num_domains - 1; i++, d++) {
> 
> It's not immediately clear to me why a domain is skipped (the -1).
> This is either worth a comment or it may be a bug?
Indeed, it no need, I will check and re-test again, thanks.
> 
> > +               if (sc->domain_id == d->id)
> > +                       d->state = l;
> > +               if (d->state > highest)
> > +                       highest = d->state;
> > +       }
> > +
> > +       if (highest == 0) {
> > +               dev_err(dvfsrc->dev, "domain not match\n");
> 
> This text is incorrect. You're checking whether all domains had a
> state of zero, not whether you found a domain match. Is this check
> actually needed?
I intend to check if the domain match or no. To avoid confusing, I will
re-write it and used flag to check it.
> 
> > +               goto out;
> 
> return 0;
ok.
> 
> > +       }
> > +
> > +       mtk_dvfsrc_send_request(dvfsrc->dev, MTK_DVFSRC_CMD_OPP_REQUEST,
> > +                               highest);
> > +
> > +       val = dvfsrc->dvd->get_current_level(dvfsrc);
> > +
> > +       dev_dbg(dvfsrc->dev, "DVFSRC_LEVEL: %x, val: %x, DVFSRC_SW_REQ: %x\n",
> > +               dvfsrc_read(dvfsrc, DVFSRC_LEVEL), val,
> > +               dvfsrc_read(dvfsrc, DVFSRC_SW_REQ));
> 
> "val:" to "current level:" or something similarly descriptive.
ok.
> 
> > +
> > +       if (val < highest) {
> > +               dev_err(dvfsrc->dev, "current: %d < highest: %x\n",
> > +                       val, highest);
> 
> This message isn't clear and should be more explicit. Something like
> "Current level %d < highest requested %d"
> 
> > +               goto out;
> 
> return 0;
ok.
> 
> > +       }
> > +
> > +out:
> 
> Out label no longer needed.
ok.
> 
> > +       return 0;
> > +}
> > +
> > +static void pstate_notifier_register(struct mtk_dvfsrc *dvfsrc)
> > +{
> > +       dvfsrc->scpsys_notifier.notifier_call = dvfsrc_set_performance;
> > +       register_scpsys_notifier(&dvfsrc->scpsys_notifier);
> > +}
> > +
> > +static int mtk_dvfsrc_probe(struct platform_device *pdev)
> > +{
> > +       struct arm_smccc_res ares;
> > +       struct resource *res;
> > +       struct mtk_dvfsrc *dvfsrc;
> > +       int ret;
> > +
> > +       dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL);
> > +       if (!dvfsrc)
> > +               return -ENOMEM;
> > +
> > +       dvfsrc->dvd = of_device_get_match_data(&pdev->dev);
> > +       dvfsrc->dev = &pdev->dev;
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       dvfsrc->regs = devm_ioremap_resource(&pdev->dev, res);
> > +       if (IS_ERR(dvfsrc->regs))
> > +               return PTR_ERR(dvfsrc->regs);
> > +
> > +       dvfsrc->clk_dvfsrc = devm_clk_get(dvfsrc->dev, "dvfsrc");
> > +       if (IS_ERR(dvfsrc->clk_dvfsrc)) {
> > +               dev_err(dvfsrc->dev, "failed to get clock: %ld\n",
> > +                       PTR_ERR(dvfsrc->clk_dvfsrc));
> > +               return PTR_ERR(dvfsrc->clk_dvfsrc);
> > +       }
> > +
> > +       ret = clk_prepare_enable(dvfsrc->clk_dvfsrc);
> > +       if (ret)
> > +               return ret;
> > +
> > +       mutex_init(&dvfsrc->lock);
> > +
> > +       arm_smccc_smc(MTK_SIP_SPM, MTK_SIP_SPM_DVFSRC_INIT, 0, 0, 0, 0, 0, 0,
> > +                     &ares);
> > +
> > +       if (!ares.a0) {
> > +               dvfsrc->dram_type = ares.a1;
> > +       } else {
> > +               dev_err(dvfsrc->dev, "init fails: %lu\n", ares.a0);
> > +               clk_disable_unprepare(dvfsrc->clk_dvfsrc);
> > +               return ares.a0;
> > +       }
> > +
> > +       platform_set_drvdata(pdev, dvfsrc);
> > +       pstate_notifier_register(dvfsrc);
> > +
> > +       return devm_of_platform_populate(&pdev->dev);
> > +}
> > +
> > +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = {
> > +       {0, 0}, {0, 1}, {0, 2}, {1, 2},
> > +};
> > +
> > +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = {
> > +       {0, 0}, {0, 1}, {1, 1}, {1, 2},
> > +};
> > +
> > +static const struct dvfsrc_opp *dvfsrc_opp_mt8183[] = {
> > +       [MT8183_DVFSRC_OPP_LP4] = dvfsrc_opp_mt8183_lp4,
> > +       [MT8183_DVFSRC_OPP_LP4X] = dvfsrc_opp_mt8183_lp3,
> > +       [MT8183_DVFSRC_OPP_LP3] = dvfsrc_opp_mt8183_lp3,
> > +};
> > +
> > +static struct dvfsrc_domain dvfsrc_domains_mt8183[] = {
> > +       { MT8183_POWER_DOMAIN_MFG_ASYNC, 0 },
> > +       { MT8183_POWER_DOMAIN_MFG, 0 },
> > +       { MT8183_POWER_DOMAIN_CAM, 0 },
> > +       { MT8183_POWER_DOMAIN_DISP, 0 },
> > +       { MT8183_POWER_DOMAIN_ISP, 0 },
> > +       { MT8183_POWER_DOMAIN_VDEC, 0 },
> > +       { MT8183_POWER_DOMAIN_VENC, 0 },
> > +};
> > +
> > +static const struct dvfsrc_soc_data mt8183_data = {
> > +       .opps = dvfsrc_opp_mt8183,
> > +       .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4),
> > +       .regs = mt8183_regs,
> > +       .domains = dvfsrc_domains_mt8183,
> > +       .num_domains = ARRAY_SIZE(dvfsrc_domains_mt8183),
> > +       .get_target_level = mt8183_get_target_level,
> > +       .get_current_level = mt8183_get_current_level,
> > +       .set_dram_bw = mt8183_set_dram_bw,
> > +       .set_opp_level = mt8183_set_opp_level,
> > +};
> > +
> > +static int mtk_dvfsrc_remove(struct platform_device *pdev)
> > +{
> > +       struct mtk_dvfsrc *dvfsrc = platform_get_drvdata(pdev);
> > +
> > +       clk_disable_unprepare(dvfsrc->clk_dvfsrc);
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct of_device_id mtk_dvfsrc_of_match[] = {
> > +       {
> > +               .compatible = "mediatek,mt8183-dvfsrc",
> > +               .data = &mt8183_data,
> > +       }, {
> > +               /* sentinel */
> > +       },
> > +};
> > +
> > +static struct platform_driver mtk_dvfsrc_driver = {
> > +       .probe  = mtk_dvfsrc_probe,
> > +       .remove = mtk_dvfsrc_remove,
> > +       .driver = {
> > +               .name = "mtk-dvfsrc",
> > +               .of_match_table = of_match_ptr(mtk_dvfsrc_of_match),
> > +       },
> > +};
> > +
> > +builtin_platform_driver(mtk_dvfsrc_driver);
> > +
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("MTK DVFSRC driver");
> > diff --git a/include/soc/mediatek/mtk_dvfsrc.h b/include/soc/mediatek/mtk_dvfsrc.h
> > new file mode 100644
> > index 0000000..e759a65
> > --- /dev/null
> > +++ b/include/soc/mediatek/mtk_dvfsrc.h
> > @@ -0,0 +1,22 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + *
> > + * Copyright (c) 2018 MediaTek Inc.
> > + */
> > +#ifndef __SOC_MTK_DVFSRC_H
> > +#define __SOC_MTK_DVFSRC_H
> > +
> > +#define MTK_DVFSRC_CMD_BW_REQUEST      0
> > +#define MTK_DVFSRC_CMD_OPP_REQUEST     1
> > +
> > +#if IS_ENABLED(CONFIG_MTK_DVFSRC)
> > +void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data);
> > +
> > +#else
> > +
> > +static inline void mtk_dvfsrc_send_request(const struct device *dev, u32 cmd,
> > +                                          u64 data)
> > +{ return -ENODEV; }
> > +
> > +#endif /* CONFIG_MTK_DVFSRC */
> > +
> > +#endif
> > --
> > 1.9.1
> >



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings
  2019-05-01 20:27   ` Rob Herring
@ 2019-08-19  1:39     ` Henry Chen
  0 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-08-19  1:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, linux-mediatek,
	Matthias Brugger, Georgi Djakov, linux-arm-kernel

Hi Rob,

Sorry for late reply.

On Wed, 2019-05-01 at 15:27 -0500, Rob Herring wrote:
> On Tue, Apr 30, 2019 at 04:51:02PM +0800, Henry Chen wrote:
> > Add interconnect provider dt-bindings for MT8183.
> > 
> > Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> > ---
> >  .../bindings/interconnect/mtk,mt8183.txt           | 24 ++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> > new file mode 100644
> > index 0000000..1cf1841
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/interconnect/mtk,mt8183.txt
> > @@ -0,0 +1,24 @@
> > +Mediatek MT8183 interconnect binding
> 
> This should be part of the dvfsrc binding.
ok, will add these into dvfsrc binding.
> 
> > +
> > +MT8183 interconnect providers support dram bandwidth requirements. The provider
> > +is able to communicate with the DVFSRC and send the dram bandwidth to it.
> > +Provider nodes must reside within an DVFSRC device node.
> > +
> > +Required properties :
> > +- compatible : shall contain only one of the following:
> > +			"mediatek,mt8183-emi-icc"
> > +- #interconnect-cells : should contain 1
> > +
> > +Examples:
> > +
> > +dvfsrc@10012000 {
> > +	compatible = "mediatek,mt8183-dvfsrc";
> > +	reg = <0 0x10012000 0 0x1000>;
> > +	clocks = <&infracfg CLK_INFRA_DVFSRC>;
> > +	clock-names = "dvfsrc";
> > +	ddr_emi: interconnect {
> > +		compatible = "mediatek,mt8183-emi-icc";
> > +		#interconnect-cells = <1>;
> 
> No need for a child node here. Just move #interconnect-cells to the 
> parent.
Ihave tried and it cannot work if move "#interconnect-cells" to the
parent.
The provider nodes must reside within an DVFSRC device node.
> 
> Rob



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node
  2019-05-01 20:28   ` Rob Herring
@ 2019-08-19  1:43     ` Henry Chen
  0 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-08-19  1:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	linux-kernel, Stephen Boyd, Fan Chen, devicetree, linux-mediatek,
	Matthias Brugger, Georgi Djakov, linux-arm-kernel

On Wed, 2019-05-01 at 15:28 -0500, Rob Herring wrote:
> On Tue, Apr 30, 2019 at 04:51:03PM +0800, Henry Chen wrote:
> > Add header file for mt8183 interconnect node that could be shared between
> > the interconeect provider driver and Device Tree source files.
> > 
> > Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> > ---
> >  include/dt-bindings/interconnect/mtk,mt8183.h | 18 ++++++++++++++++++
> >  1 file changed, 18 insertions(+)
> >  create mode 100644 include/dt-bindings/interconnect/mtk,mt8183.h
> 
> This goes with the binding patch.
ok, will merged into previous patch 08.



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver
  2019-05-14  6:43   ` Georgi Djakov
@ 2019-08-19  1:53     ` Henry Chen
  0 siblings, 0 replies; 22+ messages in thread
From: Henry Chen @ 2019-08-19  1:53 UTC (permalink / raw)
  To: Georgi Djakov
  Cc: Nicolas Boichat, Weiyi Lu, James Liao, Viresh Kumar,
	Linux PM list, linux-kernel, Stephen Boyd, Fan Chen, devicetree,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel

Hi Georgi,

Sorry for late reply.

On Tue, 2019-05-14 at 09:43 +0300, Georgi Djakov wrote:
> Hi Henry,
> 
> On 4/30/19 11:51, Henry Chen wrote:
> > Introduce Mediatek MT8183 specific provider driver using the
> > interconnect framework.
> > 
> > Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
> > ---
> >  drivers/interconnect/Kconfig           |   1 +
> >  drivers/interconnect/Makefile          |   1 +
> >  drivers/interconnect/mediatek/Kconfig  |  13 ++
> >  drivers/interconnect/mediatek/Makefile |   5 +
> >  drivers/interconnect/mediatek/mt8183.c | 223 +++++++++++++++++++++++++++++++++
> >  5 files changed, 243 insertions(+)
> >  create mode 100644 drivers/interconnect/mediatek/Kconfig
> >  create mode 100644 drivers/interconnect/mediatek/Makefile
> >  create mode 100644 drivers/interconnect/mediatek/mt8183.c
> > 
> > diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
> > index 07a8276..ac41ea6 100644
> > --- a/drivers/interconnect/Kconfig
> > +++ b/drivers/interconnect/Kconfig
> > @@ -11,5 +11,6 @@ menuconfig INTERCONNECT
> >  if INTERCONNECT
> >  
> >  source "drivers/interconnect/qcom/Kconfig"
> > +source "drivers/interconnect/mediatek/Kconfig"
> >  
> >  endif
> > diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
> > index 28f2ab0..253f24a3 100644
> > --- a/drivers/interconnect/Makefile
> > +++ b/drivers/interconnect/Makefile
> > @@ -4,3 +4,4 @@ icc-core-objs				:= core.o
> >  
> >  obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
> >  obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
> > +obj-$(CONFIG_INTERCONNECT_MTK)		+= mediatek/
> > diff --git a/drivers/interconnect/mediatek/Kconfig b/drivers/interconnect/mediatek/Kconfig
> > new file mode 100644
> > index 0000000..0686494
> > --- /dev/null
> > +++ b/drivers/interconnect/mediatek/Kconfig
> > @@ -0,0 +1,13 @@
> > +config INTERCONNECT_MTK
> > +	bool "Mediatek Network-on-Chip interconnect drivers"
> > +	depends on ARCH_MEDIATEK
> > +	help
> > +	  Support for Mediatek's Network-on-Chip interconnect hardware.
> > +
> > +config INTERCONNECT_MTK_MT8183
> > +	tristate "Mediatek MT8183 interconnect driver"
> > +	depends on INTERCONNECT_MTK
> > +	depends on (MTK_DVFSRC && OF)
> > +	help
> > +	  This is a driver for the Mediatek Network-on-Chip on mt8183-based
> > +	  platforms.
> > diff --git a/drivers/interconnect/mediatek/Makefile b/drivers/interconnect/mediatek/Makefile
> > new file mode 100644
> > index 0000000..a39ceee
> > --- /dev/null
> > +++ b/drivers/interconnect/mediatek/Makefile
> > @@ -0,0 +1,5 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +mtk-mt8183-objs			:= mt8183.o
> > +
> > +obj-$(CONFIG_INTERCONNECT_MTK_MT8183) += mtk-mt8183.o
> > \ No newline at end of file
> > diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
> > new file mode 100644
> > index 0000000..38ffe0b
> > --- /dev/null
> > +++ b/drivers/interconnect/mediatek/mt8183.c
> > @@ -0,0 +1,223 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019, The Linux Foundation. All rights reserved.
> > + *
> > + */
> > +
> > +#include <dt-bindings/interconnect/mtk,mt8183.h>
> > +#include <linux/device.h>
> > +#include <linux/interconnect.h>
> 
> This is not needed.
ok, thanks.
> 
> > +#include <linux/interconnect-provider.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <soc/mediatek/mtk_dvfsrc.h>
> > +
> > +#define MT8183_MAX_LINKS	6
> > +
> > +/**
> > + * struct mtk_icc_node - Mediatek specific interconnect nodes
> > + * @name: the node name used in debugfs
> > + * @ep: true if the node is an end point.
> > + * @id: a unique node identifier
> > + * @links: an array of nodes where we can go next while traversing
> > + * @num_links: the total number of @links
> > + * @buswidth: width of the interconnect between a node and the bus
> 
> Maybe mention the units?
ok, I will add it.
> 
> > + * @sum_avg: current sum aggregate value of all avg bw requests
> > + * @max_peak: current max aggregate value of all peak bw requests
> 
> units?
> 
> > + */
> > +struct mtk_icc_node {
> > +	unsigned char *name;
> > +	bool ep;
> > +	u16 id;
> > +	u16 links[MT8183_MAX_LINKS];
> > +	u16 num_links;
> > +	u16 buswidth;
> > +	u64 sum_avg;
> > +	u64 max_peak;
> > +};
> > +
> > +struct mtk_icc_desc {
> > +	struct mtk_icc_node **nodes;
> > +	size_t num_nodes;
> > +};
> > +
> > +#define DEFINE_MNODE(_name, _id, _buswidth, _ep, _numlinks, ...)	\
> 
> We can drop the _numlinks and..
ok, thank you for the advice.
> 
> > +		static struct mtk_icc_node _name = {			\
> > +		.name = #_name,						\
> > +		.id = _id,						\
> > +		.buswidth = _buswidth,					\
> > +		.ep = _ep,						\
> > +		.num_links = _numlinks,					\
> 
> ..just use 	.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ }))
> 
> > +		.links = { __VA_ARGS__ },				\
> > +}
> > +
> > +DEFINE_MNODE(ddr_emi, SLAVE_DDR_EMI, 1024, 1, 0, 0);
> > +DEFINE_MNODE(mcusys, MASTER_MCUSYS, 256, 0, 1, SLAVE_DDR_EMI);
> > +DEFINE_MNODE(gpu, MASTER_GPU, 256, 0, 1, SLAVE_DDR_EMI);
> > +DEFINE_MNODE(mmsys, MASTER_MMSYS, 256, 0, 1, SLAVE_DDR_EMI);
> > +DEFINE_MNODE(mm_vpu, MASTER_MM_VPU, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_disp, MASTER_MM_DISP, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_vdec, MASTER_MM_VDEC, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_venc, MASTER_MM_VENC, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_cam, MASTER_MM_CAM, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_img, MASTER_MM_IMG, 128, 0, 1, MASTER_MMSYS);
> > +DEFINE_MNODE(mm_mdp, MASTER_MM_MDP, 128, 0, 1, MASTER_MMSYS);
> > +
> > +static struct mtk_icc_node *mt8183_icc_nodes[] = {
> > +	&ddr_emi,
> > +	&mcusys,
> > +	&gpu,
> > +	&mmsys,
> > +	&mm_vpu,
> > +	&mm_disp,
> > +	&mm_vdec,
> > +	&mm_venc,
> > +	&mm_cam,
> > +	&mm_img,
> > +	&mm_mdp,
> > +};
> > +
> > +static struct mtk_icc_desc mt8183_icc = {
> > +	.nodes = mt8183_icc_nodes,
> > +	.num_nodes = ARRAY_SIZE(mt8183_icc_nodes),
> > +};
> > +
> > +static int mt8183_icc_aggregate(struct icc_node *node, u32 avg_bw,
> > +			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > +{
> > +	struct mtk_icc_node *in;
> > +
> > +	in = node->data;
> > +
> > +	*agg_avg += avg_bw;
> > +	*agg_peak = max_t(u32, *agg_peak, peak_bw);
> > +
> > +	in->sum_avg = *agg_avg;
> > +	in->max_peak = *agg_peak;
> > +
> > +	return 0;
> > +}
> > +
> > +static int mt8183_icc_set(struct icc_node *src, struct icc_node *dst)
> > +{
> > +	int ret = 0;
> > +	struct mtk_icc_node *node;
> > +
> > +	node = dst->data;
> > +	if (node->ep) {
> > +		pr_debug("sum_avg (%llu), max_peak (%llu)\n",
> > +			node->sum_avg, node->max_peak);
> > +		mtk_dvfsrc_send_request(src->provider->dev->parent,
> > +					MTK_DVFSRC_CMD_BW_REQUEST,
> > +					node->max_peak);
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int mt8183_icc_probe(struct platform_device *pdev)
> > +{
> > +	int ret;
> > +	const struct mtk_icc_desc *desc;
> > +	struct icc_node *node;
> > +	struct icc_onecell_data *data;
> > +	struct icc_provider *provider;
> > +	struct mtk_icc_node **mnodes;
> > +	size_t num_nodes, i, j;
> > +
> > +	desc = of_device_get_match_data(&pdev->dev);
> > +	if (!desc)
> > +		return -EINVAL;
> > +
> > +	mnodes = desc->nodes;
> > +	num_nodes = desc->num_nodes;
> > +
> > +	provider = devm_kzalloc(&pdev->dev, sizeof(*provider), GFP_KERNEL);
> > +	if (!provider)
> > +		return -ENOMEM;
> > +
> > +	data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
> > +	if (!data)
> > +		return -ENOMEM;
> > +
> > +	provider->dev = &pdev->dev;
> > +	provider->set = mt8183_icc_set;
> > +	provider->aggregate = mt8183_icc_aggregate;
> > +	provider->xlate = of_icc_xlate_onecell;
> > +	INIT_LIST_HEAD(&provider->nodes);
> > +	provider->data = data;
> > +
> > +	ret = icc_provider_add(provider);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "error adding interconnect provider\n");
> > +		return ret;
> > +	}
> > +
> > +	for (i = 0; i < num_nodes; i++) {
> > +		node = icc_node_create(mnodes[i]->id);
> > +		if (IS_ERR(node)) {
> > +			ret = PTR_ERR(node);
> > +			goto err;
> > +		}
> > +
> > +		node->name = mnodes[i]->name;
> > +		node->data = mnodes[i];
> > +		icc_node_add(node, provider);
> > +
> > +		dev_dbg(&pdev->dev, "registered node %s, num link: %d\n",
> > +			mnodes[i]->name, mnodes[i]->num_links);
> > +
> > +		/* populate links */
> > +		for (j = 0; j < mnodes[i]->num_links; j++)
> > +			icc_link_create(node, mnodes[i]->links[j]);
> > +
> > +		data->nodes[i] = node;
> > +	}
> > +	data->num_nodes = num_nodes;
> > +
> > +	platform_set_drvdata(pdev, provider);
> > +
> > +	return ret;
> 
> just return 0;
ok.
> 
> > +err:
> > +	list_for_each_entry(node, &provider->nodes, node_list) {
> > +		icc_node_del(node);
> > +		icc_node_destroy(node->id);
> > +	}
> > +
> > +	icc_provider_del(provider);
> > +	return ret;
> > +}
> > +
> > +static int mt8183_icc_remove(struct platform_device *pdev)
> > +{
> > +	struct icc_provider *provider = platform_get_drvdata(pdev);
> > +	struct icc_node *n;
> > +
> > +	list_for_each_entry(n, &provider->nodes, node_list) {
> > +		icc_node_del(n);
> > +		icc_node_destroy(n->id);
> > +	}
> > +
> > +	return icc_provider_del(provider);
> > +}
> > +
> > +static const struct of_device_id mt8183_icc_of_match[] = {
> > +	{ .compatible = "mediatek,mt8183-emi-icc", .data = &mt8183_icc },
> 
> A separate -icc compatible should not be needed.
ok.
> 
> Thanks,
> Georgi



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, back to index

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-30  8:50 [PATCH RFC V2] Add driver for dvfsrc, support for active state of scpsys Henry Chen
2019-04-30  8:50 ` [RFC V2 01/11] dt-bindings: soc: Add dvfsrc driver bindings Henry Chen
2019-05-01 20:25   ` Rob Herring
2019-04-30  8:50 ` [RFC V2 02/11] dt-bindings: soc: Add opp table on scpsys bindings Henry Chen
2019-05-01 20:26   ` Rob Herring
2019-04-30  8:50 ` [RFC V2 03/11] soc: mediatek: add support for the performance state Henry Chen
2019-04-30  8:50 ` [RFC V2 04/11] arm64: dts: mt8183: add performance state support of scpsys Henry Chen
2019-04-30  8:50 ` [RFC V2 05/11] soc: mediatek: add header for mediatek SIP interface Henry Chen
2019-04-30  8:51 ` [RFC V2 06/11] soc: mediatek: add MT8183 dvfsrc support Henry Chen
2019-06-10 21:00   ` Ryan Case
2019-08-19  1:35     ` Henry Chen
2019-04-30  8:51 ` [RFC V2 07/11] arm64: dts: mt8183: add dvfsrc related nodes Henry Chen
2019-04-30  8:51 ` [RFC V2 08/11] dt-bindings: interconnect: add MT8183 interconnect dt-bindings Henry Chen
2019-05-01 20:27   ` Rob Herring
2019-08-19  1:39     ` Henry Chen
2019-04-30  8:51 ` [RFC V2 09/11] dt-bindings: interconnect: Add header for interconnect node Henry Chen
2019-05-01 20:28   ` Rob Herring
2019-08-19  1:43     ` Henry Chen
2019-04-30  8:51 ` [RFC V2 10/11] interconnect: mediatek: Add mt8183 interconnect provider driver Henry Chen
2019-05-14  6:43   ` Georgi Djakov
2019-08-19  1:53     ` Henry Chen
2019-04-30  8:51 ` [RFC V2 11/11] arm64: dts: mt8183: Add interconnect provider DT nodes Henry Chen

Linux-ARM-Kernel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-arm-kernel/0 linux-arm-kernel/git/0.git
	git clone --mirror https://lore.kernel.org/linux-arm-kernel/1 linux-arm-kernel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-arm-kernel linux-arm-kernel/ https://lore.kernel.org/linux-arm-kernel \
		linux-arm-kernel@lists.infradead.org infradead-linux-arm-kernel@archiver.kernel.org
	public-inbox-index linux-arm-kernel


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-arm-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox