All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Add cpufreq and cci devfreq for mt8183
@ 2019-03-29  6:46 ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	fan.chen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

MT8183 supports CPU DVFS and CCI DVFS, and LITTLE cpus and CCI are in the same voltage domain.
So, this series is to add drivers to handle the voltage coupling between CPU and CCI DVFS.

1. coding style refine
2. Move regulator_register_notifier() into mtk_cci_governor_event_handler()
3. Add dev_pm_opp_find_max_freq_by_volt() API for opp framework.


Andrew-sh.Cheng (4):
  cpufreq: mediatek: add mt8183 cpufreq support
  opp: add API which get max freq by voltage
  dt-bindings: devfreq: add compatible for mt8183 cci devfreq
  devfreq: add mediatek cci devfreq

 .../bindings/devfreq/mt8183-cci-devfreq.txt        |  19 ++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   1 +
 drivers/cpufreq/mediatek-cpufreq.c                 |  12 +-
 drivers/devfreq/Kconfig                            |  10 +
 drivers/devfreq/Makefile                           |   1 +
 drivers/devfreq/mt8183-cci-devfreq.c               | 235 +++++++++++++++++++++
 drivers/opp/core.c                                 |  55 +++++
 include/linux/pm_opp.h                             |   8 +
 8 files changed, 339 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
 create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c

-- 
1.8.1.1.dirty

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

* [PATCH v2 0/4] Add cpufreq and cci devfreq for mt8183
@ 2019-03-29  6:46 ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, srv_heupstream, linux-pm, linux-kernel, fan.chen,
	linux-mediatek, linux-arm-kernel

MT8183 supports CPU DVFS and CCI DVFS, and LITTLE cpus and CCI are in the same voltage domain.
So, this series is to add drivers to handle the voltage coupling between CPU and CCI DVFS.

1. coding style refine
2. Move regulator_register_notifier() into mtk_cci_governor_event_handler()
3. Add dev_pm_opp_find_max_freq_by_volt() API for opp framework.


Andrew-sh.Cheng (4):
  cpufreq: mediatek: add mt8183 cpufreq support
  opp: add API which get max freq by voltage
  dt-bindings: devfreq: add compatible for mt8183 cci devfreq
  devfreq: add mediatek cci devfreq

 .../bindings/devfreq/mt8183-cci-devfreq.txt        |  19 ++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   1 +
 drivers/cpufreq/mediatek-cpufreq.c                 |  12 +-
 drivers/devfreq/Kconfig                            |  10 +
 drivers/devfreq/Makefile                           |   1 +
 drivers/devfreq/mt8183-cci-devfreq.c               | 235 +++++++++++++++++++++
 drivers/opp/core.c                                 |  55 +++++
 include/linux/pm_opp.h                             |   8 +
 8 files changed, 339 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
 create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c

-- 
1.8.1.1.dirty


_______________________________________________
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] 46+ messages in thread

* [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
  2019-03-29  6:46 ` Andrew-sh.Cheng
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Andrew-sh.Cheng,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	fan.chen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

For new mediatek chip mt8183,
cci and little cluster share the same buck,
so need to modify the attribute of regulator from exclusive to optional

Intermediate clock is not always enabled by ccf in different projects,
so cpufreq should always enable it by itself.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
 drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 47729a2..53ea52b 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -117,6 +117,7 @@
 	{ .compatible = "mediatek,mt817x", },
 	{ .compatible = "mediatek,mt8173", },
 	{ .compatible = "mediatek,mt8176", },
+	{ .compatible = "mediatek,mt8183", },
 
 	{ .compatible = "nvidia,tegra124", },
 	{ .compatible = "nvidia,tegra210", },
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 48e9829..7cd01d3 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 		goto out_free_resources;
 	}
 
-	proc_reg = regulator_get_exclusive(cpu_dev, "proc");
+	proc_reg = regulator_get_optional(cpu_dev, "proc");
 	if (IS_ERR(proc_reg)) {
 		if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
 			pr_warn("proc regulator for cpu%d not ready, retry.\n",
@@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 		goto out_free_resources;
 	}
 
+	ret = clk_prepare_enable(inter_clk);
+	if (ret)
+		goto out_free_opp_table;
+
 	/* Search a safe voltage for intermediate frequency. */
 	rate = clk_get_rate(inter_clk);
 	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
 	if (IS_ERR(opp)) {
 		pr_err("failed to get intermediate opp for cpu%d\n", cpu);
 		ret = PTR_ERR(opp);
-		goto out_free_opp_table;
+		goto out_disable_clock;
 	}
 	info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
 	dev_pm_opp_put(opp);
@@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 
 	return 0;
 
+out_disable_clock:
+	clk_disable_unprepare(inter_clk);
+
 out_free_opp_table:
 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 
@@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
 	{ .compatible = "mediatek,mt817x", },
 	{ .compatible = "mediatek,mt8173", },
 	{ .compatible = "mediatek,mt8176", },
+	{ .compatible = "mediatek,mt8183", },
 
 	{ }
 };
-- 
1.8.1.1.dirty

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

* [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

For new mediatek chip mt8183,
cci and little cluster share the same buck,
so need to modify the attribute of regulator from exclusive to optional

Intermediate clock is not always enabled by ccf in different projects,
so cpufreq should always enable it by itself.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
---
 drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
 drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 47729a2..53ea52b 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -117,6 +117,7 @@
 	{ .compatible = "mediatek,mt817x", },
 	{ .compatible = "mediatek,mt8173", },
 	{ .compatible = "mediatek,mt8176", },
+	{ .compatible = "mediatek,mt8183", },
 
 	{ .compatible = "nvidia,tegra124", },
 	{ .compatible = "nvidia,tegra210", },
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 48e9829..7cd01d3 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 		goto out_free_resources;
 	}
 
-	proc_reg = regulator_get_exclusive(cpu_dev, "proc");
+	proc_reg = regulator_get_optional(cpu_dev, "proc");
 	if (IS_ERR(proc_reg)) {
 		if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
 			pr_warn("proc regulator for cpu%d not ready, retry.\n",
@@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 		goto out_free_resources;
 	}
 
+	ret = clk_prepare_enable(inter_clk);
+	if (ret)
+		goto out_free_opp_table;
+
 	/* Search a safe voltage for intermediate frequency. */
 	rate = clk_get_rate(inter_clk);
 	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
 	if (IS_ERR(opp)) {
 		pr_err("failed to get intermediate opp for cpu%d\n", cpu);
 		ret = PTR_ERR(opp);
-		goto out_free_opp_table;
+		goto out_disable_clock;
 	}
 	info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
 	dev_pm_opp_put(opp);
@@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 
 	return 0;
 
+out_disable_clock:
+	clk_disable_unprepare(inter_clk);
+
 out_free_opp_table:
 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 
@@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
 	{ .compatible = "mediatek,mt817x", },
 	{ .compatible = "mediatek,mt8173", },
 	{ .compatible = "mediatek,mt8176", },
+	{ .compatible = "mediatek,mt8183", },
 
 	{ }
 };
-- 
1.8.1.1.dirty


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

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

* [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-03-29  6:46 ` Andrew-sh.Cheng
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Andrew-sh.Cheng,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	fan.chen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

This API will get voltage as input parameter.
Search all opp items for the item which with max frequency,
and the voltae is smaller than provided voltage.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h |  8 ++++++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 0420f7e..7323cd9 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
+/**
+ * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
+ * under provided voltage
+ * @dev:	device for which we do this operation
+ * @u_volt:	provided voltage
+ *
+ * Search for the matching available OPP which provide voltage can support.
+ *
+ * Return: matching *opp, else returns ERR_PTR in case of error
+ * and should be handled using IS_ERR.
+ * Error return values can be:
+ * EINVAL:	for bad pointer
+ * ERANGE:	no match found for search
+ * ENODEV:	if device not found in list of registered devices
+ *
+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
+ * use.
+ */
+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt)
+{
+	struct opp_table *opp_table;
+	struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+
+	if (!dev || !u_volt) {
+		dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
+			u_volt);
+		return ERR_PTR(-EINVAL);
+	}
+
+	opp_table = _find_opp_table(dev);
+	if (IS_ERR(opp_table))
+		return ERR_CAST(opp_table);
+
+	mutex_lock(&opp_table->lock);
+
+	list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
+		if (temp_opp->available) {
+			/* go to the next node, before choosing prev */
+			if (temp_opp->supplies[0].u_volt > u_volt)
+				break;
+			opp = temp_opp;
+		}
+	}
+
+	/* Increment the reference count of OPP */
+	if (!IS_ERR(opp))
+		dev_pm_opp_get(opp);
+	mutex_unlock(&opp_table->lock);
+	dev_pm_opp_put_opp_table(opp_table);
+
+	return opp;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
+
 static int _set_opp_voltage(struct device *dev, struct regulator *reg,
 			    struct dev_pm_opp_supply *supply)
 {
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 24c757a..57deef9 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 
 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 					      unsigned long *freq);
+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					     unsigned long *freq);
@@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 	return ERR_PTR(-ENOTSUPP);
 }
 
+static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					unsigned long *freq)
 {
-- 
1.8.1.1.dirty

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

* [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

This API will get voltage as input parameter.
Search all opp items for the item which with max frequency,
and the voltae is smaller than provided voltage.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
---
 drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h |  8 ++++++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 0420f7e..7323cd9 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
+/**
+ * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
+ * under provided voltage
+ * @dev:	device for which we do this operation
+ * @u_volt:	provided voltage
+ *
+ * Search for the matching available OPP which provide voltage can support.
+ *
+ * Return: matching *opp, else returns ERR_PTR in case of error
+ * and should be handled using IS_ERR.
+ * Error return values can be:
+ * EINVAL:	for bad pointer
+ * ERANGE:	no match found for search
+ * ENODEV:	if device not found in list of registered devices
+ *
+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
+ * use.
+ */
+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt)
+{
+	struct opp_table *opp_table;
+	struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+
+	if (!dev || !u_volt) {
+		dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
+			u_volt);
+		return ERR_PTR(-EINVAL);
+	}
+
+	opp_table = _find_opp_table(dev);
+	if (IS_ERR(opp_table))
+		return ERR_CAST(opp_table);
+
+	mutex_lock(&opp_table->lock);
+
+	list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
+		if (temp_opp->available) {
+			/* go to the next node, before choosing prev */
+			if (temp_opp->supplies[0].u_volt > u_volt)
+				break;
+			opp = temp_opp;
+		}
+	}
+
+	/* Increment the reference count of OPP */
+	if (!IS_ERR(opp))
+		dev_pm_opp_get(opp);
+	mutex_unlock(&opp_table->lock);
+	dev_pm_opp_put_opp_table(opp_table);
+
+	return opp;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
+
 static int _set_opp_voltage(struct device *dev, struct regulator *reg,
 			    struct dev_pm_opp_supply *supply)
 {
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 24c757a..57deef9 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 
 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 					      unsigned long *freq);
+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					     unsigned long *freq);
@@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 	return ERR_PTR(-ENOTSUPP);
 }
 
