linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Add Mediatek MMDVFS driver
@ 2020-04-15 11:18 Anthony Huang
  2020-04-15 11:18 ` [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver Anthony Huang
  2020-04-15 11:18 ` [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver Anthony Huang
  0 siblings, 2 replies; 6+ messages in thread
From: Anthony Huang @ 2020-04-15 11:18 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream

his patchset adds the Mediatek MMDVFS(Multimedia Dynamic Voltage and
Frequency Scaling) driver. The multimedia HWs, such as display, camera,
share the same power supplier, and on some platforms, they share the
same clock MUX. If each HW needs different clock frequency at the same
time, the clock MUX must be set to the clock source which can meet the
highest required clock frequency.

Following implementation is used to achieve the goal. There are OPP tables
for all the clock MUXs for MM HWs defined in DTS, ant these OPP tables have
the same number of levels. The MMDVFS registers the regulator callback and
the MM HWs can get available clock frequencies from OPP tables and set
corresponding voltage by regulor API. The MMDVFS's callback will be
triggered if the voltage is changed and this voltage represents the highest
required OPP level. The MMDVFS has a mapping table: which clock source
should be set to each clock MUX for every OPP level. So all the clock MUXs
will be set to the clock sources according to the current OPP level in the
MMDVFS's regulator callback.



Anthony Huang (2):
  dt-bindings: soc: mediatek: Add document for mmdvfs driver
  soc: mediatek: Add mtk-mmdvfs driver

 .../devicetree/bindings/soc/mediatek/mmdvfs.yaml   |  198 +++++++++++++
 drivers/soc/mediatek/Kconfig                       |    9 +
 drivers/soc/mediatek/Makefile                      |    1 +
 drivers/soc/mediatek/mtk-mmdvfs.c                  |  312 ++++++++++++++++++++
 4 files changed, 520 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
 create mode 100644 drivers/soc/mediatek/mtk-mmdvfs.c

-- 
1.7.9.5

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

* [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver
  2020-04-15 11:18 Add Mediatek MMDVFS driver Anthony Huang
@ 2020-04-15 11:18 ` Anthony Huang
  2020-04-15 16:30   ` Chun-Kuang Hu
  2020-04-16 20:45   ` Rob Herring
  2020-04-15 11:18 ` [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver Anthony Huang
  1 sibling, 2 replies; 6+ messages in thread
From: Anthony Huang @ 2020-04-15 11:18 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
	wsd_upstream, Anthony Huang

This document describes the properties what mtk mmdvfs
device node support.

Signed-off-by: Anthony Huang <anthony.huang@mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/mmdvfs.yaml   |  198 ++++++++++++++++++++
 1 file changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml

diff --git a/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml b/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
new file mode 100644
index 0000000..9ef1833
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/mediatek/mmdvfs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MMDVFS driver binding
+
+maintainers:
+  - Rob Herring <robh+dt@kernel.org>
+  - Mark Rutland <mark.rutland@arm.com>
+
+description: |
+  The Mediatek MMDVFS(Multimedia Dynamic Voltage and Frequency Scaling) driver
+  is used to set clk for Mediatek multimedia hardwares, such as display,
+  camera, mdp and video codec. MMDVFS driver reads which clock muxes and clock
+  sources are used on this platform from DTS, and sets current clock according
+  to current voltage informed by regulator callback.
+
+properties:
+  compatible:
+    items:
+      - const: mediatek,mmdvfs
+
+  operating-points-v2:
+    description:
+      Contains any one of opp tables for multimedia modules.
+      MMDVFS uses it to get voltage setting on this platform.
+
+  mediatek,support_mux:
+    description: A list of clock mux names defined in clock-names.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/string-array
+
+  clocks:
+    description:
+      A list of phandles of clock muxes and clock sources for
+      multimedia hardwares.
+
+  clock-names:
+    description:
+      A list of name strings of clock muxes and clock sources for
+      multimedia hardwares.
+
+  # If the platform needs frequency hopping for some clock sources, these
+  # following properties should be set.
+
+  mediatek,support_hopping:
+    description: a list of clock names supporting frequency hopping.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/string-array
+
+  mediatek,action:
+    description:
+      A cell with one entry.
+      It represents the action taken when setting clocks.
+      0 means not setting frequency hopping and just set clock mux.
+      1 means setting frequency hopping first if the voltage is increasing, but
+      setting clock mux first if the voltage is decreasing.
+    allOf:
+      - $ref: "/schemas/types.yaml#/definitions/uint32"
+      - enum: [0, 1]
+    maxItems: 1
+
+patternProperties:
+  "^mediatek,mux_+$":
+    description:
+      A series of properties with "mediatek,mux_" prefix.
+      Each property represents one clock mux, and its value is a list of all
+      the clock sources for it. The postfix and every item in the property
+      must be from the clock-names.
+
+  "^mediatek,hopping_+$":
+    description:
+      A cell with the same size as opp numbers of an opp table for any MM module
+      and each entry represents the clock rate for each opp. For example, the
+      first entry is the clock rate set in opp-0, and the second entry is the
+      clock rate set in opp-1.
+
+required:
+  - compatible
+  - operating-points-v2
+  - mediatek,support_mux
+  - clock
+  - clock-names
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt6779-clk.h>
+
+    opp_table_mm: opp-table-mm {
+        compatible = "operating-points-v2";
+
+        opp-0 {
+            opp-hz = /bits/ 64 <315000000>;
+            opp-microvolt = <650000>;
+        };
+        opp-1 {
+            opp-hz = /bits/ 64 <450000000>;
+            opp-microvolt = <725000>;
+        };
+        opp-2 {
+            opp-hz = /bits/ 64 <606000000>;
+            opp-microvolt = <825000>;
+        };
+    };
+
+    opp_table_cam: opp-table-cam {
+        compatible = "operating-points-v2";
+
+        opp-0 {
+            opp-hz = /bits/ 64 <315000000>;
+            opp-microvolt = <650000>;
+        };
+        opp-1 {
+            opp-hz = /bits/ 64 <416000000>;
+            opp-microvolt = <725000>;
+        };
+        opp-2 {
+            opp-hz = /bits/ 64 <560000000>;
+            opp-microvolt = <825000>;
+        };
+    };
+
+    /* Other opp tables for multimedia modules */
+
+    mmdvfs {
+        compatible = "mediatek,mmdvfs";
+
+        operating-points-v2 = <&opp_table_mm>;
+
+        mediatek,support_mux = "mm", "cam", "img", "ipe",
+            "venc", "vdec", "dpe", "ccu";
+
+        mediatek,mux_mm = "clk_mmpll_d5_d2",
+            "clk_mmpll_d7", "clk_tvdpll_mainpll_d2_ck";
+        mediatek,mux_cam = "clk_mmpll_d5_d2",
+            "clk_univpll_d3", "clk_adsppll_d5";
+        mediatek,mux_img = "clk_mmpll_d5_d2",
+            "clk_univpll_d3", "clk_tvdpll_mainpll_d2_ck";
+        mediatek,mux_ipe = "clk_mmpll_d5_d2",
+            "clk_univpll_d3", "clk_mainpll_d2";
+        mediatek,mux_venc = "clk_mainpll_d3",
+            "clk_mmpll_d7", "clk_mmpll_d5";
+        mediatek,mux_vdec = "clk_univpll_d2_d2",
+            "clk_univpll_d3", "clk_univpll_d2";
+        mediatek,mux_dpe = "clk_mainpll_d3",
+            "clk_mmpll_d7", "clk_mainpll_d2";
+        mediatek,mux_ccu = "clk_mmpll_d5_d2",
+            "clk_univpll_d3", "clk_adsppll_d5";
+
+        mediatek,support_hopping = "clk_mmpll_ck";
+        mediatek,hopping_clk_mmpll_ck = <630000000 630000000 650000000>;
+        mediatek,action = <1>;
+
+
+        clocks = <&topckgen CLK_TOP_MM>,
+                <&topckgen CLK_TOP_CAM>,
+                <&topckgen CLK_TOP_IMG>,
+                <&topckgen CLK_TOP_IPE>,
+                <&topckgen CLK_TOP_VENC>,
+                <&topckgen CLK_TOP_VDEC>,
+                <&topckgen CLK_TOP_DPE>,
+                <&topckgen CLK_TOP_CCU>,
+                <&topckgen CLK_TOP_MMPLL_D5>,
+                <&topckgen CLK_TOP_UNIVPLL_D2>,
+                <&topckgen CLK_TOP_TVDPLL_MAINPLL_D2_CK>,
+                <&topckgen CLK_TOP_ADSPPLL_D5>,
+                <&topckgen CLK_TOP_MAINPLL_D2>,
+                <&topckgen CLK_TOP_MMPLL_D6>,
+                <&topckgen CLK_TOP_MMPLL_D7>,
+                <&topckgen CLK_TOP_UNIVPLL_D3>,
+                <&topckgen CLK_TOP_MAINPLL_D3>,
+                <&topckgen CLK_TOP_MMPLL_D5_D2>,
+                <&topckgen CLK_TOP_UNIVPLL_D2_D2>,
+                <&topckgen CLK_TOP_MMPLL_CK>;
+        clock-names = "mm",
+                "cam",
+                "img",
+                "ipe",
+                "venc",
+                "vdec",
+                "dpe",
+                "ccu",
+                "clk_mmpll_d5",
+                "clk_univpll_d2",
+                "clk_tvdpll_mainpll_d2_ck",
+                "clk_adsppll_d5",
+                "clk_mainpll_d2",
+                "clk_mmpll_d6",
+                "clk_mmpll_d7",
+                "clk_univpll_d3",
+                "clk_mainpll_d3",
+                "clk_mmpll_d5_d2",
+                "clk_univpll_d2_d2",
+                "clk_mmpll_ck";
+    };
+...
-- 
1.7.9.5

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

* [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver
  2020-04-15 11:18 Add Mediatek MMDVFS driver Anthony Huang
  2020-04-15 11:18 ` [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver Anthony Huang
@ 2020-04-15 11:18 ` Anthony Huang
  2020-04-15 15:25   ` Randy Dunlap
  1 sibling, 1 reply; 6+ messages in thread
From: Anthony Huang @ 2020-04-15 11:18 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
	wsd_upstream, Anthony Huang

Mediatek MMDVFS driver is used to set clk for Mediatek multimedia
hardwares. The MMDVFS registers a regulator callback and multimedia
hardwares set voltage by regulator API and then this callback will be
triggered. The MMDVFS will get current opp level from opp table according
to the voltage, and then the MMDVFS sets all the clock MUXs to the clock
sources according to the opp level.

On some platforms, both clock MUX and frequency hopping need to be used
together. The MMDVFS supports these two clock setting methods and the
execution sequence of them can be configured in DTS.

Signed-off-by: Anthony Huang <anthony.huang@mediatek.com>
---
 drivers/soc/mediatek/Kconfig      |    9 ++
 drivers/soc/mediatek/Makefile     |    1 +
 drivers/soc/mediatek/mtk-mmdvfs.c |  312 +++++++++++++++++++++++++++++++++++++
 3 files changed, 322 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-mmdvfs.c

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 2114b56..e92762b 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -44,4 +44,13 @@ config MTK_SCPSYS
 	  Say yes here to add support for the MediaTek SCPSYS power domain
 	  driver.
 
+config MTK_MMDVFS
+	tristate "MediaTek MMDVFS Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  Say yes here to add support for the MediaTek Multimedia DVFS (MMDVFS)
+	  driver. The MMDVFS is used to set clk for Mediatek multimedia hardwares
+	  , such as display, camera, mdp and video codec. Say no if your device
+	  does not need to do DVFS for Multimedia hardwares.
+
 endmenu
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index b017330..faf52944 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+obj-$(CONFIG_MTK_MMDVFS) += mtk-mmdvfs.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-mmdvfs.c b/drivers/soc/mediatek/mtk-mmdvfs.c
new file mode 100644
index 0000000..466d266
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-mmdvfs.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regulator/consumer.h>
+
+#define MAX_OPP_NUM (6)
+#define MAX_MUX_NUM (10)
+#define MAX_HOPPING_CLK_NUM (2)
+
+enum {
+	ACTION_DEFAULT,
+	ACTION_IHDM, /* Voltage Increase: Hopping First, Decrease: MUX First*/
+};
+
+struct mmdvfs_mux_data {
+	const char *mux_name;
+	struct clk *mux;
+	struct clk *clk_src[MAX_OPP_NUM];
+};
+
+struct mmdvfs_hopping_data {
+	const char *hopping_name;
+	struct clk *hopping_clk;
+	u32 hopping_rate[MAX_OPP_NUM];
+};
+
+struct mmdvfs_drv_data {
+	bool need_change_voltage;
+	u32 request_voltage;
+	u32 num_muxes;
+	struct mmdvfs_mux_data muxes[MAX_MUX_NUM];
+	u32 num_hoppings;
+	struct mmdvfs_hopping_data hoppings[MAX_HOPPING_CLK_NUM];
+	u32 action;
+	struct notifier_block nb;
+	u32 voltages[MAX_OPP_NUM];
+};
+
+static void set_all_muxes(struct mmdvfs_drv_data *drv_data, u32 opp_level)
+{
+	u32 num_muxes = drv_data->num_muxes;
+	u32 i;
+	struct clk *mux, *clk_src;
+	s32 err;
+
+	for (i = 0; i < num_muxes; i++) {
+		mux = drv_data->muxes[i].mux;
+		clk_src = drv_data->muxes[i].clk_src[opp_level];
+		err = clk_prepare_enable(mux);
+
+		if (err) {
+			pr_notice("prepare mux(%s) fail:%d opp_level:%d\n",
+				  drv_data->muxes[i].mux_name, err, opp_level);
+			continue;
+		}
+		err = clk_set_parent(mux, clk_src);
+		if (err)
+			pr_notice("set parent(%s) fail:%d opp_level:%d\n",
+				  drv_data->muxes[i].mux_name, err, opp_level);
+		clk_disable_unprepare(mux);
+	}
+}
+
+static void set_all_hoppings(struct mmdvfs_drv_data *drv_data, u32 opp_level)
+{
+	u32 num_hoppings = drv_data->num_hoppings;
+	u32 i, hopping_rate;
+	struct clk *hopping;
+	s32 err;
+
+	for (i = 0; i < num_hoppings; i++) {
+		hopping = drv_data->hoppings[i].hopping_clk;
+		hopping_rate = drv_data->hoppings[i].hopping_rate[opp_level];
+		err = clk_prepare_enable(hopping);
+
+		if (err) {
+			pr_notice("prepare hopping(%s) fail:%d opp_level:%d\n",
+				  drv_data->hoppings[i].hopping_name,
+				  err, opp_level);
+			continue;
+		}
+		err = clk_set_rate(hopping, hopping_rate);
+		if (err)
+			pr_notice("set %s rate(%u) fail:%d opp_level:%d\n",
+				  drv_data->hoppings[i].hopping_name,
+				  hopping_rate, err, opp_level);
+		clk_disable_unprepare(hopping);
+	}
+}
+
+static void set_all_clk(struct mmdvfs_drv_data *drv_data,
+			u32 voltage, bool vol_inc)
+{
+	u32 i;
+	u32 opp_level;
+
+	for (i = 0; i < MAX_OPP_NUM; i++) {
+		if (drv_data->voltages[i] == voltage) {
+			opp_level = i;
+			break;
+		}
+	}
+	if (i == MAX_OPP_NUM) {
+		pr_notice("voltage(%d) is not found\n", voltage);
+		return;
+	}
+
+	switch (drv_data->action) {
+	/* Voltage Increase: Hopping First, Decrease: MUX First*/
+	case ACTION_IHDM:
+		if (vol_inc) {
+			set_all_hoppings(drv_data, opp_level);
+			set_all_muxes(drv_data, opp_level);
+		} else {
+			set_all_muxes(drv_data, opp_level);
+			set_all_hoppings(drv_data, opp_level);
+		}
+		break;
+	default:
+		set_all_muxes(drv_data, opp_level);
+		break;
+	}
+	pr_debug("set clk to opp level:%d\n", opp_level);
+}
+
+static int regulator_event_notify(struct notifier_block *nb,
+				  unsigned long event, void *data)
+{
+	unsigned long uV;
+	struct mmdvfs_drv_data *drv_data;
+	struct pre_voltage_change_data *pvc_data;
+
+	drv_data = container_of(nb, struct mmdvfs_drv_data, nb);
+
+	if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
+		pvc_data = data;
+		uV = pvc_data->min_uV;
+
+		if (uV < pvc_data->old_uV) {
+			set_all_clk(drv_data, uV, false);
+			drv_data->request_voltage = uV;
+		} else if (uV > pvc_data->old_uV) {
+			drv_data->need_change_voltage = true;
+		}
+		pr_debug("regulator event=PRE_VOLTAGE_CHANGE old=%lu new=%lu\n",
+			 pvc_data->old_uV, pvc_data->min_uV);
+	} else if (event == REGULATOR_EVENT_VOLTAGE_CHANGE) {
+		uV = (unsigned long)data;
+		if (drv_data->need_change_voltage) {
+			set_all_clk(drv_data, uV, true);
+			drv_data->need_change_voltage = false;
+			drv_data->request_voltage = uV;
+		}
+		pr_debug("regulator event=VOLTAGE_CHANGE voltage=%lu\n", uV);
+	} else if (event == REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) {
+		uV = (unsigned long)data;
+		/* If clk was changed, restore to previous setting */
+		if (uV != drv_data->request_voltage) {
+			set_all_clk(drv_data, uV,
+				    uV > drv_data->request_voltage);
+			drv_data->need_change_voltage = false;
+			drv_data->request_voltage = uV;
+		}
+		pr_info("regulator event=ABORT_VOLTAGE_CHANGE voltage=%lu\n",
+			uV);
+	}
+	return 0;
+}
+
+static const struct of_device_id of_mmdvfs_match_tbl[] = {
+	{
+		.compatible = "mediatek,mmdvfs",
+	},
+	{}
+};
+
+static int mmdvfs_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mmdvfs_drv_data *drv_data;
+	struct regulator *reg;
+	u32 num_mux = 0, num_hopping = 0;
+	u32 num_clksrc, index, hopping_rate, num_hopping_rate;
+	struct property *mux_prop, *clksrc_prop;
+	struct property *hopping_prop, *hopping_rate_prop;
+	const char *mux_name, *clksrc_name, *hopping_name;
+	char prop_name[32];
+	const __be32 *p;
+	s32 ret;
+	unsigned long freq;
+	struct dev_pm_opp *opp;
+
+	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	of_property_for_each_string(dev->of_node, "mediatek,support_mux",
+				    mux_prop, mux_name) {
+		if (num_mux >= MAX_MUX_NUM) {
+			pr_notice("Too many items in support_mux\n");
+			return -EINVAL;
+		}
+		drv_data->muxes[num_mux].mux = devm_clk_get(dev, mux_name);
+		drv_data->muxes[num_mux].mux_name = mux_name;
+		snprintf(prop_name, sizeof(prop_name) - 1,
+			 "mediatek,mux_%s", mux_name);
+		num_clksrc = 0;
+		of_property_for_each_string(dev->of_node, prop_name,
+					    clksrc_prop, clksrc_name) {
+			if (num_clksrc >= MAX_OPP_NUM) {
+				pr_notice("Too many items in %s\n", prop_name);
+				return -EINVAL;
+			}
+			drv_data->muxes[num_mux].clk_src[num_clksrc] =
+				devm_clk_get(dev, clksrc_name);
+			num_clksrc++;
+		}
+		num_mux++;
+	}
+	drv_data->num_muxes = num_mux;
+
+	of_property_for_each_string(dev->of_node, "mediatek,support_hopping",
+				    hopping_prop, hopping_name) {
+		if (num_hopping >= MAX_HOPPING_CLK_NUM) {
+			pr_notice("Too many items in support_hopping\n");
+			return -EINVAL;
+		}
+		drv_data->hoppings[num_hopping].hopping_clk =
+					devm_clk_get(dev, hopping_name);
+		drv_data->hoppings[num_hopping].hopping_name = hopping_name;
+		snprintf(prop_name, sizeof(prop_name) - 1,
+			 "mediatek,hopping_%s", hopping_name);
+		num_hopping_rate = 0;
+		of_property_for_each_u32(dev->of_node, prop_name,
+					 hopping_rate_prop, p, hopping_rate) {
+			if (num_hopping_rate >= MAX_OPP_NUM) {
+				pr_notice("Too many items in %s\n", prop_name);
+				return -EINVAL;
+			}
+			drv_data->hoppings[num_hopping].hopping_rate
+					[num_hopping_rate] = hopping_rate;
+			num_hopping_rate++;
+		}
+		num_hopping++;
+	}
+	drv_data->num_hoppings = num_hopping;
+
+	of_property_read_u32(dev->of_node,
+			     "mediatek,action", &drv_data->action);
+
+	/* Get voltage info from opp table */
+	dev_pm_opp_of_add_table(dev);
+	freq = 0;
+	index = 0;
+	while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) {
+		drv_data->voltages[index] = dev_pm_opp_get_voltage(opp);
+		freq++;
+		index++;
+		dev_pm_opp_put(opp);
+	}
+
+	reg = devm_regulator_get(dev, "dvfsrc-vcore");
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	drv_data->nb.notifier_call = regulator_event_notify;
+	ret = devm_regulator_register_notifier(reg, &drv_data->nb);
+	if (ret)
+		pr_notice("Failed to register notifier: %d\n", ret);
+
+	return ret;
+}
+
+static struct platform_driver mmdvfs_drv = {
+	.probe = mmdvfs_probe,
+	.driver = {
+		.name = "mtk-mmdvfs",
+		.of_match_table = of_mmdvfs_match_tbl,
+	},
+};
+
+static int __init mtk_mmdvfs_init(void)
+{
+	s32 status;
+
+	status = platform_driver_register(&mmdvfs_drv);
+	if (status) {
+		pr_notice("Failed to register MMDVFS driver(%d)\n", status);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit mtk_mmdvfs_exit(void)
+{
+	platform_driver_unregister(&mmdvfs_drv);
+}
+
+module_init(mtk_mmdvfs_init);
+module_exit(mtk_mmdvfs_exit);
+
+MODULE_DESCRIPTION("MTK MMDVFS driver");
+MODULE_AUTHOR("Anthony Huang<anthony.huang@mediatek.com>");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5

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

* Re: [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver
  2020-04-15 11:18 ` [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver Anthony Huang
@ 2020-04-15 15:25   ` Randy Dunlap
  0 siblings, 0 replies; 6+ messages in thread
From: Randy Dunlap @ 2020-04-15 15:25 UTC (permalink / raw)
  To: Anthony Huang, Rob Herring, Matthias Brugger
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream

Hi--


On 4/15/20 4:18 AM, Anthony Huang wrote:
> Mediatek MMDVFS driver is used to set clk for Mediatek multimedia
> hardwares. The MMDVFS registers a regulator callback and multimedia

  hardware.

> hardwares set voltage by regulator API and then this callback will be

  hardware

> triggered. The MMDVFS will get current opp level from opp table according
> to the voltage, and then the MMDVFS sets all the clock MUXs to the clock
> sources according to the opp level.
> 
> On some platforms, both clock MUX and frequency hopping need to be used
> together. The MMDVFS supports these two clock setting methods and the
> execution sequence of them can be configured in DTS.
> 
> Signed-off-by: Anthony Huang <anthony.huang@mediatek.com>
> ---
>  drivers/soc/mediatek/Kconfig      |    9 ++
>  drivers/soc/mediatek/Makefile     |    1 +
>  drivers/soc/mediatek/mtk-mmdvfs.c |  312 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 322 insertions(+)
>  create mode 100644 drivers/soc/mediatek/mtk-mmdvfs.c
> 
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 2114b56..e92762b 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -44,4 +44,13 @@ config MTK_SCPSYS
>  	  Say yes here to add support for the MediaTek SCPSYS power domain
>  	  driver.
>  
> +config MTK_MMDVFS
> +	tristate "MediaTek MMDVFS Support"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	help
> +	  Say yes here to add support for the MediaTek Multimedia DVFS (MMDVFS)
> +	  driver. The MMDVFS is used to set clk for Mediatek multimedia hardwares

	                                                                hardware,

> +	  , such as display, camera, mdp and video codec. Say no if your device

	  ^drop that comma.

> +	  does not need to do DVFS for Multimedia hardwares.

	                                          hardware.

> +
>  endmenu


thanks.
-- 
~Randy


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

* Re: [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver
  2020-04-15 11:18 ` [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver Anthony Huang
@ 2020-04-15 16:30   ` Chun-Kuang Hu
  2020-04-16 20:45   ` Rob Herring
  1 sibling, 0 replies; 6+ messages in thread
From: Chun-Kuang Hu @ 2020-04-15 16:30 UTC (permalink / raw)
  To: Anthony Huang
  Cc: Rob Herring, Matthias Brugger, devicetree, wsd_upstream,
	linux-kernel, moderated list:ARM/Mediatek SoC support, Linux ARM

Hi, Anthony:

Anthony Huang <anthony.huang@mediatek.com> 於 2020年4月15日 週三 下午7:19寫道:
>
> This document describes the properties what mtk mmdvfs
> device node support.
>
> Signed-off-by: Anthony Huang <anthony.huang@mediatek.com>
> ---
>  .../devicetree/bindings/soc/mediatek/mmdvfs.yaml   |  198 ++++++++++++++++++++
>  1 file changed, 198 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
>
> diff --git a/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml b/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
> new file mode 100644
> index 0000000..9ef1833
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
> @@ -0,0 +1,198 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/mediatek/mmdvfs.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Mediatek MMDVFS driver binding
> +
> +maintainers:
> +  - Rob Herring <robh+dt@kernel.org>
> +  - Mark Rutland <mark.rutland@arm.com>
> +
> +description: |
> +  The Mediatek MMDVFS(Multimedia Dynamic Voltage and Frequency Scaling) driver
> +  is used to set clk for Mediatek multimedia hardwares, such as display,
> +  camera, mdp and video codec. MMDVFS driver reads which clock muxes and clock
> +  sources are used on this platform from DTS, and sets current clock according
> +  to current voltage informed by regulator callback.
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: mediatek,mmdvfs
> +
> +  operating-points-v2:
> +    description:
> +      Contains any one of opp tables for multimedia modules.
> +      MMDVFS uses it to get voltage setting on this platform.
> +
> +  mediatek,support_mux:
> +    description: A list of clock mux names defined in clock-names.
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/string-array
> +
> +  clocks:
> +    description:
> +      A list of phandles of clock muxes and clock sources for
> +      multimedia hardwares.
> +
> +  clock-names:
> +    description:
> +      A list of name strings of clock muxes and clock sources for
> +      multimedia hardwares.
> +
> +  # If the platform needs frequency hopping for some clock sources, these
> +  # following properties should be set.
> +
> +  mediatek,support_hopping:
> +    description: a list of clock names supporting frequency hopping.
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/string-array
> +
> +  mediatek,action:
> +    description:
> +      A cell with one entry.
> +      It represents the action taken when setting clocks.
> +      0 means not setting frequency hopping and just set clock mux.
> +      1 means setting frequency hopping first if the voltage is increasing, but
> +      setting clock mux first if the voltage is decreasing.
> +    allOf:
> +      - $ref: "/schemas/types.yaml#/definitions/uint32"
> +      - enum: [0, 1]
> +    maxItems: 1
> +
> +patternProperties:
> +  "^mediatek,mux_+$":
> +    description:
> +      A series of properties with "mediatek,mux_" prefix.
> +      Each property represents one clock mux, and its value is a list of all
> +      the clock sources for it. The postfix and every item in the property
> +      must be from the clock-names.
> +
> +  "^mediatek,hopping_+$":
> +    description:
> +      A cell with the same size as opp numbers of an opp table for any MM module
> +      and each entry represents the clock rate for each opp. For example, the
> +      first entry is the clock rate set in opp-0, and the second entry is the
> +      clock rate set in opp-1.
> +
> +required:
> +  - compatible
> +  - operating-points-v2
> +  - mediatek,support_mux
> +  - clock
> +  - clock-names
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/mt6779-clk.h>
> +
> +    opp_table_mm: opp-table-mm {
> +        compatible = "operating-points-v2";
> +
> +        opp-0 {
> +            opp-hz = /bits/ 64 <315000000>;
> +            opp-microvolt = <650000>;
> +        };
> +        opp-1 {
> +            opp-hz = /bits/ 64 <450000000>;
> +            opp-microvolt = <725000>;
> +        };
> +        opp-2 {
> +            opp-hz = /bits/ 64 <606000000>;
> +            opp-microvolt = <825000>;
> +        };
> +    };
> +
> +    opp_table_cam: opp-table-cam {
> +        compatible = "operating-points-v2";
> +
> +        opp-0 {
> +            opp-hz = /bits/ 64 <315000000>;
> +            opp-microvolt = <650000>;
> +        };
> +        opp-1 {
> +            opp-hz = /bits/ 64 <416000000>;
> +            opp-microvolt = <725000>;
> +        };
> +        opp-2 {
> +            opp-hz = /bits/ 64 <560000000>;
> +            opp-microvolt = <825000>;
> +        };
> +    };
> +
> +    /* Other opp tables for multimedia modules */
> +
> +    mmdvfs {
> +        compatible = "mediatek,mmdvfs";
> +
> +        operating-points-v2 = <&opp_table_mm>;
> +
> +        mediatek,support_mux = "mm", "cam", "img", "ipe",
> +            "venc", "vdec", "dpe", "ccu";
> +
> +        mediatek,mux_mm = "clk_mmpll_d5_d2",
> +            "clk_mmpll_d7", "clk_tvdpll_mainpll_d2_ck";
> +        mediatek,mux_cam = "clk_mmpll_d5_d2",
> +            "clk_univpll_d3", "clk_adsppll_d5";
> +        mediatek,mux_img = "clk_mmpll_d5_d2",
> +            "clk_univpll_d3", "clk_tvdpll_mainpll_d2_ck";
> +        mediatek,mux_ipe = "clk_mmpll_d5_d2",
> +            "clk_univpll_d3", "clk_mainpll_d2";
> +        mediatek,mux_venc = "clk_mainpll_d3",
> +            "clk_mmpll_d7", "clk_mmpll_d5";
> +        mediatek,mux_vdec = "clk_univpll_d2_d2",
> +            "clk_univpll_d3", "clk_univpll_d2";
> +        mediatek,mux_dpe = "clk_mainpll_d3",
> +            "clk_mmpll_d7", "clk_mainpll_d2";
> +        mediatek,mux_ccu = "clk_mmpll_d5_d2",
> +            "clk_univpll_d3", "clk_adsppll_d5";
> +
> +        mediatek,support_hopping = "clk_mmpll_ck";
> +        mediatek,hopping_clk_mmpll_ck = <630000000 630000000 650000000>;
> +        mediatek,action = <1>;
> +
> +
> +        clocks = <&topckgen CLK_TOP_MM>,
> +                <&topckgen CLK_TOP_CAM>,
> +                <&topckgen CLK_TOP_IMG>,
> +                <&topckgen CLK_TOP_IPE>,
> +                <&topckgen CLK_TOP_VENC>,
> +                <&topckgen CLK_TOP_VDEC>,
> +                <&topckgen CLK_TOP_DPE>,
> +                <&topckgen CLK_TOP_CCU>,
> +                <&topckgen CLK_TOP_MMPLL_D5>,
> +                <&topckgen CLK_TOP_UNIVPLL_D2>,
> +                <&topckgen CLK_TOP_TVDPLL_MAINPLL_D2_CK>,
> +                <&topckgen CLK_TOP_ADSPPLL_D5>,
> +                <&topckgen CLK_TOP_MAINPLL_D2>,
> +                <&topckgen CLK_TOP_MMPLL_D6>,
> +                <&topckgen CLK_TOP_MMPLL_D7>,
> +                <&topckgen CLK_TOP_UNIVPLL_D3>,
> +                <&topckgen CLK_TOP_MAINPLL_D3>,
> +                <&topckgen CLK_TOP_MMPLL_D5_D2>,
> +                <&topckgen CLK_TOP_UNIVPLL_D2_D2>,
> +                <&topckgen CLK_TOP_MMPLL_CK>;
> +        clock-names = "mm",
> +                "cam",
> +                "img",
> +                "ipe",
> +                "venc",
> +                "vdec",
> +                "dpe",
> +                "ccu",
> +                "clk_mmpll_d5",
> +                "clk_univpll_d2",
> +                "clk_tvdpll_mainpll_d2_ck",
> +                "clk_adsppll_d5",
> +                "clk_mainpll_d2",
> +                "clk_mmpll_d6",
> +                "clk_mmpll_d7",
> +                "clk_univpll_d3",
> +                "clk_mainpll_d3",
> +                "clk_mmpll_d5_d2",
> +                "clk_univpll_d2_d2",
> +                "clk_mmpll_ck";
> +    };

We do not like a virtual device which does not map to a real hardware
because device tree is used to describe hardware. All mmdvfs driver do
is to controll the clock, so I think you should move the driver into
drivers/clk/mediatek, move opp_table into driver, and forget anything
in device tree.

Regards,
Chun-Kuang.

> +...
> --
> 1.7.9.5
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver
  2020-04-15 11:18 ` [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver Anthony Huang
  2020-04-15 16:30   ` Chun-Kuang Hu
@ 2020-04-16 20:45   ` Rob Herring
  1 sibling, 0 replies; 6+ messages in thread
From: Rob Herring @ 2020-04-16 20:45 UTC (permalink / raw)
  To: Anthony Huang
  Cc: Matthias Brugger, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, wsd_upstream, Anthony Huang

On Wed, 15 Apr 2020 19:18:25 +0800, Anthony Huang wrote:
> This document describes the properties what mtk mmdvfs
> device node support.
> 
> Signed-off-by: Anthony Huang <anthony.huang@mediatek.com>
> ---
>  .../devicetree/bindings/soc/mediatek/mmdvfs.yaml   |  198 ++++++++++++++++++++
>  1 file changed, 198 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mmdvfs.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.example.dt.yaml: example-0: opp-table-mm: {'compatible': ['operating-points-v2'], 'phandle': [[1]], 'opp-0': {'opp-hz': [[315000000]], 'opp-microvolt': [[650000]]}, 'opp-1': {'opp-hz': [[450000000]], 'opp-microvolt': [[725000]]}, 'opp-2': {'opp-hz': [[606000000]], 'opp-microvolt': [[825000]]}} is not valid under any of the given schemas (Possible causes of the failure):
	/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.example.dt.yaml: example-0: opp-table-mm: {'compatible': ['operating-points-v2'], 'phandle': [[1]], 'opp-0': {'opp-hz': [[315000000]], 'opp-microvolt': [[650000]]}, 'opp-1': {'opp-hz': [[450000000]], 'opp-microvolt': [[725000]]}, 'opp-2': {'opp-hz': [[606000000]], 'opp-microvolt': [[825000]]}} is not of type 'array'

/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/soc/mediatek/mmdvfs.example.dt.yaml: mmdvfs: 'clock' is a required property

See https://patchwork.ozlabs.org/patch/1271100

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure dt-schema is up to date:

pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade

Please check and re-submit.

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

end of thread, other threads:[~2020-04-16 20:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-15 11:18 Add Mediatek MMDVFS driver Anthony Huang
2020-04-15 11:18 ` [PATCH 1/2] dt-bindings: soc: mediatek: Add document for mmdvfs driver Anthony Huang
2020-04-15 16:30   ` Chun-Kuang Hu
2020-04-16 20:45   ` Rob Herring
2020-04-15 11:18 ` [PATCH 2/2] soc: mediatek: Add mtk-mmdvfs driver Anthony Huang
2020-04-15 15:25   ` Randy Dunlap

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).