+static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
+					      unsigned long u_volt)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					unsigned long *freq)
 {
-- 
1.8.1.1.dirty


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

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

* [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
  2019-03-29  6:46 ` Andrew-sh.Cheng
@ 2019-03-29  6:46   ` Andrew-sh.Cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

This adds dt-binding documentation of cci devfreq
for Mediatek MT8183 SoC platform.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
---
 .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt

diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
new file mode 100644
index 0000000..e2b61cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
@@ -0,0 +1,19 @@
+* Mediatek CCI frequency device
+
+Required properties:
+- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
+
+- clocks: for cci devfreq
+
+- clock-names: for cci devfreq driver to reference
+
+- operating-points-v2: for cci devfreq opp table
+
+Example:
+	cci: cci {
+		compatible = "mediatek,cci";
+		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
+		clock-names = "cci_clock";
+		operating-points-v2 = <&cci_opp>;
+	};
+
-- 
1.8.1.1.dirty

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

* [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
@ 2019-03-29  6:46   ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

This adds dt-binding documentation of cci devfreq
for Mediatek MT8183 SoC platform.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
---
 .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt

diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
new file mode 100644
index 0000000..e2b61cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
@@ -0,0 +1,19 @@
+* Mediatek CCI frequency device
+
+Required properties:
+- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
+
+- clocks: for cci devfreq
+
+- clock-names: for cci devfreq driver to reference
+
+- operating-points-v2: for cci devfreq opp table
+
+Example:
+	cci: cci {
+		compatible = "mediatek,cci";
+		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
+		clock-names = "cci_clock";
+		operating-points-v2 = <&cci_opp>;
+	};
+
-- 
1.8.1.1.dirty


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

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

* [PATCH v2 4/4] devfreq: add mediatek cci devfreq
  2019-03-29  6:46 ` Andrew-sh.Cheng
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Andrew-sh.Cheng,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	fan.chen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
of the Mediatek MT8183.

On the MT8183 the CCI is supplied by the same regulator as the LITTLE
cores. The driver is notified when the regulator voltage changes
(driven by cpufreq) and adjusts the CCI frequency to the maximum
possible value.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/devfreq/Kconfig              |  10 ++
 drivers/devfreq/Makefile             |   1 +
 drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 6a172d3..da2f8ec 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
 	  and adjusts the operating frequencies and voltages with OPP support.
 	  This does not yet operate with optimal voltages.
 
+config ARM_MT8183_CCI_DEVFREQ
+	tristate "MT8183 CCI DEVFREQ Driver"
+	depends on ARM_MEDIATEK_CPUFREQ
+	help
+		This adds a devfreq driver for Cache Coherent Interconnect
+		of Mediatek MT8183, which is shared the same regulator
+		with cpu cluster.
+		It can track buck voltage and update a proper cci frequency.
+		Use notification to get regulator status.
+
 config ARM_TEGRA_DEVFREQ
 	tristate "Tegra DEVFREQ Driver"
 	depends on ARCH_TEGRA_124_SOC
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 32b8d4d..817dde7 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
 
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
+obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
 
diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
new file mode 100644
index 0000000..af82d2e
--- /dev/null
+++ b/drivers/devfreq/mt8183-cci-devfreq.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/devfreq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include "governor.h"
+
+struct cci_devfreq {
+	struct devfreq		*devfreq;
+	struct regulator	*proc_reg;
+	unsigned long           proc_reg_uV;
+	struct clk		*cci_clk;
+	struct notifier_block	nb;
+};
+
+static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
+					  unsigned long val, void *data)
+{
+	struct cci_devfreq *cci_df =
+		container_of(nb, struct cci_devfreq, nb);
+
+	/* deal with reduce frequency */
+	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
+		struct pre_voltage_change_data *pvc_data = data;
+
+		if (pvc_data->min_uV < pvc_data->old_uV) {
+			cci_df->proc_reg_uV =
+				(unsigned long)(pvc_data->min_uV);
+			mutex_lock(&cci_df->devfreq->lock);
+			update_devfreq(cci_df->devfreq);
+			mutex_unlock(&cci_df->devfreq->lock);
+		}
+	}
+
+	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
+	    ((unsigned long)data > cci_df->proc_reg_uV)) {
+		cci_df->proc_reg_uV = (unsigned long)data;
+		mutex_lock(&cci_df->devfreq->lock);
+		update_devfreq(cci_df->devfreq);
+		mutex_unlock(&cci_df->devfreq->lock);
+	}
+
+	/* deal with increase frequency */
+	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
+	    (cci_df->proc_reg_uV < (unsigned long)data)) {
+		cci_df->proc_reg_uV = (unsigned long)data;
+		mutex_lock(&cci_df->devfreq->lock);
+		update_devfreq(cci_df->devfreq);
+		mutex_unlock(&cci_df->devfreq->lock);
+	}
+
+	return 0;
+}
+
+static int mtk_cci_governor_get_target(struct devfreq *devfreq,
+				       unsigned long *freq)
+{
+	struct cci_devfreq *cci_df;
+	struct dev_pm_opp *opp;
+
+	cci_df = dev_get_drvdata(devfreq->dev.parent);
+
+	/* find available frequency */
+	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
+						 cci_df->proc_reg_uV);
+	*freq = dev_pm_opp_get_freq(opp);
+
+	return 0;
+}
+
+static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
+					  unsigned int event, void *data)
+{
+	struct cci_devfreq *cci_df;
+	struct notifier_block *nb;
+
+	cci_df = dev_get_drvdata(devfreq->dev.parent);
+	nb = &cci_df->nb;
+
+	switch (event) {
+	case DEVFREQ_GOV_START:
+	case DEVFREQ_GOV_RESUME:
+		nb->notifier_call = cci_devfreq_regulator_notifier;
+		regulator_register_notifier(cci_df->proc_reg,
+					    nb);
+		break;
+
+	case DEVFREQ_GOV_STOP:
+	case DEVFREQ_GOV_SUSPEND:
+		regulator_unregister_notifier(cci_df->proc_reg,
+					    nb);
+
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct devfreq_governor mtk_cci_devfreq_governor = {
+	.name = "mtk_cci_vmon",
+	.get_target_freq = mtk_cci_governor_get_target,
+	.event_handler = mtk_cci_governor_event_handler,
+};
+
+static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
+				  u32 flags)
+{
+	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
+
+	if (!cci_df)
+		return -EINVAL;
+
+	clk_set_rate(cci_df->cci_clk, *freq);
+
+	return 0;
+}
+
+static struct devfreq_dev_profile cci_devfreq_profile = {
+	.target		= mtk_cci_devfreq_target,
+};
+
+static int mtk_cci_devfreq_probe(struct platform_device *pdev)
+{
+	struct device *cci_dev = &pdev->dev;
+	struct cci_devfreq *cci_df;
+	int ret;
+
+	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
+	if (!cci_df)
+		return -ENOMEM;
+
+	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");
+	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
+				ret);
+
+		return ret;
+	}
+
+	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");
+	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
+				ret);
+
+		goto err_put_clk;
+	}
+
+	ret = dev_pm_opp_of_add_table(&pdev->dev);
+	if (ret) {
+		dev_err(cci_dev, "Fail to init CCI OPP table\n");
+		goto err_put_reg;
+	}
+
+	platform_set_drvdata(pdev, cci_df);
+
+	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
+						       &cci_devfreq_profile,
+						       "mtk_cci_vmon",
+						       NULL);
+	if (IS_ERR(cci_df->devfreq)) {
+		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
+		goto err_put_reg;
+	}
+
+	return 0;
+
+err_put_reg:
+	regulator_put(cci_df->proc_reg);
+err_put_clk:
+	clk_put(cci_df->cci_clk);
+
+	return ret;
+}
+
+static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
+	{ .compatible = "mediatek,mt8183-cci" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
+
+static struct platform_driver cci_devfreq_driver = {
+	.probe	= mtk_cci_devfreq_probe,
+	.driver = {
+		.name = "mediatek-cci-devfreq",
+		.of_match_table = mediatek_cci_devfreq_of_match,
+	},
+};
+
+static int __init mtk_cci_devfreq_init(void)
+{
+	int ret;
+
+	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
+	if (ret) {
+		pr_err("%s: failed to add governor: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = platform_driver_register(&cci_devfreq_driver);
+	if (ret)
+		devfreq_remove_governor(&mtk_cci_devfreq_governor);
+
+	return ret;
+}
+module_init(mtk_cci_devfreq_init)
+
+static void __exit mtk_cci_devfreq_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
+	if (ret)
+		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
+
+	platform_driver_unregister(&cci_devfreq_driver);
+}
+module_exit(mtk_cci_devfreq_exit)
+
+MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
+MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.1.dirty

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

* [PATCH v2 4/4] devfreq: add mediatek cci devfreq
@ 2019-03-29  6:46     ` Andrew-sh.Cheng
  0 siblings, 0 replies; 46+ messages in thread
From: Andrew-sh.Cheng @ 2019-03-29  6:46 UTC (permalink / raw)
  To: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
of the Mediatek MT8183.

On the MT8183 the CCI is supplied by the same regulator as the LITTLE
cores. The driver is notified when the regulator voltage changes
(driven by cpufreq) and adjusts the CCI frequency to the maximum
possible value.

Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
---
 drivers/devfreq/Kconfig              |  10 ++
 drivers/devfreq/Makefile             |   1 +
 drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 6a172d3..da2f8ec 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
 	  and adjusts the operating frequencies and voltages with OPP support.
 	  This does not yet operate with optimal voltages.
 
+config ARM_MT8183_CCI_DEVFREQ
+	tristate "MT8183 CCI DEVFREQ Driver"
+	depends on ARM_MEDIATEK_CPUFREQ
+	help
+		This adds a devfreq driver for Cache Coherent Interconnect
+		of Mediatek MT8183, which is shared the same regulator
+		with cpu cluster.
+		It can track buck voltage and update a proper cci frequency.
+		Use notification to get regulator status.
+
 config ARM_TEGRA_DEVFREQ
 	tristate "Tegra DEVFREQ Driver"
 	depends on ARCH_TEGRA_124_SOC
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 32b8d4d..817dde7 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
 
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
+obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
 
diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
new file mode 100644
index 0000000..af82d2e
--- /dev/null
+++ b/drivers/devfreq/mt8183-cci-devfreq.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/devfreq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include "governor.h"
+
+struct cci_devfreq {
+	struct devfreq		*devfreq;
+	struct regulator	*proc_reg;
+	unsigned long           proc_reg_uV;
+	struct clk		*cci_clk;
+	struct notifier_block	nb;
+};
+
+static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
+					  unsigned long val, void *data)
+{
+	struct cci_devfreq *cci_df =
+		container_of(nb, struct cci_devfreq, nb);
+
+	/* deal with reduce frequency */
+	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
+		struct pre_voltage_change_data *pvc_data = data;
+
+		if (pvc_data->min_uV < pvc_data->old_uV) {
+			cci_df->proc_reg_uV =
+				(unsigned long)(pvc_data->min_uV);
+			mutex_lock(&cci_df->devfreq->lock);
+			update_devfreq(cci_df->devfreq);
+			mutex_unlock(&cci_df->devfreq->lock);
+		}
+	}
+
+	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
+	    ((unsigned long)data > cci_df->proc_reg_uV)) {
+		cci_df->proc_reg_uV = (unsigned long)data;
+		mutex_lock(&cci_df->devfreq->lock);
+		update_devfreq(cci_df->devfreq);
+		mutex_unlock(&cci_df->devfreq->lock);
+	}
+
+	/* deal with increase frequency */
+	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
+	    (cci_df->proc_reg_uV < (unsigned long)data)) {
+		cci_df->proc_reg_uV = (unsigned long)data;
+		mutex_lock(&cci_df->devfreq->lock);
+		update_devfreq(cci_df->devfreq);
+		mutex_unlock(&cci_df->devfreq->lock);
+	}
+
+	return 0;
+}
+
+static int mtk_cci_governor_get_target(struct devfreq *devfreq,
+				       unsigned long *freq)
+{
+	struct cci_devfreq *cci_df;
+	struct dev_pm_opp *opp;
+
+	cci_df = dev_get_drvdata(devfreq->dev.parent);
+
+	/* find available frequency */
+	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
+						 cci_df->proc_reg_uV);
+	*freq = dev_pm_opp_get_freq(opp);
+
+	return 0;
+}
+
+static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
+					  unsigned int event, void *data)
+{
+	struct cci_devfreq *cci_df;
+	struct notifier_block *nb;
+
+	cci_df = dev_get_drvdata(devfreq->dev.parent);
+	nb = &cci_df->nb;
+
+	switch (event) {
+	case DEVFREQ_GOV_START:
+	case DEVFREQ_GOV_RESUME:
+		nb->notifier_call = cci_devfreq_regulator_notifier;
+		regulator_register_notifier(cci_df->proc_reg,
+					    nb);
+		break;
+
+	case DEVFREQ_GOV_STOP:
+	case DEVFREQ_GOV_SUSPEND:
+		regulator_unregister_notifier(cci_df->proc_reg,
+					    nb);
+
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct devfreq_governor mtk_cci_devfreq_governor = {
+	.name = "mtk_cci_vmon",
+	.get_target_freq = mtk_cci_governor_get_target,
+	.event_handler = mtk_cci_governor_event_handler,
+};
+
+static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
+				  u32 flags)
+{
+	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
+
+	if (!cci_df)
+		return -EINVAL;
+
+	clk_set_rate(cci_df->cci_clk, *freq);
+
+	return 0;
+}
+
+static struct devfreq_dev_profile cci_devfreq_profile = {
+	.target		= mtk_cci_devfreq_target,
+};
+
+static int mtk_cci_devfreq_probe(struct platform_device *pdev)
+{
+	struct device *cci_dev = &pdev->dev;
+	struct cci_devfreq *cci_df;
+	int ret;
+
+	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
+	if (!cci_df)
+		return -ENOMEM;
+
+	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");
+	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
+				ret);
+
+		return ret;
+	}
+
+	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");
+	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
+				ret);
+
+		goto err_put_clk;
+	}
+
+	ret = dev_pm_opp_of_add_table(&pdev->dev);
+	if (ret) {
+		dev_err(cci_dev, "Fail to init CCI OPP table\n");
+		goto err_put_reg;
+	}
+
+	platform_set_drvdata(pdev, cci_df);
+
+	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
+						       &cci_devfreq_profile,
+						       "mtk_cci_vmon",
+						       NULL);
+	if (IS_ERR(cci_df->devfreq)) {
+		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
+		goto err_put_reg;
+	}
+
+	return 0;
+
+err_put_reg:
+	regulator_put(cci_df->proc_reg);
+err_put_clk:
+	clk_put(cci_df->cci_clk);
+
+	return ret;
+}
+
+static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
+	{ .compatible = "mediatek,mt8183-cci" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
+
+static struct platform_driver cci_devfreq_driver = {
+	.probe	= mtk_cci_devfreq_probe,
+	.driver = {
+		.name = "mediatek-cci-devfreq",
+		.of_match_table = mediatek_cci_devfreq_of_match,
+	},
+};
+
+static int __init mtk_cci_devfreq_init(void)
+{
+	int ret;
+
+	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
+	if (ret) {
+		pr_err("%s: failed to add governor: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = platform_driver_register(&cci_devfreq_driver);
+	if (ret)
+		devfreq_remove_governor(&mtk_cci_devfreq_governor);
+
+	return ret;
+}
+module_init(mtk_cci_devfreq_init)
+
+static void __exit mtk_cci_devfreq_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
+	if (ret)
+		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
+
+	platform_driver_unregister(&cci_devfreq_driver);
+}
+module_exit(mtk_cci_devfreq_exit)
+
+MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
+MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.1.dirty


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

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

* Re: [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
  2019-03-29  6:46     ` Andrew-sh.Cheng
  (?)
@ 2019-03-31  0:06       ` Nicolas Boichat
  -1 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-03-31  0:06 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar,
	devicetree, srv_heupstream, linux-pm, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, linux-arm Mailing List

On Thu, Mar 28, 2019 at 11:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> For new mediatek chip mt8183,
> cci and little cluster share the same buck,
> so need to modify the attribute of regulator from exclusive to optional
>
> Intermediate clock is not always enabled by ccf in different projects,
> so cpufreq should always enable it by itself.

One comment, otherwise the changes look good. However, I feel that
this patch should be split in 3:
 1. Change to regulator_get_optional
 2. Enable inter_clk
 3. Add support for 8183

> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
>  drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
>  2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 47729a2..53ea52b 100644
> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> @@ -117,6 +117,7 @@
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { .compatible = "nvidia,tegra124", },
>         { .compatible = "nvidia,tegra210", },
> diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> index 48e9829..7cd01d3 100644
> --- a/drivers/cpufreq/mediatek-cpufreq.c
> +++ b/drivers/cpufreq/mediatek-cpufreq.c
> @@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> -       proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> +       proc_reg = regulator_get_optional(cpu_dev, "proc");
>         if (IS_ERR(proc_reg)) {
>                 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
>                         pr_warn("proc regulator for cpu%d not ready, retry.\n",
> @@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> +       ret = clk_prepare_enable(inter_clk);

Should you disable the clock in mtk_cpu_dvfs_info_release?

> +       if (ret)
> +               goto out_free_opp_table;
> +
>         /* Search a safe voltage for intermediate frequency. */
>         rate = clk_get_rate(inter_clk);
>         opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
>         if (IS_ERR(opp)) {
>                 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
>                 ret = PTR_ERR(opp);
> -               goto out_free_opp_table;
> +               goto out_disable_clock;
>         }
>         info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
>         dev_pm_opp_put(opp);
> @@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>
>         return 0;
>
> +out_disable_clock:
> +       clk_disable_unprepare(inter_clk);
> +
>  out_free_opp_table:
>         dev_pm_opp_of_cpumask_remove_table(&info->cpus);
>
> @@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { }
>  };
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
@ 2019-03-31  0:06       ` Nicolas Boichat
  0 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-03-31  0:06 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar,
	devicetree, srv_heupstream, linux-pm, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, linux-arm Mailing List

On Thu, Mar 28, 2019 at 11:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> For new mediatek chip mt8183,
> cci and little cluster share the same buck,
> so need to modify the attribute of regulator from exclusive to optional
>
> Intermediate clock is not always enabled by ccf in different projects,
> so cpufreq should always enable it by itself.

One comment, otherwise the changes look good. However, I feel that
this patch should be split in 3:
 1. Change to regulator_get_optional
 2. Enable inter_clk
 3. Add support for 8183

> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
>  drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
>  2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 47729a2..53ea52b 100644
> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> @@ -117,6 +117,7 @@
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { .compatible = "nvidia,tegra124", },
>         { .compatible = "nvidia,tegra210", },
> diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> index 48e9829..7cd01d3 100644
> --- a/drivers/cpufreq/mediatek-cpufreq.c
> +++ b/drivers/cpufreq/mediatek-cpufreq.c
> @@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> -       proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> +       proc_reg = regulator_get_optional(cpu_dev, "proc");
>         if (IS_ERR(proc_reg)) {
>                 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
>                         pr_warn("proc regulator for cpu%d not ready, retry.\n",
> @@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> +       ret = clk_prepare_enable(inter_clk);

Should you disable the clock in mtk_cpu_dvfs_info_release?

> +       if (ret)
> +               goto out_free_opp_table;
> +
>         /* Search a safe voltage for intermediate frequency. */
>         rate = clk_get_rate(inter_clk);
>         opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
>         if (IS_ERR(opp)) {
>                 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
>                 ret = PTR_ERR(opp);
> -               goto out_free_opp_table;
> +               goto out_disable_clock;
>         }
>         info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
>         dev_pm_opp_put(opp);
> @@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>
>         return 0;
>
> +out_disable_clock:
> +       clk_disable_unprepare(inter_clk);
> +
>  out_free_opp_table:
>         dev_pm_opp_of_cpumask_remove_table(&info->cpus);
>
> @@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { }
>  };
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
@ 2019-03-31  0:06       ` Nicolas Boichat
  0 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-03-31  0:06 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Fan Chen, linux-arm Mailing List

On Thu, Mar 28, 2019 at 11:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> For new mediatek chip mt8183,
> cci and little cluster share the same buck,
> so need to modify the attribute of regulator from exclusive to optional
>
> Intermediate clock is not always enabled by ccf in different projects,
> so cpufreq should always enable it by itself.

One comment, otherwise the changes look good. However, I feel that
this patch should be split in 3:
 1. Change to regulator_get_optional
 2. Enable inter_clk
 3. Add support for 8183

> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
>  drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
>  2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 47729a2..53ea52b 100644
> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> @@ -117,6 +117,7 @@
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { .compatible = "nvidia,tegra124", },
>         { .compatible = "nvidia,tegra210", },
> diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> index 48e9829..7cd01d3 100644
> --- a/drivers/cpufreq/mediatek-cpufreq.c
> +++ b/drivers/cpufreq/mediatek-cpufreq.c
> @@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> -       proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> +       proc_reg = regulator_get_optional(cpu_dev, "proc");
>         if (IS_ERR(proc_reg)) {
>                 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
>                         pr_warn("proc regulator for cpu%d not ready, retry.\n",
> @@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>                 goto out_free_resources;
>         }
>
> +       ret = clk_prepare_enable(inter_clk);

Should you disable the clock in mtk_cpu_dvfs_info_release?

> +       if (ret)
> +               goto out_free_opp_table;
> +
>         /* Search a safe voltage for intermediate frequency. */
>         rate = clk_get_rate(inter_clk);
>         opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
>         if (IS_ERR(opp)) {
>                 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
>                 ret = PTR_ERR(opp);
> -               goto out_free_opp_table;
> +               goto out_disable_clock;
>         }
>         info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
>         dev_pm_opp_put(opp);
> @@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
>
>         return 0;
>
> +out_disable_clock:
> +       clk_disable_unprepare(inter_clk);
> +
>  out_free_opp_table:
>         dev_pm_opp_of_cpumask_remove_table(&info->cpus);
>
> @@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
>         { .compatible = "mediatek,mt817x", },
>         { .compatible = "mediatek,mt8173", },
>         { .compatible = "mediatek,mt8176", },
> +       { .compatible = "mediatek,mt8183", },
>
>         { }
>  };
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

_______________________________________________
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] 46+ messages in thread

* RE: [PATCH v2 2/4] opp: add API which get max freq by voltage
       [not found] ` <CGME20190329064632epcas2p4d10ea099bfea4ad682d7312a75bfbe68@epcms1p8>
  2019-04-01  2:30     ` MyungJoo Ham
@ 2019-04-01  2:30     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  2:30 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, srv_heupstream, fan.chen, Andrew-sh.Cheng

>This API will get voltage as input parameter.
>Search all opp items for the item which with max frequency,
>and the voltae is smaller than provided voltage.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pm_opp.h |  8 ++++++++
> 2 files changed, 63 insertions(+)
>
>diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
>index 24c757a..57deef9 100644
>--- a/include/linux/pm_opp.h
>+++ b/include/linux/pm_opp.h
>@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> 
> struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> 					      unsigned long *freq);
>+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
>+					      unsigned long u_volt);

For the symmetricity, wouldn't it be better to name it
dev_pm_opp_find_volt_ceiling(dev, u_volt); ?

Cheers,
MyungJoo



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

* RE: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-01  2:30     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  2:30 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

>This API will get voltage as input parameter.
>Search all opp items for the item which with max frequency,
>and the voltae is smaller than provided voltage.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pm_opp.h |  8 ++++++++
> 2 files changed, 63 insertions(+)
>
>diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
>index 24c757a..57deef9 100644
>--- a/include/linux/pm_opp.h
>+++ b/include/linux/pm_opp.h
>@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> 
> struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> 					      unsigned long *freq);
>+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
>+					      unsigned long u_volt);

For the symmetricity, wouldn't it be better to name it
dev_pm_opp_find_volt_ceiling(dev, u_volt); ?

Cheers,
MyungJoo

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

* RE: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-01  2:30     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  2:30 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

>This API will get voltage as input parameter.
>Search all opp items for the item which with max frequency,
>and the voltae is smaller than provided voltage.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pm_opp.h |  8 ++++++++
> 2 files changed, 63 insertions(+)
>
>diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
>index 24c757a..57deef9 100644
>--- a/include/linux/pm_opp.h
>+++ b/include/linux/pm_opp.h
>@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> 
> struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> 					      unsigned long *freq);
>+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
>+					      unsigned long u_volt);

For the symmetricity, wouldn't it be better to name it
dev_pm_opp_find_volt_ceiling(dev, u_volt); ?

Cheers,
MyungJoo



_______________________________________________
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] 46+ messages in thread

* RE: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
       [not found] ` <CGME20190329064636epcas1p13633ae078ef83ceda0b8189df1399753@epcms1p1>
  2019-04-01  4:18     ` MyungJoo Ham
@ 2019-04-01  4:18     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  4:18 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, srv_heupstream, fan.chen, Andrew-sh.Cheng

>This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
>of the Mediatek MT8183.
>
>On the MT8183 the CCI is supplied by the same regulator as the LITTLE
>cores. The driver is notified when the regulator voltage changes
>(driven by cpufreq) and adjusts the CCI frequency to the maximum
>possible value.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/devfreq/Kconfig              |  10 ++
> drivers/devfreq/Makefile             |   1 +
> drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> 3 files changed, 246 insertions(+)
> create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
>

1. It appears that proc_reg_uV might be used before initialization.
It would be appropriate to initialize it at the probe function.

2. Because you are already using OPP, why don't you rely on
OPP fully? (use OPP from CPUFreq drivers as well in order to get
OPP events automatically.) Anyway, this is a minor item that does
not need to be corrected.

Cheers
MyungJoo

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

* RE: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
@ 2019-04-01  4:18     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  4:18 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, srv_heupstream, fan.chen, Andrew-sh.Cheng

>This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
>of the Mediatek MT8183.
>
>On the MT8183 the CCI is supplied by the same regulator as the LITTLE
>cores. The driver is notified when the regulator voltage changes
>(driven by cpufreq) and adjusts the CCI frequency to the maximum
>possible value.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/devfreq/Kconfig              |  10 ++
> drivers/devfreq/Makefile             |   1 +
> drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> 3 files changed, 246 insertions(+)
> create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
>

1. It appears that proc_reg_uV might be used before initialization.
It would be appropriate to initialize it at the probe function.

2. Because you are already using OPP, why don't you rely on
OPP fully? (use OPP from CPUFreq drivers as well in order to get
OPP events automatically.) Anyway, this is a minor item that does
not need to be corrected.

Cheers
MyungJoo

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

* RE: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
@ 2019-04-01  4:18     ` MyungJoo Ham
  0 siblings, 0 replies; 46+ messages in thread
From: MyungJoo Ham @ 2019-04-01  4:18 UTC (permalink / raw)
  To: Kyungmin Park, Chanwoo Choi, Rob Herring, Mark Rutland,
	Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, Andrew-sh.Cheng, srv_heupstream, linux-pm,
	linux-kernel, fan.chen, linux-mediatek, linux-arm-kernel

>This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
>of the Mediatek MT8183.
>
>On the MT8183 the CCI is supplied by the same regulator as the LITTLE
>cores. The driver is notified when the regulator voltage changes
>(driven by cpufreq) and adjusts the CCI frequency to the maximum
>possible value.
>
>Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>---
> drivers/devfreq/Kconfig              |  10 ++
> drivers/devfreq/Makefile             |   1 +
> drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> 3 files changed, 246 insertions(+)
> create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
>

1. It appears that proc_reg_uV might be used before initialization.
It would be appropriate to initialize it at the probe function.

2. Because you are already using OPP, why don't you rely on
OPP fully? (use OPP from CPUFreq drivers as well in order to get
OPP events automatically.) Anyway, this is a minor item that does
not need to be corrected.

Cheers
MyungJoo

_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-03-29  6:46     ` Andrew-sh.Cheng
  (?)
@ 2019-04-03  4:32       ` Nicolas Boichat
  -1 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-04-03  4:32 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar,
	devicetree, srv_heupstream, linux-pm, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, linux-arm Mailing List

On Fri, Mar 29, 2019 at 2:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)
>
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 0420f7e..7323cd9 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
>
> +/**
> + * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
> + * under provided voltage
> + * @dev:       device for which we do this operation
> + * @u_volt:    provided voltage
> + *
> + * Search for the matching available OPP which provide voltage can support.
> + *
> + * Return: matching *opp, else returns ERR_PTR in case of error
> + * and should be handled using IS_ERR.
> + * Error return values can be:
> + * EINVAL:     for bad pointer
> + * ERANGE:     no match found for search
> + * ENODEV:     if device not found in list of registered devices
> + *
> + * The callers are required to call dev_pm_opp_put() for the returned OPP after
> + * use.
> + */
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       struct opp_table *opp_table;
> +       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
> +
> +       if (!dev || !u_volt) {
> +               dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
> +                       u_volt);

u_volt is an unsigned long, so you should use %lu.

drivers/opp/core.c:582:3: error: format '%d' expects argument of type
'int', but argument 4 has type 'long unsigned int' [-Werror=format=]
  chromeos-kernel-4_19-4.19.32-r271:    dev_err(dev, "%s: Invalid
argument volt=%d\n", __func__,
  chromeos-kernel-4_19-4.19.32-r271:    ^

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       opp_table = _find_opp_table(dev);
> +       if (IS_ERR(opp_table))
> +               return ERR_CAST(opp_table);
> +
> +       mutex_lock(&opp_table->lock);
> +
> +       list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
> +               if (temp_opp->available) {
> +                       /* go to the next node, before choosing prev */
> +                       if (temp_opp->supplies[0].u_volt > u_volt)
> +                               break;
> +                       opp = temp_opp;
> +               }
> +       }
> +
> +       /* Increment the reference count of OPP */
> +       if (!IS_ERR(opp))
> +               dev_pm_opp_get(opp);
> +       mutex_unlock(&opp_table->lock);
> +       dev_pm_opp_put_opp_table(opp_table);
> +
> +       return opp;
> +}
> +EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
> +
>  static int _set_opp_voltage(struct device *dev, struct regulator *reg,
>                             struct dev_pm_opp_supply *supply)
>  {
> diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> index 24c757a..57deef9 100644
> --- a/include/linux/pm_opp.h
> +++ b/include/linux/pm_opp.h
> @@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>                                               unsigned long *freq);
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt);
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                              unsigned long *freq);
> @@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>         return ERR_PTR(-ENOTSUPP);
>  }
>
> +static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       return ERR_PTR(-ENOTSUPP);
> +}
> +
>  static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                         unsigned long *freq)
>  {
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-03  4:32       ` Nicolas Boichat
  0 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-04-03  4:32 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar,
	devicetree, srv_heupstream, linux-pm, lkml, Fan Chen,
	moderated list:ARM/Mediatek SoC support, linux-arm Mailing List

On Fri, Mar 29, 2019 at 2:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)
>
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 0420f7e..7323cd9 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
>
> +/**
> + * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
> + * under provided voltage
> + * @dev:       device for which we do this operation
> + * @u_volt:    provided voltage
> + *
> + * Search for the matching available OPP which provide voltage can support.
> + *
> + * Return: matching *opp, else returns ERR_PTR in case of error
> + * and should be handled using IS_ERR.
> + * Error return values can be:
> + * EINVAL:     for bad pointer
> + * ERANGE:     no match found for search
> + * ENODEV:     if device not found in list of registered devices
> + *
> + * The callers are required to call dev_pm_opp_put() for the returned OPP after
> + * use.
> + */
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       struct opp_table *opp_table;
> +       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
> +
> +       if (!dev || !u_volt) {
> +               dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
> +                       u_volt);

u_volt is an unsigned long, so you should use %lu.

drivers/opp/core.c:582:3: error: format '%d' expects argument of type
'int', but argument 4 has type 'long unsigned int' [-Werror=format=]
  chromeos-kernel-4_19-4.19.32-r271:    dev_err(dev, "%s: Invalid
argument volt=%d\n", __func__,
  chromeos-kernel-4_19-4.19.32-r271:    ^

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       opp_table = _find_opp_table(dev);
> +       if (IS_ERR(opp_table))
> +               return ERR_CAST(opp_table);
> +
> +       mutex_lock(&opp_table->lock);
> +
> +       list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
> +               if (temp_opp->available) {
> +                       /* go to the next node, before choosing prev */
> +                       if (temp_opp->supplies[0].u_volt > u_volt)
> +                               break;
> +                       opp = temp_opp;
> +               }
> +       }
> +
> +       /* Increment the reference count of OPP */
> +       if (!IS_ERR(opp))
> +               dev_pm_opp_get(opp);
> +       mutex_unlock(&opp_table->lock);
> +       dev_pm_opp_put_opp_table(opp_table);
> +
> +       return opp;
> +}
> +EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
> +
>  static int _set_opp_voltage(struct device *dev, struct regulator *reg,
>                             struct dev_pm_opp_supply *supply)
>  {
> diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> index 24c757a..57deef9 100644
> --- a/include/linux/pm_opp.h
> +++ b/include/linux/pm_opp.h
> @@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>                                               unsigned long *freq);
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt);
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                              unsigned long *freq);
> @@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>         return ERR_PTR(-ENOTSUPP);
>  }
>
> +static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       return ERR_PTR(-ENOTSUPP);
> +}
> +
>  static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                         unsigned long *freq)
>  {
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-03  4:32       ` Nicolas Boichat
  0 siblings, 0 replies; 46+ messages in thread
From: Nicolas Boichat @ 2019-04-03  4:32 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Fan Chen, linux-arm Mailing List

On Fri, Mar 29, 2019 at 2:46 PM Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)
>
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 0420f7e..7323cd9 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
>
> +/**
> + * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
> + * under provided voltage
> + * @dev:       device for which we do this operation
> + * @u_volt:    provided voltage
> + *
> + * Search for the matching available OPP which provide voltage can support.
> + *
> + * Return: matching *opp, else returns ERR_PTR in case of error
> + * and should be handled using IS_ERR.
> + * Error return values can be:
> + * EINVAL:     for bad pointer
> + * ERANGE:     no match found for search
> + * ENODEV:     if device not found in list of registered devices
> + *
> + * The callers are required to call dev_pm_opp_put() for the returned OPP after
> + * use.
> + */
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       struct opp_table *opp_table;
> +       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
> +
> +       if (!dev || !u_volt) {
> +               dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
> +                       u_volt);

u_volt is an unsigned long, so you should use %lu.

drivers/opp/core.c:582:3: error: format '%d' expects argument of type
'int', but argument 4 has type 'long unsigned int' [-Werror=format=]
  chromeos-kernel-4_19-4.19.32-r271:    dev_err(dev, "%s: Invalid
argument volt=%d\n", __func__,
  chromeos-kernel-4_19-4.19.32-r271:    ^

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       opp_table = _find_opp_table(dev);
> +       if (IS_ERR(opp_table))
> +               return ERR_CAST(opp_table);
> +
> +       mutex_lock(&opp_table->lock);
> +
> +       list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
> +               if (temp_opp->available) {
> +                       /* go to the next node, before choosing prev */
> +                       if (temp_opp->supplies[0].u_volt > u_volt)
> +                               break;
> +                       opp = temp_opp;
> +               }
> +       }
> +
> +       /* Increment the reference count of OPP */
> +       if (!IS_ERR(opp))
> +               dev_pm_opp_get(opp);
> +       mutex_unlock(&opp_table->lock);
> +       dev_pm_opp_put_opp_table(opp_table);
> +
> +       return opp;
> +}
> +EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
> +
>  static int _set_opp_voltage(struct device *dev, struct regulator *reg,
>                             struct dev_pm_opp_supply *supply)
>  {
> diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> index 24c757a..57deef9 100644
> --- a/include/linux/pm_opp.h
> +++ b/include/linux/pm_opp.h
> @@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>                                               unsigned long *freq);
> +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt);
>
>  struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                              unsigned long *freq);
> @@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
>         return ERR_PTR(-ENOTSUPP);
>  }
>
> +static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> +                                             unsigned long u_volt)
> +{
> +       return ERR_PTR(-ENOTSUPP);
> +}
> +
>  static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
>                                         unsigned long *freq)
>  {
> --
> 1.8.1.1.dirty
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

_______________________________________________
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] 46+ messages in thread

* Re: [v2,4/4] devfreq: add mediatek cci devfreq
  2019-03-29  6:46     ` Andrew-sh.Cheng
@ 2019-04-08 17:22       ` Guenter Roeck
  -1 siblings, 0 replies; 46+ messages in thread
From: Guenter Roeck @ 2019-04-08 17:22 UTC (permalink / raw)
  To: Andrew-sh Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar,
	devicetree, srv_heupstream, linux-pm, linux-kernel, fan.chen,
	linux-mediatek, linux-arm-kernel

On Fri, Mar 29, 2019 at 02:46:12PM +0800, Andrew-sh Cheng wrote:
> This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> of the Mediatek MT8183.
> 
> On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> cores. The driver is notified when the regulator voltage changes
> (driven by cpufreq) and adjusts the CCI frequency to the maximum
> possible value.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/devfreq/Kconfig              |  10 ++
>  drivers/devfreq/Makefile             |   1 +
>  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
>  3 files changed, 246 insertions(+)
>  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> 
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 6a172d3..da2f8ec 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
>  	  and adjusts the operating frequencies and voltages with OPP support.
>  	  This does not yet operate with optimal voltages.
>  
> +config ARM_MT8183_CCI_DEVFREQ
> +	tristate "MT8183 CCI DEVFREQ Driver"
> +	depends on ARM_MEDIATEK_CPUFREQ
> +	help
> +		This adds a devfreq driver for Cache Coherent Interconnect
> +		of Mediatek MT8183, which is shared the same regulator
> +		with cpu cluster.
> +		It can track buck voltage and update a proper cci frequency.
> +		Use notification to get regulator status.
> +
>  config ARM_TEGRA_DEVFREQ
>  	tristate "Tegra DEVFREQ Driver"
>  	depends on ARCH_TEGRA_124_SOC
> diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> index 32b8d4d..817dde7 100644
> --- a/drivers/devfreq/Makefile
> +++ b/drivers/devfreq/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
>  
>  # DEVFREQ Drivers
>  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
>  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
>  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
>  
> diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> new file mode 100644
> index 0000000..af82d2e
> --- /dev/null
> +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/devfreq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "governor.h"
> +
> +struct cci_devfreq {
> +	struct devfreq		*devfreq;
> +	struct regulator	*proc_reg;
> +	unsigned long           proc_reg_uV;
> +	struct clk		*cci_clk;
> +	struct notifier_block	nb;
> +};
> +
> +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> +					  unsigned long val, void *data)
> +{
> +	struct cci_devfreq *cci_df =
> +		container_of(nb, struct cci_devfreq, nb);
> +
> +	/* deal with reduce frequency */
> +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> +		struct pre_voltage_change_data *pvc_data = data;
> +
> +		if (pvc_data->min_uV < pvc_data->old_uV) {
> +			cci_df->proc_reg_uV =
> +				(unsigned long)(pvc_data->min_uV);
> +			mutex_lock(&cci_df->devfreq->lock);
> +			update_devfreq(cci_df->devfreq);
> +			mutex_unlock(&cci_df->devfreq->lock);
> +		}
> +	}
> +
> +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
> +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);
> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	/* deal with increase frequency */
> +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
> +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);
> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> +				       unsigned long *freq)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct dev_pm_opp *opp;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +
> +	/* find available frequency */
> +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> +						 cci_df->proc_reg_uV);
> +	*freq = dev_pm_opp_get_freq(opp);
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> +					  unsigned int event, void *data)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct notifier_block *nb;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +	nb = &cci_df->nb;
> +
> +	switch (event) {
> +	case DEVFREQ_GOV_START:
> +	case DEVFREQ_GOV_RESUME:
> +		nb->notifier_call = cci_devfreq_regulator_notifier;
> +		regulator_register_notifier(cci_df->proc_reg,
> +					    nb);
> +		break;
> +
> +	case DEVFREQ_GOV_STOP:
> +	case DEVFREQ_GOV_SUSPEND:
> +		regulator_unregister_notifier(cci_df->proc_reg,
> +					    nb);
> +
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct devfreq_governor mtk_cci_devfreq_governor = {
> +	.name = "mtk_cci_vmon",
> +	.get_target_freq = mtk_cci_governor_get_target,
> +	.event_handler = mtk_cci_governor_event_handler,
> +};
> +
> +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> +				  u32 flags)
> +{
> +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> +
> +	if (!cci_df)
> +		return -EINVAL;
> +
> +	clk_set_rate(cci_df->cci_clk, *freq);
> +
> +	return 0;
> +}
> +
> +static struct devfreq_dev_profile cci_devfreq_profile = {
> +	.target		= mtk_cci_devfreq_target,
> +};
> +
> +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> +{
> +	struct device *cci_dev = &pdev->dev;
> +	struct cci_devfreq *cci_df;
> +	int ret;
> +
> +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> +	if (!cci_df)
> +		return -ENOMEM;
> +
> +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");

Should use devm_clk_get().

> +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> +				ret);
> +
> +		return ret;
> +	}
> +
> +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");

Should use devm_regulator_get_optional().

> +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> +				ret);
> +
> +		goto err_put_clk;
> +	}
> +
> +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> +	if (ret) {
> +		dev_err(cci_dev, "Fail to init CCI OPP table\n");

No error code display here ? Not that it really matters, but it is
inconsistent with the other error messages.

> +		goto err_put_reg;
> +	}
> +
> +	platform_set_drvdata(pdev, cci_df);
> +
> +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> +						       &cci_devfreq_profile,
> +						       "mtk_cci_vmon",
> +						       NULL);
> +	if (IS_ERR(cci_df->devfreq)) {

		ret = PTR_ERR(cci_df->devfreq);

> +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);

		dev_err(cci_dev, "cannot create cci devfreq device: %d\n", ret);

Something like
		dev_pm_opp_of_remove_table(...);
seems to be missing here.

> +		goto err_put_reg;
> +	}
> +
> +	return 0;
> +
> +err_put_reg:
> +	regulator_put(cci_df->proc_reg);
> +err_put_clk:
> +	clk_put(cci_df->cci_clk);

Can be dropped when using devm_ functions above.

> +
> +	return ret;
> +}
> +
> +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> +	{ .compatible = "mediatek,mt8183-cci" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> +
> +static struct platform_driver cci_devfreq_driver = {
> +	.probe	= mtk_cci_devfreq_probe,
> +	.driver = {
> +		.name = "mediatek-cci-devfreq",
> +		.of_match_table = mediatek_cci_devfreq_of_match,

If the driver depends on OF, that should be stated in the Kconfig file.
Otherwise, of_match_ptr() should be used, and mediatek_cci_devfreq_of_match
should be tagged with __maybe_unused (or made conditional with #ifdef).

> +	},
> +};
> +
> +static int __init mtk_cci_devfreq_init(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> +	if (ret) {
> +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	ret = platform_driver_register(&cci_devfreq_driver);
> +	if (ret)
> +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +
> +	return ret;
> +}
> +module_init(mtk_cci_devfreq_init)
> +
> +static void __exit mtk_cci_devfreq_exit(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +	if (ret)
> +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> +
> +	platform_driver_unregister(&cci_devfreq_driver);
> +}
> +module_exit(mtk_cci_devfreq_exit)
> +
> +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> +MODULE_LICENSE("GPL v2");

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

* Re: [v2,4/4] devfreq: add mediatek cci devfreq
@ 2019-04-08 17:22       ` Guenter Roeck
  0 siblings, 0 replies; 46+ messages in thread
From: Guenter Roeck @ 2019-04-08 17:22 UTC (permalink / raw)
  To: Andrew-sh Cheng
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham, linux-mediatek, Matthias Brugger,
	fan.chen, linux-arm-kernel

On Fri, Mar 29, 2019 at 02:46:12PM +0800, Andrew-sh Cheng wrote:
> This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> of the Mediatek MT8183.
> 
> On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> cores. The driver is notified when the regulator voltage changes
> (driven by cpufreq) and adjusts the CCI frequency to the maximum
> possible value.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/devfreq/Kconfig              |  10 ++
>  drivers/devfreq/Makefile             |   1 +
>  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
>  3 files changed, 246 insertions(+)
>  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> 
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 6a172d3..da2f8ec 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
>  	  and adjusts the operating frequencies and voltages with OPP support.
>  	  This does not yet operate with optimal voltages.
>  
> +config ARM_MT8183_CCI_DEVFREQ
> +	tristate "MT8183 CCI DEVFREQ Driver"
> +	depends on ARM_MEDIATEK_CPUFREQ
> +	help
> +		This adds a devfreq driver for Cache Coherent Interconnect
> +		of Mediatek MT8183, which is shared the same regulator
> +		with cpu cluster.
> +		It can track buck voltage and update a proper cci frequency.
> +		Use notification to get regulator status.
> +
>  config ARM_TEGRA_DEVFREQ
>  	tristate "Tegra DEVFREQ Driver"
>  	depends on ARCH_TEGRA_124_SOC
> diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> index 32b8d4d..817dde7 100644
> --- a/drivers/devfreq/Makefile
> +++ b/drivers/devfreq/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
>  
>  # DEVFREQ Drivers
>  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
>  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
>  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
>  
> diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> new file mode 100644
> index 0000000..af82d2e
> --- /dev/null
> +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/devfreq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "governor.h"
> +
> +struct cci_devfreq {
> +	struct devfreq		*devfreq;
> +	struct regulator	*proc_reg;
> +	unsigned long           proc_reg_uV;
> +	struct clk		*cci_clk;
> +	struct notifier_block	nb;
> +};
> +
> +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> +					  unsigned long val, void *data)
> +{
> +	struct cci_devfreq *cci_df =
> +		container_of(nb, struct cci_devfreq, nb);
> +
> +	/* deal with reduce frequency */
> +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> +		struct pre_voltage_change_data *pvc_data = data;
> +
> +		if (pvc_data->min_uV < pvc_data->old_uV) {
> +			cci_df->proc_reg_uV =
> +				(unsigned long)(pvc_data->min_uV);
> +			mutex_lock(&cci_df->devfreq->lock);
> +			update_devfreq(cci_df->devfreq);
> +			mutex_unlock(&cci_df->devfreq->lock);
> +		}
> +	}
> +
> +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
> +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);
> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	/* deal with increase frequency */
> +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
> +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);
> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> +				       unsigned long *freq)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct dev_pm_opp *opp;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +
> +	/* find available frequency */
> +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> +						 cci_df->proc_reg_uV);
> +	*freq = dev_pm_opp_get_freq(opp);
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> +					  unsigned int event, void *data)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct notifier_block *nb;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +	nb = &cci_df->nb;
> +
> +	switch (event) {
> +	case DEVFREQ_GOV_START:
> +	case DEVFREQ_GOV_RESUME:
> +		nb->notifier_call = cci_devfreq_regulator_notifier;
> +		regulator_register_notifier(cci_df->proc_reg,
> +					    nb);
> +		break;
> +
> +	case DEVFREQ_GOV_STOP:
> +	case DEVFREQ_GOV_SUSPEND:
> +		regulator_unregister_notifier(cci_df->proc_reg,
> +					    nb);
> +
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct devfreq_governor mtk_cci_devfreq_governor = {
> +	.name = "mtk_cci_vmon",
> +	.get_target_freq = mtk_cci_governor_get_target,
> +	.event_handler = mtk_cci_governor_event_handler,
> +};
> +
> +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> +				  u32 flags)
> +{
> +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> +
> +	if (!cci_df)
> +		return -EINVAL;
> +
> +	clk_set_rate(cci_df->cci_clk, *freq);
> +
> +	return 0;
> +}
> +
> +static struct devfreq_dev_profile cci_devfreq_profile = {
> +	.target		= mtk_cci_devfreq_target,
> +};
> +
> +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> +{
> +	struct device *cci_dev = &pdev->dev;
> +	struct cci_devfreq *cci_df;
> +	int ret;
> +
> +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> +	if (!cci_df)
> +		return -ENOMEM;
> +
> +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");

Should use devm_clk_get().

> +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> +				ret);
> +
> +		return ret;
> +	}
> +
> +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");

Should use devm_regulator_get_optional().

> +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> +				ret);
> +
> +		goto err_put_clk;
> +	}
> +
> +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> +	if (ret) {
> +		dev_err(cci_dev, "Fail to init CCI OPP table\n");

No error code display here ? Not that it really matters, but it is
inconsistent with the other error messages.

> +		goto err_put_reg;
> +	}
> +
> +	platform_set_drvdata(pdev, cci_df);
> +
> +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> +						       &cci_devfreq_profile,
> +						       "mtk_cci_vmon",
> +						       NULL);
> +	if (IS_ERR(cci_df->devfreq)) {

		ret = PTR_ERR(cci_df->devfreq);

> +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);

		dev_err(cci_dev, "cannot create cci devfreq device: %d\n", ret);

Something like
		dev_pm_opp_of_remove_table(...);
seems to be missing here.

> +		goto err_put_reg;
> +	}
> +
> +	return 0;
> +
> +err_put_reg:
> +	regulator_put(cci_df->proc_reg);
> +err_put_clk:
> +	clk_put(cci_df->cci_clk);

Can be dropped when using devm_ functions above.

> +
> +	return ret;
> +}
> +
> +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> +	{ .compatible = "mediatek,mt8183-cci" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> +
> +static struct platform_driver cci_devfreq_driver = {
> +	.probe	= mtk_cci_devfreq_probe,
> +	.driver = {
> +		.name = "mediatek-cci-devfreq",
> +		.of_match_table = mediatek_cci_devfreq_of_match,

If the driver depends on OF, that should be stated in the Kconfig file.
Otherwise, of_match_ptr() should be used, and mediatek_cci_devfreq_of_match
should be tagged with __maybe_unused (or made conditional with #ifdef).

> +	},
> +};
> +
> +static int __init mtk_cci_devfreq_init(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> +	if (ret) {
> +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	ret = platform_driver_register(&cci_devfreq_driver);
> +	if (ret)
> +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +
> +	return ret;
> +}
> +module_init(mtk_cci_devfreq_init)
> +
> +static void __exit mtk_cci_devfreq_exit(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +	if (ret)
> +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> +
> +	platform_driver_unregister(&cci_devfreq_driver);
> +}
> +module_exit(mtk_cci_devfreq_exit)
> +
> +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> +MODULE_LICENSE("GPL v2");

_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-03-29  6:46     ` Andrew-sh.Cheng
@ 2019-04-10  6:29       ` Viresh Kumar
  -1 siblings, 0 replies; 46+ messages in thread
From: Viresh Kumar @ 2019-04-10  6:29 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, linux-pm,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	srv_heupstream, fan.chen

On 29-03-19, 14:46, Andrew-sh.Cheng wrote:
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)

I have applied this patch with some modifications, here is the diff:

---
 drivers/opp/core.c     | 29 ++++++++++++++---------------
 include/linux/pm_opp.h |  8 ++++----
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 7323cd9aabf9..0e7703fe733f 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -527,31 +527,30 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
- * under provided voltage
- * @dev:	device for which we do this operation
- * @u_volt:	provided voltage
+ * dev_pm_opp_find_freq_ceil_by_volt() - Find OPP with highest frequency for
+ *					 target voltage.
+ * @dev:	Device for which we do this operation.
+ * @u_volt:	Target voltage.
+ *
+ * Search for OPP with highest (ceil) frequency and has voltage <= u_volt.
  *
- * Search for the matching available OPP which provide voltage can support.
+ * Return: matching *opp, else returns ERR_PTR in case of error which should be
+ * handled using IS_ERR.
  *
- * Return: matching *opp, else returns ERR_PTR in case of error
- * and should be handled using IS_ERR.
  * Error return values can be:
- * EINVAL:	for bad pointer
- * ERANGE:	no match found for search
- * ENODEV:	if device not found in list of registered devices
+ * EINVAL:	bad parameters
  *
  * The callers are required to call dev_pm_opp_put() for the returned OPP after
  * use.
  */
-struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt)
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+						     unsigned long u_volt)
 {
 	struct opp_table *opp_table;
 	struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
 	if (!dev || !u_volt) {
-		dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
+		dev_err(dev, "%s: Invalid argument volt=%lu\n", __func__,
 			u_volt);
 		return ERR_PTR(-EINVAL);
 	}
@@ -564,7 +563,6 @@ struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
 
 	list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
 		if (temp_opp->available) {
-			/* go to the next node, before choosing prev */
 			if (temp_opp->supplies[0].u_volt > u_volt)
 				break;
 			opp = temp_opp;
@@ -574,12 +572,13 @@ struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
 	/* Increment the reference count of OPP */
 	if (!IS_ERR(opp))
 		dev_pm_opp_get(opp);
+
 	mutex_unlock(&opp_table->lock);
 	dev_pm_opp_put_opp_table(opp_table);
 
 	return opp;
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_by_volt);
 
 static int _set_opp_voltage(struct device *dev, struct regulator *reg,
 			    struct dev_pm_opp_supply *supply)
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 57deef9cf5d3..b150fe97ce5a 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -102,8 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 
 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 					      unsigned long *freq);
-struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt);
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+						     unsigned long u_volt);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					     unsigned long *freq);
@@ -209,8 +209,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 	return ERR_PTR(-ENOTSUPP);
 }
 
-static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt)
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+					unsigned long u_volt)
 {
 	return ERR_PTR(-ENOTSUPP);
 }

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-10  6:29       ` Viresh Kumar
  0 siblings, 0 replies; 46+ messages in thread
From: Viresh Kumar @ 2019-04-10  6:29 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm,
	Rafael J. Wysocki, linux-kernel, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham, linux-mediatek, Matthias Brugger,
	fan.chen, linux-arm-kernel

On 29-03-19, 14:46, Andrew-sh.Cheng wrote:
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)

I have applied this patch with some modifications, here is the diff:

---
 drivers/opp/core.c     | 29 ++++++++++++++---------------
 include/linux/pm_opp.h |  8 ++++----
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 7323cd9aabf9..0e7703fe733f 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -527,31 +527,30 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
- * under provided voltage
- * @dev:	device for which we do this operation
- * @u_volt:	provided voltage
+ * dev_pm_opp_find_freq_ceil_by_volt() - Find OPP with highest frequency for
+ *					 target voltage.
+ * @dev:	Device for which we do this operation.
+ * @u_volt:	Target voltage.
+ *
+ * Search for OPP with highest (ceil) frequency and has voltage <= u_volt.
  *
- * Search for the matching available OPP which provide voltage can support.
+ * Return: matching *opp, else returns ERR_PTR in case of error which should be
+ * handled using IS_ERR.
  *
- * Return: matching *opp, else returns ERR_PTR in case of error
- * and should be handled using IS_ERR.
  * Error return values can be:
- * EINVAL:	for bad pointer
- * ERANGE:	no match found for search
- * ENODEV:	if device not found in list of registered devices
+ * EINVAL:	bad parameters
  *
  * The callers are required to call dev_pm_opp_put() for the returned OPP after
  * use.
  */
-struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt)
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+						     unsigned long u_volt)
 {
 	struct opp_table *opp_table;
 	struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
 	if (!dev || !u_volt) {
-		dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
+		dev_err(dev, "%s: Invalid argument volt=%lu\n", __func__,
 			u_volt);
 		return ERR_PTR(-EINVAL);
 	}
@@ -564,7 +563,6 @@ struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
 
 	list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
 		if (temp_opp->available) {
-			/* go to the next node, before choosing prev */
 			if (temp_opp->supplies[0].u_volt > u_volt)
 				break;
 			opp = temp_opp;
@@ -574,12 +572,13 @@ struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
 	/* Increment the reference count of OPP */
 	if (!IS_ERR(opp))
 		dev_pm_opp_get(opp);
+
 	mutex_unlock(&opp_table->lock);
 	dev_pm_opp_put_opp_table(opp_table);
 
 	return opp;
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_by_volt);
 
 static int _set_opp_voltage(struct device *dev, struct regulator *reg,
 			    struct dev_pm_opp_supply *supply)
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 57deef9cf5d3..b150fe97ce5a 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -102,8 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 
 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 					      unsigned long *freq);
-struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt);
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+						     unsigned long u_volt);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
 					     unsigned long *freq);
@@ -209,8 +209,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 	return ERR_PTR(-ENOTSUPP);
 }
 
-static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
-					      unsigned long u_volt)
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
+					unsigned long u_volt)
 {
 	return ERR_PTR(-ENOTSUPP);
 }

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

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

* Re: [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
  2019-03-31  0:06       ` Nicolas Boichat
@ 2019-04-13  2:33         ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  2:33 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Chanwoo Choi, Kyungmin Park,
	Rob Herring, moderated list:ARM/Mediatek SoC support,
	MyungJoo Ham, Matthias Brugger, Fan Chen, linux-arm Mailing List

On Sat, 2019-03-30 at 17:06 -0700, Nicolas Boichat wrote:
> On Thu, Mar 28, 2019 at 11:46 PM Andrew-sh.Cheng
> <andrew-sh.cheng@mediatek.com> wrote:
> >
> > For new mediatek chip mt8183,
> > cci and little cluster share the same buck,
> > so need to modify the attribute of regulator from exclusive to optional
> >
> > Intermediate clock is not always enabled by ccf in different projects,
> > so cpufreq should always enable it by itself.
> 
> One comment, otherwise the changes look good. However, I feel that
> this patch should be split in 3:
>  1. Change to regulator_get_optional
>  2. Enable inter_clk
>  3. Add support for 8183
Okay, I will split it into 3 patches
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
> >  drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
> >  2 files changed, 11 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index 47729a2..53ea52b 100644
> > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > @@ -117,6 +117,7 @@
> >         { .compatible = "mediatek,mt817x", },
> >         { .compatible = "mediatek,mt8173", },
> >         { .compatible = "mediatek,mt8176", },
> > +       { .compatible = "mediatek,mt8183", },
> >
> >         { .compatible = "nvidia,tegra124", },
> >         { .compatible = "nvidia,tegra210", },
> > diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> > index 48e9829..7cd01d3 100644
> > --- a/drivers/cpufreq/mediatek-cpufreq.c
> > +++ b/drivers/cpufreq/mediatek-cpufreq.c
> > @@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >                 goto out_free_resources;
> >         }
> >
> > -       proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> > +       proc_reg = regulator_get_optional(cpu_dev, "proc");
> >         if (IS_ERR(proc_reg)) {
> >                 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
> >                         pr_warn("proc regulator for cpu%d not ready, retry.\n",
> > @@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >                 goto out_free_resources;
> >         }
> >
> > +       ret = clk_prepare_enable(inter_clk);
> 
> Should you disable the clock in mtk_cpu_dvfs_info_release?
Yes, I will add it.
> 
> > +       if (ret)
> > +               goto out_free_opp_table;
> > +
> >         /* Search a safe voltage for intermediate frequency. */
> >         rate = clk_get_rate(inter_clk);
> >         opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
> >         if (IS_ERR(opp)) {
> >                 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
> >                 ret = PTR_ERR(opp);
> > -               goto out_free_opp_table;
> > +               goto out_disable_clock;
> >         }
> >         info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
> >         dev_pm_opp_put(opp);
> > @@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >
> >         return 0;
> >
> > +out_disable_clock:
> > +       clk_disable_unprepare(inter_clk);
> > +
> >  out_free_opp_table:
> >         dev_pm_opp_of_cpumask_remove_table(&info->cpus);
> >
> > @@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
> >         { .compatible = "mediatek,mt817x", },
> >         { .compatible = "mediatek,mt8173", },
> >         { .compatible = "mediatek,mt8176", },
> > +       { .compatible = "mediatek,mt8183", },
> >
> >         { }
> >  };
> > --
> > 1.8.1.1.dirty
> >
> >
> > _______________________________________________
> > Linux-mediatek mailing list
> > Linux-mediatek@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support
@ 2019-04-13  2:33         ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  2:33 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Chanwoo Choi, Kyungmin Park,
	Rob Herring, moderated list:ARM/Mediatek SoC support,
	MyungJoo Ham, Matthias Brugger, Fan Chen, linux-arm Mailing List

On Sat, 2019-03-30 at 17:06 -0700, Nicolas Boichat wrote:
> On Thu, Mar 28, 2019 at 11:46 PM Andrew-sh.Cheng
> <andrew-sh.cheng@mediatek.com> wrote:
> >
> > For new mediatek chip mt8183,
> > cci and little cluster share the same buck,
> > so need to modify the attribute of regulator from exclusive to optional
> >
> > Intermediate clock is not always enabled by ccf in different projects,
> > so cpufreq should always enable it by itself.
> 
> One comment, otherwise the changes look good. However, I feel that
> this patch should be split in 3:
>  1. Change to regulator_get_optional
>  2. Enable inter_clk
>  3. Add support for 8183
Okay, I will split it into 3 patches
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/cpufreq/cpufreq-dt-platdev.c |  1 +
> >  drivers/cpufreq/mediatek-cpufreq.c   | 12 ++++++++++--
> >  2 files changed, 11 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index 47729a2..53ea52b 100644
> > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > @@ -117,6 +117,7 @@
> >         { .compatible = "mediatek,mt817x", },
> >         { .compatible = "mediatek,mt8173", },
> >         { .compatible = "mediatek,mt8176", },
> > +       { .compatible = "mediatek,mt8183", },
> >
> >         { .compatible = "nvidia,tegra124", },
> >         { .compatible = "nvidia,tegra210", },
> > diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> > index 48e9829..7cd01d3 100644
> > --- a/drivers/cpufreq/mediatek-cpufreq.c
> > +++ b/drivers/cpufreq/mediatek-cpufreq.c
> > @@ -346,7 +346,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >                 goto out_free_resources;
> >         }
> >
> > -       proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> > +       proc_reg = regulator_get_optional(cpu_dev, "proc");
> >         if (IS_ERR(proc_reg)) {
> >                 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
> >                         pr_warn("proc regulator for cpu%d not ready, retry.\n",
> > @@ -376,13 +376,17 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >                 goto out_free_resources;
> >         }
> >
> > +       ret = clk_prepare_enable(inter_clk);
> 
> Should you disable the clock in mtk_cpu_dvfs_info_release?
Yes, I will add it.
> 
> > +       if (ret)
> > +               goto out_free_opp_table;
> > +
> >         /* Search a safe voltage for intermediate frequency. */
> >         rate = clk_get_rate(inter_clk);
> >         opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
> >         if (IS_ERR(opp)) {
> >                 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
> >                 ret = PTR_ERR(opp);
> > -               goto out_free_opp_table;
> > +               goto out_disable_clock;
> >         }
> >         info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
> >         dev_pm_opp_put(opp);
> > @@ -401,6 +405,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
> >
> >         return 0;
> >
> > +out_disable_clock:
> > +       clk_disable_unprepare(inter_clk);
> > +
> >  out_free_opp_table:
> >         dev_pm_opp_of_cpumask_remove_table(&info->cpus);
> >
> > @@ -543,6 +550,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
> >         { .compatible = "mediatek,mt817x", },
> >         { .compatible = "mediatek,mt8173", },
> >         { .compatible = "mediatek,mt8176", },
> > +       { .compatible = "mediatek,mt8183", },
> >
> >         { }
> >  };
> > --
> > 1.8.1.1.dirty
> >
> >
> > _______________________________________________
> > Linux-mediatek mailing list
> > Linux-mediatek@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-04-01  2:30     ` MyungJoo Ham
@ 2019-04-13  3:36       ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  3:36 UTC (permalink / raw)
  To: myungjoo.ham
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, Matthias Brugger, fan.chen,
	linux-arm-kernel

On Mon, 2019-04-01 at 11:30 +0900, MyungJoo Ham wrote:
> >This API will get voltage as input parameter.
> >Search all opp items for the item which with max frequency,
> >and the voltae is smaller than provided voltage.
> >
> >Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> >---
> > drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > include/linux/pm_opp.h |  8 ++++++++
> > 2 files changed, 63 insertions(+)
> >
> >diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> >index 24c757a..57deef9 100644
> >--- a/include/linux/pm_opp.h
> >+++ b/include/linux/pm_opp.h
> >@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> > 
> > struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> > 					      unsigned long *freq);
> >+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> >+					      unsigned long u_volt);
> 
> For the symmetricity, wouldn't it be better to name it
> dev_pm_opp_find_volt_ceiling(dev, u_volt); ?
Yes.
Viresh has comment on this, too.
I will use dev_pm_opp_find_freq_ceil_by_volt() in next patch.

> 
> Cheers,
> MyungJoo
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-13  3:36       ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  3:36 UTC (permalink / raw)
  To: myungjoo.ham
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, Matthias Brugger, fan.chen,
	linux-arm-kernel

On Mon, 2019-04-01 at 11:30 +0900, MyungJoo Ham wrote:
> >This API will get voltage as input parameter.
> >Search all opp items for the item which with max frequency,
> >and the voltae is smaller than provided voltage.
> >
> >Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> >---
> > drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > include/linux/pm_opp.h |  8 ++++++++
> > 2 files changed, 63 insertions(+)
> >
> >diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> >index 24c757a..57deef9 100644
> >--- a/include/linux/pm_opp.h
> >+++ b/include/linux/pm_opp.h
> >@@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> > 
> > struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> > 					      unsigned long *freq);
> >+struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> >+					      unsigned long u_volt);
> 
> For the symmetricity, wouldn't it be better to name it
> dev_pm_opp_find_volt_ceiling(dev, u_volt); ?
Yes.
Viresh has comment on this, too.
I will use dev_pm_opp_find_freq_ceil_by_volt() in next patch.

> 
> Cheers,
> MyungJoo
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-04-03  4:32       ` Nicolas Boichat
@ 2019-04-13  4:39         ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  4:39 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Fan Chen, linux-arm Mailing List

On Wed, 2019-04-03 at 12:32 +0800, Nicolas Boichat wrote:
> On Fri, Mar 29, 2019 at 2:46 PM Andrew-sh.Cheng
> <andrew-sh.cheng@mediatek.com> wrote:
> >
> > This API will get voltage as input parameter.
> > Search all opp items for the item which with max frequency,
> > and the voltae is smaller than provided voltage.
> >
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/pm_opp.h |  8 ++++++++
> >  2 files changed, 63 insertions(+)
> >
> > diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> > index 0420f7e..7323cd9 100644
> > --- a/drivers/opp/core.c
> > +++ b/drivers/opp/core.c
> > @@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >  }
> >  EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
> >
> > +/**
> > + * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
> > + * under provided voltage
> > + * @dev:       device for which we do this operation
> > + * @u_volt:    provided voltage
> > + *
> > + * Search for the matching available OPP which provide voltage can support.
> > + *
> > + * Return: matching *opp, else returns ERR_PTR in case of error
> > + * and should be handled using IS_ERR.
> > + * Error return values can be:
> > + * EINVAL:     for bad pointer
> > + * ERANGE:     no match found for search
> > + * ENODEV:     if device not found in list of registered devices
> > + *
> > + * The callers are required to call dev_pm_opp_put() for the returned OPP after
> > + * use.
> > + */
> > +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt)
> > +{
> > +       struct opp_table *opp_table;
> > +       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
> > +
> > +       if (!dev || !u_volt) {
> > +               dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
> > +                       u_volt);
> 
> u_volt is an unsigned long, so you should use %lu.
> 
> drivers/opp/core.c:582:3: error: format '%d' expects argument of type
> 'int', but argument 4 has type 'long unsigned int' [-Werror=format=]
>   chromeos-kernel-4_19-4.19.32-r271:    dev_err(dev, "%s: Invalid
> argument volt=%d\n", __func__,
>   chromeos-kernel-4_19-4.19.32-r271:    ^
> 
Got it. I will fix this on next patch
> > +               return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       opp_table = _find_opp_table(dev);
> > +       if (IS_ERR(opp_table))
> > +               return ERR_CAST(opp_table);
> > +
> > +       mutex_lock(&opp_table->lock);
> > +
> > +       list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
> > +               if (temp_opp->available) {
> > +                       /* go to the next node, before choosing prev */
> > +                       if (temp_opp->supplies[0].u_volt > u_volt)
> > +                               break;
> > +                       opp = temp_opp;
> > +               }
> > +       }
> > +
> > +       /* Increment the reference count of OPP */
> > +       if (!IS_ERR(opp))
> > +               dev_pm_opp_get(opp);
> > +       mutex_unlock(&opp_table->lock);
> > +       dev_pm_opp_put_opp_table(opp_table);
> > +
> > +       return opp;
> > +}
> > +EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
> > +
> >  static int _set_opp_voltage(struct device *dev, struct regulator *reg,
> >                             struct dev_pm_opp_supply *supply)
> >  {
> > diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> > index 24c757a..57deef9 100644
> > --- a/include/linux/pm_opp.h
> > +++ b/include/linux/pm_opp.h
> > @@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> >
> >  struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >                                               unsigned long *freq);
> > +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt);
> >
> >  struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
> >                                              unsigned long *freq);
> > @@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >         return ERR_PTR(-ENOTSUPP);
> >  }
> >
> > +static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt)
> > +{
> > +       return ERR_PTR(-ENOTSUPP);
> > +}
> > +
> >  static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
> >                                         unsigned long *freq)
> >  {
> > --
> > 1.8.1.1.dirty
> >
> >
> > _______________________________________________
> > Linux-mediatek mailing list
> > Linux-mediatek@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2019-04-13  4:39         ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  4:39 UTC (permalink / raw)
  To: Nicolas Boichat
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, lkml, Rob Herring, Chanwoo Choi,
	Kyungmin Park, MyungJoo Ham,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Fan Chen, linux-arm Mailing List

On Wed, 2019-04-03 at 12:32 +0800, Nicolas Boichat wrote:
> On Fri, Mar 29, 2019 at 2:46 PM Andrew-sh.Cheng
> <andrew-sh.cheng@mediatek.com> wrote:
> >
> > This API will get voltage as input parameter.
> > Search all opp items for the item which with max frequency,
> > and the voltae is smaller than provided voltage.
> >
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/pm_opp.h |  8 ++++++++
> >  2 files changed, 63 insertions(+)
> >
> > diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> > index 0420f7e..7323cd9 100644
> > --- a/drivers/opp/core.c
> > +++ b/drivers/opp/core.c
> > @@ -526,6 +526,61 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >  }
> >  EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
> >
> > +/**
> > + * dev_pm_opp_find_max_freq_by_volt() - Search for a opp with max freq
> > + * under provided voltage
> > + * @dev:       device for which we do this operation
> > + * @u_volt:    provided voltage
> > + *
> > + * Search for the matching available OPP which provide voltage can support.
> > + *
> > + * Return: matching *opp, else returns ERR_PTR in case of error
> > + * and should be handled using IS_ERR.
> > + * Error return values can be:
> > + * EINVAL:     for bad pointer
> > + * ERANGE:     no match found for search
> > + * ENODEV:     if device not found in list of registered devices
> > + *
> > + * The callers are required to call dev_pm_opp_put() for the returned OPP after
> > + * use.
> > + */
> > +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt)
> > +{
> > +       struct opp_table *opp_table;
> > +       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
> > +
> > +       if (!dev || !u_volt) {
> > +               dev_err(dev, "%s: Invalid argument volt=%d\n", __func__,
> > +                       u_volt);
> 
> u_volt is an unsigned long, so you should use %lu.
> 
> drivers/opp/core.c:582:3: error: format '%d' expects argument of type
> 'int', but argument 4 has type 'long unsigned int' [-Werror=format=]
>   chromeos-kernel-4_19-4.19.32-r271:    dev_err(dev, "%s: Invalid
> argument volt=%d\n", __func__,
>   chromeos-kernel-4_19-4.19.32-r271:    ^
> 
Got it. I will fix this on next patch
> > +               return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       opp_table = _find_opp_table(dev);
> > +       if (IS_ERR(opp_table))
> > +               return ERR_CAST(opp_table);
> > +
> > +       mutex_lock(&opp_table->lock);
> > +
> > +       list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
> > +               if (temp_opp->available) {
> > +                       /* go to the next node, before choosing prev */
> > +                       if (temp_opp->supplies[0].u_volt > u_volt)
> > +                               break;
> > +                       opp = temp_opp;
> > +               }
> > +       }
> > +
> > +       /* Increment the reference count of OPP */
> > +       if (!IS_ERR(opp))
> > +               dev_pm_opp_get(opp);
> > +       mutex_unlock(&opp_table->lock);
> > +       dev_pm_opp_put_opp_table(opp_table);
> > +
> > +       return opp;
> > +}
> > +EXPORT_SYMBOL_GPL(dev_pm_opp_find_max_freq_by_volt);
> > +
> >  static int _set_opp_voltage(struct device *dev, struct regulator *reg,
> >                             struct dev_pm_opp_supply *supply)
> >  {
> > diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> > index 24c757a..57deef9 100644
> > --- a/include/linux/pm_opp.h
> > +++ b/include/linux/pm_opp.h
> > @@ -102,6 +102,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
> >
> >  struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >                                               unsigned long *freq);
> > +struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt);
> >
> >  struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
> >                                              unsigned long *freq);
> > @@ -207,6 +209,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> >         return ERR_PTR(-ENOTSUPP);
> >  }
> >
> > +static inline struct dev_pm_opp *dev_pm_opp_find_max_freq_by_volt(struct device *dev,
> > +                                             unsigned long u_volt)
> > +{
> > +       return ERR_PTR(-ENOTSUPP);
> > +}
> > +
> >  static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
> >                                         unsigned long *freq)
> >  {
> > --
> > 1.8.1.1.dirty
> >
> >
> > _______________________________________________
> > Linux-mediatek mailing list
> > Linux-mediatek@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
  2019-04-01  4:18     ` MyungJoo Ham
@ 2019-04-13  5:54       ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  5:54 UTC (permalink / raw)
  To: myungjoo.ham
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, Matthias Brugger, fan.chen,
	linux-arm-kernel

On Mon, 2019-04-01 at 13:18 +0900, MyungJoo Ham wrote:
> >This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> >of the Mediatek MT8183.
> >
> >On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> >cores. The driver is notified when the regulator voltage changes
> >(driven by cpufreq) and adjusts the CCI frequency to the maximum
> >possible value.
> >
> >Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> >---
> > drivers/devfreq/Kconfig              |  10 ++
> > drivers/devfreq/Makefile             |   1 +
> > drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> > 3 files changed, 246 insertions(+)
> > create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> >
> 
> 1. It appears that proc_reg_uV might be used before initialization.
> It would be appropriate to initialize it at the probe function.
In this governor, cci only change frequency after get notification.
So it must set proc_reg_uV first, and then call update_devfreq() which
call to mtk_cci_governor_get_target() and use proc_reg_uV.
> 
> 2. Because you are already using OPP, why don't you rely on
> OPP fully? (use OPP from CPUFreq drivers as well in order to get
> OPP events automatically.) Anyway, this is a minor item that does
> not need to be corrected.
For some discuss about this in Mediatek before, we decide to put the
operation of CCI in CCI related driver and separated from CPUFreq.
> 
> Cheers
> MyungJoo
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
@ 2019-04-13  5:54       ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  5:54 UTC (permalink / raw)
  To: myungjoo.ham
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, Matthias Brugger, fan.chen,
	linux-arm-kernel

On Mon, 2019-04-01 at 13:18 +0900, MyungJoo Ham wrote:
> >This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> >of the Mediatek MT8183.
> >
> >On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> >cores. The driver is notified when the regulator voltage changes
> >(driven by cpufreq) and adjusts the CCI frequency to the maximum
> >possible value.
> >
> >Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> >---
> > drivers/devfreq/Kconfig              |  10 ++
> > drivers/devfreq/Makefile             |   1 +
> > drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> > 3 files changed, 246 insertions(+)
> > create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> >
> 
> 1. It appears that proc_reg_uV might be used before initialization.
> It would be appropriate to initialize it at the probe function.
In this governor, cci only change frequency after get notification.
So it must set proc_reg_uV first, and then call update_devfreq() which
call to mtk_cci_governor_get_target() and use proc_reg_uV.
> 
> 2. Because you are already using OPP, why don't you rely on
> OPP fully? (use OPP from CPUFreq drivers as well in order to get
> OPP events automatically.) Anyway, this is a minor item that does
> not need to be corrected.
For some discuss about this in Mediatek before, we decide to put the
operation of CCI in CCI related driver and separated from CPUFreq.
> 
> Cheers
> MyungJoo
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
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] 46+ messages in thread

* Re: [v2,4/4] devfreq: add mediatek cci devfreq
  2019-04-08 17:22       ` Guenter Roeck
@ 2019-04-13  7:07         ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  7:07 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, MyungJoo Ham, Matthias Brugger,
	fan.chen, linux-arm-kernel

On Mon, 2019-04-08 at 10:22 -0700, Guenter Roeck wrote:
> On Fri, Mar 29, 2019 at 02:46:12PM +0800, Andrew-sh Cheng wrote:
> > This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> > of the Mediatek MT8183.
> > 
> > On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> > cores. The driver is notified when the regulator voltage changes
> > (driven by cpufreq) and adjusts the CCI frequency to the maximum
> > possible value.
> > 
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/devfreq/Kconfig              |  10 ++
> >  drivers/devfreq/Makefile             |   1 +
> >  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 246 insertions(+)
> >  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> > 
> > diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> > index 6a172d3..da2f8ec 100644
> > --- a/drivers/devfreq/Kconfig
> > +++ b/drivers/devfreq/Kconfig
> > @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
> >  	  and adjusts the operating frequencies and voltages with OPP support.
> >  	  This does not yet operate with optimal voltages.
> >  
> > +config ARM_MT8183_CCI_DEVFREQ
> > +	tristate "MT8183 CCI DEVFREQ Driver"
> > +	depends on ARM_MEDIATEK_CPUFREQ
> > +	help
> > +		This adds a devfreq driver for Cache Coherent Interconnect
> > +		of Mediatek MT8183, which is shared the same regulator
> > +		with cpu cluster.
> > +		It can track buck voltage and update a proper cci frequency.
> > +		Use notification to get regulator status.
> > +
> >  config ARM_TEGRA_DEVFREQ
> >  	tristate "Tegra DEVFREQ Driver"
> >  	depends on ARCH_TEGRA_124_SOC
> > diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> > index 32b8d4d..817dde7 100644
> > --- a/drivers/devfreq/Makefile
> > +++ b/drivers/devfreq/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
> >  
> >  # DEVFREQ Drivers
> >  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> > +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
> >  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
> >  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
> >  
> > diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> > new file mode 100644
> > index 0000000..af82d2e
> > --- /dev/null
> > +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> > @@ -0,0 +1,235 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/devfreq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +
> > +#include "governor.h"
> > +
> > +struct cci_devfreq {
> > +	struct devfreq		*devfreq;
> > +	struct regulator	*proc_reg;
> > +	unsigned long           proc_reg_uV;
> > +	struct clk		*cci_clk;
> > +	struct notifier_block	nb;
> > +};
> > +
> > +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> > +					  unsigned long val, void *data)
> > +{
> > +	struct cci_devfreq *cci_df =
> > +		container_of(nb, struct cci_devfreq, nb);
> > +
> > +	/* deal with reduce frequency */
> > +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> > +		struct pre_voltage_change_data *pvc_data = data;
> > +
> > +		if (pvc_data->min_uV < pvc_data->old_uV) {
> > +			cci_df->proc_reg_uV =
> > +				(unsigned long)(pvc_data->min_uV);
> > +			mutex_lock(&cci_df->devfreq->lock);
> > +			update_devfreq(cci_df->devfreq);
> > +			mutex_unlock(&cci_df->devfreq->lock);
> > +		}
> > +	}
> > +
> > +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
> > +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	/* deal with increase frequency */
> > +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
> > +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> > +				       unsigned long *freq)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct dev_pm_opp *opp;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +
> > +	/* find available frequency */
> > +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> > +						 cci_df->proc_reg_uV);
> > +	*freq = dev_pm_opp_get_freq(opp);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> > +					  unsigned int event, void *data)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct notifier_block *nb;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +	nb = &cci_df->nb;
> > +
> > +	switch (event) {
> > +	case DEVFREQ_GOV_START:
> > +	case DEVFREQ_GOV_RESUME:
> > +		nb->notifier_call = cci_devfreq_regulator_notifier;
> > +		regulator_register_notifier(cci_df->proc_reg,
> > +					    nb);
> > +		break;
> > +
> > +	case DEVFREQ_GOV_STOP:
> > +	case DEVFREQ_GOV_SUSPEND:
> > +		regulator_unregister_notifier(cci_df->proc_reg,
> > +					    nb);
> > +
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_governor mtk_cci_devfreq_governor = {
> > +	.name = "mtk_cci_vmon",
> > +	.get_target_freq = mtk_cci_governor_get_target,
> > +	.event_handler = mtk_cci_governor_event_handler,
> > +};
> > +
> > +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> > +				  u32 flags)
> > +{
> > +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> > +
> > +	if (!cci_df)
> > +		return -EINVAL;
> > +
> > +	clk_set_rate(cci_df->cci_clk, *freq);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_dev_profile cci_devfreq_profile = {
> > +	.target		= mtk_cci_devfreq_target,
> > +};
> > +
> > +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> > +{
> > +	struct device *cci_dev = &pdev->dev;
> > +	struct cci_devfreq *cci_df;
> > +	int ret;
> > +
> > +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> > +	if (!cci_df)
> > +		return -ENOMEM;
> > +
> > +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");
> 
> Should use devm_clk_get().
I will change it on next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> > +				ret);
> > +
> > +		return ret;
> > +	}
> > +
> > +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");
> 
> Should use devm_regulator_get_optional().
I will change it on next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> > +				ret);
> > +
> > +		goto err_put_clk;
> > +	}
> > +
> > +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> > +	if (ret) {
> > +		dev_err(cci_dev, "Fail to init CCI OPP table\n");
> 
> No error code display here ? Not that it really matters, but it is
> inconsistent with the other error messages.
I will add it on next patch.
> 
> > +		goto err_put_reg;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, cci_df);
> > +
> > +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> > +						       &cci_devfreq_profile,
> > +						       "mtk_cci_vmon",
> > +						       NULL);
> > +	if (IS_ERR(cci_df->devfreq)) {
> 
> 		ret = PTR_ERR(cci_df->devfreq);
> 
> > +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
> 
> 		dev_err(cci_dev, "cannot create cci devfreq device: %d\n", ret);
> 
> Something like
> 		dev_pm_opp_of_remove_table(...);
> seems to be missing here.
I will fix this, and add dev_pm_opp_of_remove_table(...) when error
occur.
> 
> > +		goto err_put_reg;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_put_reg:
> > +	regulator_put(cci_df->proc_reg);
> > +err_put_clk:
> > +	clk_put(cci_df->cci_clk);
> 
> Can be dropped when using devm_ functions above.
I will remove these code.
> 
> > +
> > +	return ret;
> > +}
> > +
> > +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> > +	{ .compatible = "mediatek,mt8183-cci" },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> > +
> > +static struct platform_driver cci_devfreq_driver = {
> > +	.probe	= mtk_cci_devfreq_probe,
> > +	.driver = {
> > +		.name = "mediatek-cci-devfreq",
> > +		.of_match_table = mediatek_cci_devfreq_of_match,
> 
> If the driver depends on OF, that should be stated in the Kconfig file.
> Otherwise, of_match_ptr() should be used, and mediatek_cci_devfreq_of_match
> should be tagged with __maybe_unused (or made conditional with #ifdef).
I will fix this on next patch.
> 
> > +	},
> > +};
> > +
> > +static int __init mtk_cci_devfreq_init(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> > +	if (ret) {
> > +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> > +		return ret;
> > +	}
> > +
> > +	ret = platform_driver_register(&cci_devfreq_driver);
> > +	if (ret)
> > +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +
> > +	return ret;
> > +}
> > +module_init(mtk_cci_devfreq_init)
> > +
> > +static void __exit mtk_cci_devfreq_exit(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +	if (ret)
> > +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> > +
> > +	platform_driver_unregister(&cci_devfreq_driver);
> > +}
> > +module_exit(mtk_cci_devfreq_exit)
> > +
> > +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> > +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> > +MODULE_LICENSE("GPL v2");
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [v2,4/4] devfreq: add mediatek cci devfreq
@ 2019-04-13  7:07         ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-04-13  7:07 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Chanwoo Choi, Kyungmin Park,
	Rob Herring, linux-mediatek, MyungJoo Ham, Matthias Brugger,
	fan.chen, linux-arm-kernel

On Mon, 2019-04-08 at 10:22 -0700, Guenter Roeck wrote:
> On Fri, Mar 29, 2019 at 02:46:12PM +0800, Andrew-sh Cheng wrote:
> > This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> > of the Mediatek MT8183.
> > 
> > On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> > cores. The driver is notified when the regulator voltage changes
> > (driven by cpufreq) and adjusts the CCI frequency to the maximum
> > possible value.
> > 
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/devfreq/Kconfig              |  10 ++
> >  drivers/devfreq/Makefile             |   1 +
> >  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 246 insertions(+)
> >  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> > 
> > diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> > index 6a172d3..da2f8ec 100644
> > --- a/drivers/devfreq/Kconfig
> > +++ b/drivers/devfreq/Kconfig
> > @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
> >  	  and adjusts the operating frequencies and voltages with OPP support.
> >  	  This does not yet operate with optimal voltages.
> >  
> > +config ARM_MT8183_CCI_DEVFREQ
> > +	tristate "MT8183 CCI DEVFREQ Driver"
> > +	depends on ARM_MEDIATEK_CPUFREQ
> > +	help
> > +		This adds a devfreq driver for Cache Coherent Interconnect
> > +		of Mediatek MT8183, which is shared the same regulator
> > +		with cpu cluster.
> > +		It can track buck voltage and update a proper cci frequency.
> > +		Use notification to get regulator status.
> > +
> >  config ARM_TEGRA_DEVFREQ
> >  	tristate "Tegra DEVFREQ Driver"
> >  	depends on ARCH_TEGRA_124_SOC
> > diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> > index 32b8d4d..817dde7 100644
> > --- a/drivers/devfreq/Makefile
> > +++ b/drivers/devfreq/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
> >  
> >  # DEVFREQ Drivers
> >  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> > +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
> >  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
> >  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
> >  
> > diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> > new file mode 100644
> > index 0000000..af82d2e
> > --- /dev/null
> > +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> > @@ -0,0 +1,235 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/devfreq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +
> > +#include "governor.h"
> > +
> > +struct cci_devfreq {
> > +	struct devfreq		*devfreq;
> > +	struct regulator	*proc_reg;
> > +	unsigned long           proc_reg_uV;
> > +	struct clk		*cci_clk;
> > +	struct notifier_block	nb;
> > +};
> > +
> > +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> > +					  unsigned long val, void *data)
> > +{
> > +	struct cci_devfreq *cci_df =
> > +		container_of(nb, struct cci_devfreq, nb);
> > +
> > +	/* deal with reduce frequency */
> > +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> > +		struct pre_voltage_change_data *pvc_data = data;
> > +
> > +		if (pvc_data->min_uV < pvc_data->old_uV) {
> > +			cci_df->proc_reg_uV =
> > +				(unsigned long)(pvc_data->min_uV);
> > +			mutex_lock(&cci_df->devfreq->lock);
> > +			update_devfreq(cci_df->devfreq);
> > +			mutex_unlock(&cci_df->devfreq->lock);
> > +		}
> > +	}
> > +
> > +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
> > +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	/* deal with increase frequency */
> > +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
> > +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> > +				       unsigned long *freq)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct dev_pm_opp *opp;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +
> > +	/* find available frequency */
> > +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> > +						 cci_df->proc_reg_uV);
> > +	*freq = dev_pm_opp_get_freq(opp);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> > +					  unsigned int event, void *data)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct notifier_block *nb;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +	nb = &cci_df->nb;
> > +
> > +	switch (event) {
> > +	case DEVFREQ_GOV_START:
> > +	case DEVFREQ_GOV_RESUME:
> > +		nb->notifier_call = cci_devfreq_regulator_notifier;
> > +		regulator_register_notifier(cci_df->proc_reg,
> > +					    nb);
> > +		break;
> > +
> > +	case DEVFREQ_GOV_STOP:
> > +	case DEVFREQ_GOV_SUSPEND:
> > +		regulator_unregister_notifier(cci_df->proc_reg,
> > +					    nb);
> > +
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_governor mtk_cci_devfreq_governor = {
> > +	.name = "mtk_cci_vmon",
> > +	.get_target_freq = mtk_cci_governor_get_target,
> > +	.event_handler = mtk_cci_governor_event_handler,
> > +};
> > +
> > +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> > +				  u32 flags)
> > +{
> > +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> > +
> > +	if (!cci_df)
> > +		return -EINVAL;
> > +
> > +	clk_set_rate(cci_df->cci_clk, *freq);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_dev_profile cci_devfreq_profile = {
> > +	.target		= mtk_cci_devfreq_target,
> > +};
> > +
> > +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> > +{
> > +	struct device *cci_dev = &pdev->dev;
> > +	struct cci_devfreq *cci_df;
> > +	int ret;
> > +
> > +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> > +	if (!cci_df)
> > +		return -ENOMEM;
> > +
> > +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");
> 
> Should use devm_clk_get().
I will change it on next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> > +				ret);
> > +
> > +		return ret;
> > +	}
> > +
> > +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");
> 
> Should use devm_regulator_get_optional().
I will change it on next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> > +				ret);
> > +
> > +		goto err_put_clk;
> > +	}
> > +
> > +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> > +	if (ret) {
> > +		dev_err(cci_dev, "Fail to init CCI OPP table\n");
> 
> No error code display here ? Not that it really matters, but it is
> inconsistent with the other error messages.
I will add it on next patch.
> 
> > +		goto err_put_reg;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, cci_df);
> > +
> > +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> > +						       &cci_devfreq_profile,
> > +						       "mtk_cci_vmon",
> > +						       NULL);
> > +	if (IS_ERR(cci_df->devfreq)) {
> 
> 		ret = PTR_ERR(cci_df->devfreq);
> 
> > +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
> 
> 		dev_err(cci_dev, "cannot create cci devfreq device: %d\n", ret);
> 
> Something like
> 		dev_pm_opp_of_remove_table(...);
> seems to be missing here.
I will fix this, and add dev_pm_opp_of_remove_table(...) when error
occur.
> 
> > +		goto err_put_reg;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_put_reg:
> > +	regulator_put(cci_df->proc_reg);
> > +err_put_clk:
> > +	clk_put(cci_df->cci_clk);
> 
> Can be dropped when using devm_ functions above.
I will remove these code.
> 
> > +
> > +	return ret;
> > +}
> > +
> > +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> > +	{ .compatible = "mediatek,mt8183-cci" },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> > +
> > +static struct platform_driver cci_devfreq_driver = {
> > +	.probe	= mtk_cci_devfreq_probe,
> > +	.driver = {
> > +		.name = "mediatek-cci-devfreq",
> > +		.of_match_table = mediatek_cci_devfreq_of_match,
> 
> If the driver depends on OF, that should be stated in the Kconfig file.
> Otherwise, of_match_ptr() should be used, and mediatek_cci_devfreq_of_match
> should be tagged with __maybe_unused (or made conditional with #ifdef).
I will fix this on next patch.
> 
> > +	},
> > +};
> > +
> > +static int __init mtk_cci_devfreq_init(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> > +	if (ret) {
> > +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> > +		return ret;
> > +	}
> > +
> > +	ret = platform_driver_register(&cci_devfreq_driver);
> > +	if (ret)
> > +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +
> > +	return ret;
> > +}
> > +module_init(mtk_cci_devfreq_init)
> > +
> > +static void __exit mtk_cci_devfreq_exit(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +	if (ret)
> > +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> > +
> > +	platform_driver_unregister(&cci_devfreq_driver);
> > +}
> > +module_exit(mtk_cci_devfreq_exit)
> > +
> > +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> > +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> > +MODULE_LICENSE("GPL v2");
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
  2019-03-29  6:46     ` Andrew-sh.Cheng
@ 2019-04-16  9:05       ` Chanwoo Choi
  -1 siblings, 0 replies; 46+ messages in thread
From: Chanwoo Choi @ 2019-04-16  9:05 UTC (permalink / raw)
  To: Andrew-sh.Cheng, MyungJoo Ham, Kyungmin Park, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, srv_heupstream, fan.chen

Hi Andrew-sh.Cheng,

Please add the dt-binding documentation.

On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> of the Mediatek MT8183.
> 
> On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> cores. The driver is notified when the regulator voltage changes
> (driven by cpufreq) and adjusts the CCI frequency to the maximum
> possible value.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/devfreq/Kconfig              |  10 ++
>  drivers/devfreq/Makefile             |   1 +
>  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
>  3 files changed, 246 insertions(+)
>  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> 
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 6a172d3..da2f8ec 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
>  	  and adjusts the operating frequencies and voltages with OPP support.
>  	  This does not yet operate with optimal voltages.
>  
> +config ARM_MT8183_CCI_DEVFREQ
> +	tristate "MT8183 CCI DEVFREQ Driver"
> +	depends on ARM_MEDIATEK_CPUFREQ
> +	help
> +		This adds a devfreq driver for Cache Coherent Interconnect
> +		of Mediatek MT8183, which is shared the same regulator
> +		with cpu cluster.
> +		It can track buck voltage and update a proper cci frequency.
> +		Use notification to get regulator status.
> +
>  config ARM_TEGRA_DEVFREQ
>  	tristate "Tegra DEVFREQ Driver"
>  	depends on ARCH_TEGRA_124_SOC
> diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> index 32b8d4d..817dde7 100644
> --- a/drivers/devfreq/Makefile
> +++ b/drivers/devfreq/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
>  
>  # DEVFREQ Drivers
>  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
>  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
>  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
>  
> diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> new file mode 100644
> index 0000000..af82d2e
> --- /dev/null
> +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.

You can add the author information under copyright information.

> + */
> +
> +#include <linux/clk.h>
> +#include <linux/devfreq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "governor.h"
> +
> +struct cci_devfreq {
> +	struct devfreq		*devfreq;
> +	struct regulator	*proc_reg;
> +	unsigned long           proc_reg_uV;
> +	struct clk		*cci_clk;
> +	struct notifier_block	nb;

Just use the space instead of tab as following:

	struct devfreq *devfreq;
	struct regulator *proc_reg;
	unsigned long proc_reg_uV;
	struct clk *cci_clk;
	struct notifier_block nb;

> +};
> +
> +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> +					  unsigned long val, void *data)
> +{
> +	struct cci_devfreq *cci_df =
> +		container_of(nb, struct cci_devfreq, nb);
> +
> +	/* deal with reduce frequency */
> +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> +		struct pre_voltage_change_data *pvc_data = data;
> +
> +		if (pvc_data->min_uV < pvc_data->old_uV) {
> +			cci_df->proc_reg_uV =
> +				(unsigned long)(pvc_data->min_uV);
> +			mutex_lock(&cci_df->devfreq->lock);
> +			update_devfreq(cci_df->devfreq);

Please handle the return value of update_devfreq() for exception handling.

> +			mutex_unlock(&cci_df->devfreq->lock);
> +		}
> +	}
> +
> +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&

if -> else if

At the same time, receives only one notification.
It is not necessary to check the two if statement always, .


> +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);

ditto. Please check the return value of update_devfreq.

> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	/* deal with increase frequency */
> +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&

ditto.
if -> else if

At the same time, receives only one notification.
It is not necessary to check the two if statement always, .


> +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);

ditto. Please check the return value of update_devfreq.

> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> +				       unsigned long *freq)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct dev_pm_opp *opp;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +
> +	/* find available frequency */
> +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> +						 cci_df->proc_reg_uV);
> +	*freq = dev_pm_opp_get_freq(opp);
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> +					  unsigned int event, void *data)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct notifier_block *nb;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +	nb = &cci_df->nb;
> +
> +	switch (event) {
> +	case DEVFREQ_GOV_START:
> +	case DEVFREQ_GOV_RESUME:
> +		nb->notifier_call = cci_devfreq_regulator_notifier;
> +		regulator_register_notifier(cci_df->proc_reg,
> +					    nb);

Please check the return value of regulator_register_notifier
in order to handle the exception handling.


> +		break;
> +
> +	case DEVFREQ_GOV_STOP:
> +	case DEVFREQ_GOV_SUSPEND:
> +		regulator_unregister_notifier(cci_df->proc_reg,
> +					    nb);

ditto.

> +

Remove unneeded blank line.

> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct devfreq_governor mtk_cci_devfreq_governor = {
> +	.name = "mtk_cci_vmon",

How about editing the name from mtk_cci_vmon to mediatek_cci_voltage_monitor
for the readability? Actually, 'mtk' and 'vmon' are not standard expression.

> +	.get_target_freq = mtk_cci_governor_get_target,
> +	.event_handler = mtk_cci_governor_event_handler,

Please add following code to make it as the immutable
because the governor for this driver will not be changed
through sysfs interface.

	.immutable = true

> +};
> +
> +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> +				  u32 flags)
> +{
> +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> +
> +	if (!cci_df)
> +		return -EINVAL;
> +
> +	clk_set_rate(cci_df->cci_clk, *freq);

Please check the return value of clk_set_rate().

> +
> +	return 0;
> +}
> +
> +static struct devfreq_dev_profile cci_devfreq_profile = {
> +	.target		= mtk_cci_devfreq_target,

Just use the space instead of tab because cci_devfreq_profile
only has one record.

	.target = mtk_cci_devfreq_target,

> +};
> +
> +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> +{
> +	struct device *cci_dev = &pdev->dev;
> +	struct cci_devfreq *cci_df;
> +	int ret;
> +
> +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> +	if (!cci_df)
> +		return -ENOMEM;
> +
> +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");

clk_get -> devm_clk_get()

> +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> +				ret);
> +

Remove unneeded blank line.

> +		return ret;
> +	}> +
> +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");


regulator_get_optional -> devm_regulator_get_optional

> +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> +				ret);
> +

Remove unneeded blank line.

> +		goto err_put_clk;

If you use devm_clk_get(), just return instead of goto.

> +	}
> +
> +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> +	if (ret) {
> +		dev_err(cci_dev, "Fail to init CCI OPP table\n");
> +		goto err_put_reg;
> +	}
> +
> +	platform_set_drvdata(pdev, cci_df);
> +
> +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> +						       &cci_devfreq_profile,
> +						       "mtk_cci_vmon",
> +						       NULL);
> +	if (IS_ERR(cci_df->devfreq)) {
> +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
> +		goto err_put_reg;
> +	}
> +
> +	return 0;
> +
> +err_put_reg:
> +	regulator_put(cci_df->proc_reg);
> +err_put_clk:
> +	clk_put(cci_df->cci_clk);

If you use devm_clk_get()/devm_regulator_get(),
'err_put_reg' and 'err_put_clk' are unneeded.

> +
> +	return ret;
> +}
> +
> +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> +	{ .compatible = "mediatek,mt8183-cci" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> +
> +static struct platform_driver cci_devfreq_driver = {
> +	.probe	= mtk_cci_devfreq_probe,
> +	.driver = {
> +		.name = "mediatek-cci-devfreq",
> +		.of_match_table = mediatek_cci_devfreq_of_match,
> +	},
> +};
> +
> +static int __init mtk_cci_devfreq_init(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> +	if (ret) {
> +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	ret = platform_driver_register(&cci_devfreq_driver);
> +	if (ret)
> +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +
> +	return ret;
> +}
> +module_init(mtk_cci_devfreq_init)
> +
> +static void __exit mtk_cci_devfreq_exit(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +	if (ret)
> +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> +
> +	platform_driver_unregister(&cci_devfreq_driver);
> +}
> +module_exit(mtk_cci_devfreq_exit)
> +
> +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> +MODULE_LICENSE("GPL v2");
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
@ 2019-04-16  9:05       ` Chanwoo Choi
  0 siblings, 0 replies; 46+ messages in thread
From: Chanwoo Choi @ 2019-04-16  9:05 UTC (permalink / raw)
  To: Andrew-sh.Cheng, MyungJoo Ham, Kyungmin Park, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, srv_heupstream, linux-pm, linux-kernel, fan.chen,
	linux-mediatek, linux-arm-kernel

Hi Andrew-sh.Cheng,

Please add the dt-binding documentation.

On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> of the Mediatek MT8183.
> 
> On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> cores. The driver is notified when the regulator voltage changes
> (driven by cpufreq) and adjusts the CCI frequency to the maximum
> possible value.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/devfreq/Kconfig              |  10 ++
>  drivers/devfreq/Makefile             |   1 +
>  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
>  3 files changed, 246 insertions(+)
>  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> 
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 6a172d3..da2f8ec 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
>  	  and adjusts the operating frequencies and voltages with OPP support.
>  	  This does not yet operate with optimal voltages.
>  
> +config ARM_MT8183_CCI_DEVFREQ
> +	tristate "MT8183 CCI DEVFREQ Driver"
> +	depends on ARM_MEDIATEK_CPUFREQ
> +	help
> +		This adds a devfreq driver for Cache Coherent Interconnect
> +		of Mediatek MT8183, which is shared the same regulator
> +		with cpu cluster.
> +		It can track buck voltage and update a proper cci frequency.
> +		Use notification to get regulator status.
> +
>  config ARM_TEGRA_DEVFREQ
>  	tristate "Tegra DEVFREQ Driver"
>  	depends on ARCH_TEGRA_124_SOC
> diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> index 32b8d4d..817dde7 100644
> --- a/drivers/devfreq/Makefile
> +++ b/drivers/devfreq/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
>  
>  # DEVFREQ Drivers
>  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
>  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
>  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
>  
> diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> new file mode 100644
> index 0000000..af82d2e
> --- /dev/null
> +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.

You can add the author information under copyright information.

> + */
> +
> +#include <linux/clk.h>
> +#include <linux/devfreq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "governor.h"
> +
> +struct cci_devfreq {
> +	struct devfreq		*devfreq;
> +	struct regulator	*proc_reg;
> +	unsigned long           proc_reg_uV;
> +	struct clk		*cci_clk;
> +	struct notifier_block	nb;

Just use the space instead of tab as following:

	struct devfreq *devfreq;
	struct regulator *proc_reg;
	unsigned long proc_reg_uV;
	struct clk *cci_clk;
	struct notifier_block nb;

> +};
> +
> +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> +					  unsigned long val, void *data)
> +{
> +	struct cci_devfreq *cci_df =
> +		container_of(nb, struct cci_devfreq, nb);
> +
> +	/* deal with reduce frequency */
> +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> +		struct pre_voltage_change_data *pvc_data = data;
> +
> +		if (pvc_data->min_uV < pvc_data->old_uV) {
> +			cci_df->proc_reg_uV =
> +				(unsigned long)(pvc_data->min_uV);
> +			mutex_lock(&cci_df->devfreq->lock);
> +			update_devfreq(cci_df->devfreq);

Please handle the return value of update_devfreq() for exception handling.

> +			mutex_unlock(&cci_df->devfreq->lock);
> +		}
> +	}
> +
> +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&

if -> else if

At the same time, receives only one notification.
It is not necessary to check the two if statement always, .


> +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);

ditto. Please check the return value of update_devfreq.

> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	/* deal with increase frequency */
> +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&

ditto.
if -> else if

At the same time, receives only one notification.
It is not necessary to check the two if statement always, .


> +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> +		cci_df->proc_reg_uV = (unsigned long)data;
> +		mutex_lock(&cci_df->devfreq->lock);
> +		update_devfreq(cci_df->devfreq);

ditto. Please check the return value of update_devfreq.

> +		mutex_unlock(&cci_df->devfreq->lock);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> +				       unsigned long *freq)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct dev_pm_opp *opp;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +
> +	/* find available frequency */
> +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> +						 cci_df->proc_reg_uV);
> +	*freq = dev_pm_opp_get_freq(opp);
> +
> +	return 0;
> +}
> +
> +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> +					  unsigned int event, void *data)
> +{
> +	struct cci_devfreq *cci_df;
> +	struct notifier_block *nb;
> +
> +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> +	nb = &cci_df->nb;
> +
> +	switch (event) {
> +	case DEVFREQ_GOV_START:
> +	case DEVFREQ_GOV_RESUME:
> +		nb->notifier_call = cci_devfreq_regulator_notifier;
> +		regulator_register_notifier(cci_df->proc_reg,
> +					    nb);

Please check the return value of regulator_register_notifier
in order to handle the exception handling.


> +		break;
> +
> +	case DEVFREQ_GOV_STOP:
> +	case DEVFREQ_GOV_SUSPEND:
> +		regulator_unregister_notifier(cci_df->proc_reg,
> +					    nb);

ditto.

> +

Remove unneeded blank line.

> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct devfreq_governor mtk_cci_devfreq_governor = {
> +	.name = "mtk_cci_vmon",

How about editing the name from mtk_cci_vmon to mediatek_cci_voltage_monitor
for the readability? Actually, 'mtk' and 'vmon' are not standard expression.

> +	.get_target_freq = mtk_cci_governor_get_target,
> +	.event_handler = mtk_cci_governor_event_handler,

Please add following code to make it as the immutable
because the governor for this driver will not be changed
through sysfs interface.

	.immutable = true

> +};
> +
> +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> +				  u32 flags)
> +{
> +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> +
> +	if (!cci_df)
> +		return -EINVAL;
> +
> +	clk_set_rate(cci_df->cci_clk, *freq);

Please check the return value of clk_set_rate().

> +
> +	return 0;
> +}
> +
> +static struct devfreq_dev_profile cci_devfreq_profile = {
> +	.target		= mtk_cci_devfreq_target,

Just use the space instead of tab because cci_devfreq_profile
only has one record.

	.target = mtk_cci_devfreq_target,

> +};
> +
> +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> +{
> +	struct device *cci_dev = &pdev->dev;
> +	struct cci_devfreq *cci_df;
> +	int ret;
> +
> +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> +	if (!cci_df)
> +		return -ENOMEM;
> +
> +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");

clk_get -> devm_clk_get()

> +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> +				ret);
> +

Remove unneeded blank line.

> +		return ret;
> +	}> +
> +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");


regulator_get_optional -> devm_regulator_get_optional

> +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> +	if (ret) {
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> +				ret);
> +

Remove unneeded blank line.

> +		goto err_put_clk;

If you use devm_clk_get(), just return instead of goto.

> +	}
> +
> +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> +	if (ret) {
> +		dev_err(cci_dev, "Fail to init CCI OPP table\n");
> +		goto err_put_reg;
> +	}
> +
> +	platform_set_drvdata(pdev, cci_df);
> +
> +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> +						       &cci_devfreq_profile,
> +						       "mtk_cci_vmon",
> +						       NULL);
> +	if (IS_ERR(cci_df->devfreq)) {
> +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
> +		goto err_put_reg;
> +	}
> +
> +	return 0;
> +
> +err_put_reg:
> +	regulator_put(cci_df->proc_reg);
> +err_put_clk:
> +	clk_put(cci_df->cci_clk);

If you use devm_clk_get()/devm_regulator_get(),
'err_put_reg' and 'err_put_clk' are unneeded.

> +
> +	return ret;
> +}
> +
> +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> +	{ .compatible = "mediatek,mt8183-cci" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> +
> +static struct platform_driver cci_devfreq_driver = {
> +	.probe	= mtk_cci_devfreq_probe,
> +	.driver = {
> +		.name = "mediatek-cci-devfreq",
> +		.of_match_table = mediatek_cci_devfreq_of_match,
> +	},
> +};
> +
> +static int __init mtk_cci_devfreq_init(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> +	if (ret) {
> +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	ret = platform_driver_register(&cci_devfreq_driver);
> +	if (ret)
> +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +
> +	return ret;
> +}
> +module_init(mtk_cci_devfreq_init)
> +
> +static void __exit mtk_cci_devfreq_exit(void)
> +{
> +	int ret;
> +
> +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> +	if (ret)
> +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> +
> +	platform_driver_unregister(&cci_devfreq_driver);
> +}
> +module_exit(mtk_cci_devfreq_exit)
> +
> +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> +MODULE_LICENSE("GPL v2");
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
  2019-03-29  6:46   ` Andrew-sh.Cheng
@ 2019-04-16  9:08     ` Chanwoo Choi
  -1 siblings, 0 replies; 46+ messages in thread
From: Chanwoo Choi @ 2019-04-16  9:08 UTC (permalink / raw)
  To: Andrew-sh.Cheng, MyungJoo Ham, Kyungmin Park, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, srv_heupstream, fan.chen

Hi,

I already reviewed this patch on v1[1].
[1] https://lkml.org/lkml/2019/2/11/2228

But, the second version patch doesn't include the anything
about review. Please check it[1].

On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> This adds dt-binding documentation of cci devfreq
> for Mediatek MT8183 SoC platform.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> 
> diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> new file mode 100644
> index 0000000..e2b61cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> @@ -0,0 +1,19 @@
> +* Mediatek CCI frequency device
> +
> +Required properties:
> +- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
> +
> +- clocks: for cci devfreq
> +
> +- clock-names: for cci devfreq driver to reference
> +
> +- operating-points-v2: for cci devfreq opp table
> +
> +Example:
> +	cci: cci {
> +		compatible = "mediatek,cci";
> +		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
> +		clock-names = "cci_clock";
> +		operating-points-v2 = <&cci_opp>;
> +	};
> +
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
@ 2019-04-16  9:08     ` Chanwoo Choi
  0 siblings, 0 replies; 46+ messages in thread
From: Chanwoo Choi @ 2019-04-16  9:08 UTC (permalink / raw)
  To: Andrew-sh.Cheng, MyungJoo Ham, Kyungmin Park, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, Viresh Kumar
  Cc: devicetree, srv_heupstream, linux-pm, linux-kernel, fan.chen,
	linux-mediatek, linux-arm-kernel

Hi,

I already reviewed this patch on v1[1].
[1] https://lkml.org/lkml/2019/2/11/2228

But, the second version patch doesn't include the anything
about review. Please check it[1].

On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> This adds dt-binding documentation of cci devfreq
> for Mediatek MT8183 SoC platform.
> 
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> 
> diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> new file mode 100644
> index 0000000..e2b61cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> @@ -0,0 +1,19 @@
> +* Mediatek CCI frequency device
> +
> +Required properties:
> +- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
> +
> +- clocks: for cci devfreq
> +
> +- clock-names: for cci devfreq driver to reference
> +
> +- operating-points-v2: for cci devfreq opp table
> +
> +Example:
> +	cci: cci {
> +		compatible = "mediatek,cci";
> +		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
> +		clock-names = "cci_clock";
> +		operating-points-v2 = <&cci_opp>;
> +	};
> +
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
  2019-04-16  9:08     ` Chanwoo Choi
@ 2019-05-08  9:27         ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-05-08  9:27 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	linux-pm-u79uwXL29TY76Z2rM5mHXA, Viresh Kumar, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	fan.chen-NuS5LvNUpcJWk0Htik3J/w, Kyungmin Park, MyungJoo Ham,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Matthias Brugger,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Tue, 2019-04-16 at 18:08 +0900, Chanwoo Choi wrote:
> Hi,
> 
> I already reviewed this patch on v1[1].
> [1] https://lkml.org/lkml/2019/2/11/2228
> 
> But, the second version patch doesn't include the anything
> about review. Please check it[1].
HI Chanwoo,
Sorry for this clumsy mistake.
I will update at patch v3
> 
> On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> > This adds dt-binding documentation of cci devfreq
> > for Mediatek MT8183 SoC platform.
> > 
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
> >  1 file changed, 19 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > new file mode 100644
> > index 0000000..e2b61cf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > @@ -0,0 +1,19 @@
> > +* Mediatek CCI frequency device
> > +
> > +Required properties:
> > +- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
> > +
> > +- clocks: for cci devfreq
> > +
> > +- clock-names: for cci devfreq driver to reference
> > +
> > +- operating-points-v2: for cci devfreq opp table
> > +
> > +Example:
> > +	cci: cci {
> > +		compatible = "mediatek,cci";
> > +		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
> > +		clock-names = "cci_clock";
> > +		operating-points-v2 = <&cci_opp>;
> > +	};
> > +
> > 
> 
> 



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

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

* Re: [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 cci devfreq
@ 2019-05-08  9:27         ` andrew-sh.cheng
  0 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-05-08  9:27 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Rob Herring, fan.chen,
	Kyungmin Park, MyungJoo Ham, linux-mediatek, Matthias Brugger,
	linux-arm-kernel

On Tue, 2019-04-16 at 18:08 +0900, Chanwoo Choi wrote:
> Hi,
> 
> I already reviewed this patch on v1[1].
> [1] https://lkml.org/lkml/2019/2/11/2228
> 
> But, the second version patch doesn't include the anything
> about review. Please check it[1].
HI Chanwoo,
Sorry for this clumsy mistake.
I will update at patch v3
> 
> On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> > This adds dt-binding documentation of cci devfreq
> > for Mediatek MT8183 SoC platform.
> > 
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  .../bindings/devfreq/mt8183-cci-devfreq.txt           | 19 +++++++++++++++++++
> >  1 file changed, 19 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > new file mode 100644
> > index 0000000..e2b61cf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt
> > @@ -0,0 +1,19 @@
> > +* Mediatek CCI frequency device
> > +
> > +Required properties:
> > +- compatible: should contain "mediatek,mt8183-cci" for cci devfreq
> > +
> > +- clocks: for cci devfreq
> > +
> > +- clock-names: for cci devfreq driver to reference
> > +
> > +- operating-points-v2: for cci devfreq opp table
> > +
> > +Example:
> > +	cci: cci {
> > +		compatible = "mediatek,cci";
> > +		clocks = <&apmixedsys CLK_APMIXED_CCIPLL>;
> > +		clock-names = "cci_clock";
> > +		operating-points-v2 = <&cci_opp>;
> > +	};
> > +
> > 
> 
> 



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 4/4] devfreq: add mediatek cci devfreq
  2019-04-16  9:05       ` Chanwoo Choi
  (?)
@ 2019-05-10  9:24       ` andrew-sh.cheng
  -1 siblings, 0 replies; 46+ messages in thread
From: andrew-sh.cheng @ 2019-05-10  9:24 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Mark Rutland, devicetree, srv_heupstream, linux-pm, Viresh Kumar,
	Rafael J. Wysocki, linux-kernel, Rob Herring, fan.chen,
	Kyungmin Park, MyungJoo Ham, linux-mediatek, Matthias Brugger,
	linux-arm-kernel

On Tue, 2019-04-16 at 18:05 +0900, Chanwoo Choi wrote:
> Hi Andrew-sh.Cheng,
> 
> Please add the dt-binding documentation.
> 
> On 19. 3. 29. 오후 3:46, Andrew-sh.Cheng wrote:
> > This adds a devfreq driver for the Cache Coherent Interconnect (CCI)
> > of the Mediatek MT8183.
> > 
> > On the MT8183 the CCI is supplied by the same regulator as the LITTLE
> > cores. The driver is notified when the regulator voltage changes
> > (driven by cpufreq) and adjusts the CCI frequency to the maximum
> > possible value.
> > 
> > Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> > ---
> >  drivers/devfreq/Kconfig              |  10 ++
> >  drivers/devfreq/Makefile             |   1 +
> >  drivers/devfreq/mt8183-cci-devfreq.c | 235 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 246 insertions(+)
> >  create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c
> > 
> > diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> > index 6a172d3..da2f8ec 100644
> > --- a/drivers/devfreq/Kconfig
> > +++ b/drivers/devfreq/Kconfig
> > @@ -91,6 +91,16 @@ config ARM_EXYNOS_BUS_DEVFREQ
> >  	  and adjusts the operating frequencies and voltages with OPP support.
> >  	  This does not yet operate with optimal voltages.
> >  
> > +config ARM_MT8183_CCI_DEVFREQ
> > +	tristate "MT8183 CCI DEVFREQ Driver"
> > +	depends on ARM_MEDIATEK_CPUFREQ
> > +	help
> > +		This adds a devfreq driver for Cache Coherent Interconnect
> > +		of Mediatek MT8183, which is shared the same regulator
> > +		with cpu cluster.
> > +		It can track buck voltage and update a proper cci frequency.
> > +		Use notification to get regulator status.
> > +
> >  config ARM_TEGRA_DEVFREQ
> >  	tristate "Tegra DEVFREQ Driver"
> >  	depends on ARCH_TEGRA_124_SOC
> > diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> > index 32b8d4d..817dde7 100644
> > --- a/drivers/devfreq/Makefile
> > +++ b/drivers/devfreq/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
> >  
> >  # DEVFREQ Drivers
> >  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
> > +obj-$(CONFIG_ARM_MT8183_CCI_DEVFREQ)    += mt8183-cci-devfreq.o
> >  obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
> >  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
> >  
> > diff --git a/drivers/devfreq/mt8183-cci-devfreq.c b/drivers/devfreq/mt8183-cci-devfreq.c
> > new file mode 100644
> > index 0000000..af82d2e
> > --- /dev/null
> > +++ b/drivers/devfreq/mt8183-cci-devfreq.c
> > @@ -0,0 +1,235 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> 
> You can add the author information under copyright information.
ok~
> 
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/devfreq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +
> > +#include "governor.h"
> > +
> > +struct cci_devfreq {
> > +	struct devfreq		*devfreq;
> > +	struct regulator	*proc_reg;
> > +	unsigned long           proc_reg_uV;
> > +	struct clk		*cci_clk;
> > +	struct notifier_block	nb;
> 
> Just use the space instead of tab as following:
> 
> 	struct devfreq *devfreq;
> 	struct regulator *proc_reg;
> 	unsigned long proc_reg_uV;
> 	struct clk *cci_clk;
> 	struct notifier_block nb;
> 
OK, I will modify at next patch.
> > +};
> > +
> > +static int cci_devfreq_regulator_notifier(struct notifier_block *nb,
> > +					  unsigned long val, void *data)
> > +{
> > +	struct cci_devfreq *cci_df =
> > +		container_of(nb, struct cci_devfreq, nb);
> > +
> > +	/* deal with reduce frequency */
> > +	if (val & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
> > +		struct pre_voltage_change_data *pvc_data = data;
> > +
> > +		if (pvc_data->min_uV < pvc_data->old_uV) {
> > +			cci_df->proc_reg_uV =
> > +				(unsigned long)(pvc_data->min_uV);
> > +			mutex_lock(&cci_df->devfreq->lock);
> > +			update_devfreq(cci_df->devfreq);
> 
> Please handle the return value of update_devfreq() for exception handling.
OK, I will modify at next patch.
> 
> > +			mutex_unlock(&cci_df->devfreq->lock);
> > +		}
> > +	}
> > +
> > +	if ((val & REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE) &&
> 
> if -> else if
> 
> At the same time, receives only one notification.
> It is not necessary to check the two if statement always, .
OK, I will modify at next patch.
> 
> 
> > +	    ((unsigned long)data > cci_df->proc_reg_uV)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> 
> ditto. Please check the return value of update_devfreq.
OK, I will modify at next patch.
> 
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	/* deal with increase frequency */
> > +	if ((val & REGULATOR_EVENT_VOLTAGE_CHANGE) &&
> 
> ditto.
> if -> else if
> 
> At the same time, receives only one notification.
> It is not necessary to check the two if statement always, .
OK, I will modify at next patch.
> 
> 
> > +	    (cci_df->proc_reg_uV < (unsigned long)data)) {
> > +		cci_df->proc_reg_uV = (unsigned long)data;
> > +		mutex_lock(&cci_df->devfreq->lock);
> > +		update_devfreq(cci_df->devfreq);
> 
> ditto. Please check the return value of update_devfreq.
OK, I will modify at next patch.
> 
> > +		mutex_unlock(&cci_df->devfreq->lock);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_get_target(struct devfreq *devfreq,
> > +				       unsigned long *freq)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct dev_pm_opp *opp;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +
> > +	/* find available frequency */
> > +	opp = dev_pm_opp_find_max_freq_by_volt(devfreq->dev.parent,
> > +						 cci_df->proc_reg_uV);
> > +	*freq = dev_pm_opp_get_freq(opp);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_cci_governor_event_handler(struct devfreq *devfreq,
> > +					  unsigned int event, void *data)
> > +{
> > +	struct cci_devfreq *cci_df;
> > +	struct notifier_block *nb;
> > +
> > +	cci_df = dev_get_drvdata(devfreq->dev.parent);
> > +	nb = &cci_df->nb;
> > +
> > +	switch (event) {
> > +	case DEVFREQ_GOV_START:
> > +	case DEVFREQ_GOV_RESUME:
> > +		nb->notifier_call = cci_devfreq_regulator_notifier;
> > +		regulator_register_notifier(cci_df->proc_reg,
> > +					    nb);
> 
> Please check the return value of regulator_register_notifier
> in order to handle the exception handling.
OK, I will modify at next patch.
> 
> 
> > +		break;
> > +
> > +	case DEVFREQ_GOV_STOP:
> > +	case DEVFREQ_GOV_SUSPEND:
> > +		regulator_unregister_notifier(cci_df->proc_reg,
> > +					    nb);
> 
> ditto.
> 
> > +
> 
> Remove unneeded blank line.
OK, I will modify at next patch.
> 
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_governor mtk_cci_devfreq_governor = {
> > +	.name = "mtk_cci_vmon",
> 
> How about editing the name from mtk_cci_vmon to mediatek_cci_voltage_monitor
> for the readability? Actually, 'mtk' and 'vmon' are not standard expression.
The srting of name is only [16], I'll leave it as mtk_cci_vmon.
> 
> > +	.get_target_freq = mtk_cci_governor_get_target,
> > +	.event_handler = mtk_cci_governor_event_handler,
> 
> Please add following code to make it as the immutable
> because the governor for this driver will not be changed
> through sysfs interface.
> 
> 	.immutable = true
OK, I will modify at next patch.
> 
> > +};
> > +
> > +static int mtk_cci_devfreq_target(struct device *dev, unsigned long *freq,
> > +				  u32 flags)
> > +{
> > +	struct cci_devfreq *cci_df = dev_get_drvdata(dev);
> > +
> > +	if (!cci_df)
> > +		return -EINVAL;
> > +
> > +	clk_set_rate(cci_df->cci_clk, *freq);
> 
> Please check the return value of clk_set_rate().
OK, I will modify at next patch.
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static struct devfreq_dev_profile cci_devfreq_profile = {
> > +	.target		= mtk_cci_devfreq_target,
> 
> Just use the space instead of tab because cci_devfreq_profile
> only has one record.
> 
> 	.target = mtk_cci_devfreq_target,
OK, I will modify at next patch.
> 
> > +};
> > +
> > +static int mtk_cci_devfreq_probe(struct platform_device *pdev)
> > +{
> > +	struct device *cci_dev = &pdev->dev;
> > +	struct cci_devfreq *cci_df;
> > +	int ret;
> > +
> > +	cci_df = devm_kzalloc(cci_dev, sizeof(*cci_df), GFP_KERNEL);
> > +	if (!cci_df)
> > +		return -ENOMEM;
> > +
> > +	cci_df->cci_clk = clk_get(cci_dev, "cci_clock");
> 
> clk_get -> devm_clk_get()
OK, I will modify at next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->cci_clk);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get clock for CCI: %d\n",
> > +				ret);
> > +
> 
> Remove unneeded blank line.
> 
> > +		return ret;
> > +	}> +
> > +	cci_df->proc_reg = regulator_get_optional(cci_dev, "proc");
> 
> 
> regulator_get_optional -> devm_regulator_get_optional
OK, I will modify at next patch.
> 
> > +	ret = PTR_ERR_OR_ZERO(cci_df->proc_reg);
> > +	if (ret) {
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(cci_dev, "failed to get regulator for CCI: %d\n",
> > +				ret);
> > +
> 
> Remove unneeded blank line.
> 
> > +		goto err_put_clk;
> 
> If you use devm_clk_get(), just return instead of goto.
OK, I will rewrite these code.
> 
> > +	}
> > +
> > +	ret = dev_pm_opp_of_add_table(&pdev->dev);
> > +	if (ret) {
> > +		dev_err(cci_dev, "Fail to init CCI OPP table\n");
> > +		goto err_put_reg;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, cci_df);
> > +
> > +	cci_df->devfreq = devm_devfreq_add_device(cci_dev,
> > +						       &cci_devfreq_profile,
> > +						       "mtk_cci_vmon",
> > +						       NULL);
> > +	if (IS_ERR(cci_df->devfreq)) {
> > +		dev_err(cci_dev, "cannot create cci devfreq device\n", ret);
> > +		goto err_put_reg;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_put_reg:
> > +	regulator_put(cci_df->proc_reg);
> > +err_put_clk:
> > +	clk_put(cci_df->cci_clk);
> 
> If you use devm_clk_get()/devm_regulator_get(),
> 'err_put_reg' and 'err_put_clk' are unneeded.
OK, I will rewrite these code.
> 
> > +
> > +	return ret;
> > +}
> > +
> > +static const struct of_device_id mediatek_cci_devfreq_of_match[] = {
> > +	{ .compatible = "mediatek,mt8183-cci" },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, mediatek_cci_devfreq_of_match);
> > +
> > +static struct platform_driver cci_devfreq_driver = {
> > +	.probe	= mtk_cci_devfreq_probe,
> > +	.driver = {
> > +		.name = "mediatek-cci-devfreq",
> > +		.of_match_table = mediatek_cci_devfreq_of_match,
> > +	},
> > +};
> > +
> > +static int __init mtk_cci_devfreq_init(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_add_governor(&mtk_cci_devfreq_governor);
> > +	if (ret) {
> > +		pr_err("%s: failed to add governor: %d\n", __func__, ret);
> > +		return ret;
> > +	}
> > +
> > +	ret = platform_driver_register(&cci_devfreq_driver);
> > +	if (ret)
> > +		devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +
> > +	return ret;
> > +}
> > +module_init(mtk_cci_devfreq_init)
> > +
> > +static void __exit mtk_cci_devfreq_exit(void)
> > +{
> > +	int ret;
> > +
> > +	ret = devfreq_remove_governor(&mtk_cci_devfreq_governor);
> > +	if (ret)
> > +		pr_err("%s: failed to remove governor: %d\n", __func__, ret);
> > +
> > +	platform_driver_unregister(&cci_devfreq_driver);
> > +}
> > +module_exit(mtk_cci_devfreq_exit)
> > +
> > +MODULE_DESCRIPTION("Mediatek CCI devfreq driver");
> > +MODULE_AUTHOR("Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>");
> > +MODULE_LICENSE("GPL v2");
> > 
> 
> 



_______________________________________________
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] 46+ messages in thread

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
  2019-03-29  6:46     ` Andrew-sh.Cheng
  (?)
@ 2022-06-02  6:54       ` Viresh Kumar
  -1 siblings, 0 replies; 46+ messages in thread
From: Viresh Kumar @ 2022-06-02  6:54 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, linux-pm,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	srv_heupstream, fan.chen

On Fri, 29 Mar 2019 at 12:16, Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)

This patch added dev_pm_opp_find_freq_ceil_by_volt() but I don't find anything
in the kernel which uses it? The patchset for CCI never got merged ?

I will remove the API now.

--
Viresh

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2022-06-02  6:54       ` Viresh Kumar
  0 siblings, 0 replies; 46+ messages in thread
From: Viresh Kumar @ 2022-06-02  6:54 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, linux-pm,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	srv_heupstream, fan.chen

On Fri, 29 Mar 2019 at 12:16, Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)

This patch added dev_pm_opp_find_freq_ceil_by_volt() but I don't find anything
in the kernel which uses it? The patchset for CCI never got merged ?

I will remove the API now.

--
Viresh

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

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

* Re: [PATCH v2 2/4] opp: add API which get max freq by voltage
@ 2022-06-02  6:54       ` Viresh Kumar
  0 siblings, 0 replies; 46+ messages in thread
From: Viresh Kumar @ 2022-06-02  6:54 UTC (permalink / raw)
  To: Andrew-sh.Cheng
  Cc: MyungJoo Ham, Kyungmin Park, Chanwoo Choi, Rob Herring,
	Mark Rutland, Matthias Brugger, Rafael J. Wysocki, linux-pm,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	srv_heupstream, fan.chen

On Fri, 29 Mar 2019 at 12:16, Andrew-sh.Cheng
<andrew-sh.cheng@mediatek.com> wrote:
>
> This API will get voltage as input parameter.
> Search all opp items for the item which with max frequency,
> and the voltae is smaller than provided voltage.
>
> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> ---
>  drivers/opp/core.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  8 ++++++++
>  2 files changed, 63 insertions(+)

This patch added dev_pm_opp_find_freq_ceil_by_volt() but I don't find anything
in the kernel which uses it? The patchset for CCI never got merged ?

I will remove the API now.

--
Viresh

_______________________________________________
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] 46+ messages in thread

end of thread, other threads:[~2022-06-02  6:55 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-29  6:46 [PATCH v2 0/4] Add cpufreq and cci devfreq for mt8183 Andrew-sh.Cheng
2019-03-29  6:46 ` Andrew-sh.Cheng
     [not found] ` <1553841972-19737-1-git-send-email-andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2019-03-29  6:46   ` [PATCH v2 1/4] cpufreq: mediatek: add mt8183 cpufreq support Andrew-sh.Cheng
2019-03-29  6:46     ` Andrew-sh.Cheng
2019-03-31  0:06     ` Nicolas Boichat
2019-03-31  0:06       ` Nicolas Boichat
2019-03-31  0:06       ` Nicolas Boichat
2019-04-13  2:33       ` andrew-sh.cheng
2019-04-13  2:33         ` andrew-sh.cheng
2019-03-29  6:46   ` [PATCH v2 2/4] opp: add API which get max freq by voltage Andrew-sh.Cheng
2019-03-29  6:46     ` Andrew-sh.Cheng
2019-04-03  4:32     ` Nicolas Boichat
2019-04-03  4:32       ` Nicolas Boichat
2019-04-03  4:32       ` Nicolas Boichat
2019-04-13  4:39       ` andrew-sh.cheng
2019-04-13  4:39         ` andrew-sh.cheng
2019-04-10  6:29     ` Viresh Kumar
2019-04-10  6:29       ` Viresh Kumar
2022-06-02  6:54     ` Viresh Kumar
2022-06-02  6:54       ` Viresh Kumar
2022-06-02  6:54       ` Viresh Kumar
2019-03-29  6:46   ` [PATCH v2 4/4] devfreq: add mediatek cci devfreq Andrew-sh.Cheng
2019-03-29  6:46     ` Andrew-sh.Cheng
2019-04-08 17:22     ` [v2,4/4] " Guenter Roeck
2019-04-08 17:22       ` Guenter Roeck
2019-04-13  7:07       ` andrew-sh.cheng
2019-04-13  7:07         ` andrew-sh.cheng
2019-04-16  9:05     ` [PATCH v2 4/4] " Chanwoo Choi
2019-04-16  9:05       ` Chanwoo Choi
2019-05-10  9:24       ` andrew-sh.cheng
2019-03-29  6:46 ` [PATCH v2 3/4] dt-bindings: devfreq: add compatible for mt8183 " Andrew-sh.Cheng
2019-03-29  6:46   ` Andrew-sh.Cheng
2019-04-16  9:08   ` Chanwoo Choi
2019-04-16  9:08     ` Chanwoo Choi
     [not found]     ` <28f2c90a-9588-3afa-193d-2572c9cc9bf5-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2019-05-08  9:27       ` andrew-sh.cheng
2019-05-08  9:27         ` andrew-sh.cheng
     [not found] ` <CGME20190329064632epcas2p4d10ea099bfea4ad682d7312a75bfbe68@epcms1p8>
2019-04-01  2:30   ` [PATCH v2 2/4] opp: add API which get max freq by voltage MyungJoo Ham
2019-04-01  2:30     ` MyungJoo Ham
2019-04-01  2:30     ` MyungJoo Ham
2019-04-13  3:36     ` andrew-sh.cheng
2019-04-13  3:36       ` andrew-sh.cheng
     [not found] ` <CGME20190329064636epcas1p13633ae078ef83ceda0b8189df1399753@epcms1p1>
2019-04-01  4:18   ` [PATCH v2 4/4] devfreq: add mediatek cci devfreq MyungJoo Ham
2019-04-01  4:18     ` MyungJoo Ham
2019-04-01  4:18     ` MyungJoo Ham
2019-04-13  5:54     ` andrew-sh.cheng
2019-04-13  5:54       ` andrew-sh.cheng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.