All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers
@ 2020-03-31 11:09 Akash Asthana
  2020-03-31 11:09   ` Akash Asthana
                   ` (7 more replies)
  0 siblings, 8 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

dt-binding patch for QUP drivers.
 - https://patchwork.kernel.org/patch/11436621/ [Convert QUP bindings
        to YAML and add ICC, pin swap doc]

dt-binding patch for QSPI.
 - https://patchwork.kernel.org/patch/11436719/ [Convert QSPI binding
        to YAML and add interconnect doc]

High level design:
 - QUP wrapper/common driver.
   Vote for QUP core on behalf of earlycon from probe.
   Remove BW vote during earlycon exit call

 - SERIAL driver.
   Vote only for CPU/CORE path because driver is in FIFO mode only
   Vote/unvote from qcom_geni_serial_pm func.
   Bump up the CPU vote from set_termios call based on real time need

 - I2C driver.
   Vote for CORE/CPU/DDR path
   Vote/unvote from runtime resume/suspend callback
   As bus speed for I2C is fixed from probe itself no need for bump up.

 - SPI QUP driver.
   Vote only for CPU/CORE path because driver is in FIFO mode only
   Vote/unvote from runtime resume/suspend callback
   Bump up CPU vote based on real time need per transfer.

 - QSPI driver.
   Vote only for CPU path
   Vote/unvote from runtime resume/suspend callback
   Bump up CPU vote based on real time need per transfer.

Changes in V2:
 - Add devm_of_icc_get() API interconnect core.
 - Add ICC support to common driver to fix earlyconsole crash.

Changes in V3:
 - Define common ICC APIs in geni-se driver and use it across geni based
   I2C,SPI and UART driver.

Akash Asthana (8):
  interconnect: Add devm_of_icc_get() as exported API for users
  soc: qcom: geni: Support for ICC voting
  soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  i2c: i2c-qcom-geni: Add interconnect support
  spi: spi-geni-qcom: Add interconnect support
  tty: serial: qcom_geni_serial: Add interconnect support
  spi: spi-qcom-qspi: Add interconnect support
  arm64: dts: sc7180: Add interconnect for QUP and QSPI

 arch/arm64/boot/dts/qcom/sc7180.dtsi  | 127 +++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-qcom-geni.c    |  30 ++++++-
 drivers/interconnect/core.c           |  25 ++++++
 drivers/soc/qcom/qcom-geni-se.c       | 149 ++++++++++++++++++++++++++++++++++
 drivers/spi/spi-geni-qcom.c           |  31 ++++++-
 drivers/spi/spi-qcom-qspi.c           |  46 ++++++++++-
 drivers/tty/serial/qcom_geni_serial.c |  35 +++++++-
 include/linux/interconnect.h          |   7 ++
 include/linux/qcom-geni-se.h          |  38 +++++++++
 9 files changed, 482 insertions(+), 6 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 1/8] interconnect: Add devm_of_icc_get() as exported API for users
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Users can use devm version of of_icc_get() to benefit from automatic
resource release.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
Reviewed by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/interconnect/core.c  | 25 +++++++++++++++++++++++++
 include/linux/interconnect.h |  7 +++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 2c6515e..f5699ed 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -350,6 +350,31 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 	return node;
 }
 
+static void devm_icc_release(struct device *dev, void *res)
+{
+	icc_put(*(struct icc_path **)res);
+}
+
+struct icc_path *devm_of_icc_get(struct device *dev, const char *name)
+{
+	struct icc_path **ptr, *path;
+
+	ptr = devres_alloc(devm_icc_release, sizeof(**ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	path = of_icc_get(dev, name);
+	if (!IS_ERR(path)) {
+		*ptr = path;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return path;
+}
+EXPORT_SYMBOL_GPL(devm_of_icc_get);
+
 /**
  * of_icc_get() - get a path handle from a DT node based on name
  * @dev: device pointer for the consumer device
diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h
index d70a914..7706924 100644
--- a/include/linux/interconnect.h
+++ b/include/linux/interconnect.h
@@ -28,6 +28,7 @@ struct device;
 struct icc_path *icc_get(struct device *dev, const int src_id,
 			 const int dst_id);
 struct icc_path *of_icc_get(struct device *dev, const char *name);
+struct icc_path *devm_of_icc_get(struct device *dev, const char *name);
 void icc_put(struct icc_path *path);
 int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw);
 void icc_set_tag(struct icc_path *path, u32 tag);
@@ -46,6 +47,12 @@ static inline struct icc_path *of_icc_get(struct device *dev,
 	return NULL;
 }
 
+static inline struct icc_path *devm_of_icc_get(struct device *dev,
+						const char *name)
+{
+	return NULL;
+}
+
 static inline void icc_put(struct icc_path *path)
 {
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 1/8] interconnect: Add devm_of_icc_get() as exported API for users
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, mka-F7+t8E8rja9g9hUCZPvPmw,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw,
	Akash Asthana

Users can use devm version of of_icc_get() to benefit from automatic
resource release.

Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Reviewed by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/interconnect/core.c  | 25 +++++++++++++++++++++++++
 include/linux/interconnect.h |  7 +++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 2c6515e..f5699ed 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -350,6 +350,31 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 	return node;
 }
 
+static void devm_icc_release(struct device *dev, void *res)
+{
+	icc_put(*(struct icc_path **)res);
+}
+
+struct icc_path *devm_of_icc_get(struct device *dev, const char *name)
+{
+	struct icc_path **ptr, *path;
+
+	ptr = devres_alloc(devm_icc_release, sizeof(**ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	path = of_icc_get(dev, name);
+	if (!IS_ERR(path)) {
+		*ptr = path;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return path;
+}
+EXPORT_SYMBOL_GPL(devm_of_icc_get);
+
 /**
  * of_icc_get() - get a path handle from a DT node based on name
  * @dev: device pointer for the consumer device
diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h
index d70a914..7706924 100644
--- a/include/linux/interconnect.h
+++ b/include/linux/interconnect.h
@@ -28,6 +28,7 @@ struct device;
 struct icc_path *icc_get(struct device *dev, const int src_id,
 			 const int dst_id);
 struct icc_path *of_icc_get(struct device *dev, const char *name);
+struct icc_path *devm_of_icc_get(struct device *dev, const char *name);
 void icc_put(struct icc_path *path);
 int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw);
 void icc_set_tag(struct icc_path *path, u32 tag);
@@ -46,6 +47,12 @@ static inline struct icc_path *of_icc_get(struct device *dev,
 	return NULL;
 }
 
+static inline struct icc_path *devm_of_icc_get(struct device *dev,
+						const char *name)
+{
+	return NULL;
+}
+
 static inline void icc_put(struct icc_path *path)
 {
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
  2020-03-31 11:09   ` Akash Asthana
@ 2020-03-31 11:09 ` Akash Asthana
  2020-03-31 17:52     ` Matthias Kaehlcke
  2020-03-31 23:32     ` Bjorn Andersson
  2020-03-31 11:09 ` [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash Akash Asthana
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Add necessary macros and structure variables to support ICC BW
voting from individual SE drivers.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment dropped enums for ICC paths, given the three
   paths individual members

Changes in V3:
 - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
 - Add geni_icc_path structure in common header

 drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
 include/linux/qcom-geni-se.h    | 36 +++++++++++++++
 2 files changed, 134 insertions(+)

diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 7d622ea..9344c14 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
 }
 EXPORT_SYMBOL(geni_se_rx_dma_unprep);
 
+int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
+		const char *icc_ddr)
+{
+	if (icc_core) {
+		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
+		if (IS_ERR(se->to_core.path))
+			return PTR_ERR(se->to_core.path);
+	}
+
+	if (icc_cpu) {
+		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
+		if (IS_ERR(se->from_cpu.path))
+			return PTR_ERR(se->from_cpu.path);
+	}
+
+	if (icc_ddr) {
+		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
+		if (IS_ERR(se->to_ddr.path))
+			return PTR_ERR(se->to_ddr.path);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(geni_icc_get);
+
+int geni_icc_vote_on(struct geni_se *se)
+{
+	int ret;
+
+	if (se->to_core.path) {
+		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
+			se->to_core.peak_bw);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	if (se->from_cpu.path) {
+		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
+			se->from_cpu.peak_bw);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	if (se->to_ddr.path) {
+		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
+			se->to_ddr.peak_bw);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(geni_icc_vote_on);
+
+int geni_icc_vote_off(struct geni_se *se)
+{
+	int ret;
+
+	if (se->to_core.path) {
+		ret = icc_set_bw(se->to_core.path, 0, 0);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	if (se->from_cpu.path) {
+		ret = icc_set_bw(se->from_cpu.path, 0, 0);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	if (se->to_ddr.path) {
+		ret = icc_set_bw(se->to_ddr.path, 0, 0);
+		if (ret) {
+			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
+						__func__);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(geni_icc_vote_off);
+
 static int geni_se_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index dd46494..a83c86b 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -6,6 +6,8 @@
 #ifndef _LINUX_QCOM_GENI_SE
 #define _LINUX_QCOM_GENI_SE
 
+#include <linux/interconnect.h>
+
 /* Transfer mode supported by GENI Serial Engines */
 enum geni_se_xfer_mode {
 	GENI_SE_INVALID,
@@ -25,6 +27,12 @@ enum geni_se_protocol_type {
 struct geni_wrapper;
 struct clk;
 
+struct geni_icc_path {
+	struct icc_path *path;
+	unsigned int avg_bw;
+	unsigned int peak_bw;
+};
+
 /**
  * struct geni_se - GENI Serial Engine
  * @base:		Base Address of the Serial Engine's register block
@@ -33,6 +41,9 @@ struct clk;
  * @clk:		Handle to the core serial engine clock
  * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl
  * @clk_perf_tbl:	Table of clock frequency input to serial engine clock
+ * @to_core:	ICC path structure for geni to core
+ * @from_cpu:	ICC path structure for cpu to geni
+ * @to_ddr:	ICC path structure for geni to ddr
  */
 struct geni_se {
 	void __iomem *base;
@@ -41,6 +52,9 @@ struct geni_se {
 	struct clk *clk;
 	unsigned int num_clk_levels;
 	unsigned long *clk_perf_tbl;
+	struct geni_icc_path to_core;
+	struct geni_icc_path from_cpu;
+	struct geni_icc_path to_ddr;
 };
 
 /* Common SE registers */
@@ -229,6 +243,21 @@ struct geni_se {
 #define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT)
 #define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK)
 
+/*
+ * Define bandwidth thresholds that cause the underlying Core 2X interconnect
+ * clock to run at the named frequency. These baseline values are recommended
+ * by the hardware team, and are not dynamically scaled with GENI bandwidth
+ * beyond basic on/off.
+ */
+#define CORE_2X_19_2_MHZ		960
+#define CORE_2X_50_MHZ			2500
+#define CORE_2X_100_MHZ			5000
+#define CORE_2X_150_MHZ			7500
+#define CORE_2X_200_MHZ			10000
+#define CORE_2X_236_MHZ			16383
+
+#define GENI_DEFAULT_BW			Bps_to_icc(1000)
+
 #if IS_ENABLED(CONFIG_QCOM_GENI_SE)
 
 u32 geni_se_get_qup_hw_version(struct geni_se *se);
@@ -416,5 +445,12 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
 void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
 
 void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
+
+int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
+		const char *icc_ddr);
+
+int geni_icc_vote_on(struct geni_se *se);
+
+int geni_icc_vote_off(struct geni_se *se);
 #endif
 #endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
  2020-03-31 11:09   ` Akash Asthana
  2020-03-31 11:09 ` [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting Akash Asthana
@ 2020-03-31 11:09 ` Akash Asthana
  2020-03-31 18:24     ` Matthias Kaehlcke
  2020-03-31 11:09 ` [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support Akash Asthana
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

QUP core clock is shared among all the SE drivers present on particular
QUP wrapper, the system will reset(unclocked access) if earlycon used after
QUP core clock is put to 0 from other SE drivers before real console comes
up.

As earlycon can't vote for it's QUP core need, to fix this add ICC
support to common/QUP wrapper driver and put vote for QUP core from
probe on behalf of earlycon and remove vote during earlycon exit call.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
Reported-by: Matthias Kaehlcke <mka@chromium.org>
---
Change is V3:
 - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
   exit function to remove ICC vote for earlyconsole.
 - Remove suspend/resume hook for geni-se driver as we are no longer
   removing earlyconsole ICC vote from system suspend, we are removing
   from earlycon exit.

 drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
 drivers/tty/serial/qcom_geni_serial.c |  7 +++++
 include/linux/qcom-geni-se.h          |  2 ++
 3 files changed, 60 insertions(+)

diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 9344c14..d30c282 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -90,8 +90,11 @@ struct geni_wrapper {
 	struct device *dev;
 	void __iomem *base;
 	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
+	struct geni_icc_path to_core;
 };
 
+struct geni_wrapper *earlycon_wrapper;
+
 #define QUP_HW_VER_REG			0x4
 
 /* Common SE registers */
@@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
 }
 EXPORT_SYMBOL(geni_icc_vote_off);
 
+void geni_remove_earlycon_icc_vote(void)
+{
+	struct geni_wrapper *wrapper = earlycon_wrapper;
+	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
+	struct device_node *child;
+
+	for_each_child_of_node(parent, child) {
+		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
+			wrapper = platform_get_drvdata(of_find_device_by_node(
+					child));
+			icc_put(wrapper->to_core.path);
+			wrapper->to_core.path = NULL;
+		}
+	}
+	of_node_put(parent);
+
+	earlycon_wrapper = NULL;
+}
+EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
+
 static int geni_se_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
 		}
 	}
 
+#ifdef CONFIG_SERIAL_EARLYCON
+	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
+	if (IS_ERR(wrapper->to_core.path))
+		return PTR_ERR(wrapper->to_core.path);
+	/*
+	 * Put minmal BW request on core clocks on behalf of early console.
+	 * The vote will be removed earlycon exit function.
+	 *
+	 * Note: We are putting vote on each QUP wrapper instead only to which
+	 * earlycon is connected because QUP core clock of different wrapper
+	 * share same voltage domain. If core1 is put to 0, then core2 will
+	 * also run at 0, if not voted. Default ICC vote will be removed ASA
+	 * we touch any of the core clock.
+	 * core1 = core2 = max(core1, core2)
+	 */
+	ret = icc_set_bw(wrapper->to_core.path, GENI_DEFAULT_BW,
+			GENI_DEFAULT_BW);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: ICC BW voting failed for core\n",
+			__func__);
+		return ret;
+	}
+
+	if (of_get_compatible_child(pdev->dev.of_node, "qcom,geni-debug-uart"))
+		earlycon_wrapper = wrapper;
+	of_node_put(pdev->dev.of_node);
+#endif
+
 	dev_set_drvdata(dev, wrapper);
 	dev_dbg(dev, "GENI SE Driver probed\n");
 	return devm_of_platform_populate(dev);
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 6119090..8c5d97c 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1090,6 +1090,12 @@ static void qcom_geni_serial_earlycon_write(struct console *con,
 	__qcom_geni_serial_console_write(&dev->port, s, n);
 }
 
+static int qcom_geni_serial_earlycon_exit(struct console *con)
+{
+	geni_remove_earlycon_icc_vote();
+	return 0;
+}
+
 static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev,
 								const char *opt)
 {
@@ -1135,6 +1141,7 @@ static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev,
 	writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
 
 	dev->con->write = qcom_geni_serial_earlycon_write;
+	dev->con->exit = qcom_geni_serial_earlycon_exit;
 	dev->con->setup = NULL;
 	return 0;
 }
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index a83c86b..c830b38 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -452,5 +452,7 @@ int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
 int geni_icc_vote_on(struct geni_se *se);
 
 int geni_icc_vote_off(struct geni_se *se);
+
+void geni_remove_earlycon_icc_vote(void);
 #endif
 #endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support
  2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
                   ` (2 preceding siblings ...)
  2020-03-31 11:09 ` [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash Akash Asthana
@ 2020-03-31 11:09 ` Akash Asthana
  2020-03-31 18:49     ` Matthias Kaehlcke
  2020-03-31 11:09 ` [PATCH V3 5/8] spi: spi-geni-qcom: " Akash Asthana
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Get the interconnect paths for I2C based Serial Engine device
and vote according to the bus speed of the driver.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment, removed se == NULL check from geni_i2c_icc_get
 - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
 - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
   path handle
 - As per Matthias comment, added error handling for icc_set_bw call

Changes in V3:
 - As per Matthias comment, use common library APIs defined in geni-se
   driver for ICC functionality.

 drivers/i2c/busses/i2c-qcom-geni.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 18d1e4f..373c2ca 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -557,6 +557,26 @@ static int geni_i2c_probe(struct platform_device *pdev)
 	gi2c->adap.dev.of_node = dev->of_node;
 	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
 
+	ret = geni_icc_get(&gi2c->se, "qup-core", "qup-config", "qup-memory");
+	if (ret)
+		return ret;
+	/*
+	 * Set the bus quota for core and cpu to a reasonable value for
+	 * register access.
+	 * Set quota for DDR based on bus speed, assume peak requirement
+	 * as twice of avg bw.
+	 */
+	gi2c->se.to_core.avg_bw = GENI_DEFAULT_BW;
+	gi2c->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
+	gi2c->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
+	gi2c->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
+	gi2c->se.to_ddr.avg_bw = Bps_to_icc(gi2c->clk_freq_out);
+	gi2c->se.to_ddr.peak_bw = Bps_to_icc(2 * gi2c->clk_freq_out);
+
+	ret = geni_icc_vote_on(&gi2c->se);
+	if (ret)
+		return ret;
+
 	ret = geni_se_resources_on(&gi2c->se);
 	if (ret) {
 		dev_err(dev, "Error turning on resources %d\n", ret);
@@ -579,6 +599,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ret = geni_icc_vote_off(&gi2c->se);
+	if (ret)
+		return ret;
+
 	dev_dbg(dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
 
 	gi2c->suspended = 1;
@@ -623,7 +647,7 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
 		gi2c->suspended = 1;
 	}
 
-	return 0;
+	return geni_icc_vote_off(&gi2c->se);
 }
 
 static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
@@ -631,6 +655,10 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
 	int ret;
 	struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
 
+	ret = geni_icc_vote_on(&gi2c->se);
+	if (ret)
+		return ret;
+
 	ret = geni_se_resources_on(&gi2c->se);
 	if (ret)
 		return ret;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 5/8] spi: spi-geni-qcom: Add interconnect support
  2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
                   ` (3 preceding siblings ...)
  2020-03-31 11:09 ` [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support Akash Asthana
@ 2020-03-31 11:09 ` Akash Asthana
  2020-03-31 19:02     ` Matthias Kaehlcke
  2020-03-31 11:09   ` Akash Asthana
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Get the interconnect paths for SPI based Serial Engine device
and vote according to the current bus speed of the driver.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment, removed se == NULL check from geni_spi_icc_get
 - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
 - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
   path handle
 - As per Matthias comment, added error handling for icc_set_bw call

Changes in V3:
 - As per Matthias's comment, use helper ICC function from geni-se driver.

 drivers/spi/spi-geni-qcom.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index c397242..f1dae2d 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -234,6 +234,16 @@ static int setup_fifo_params(struct spi_device *spi_slv,
 		return ret;
 	}
 
+	/*
+	 * Set BW quota for CPU as driver supports FIFO mode only.
+	 * Assume peak bw as twice of avg bw.
+	 */
+	se->from_cpu.avg_bw = Bps_to_icc(mas->cur_speed_hz);
+	se->from_cpu.peak_bw = Bps_to_icc(2 * mas->cur_speed_hz);
+	ret = geni_icc_vote_on(se);
+	if (ret)
+		return ret;
+
 	clk_sel = idx & CLK_SEL_MSK;
 	m_clk_cfg = (div << CLK_DIV_SHFT) | SER_CLK_EN;
 	spi_setup_word_len(mas, spi_slv->mode, spi_slv->bits_per_word);
@@ -578,6 +588,15 @@ static int spi_geni_probe(struct platform_device *pdev)
 	spin_lock_init(&mas->lock);
 	pm_runtime_enable(dev);
 
+	ret = geni_icc_get(&mas->se, "qup-core", "qup-config", NULL);
+	if (ret)
+		goto spi_geni_probe_runtime_disable;
+	/* Set the bus quota to a reasonable value for register access */
+	mas->se.to_core.avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
+	mas->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
+	mas->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
+	mas->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
+
 	ret = spi_geni_init(mas);
 	if (ret)
 		goto spi_geni_probe_runtime_disable;
@@ -616,14 +635,24 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
 {
 	struct spi_master *spi = dev_get_drvdata(dev);
 	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+	int ret;
+
+	ret = geni_se_resources_off(&mas->se);
+	if (ret)
+		return ret;
 
-	return geni_se_resources_off(&mas->se);
+	return geni_icc_vote_off(&mas->se);
 }
 
 static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
 {
 	struct spi_master *spi = dev_get_drvdata(dev);
 	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+	int ret;
+
+	ret = geni_icc_vote_on(&mas->se);
+	if (ret)
+		return ret;
 
 	return geni_se_resources_on(&mas->se);
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Get the interconnect paths for Uart based Serial Engine device
and vote according to the baud rate requirement of the driver.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment, removed se == NULL check from geni_serial_icc_get
 - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
 - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
   path handle
 - As per Matthias comment, added error handling for icc_set_bw call

Changes in V3:
 - As per Matthias comment, use common library APIs defined in geni-se
   driver for ICC functionality.

 drivers/tty/serial/qcom_geni_serial.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 8c5d97c..2befe72 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -965,6 +965,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
 	ser_clk_cfg = SER_CLK_EN;
 	ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
 
+	/*
+	 * Bump up BW vote on CPU path as driver supports FIFO mode only.
+	 * Assume peak_bw as twice of avg_bw.
+	 */
+	port->se.from_cpu.avg_bw = Bps_to_icc(baud);
+	port->se.from_cpu.peak_bw = Bps_to_icc(2 * baud);
+	geni_icc_vote_on(&port->se);
+
 	/* parity */
 	tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
 	tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
@@ -1202,11 +1210,14 @@ static void qcom_geni_serial_pm(struct uart_port *uport,
 	if (old_state == UART_PM_STATE_UNDEFINED)
 		old_state = UART_PM_STATE_OFF;
 
-	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
+	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) {
+		geni_icc_vote_on(&port->se);
 		geni_se_resources_on(&port->se);
-	else if (new_state == UART_PM_STATE_OFF &&
-			old_state == UART_PM_STATE_ON)
+	} else if (new_state == UART_PM_STATE_OFF &&
+			old_state == UART_PM_STATE_ON) {
 		geni_se_resources_off(&port->se);
+		geni_icc_vote_off(&port->se);
+	}
 }
 
 static const struct uart_ops qcom_geni_console_pops = {
@@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
 			return -ENOMEM;
 	}
 
+	ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
+	if (ret)
+		return ret;
+	/* Set the bus quota to a reasonable value */
+	port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
+		Bps_to_icc(CORE_2X_50_MHZ);
+	port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
+		Bps_to_icc(CORE_2X_100_MHZ);
+	port->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
+	port->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
+
 	port->name = devm_kasprintf(uport->dev, GFP_KERNEL,
 			"qcom_geni_serial_%s%d",
 			uart_console(uport) ? "console" : "uart", uport->line);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, mka-F7+t8E8rja9g9hUCZPvPmw,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw,
	Akash Asthana

Get the interconnect paths for Uart based Serial Engine device
and vote according to the baud rate requirement of the driver.

Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
Changes in V2:
 - As per Bjorn's comment, removed se == NULL check from geni_serial_icc_get
 - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
 - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
   path handle
 - As per Matthias comment, added error handling for icc_set_bw call

Changes in V3:
 - As per Matthias comment, use common library APIs defined in geni-se
   driver for ICC functionality.

 drivers/tty/serial/qcom_geni_serial.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 8c5d97c..2befe72 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -965,6 +965,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
 	ser_clk_cfg = SER_CLK_EN;
 	ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
 
+	/*
+	 * Bump up BW vote on CPU path as driver supports FIFO mode only.
+	 * Assume peak_bw as twice of avg_bw.
+	 */
+	port->se.from_cpu.avg_bw = Bps_to_icc(baud);
+	port->se.from_cpu.peak_bw = Bps_to_icc(2 * baud);
+	geni_icc_vote_on(&port->se);
+
 	/* parity */
 	tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
 	tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
@@ -1202,11 +1210,14 @@ static void qcom_geni_serial_pm(struct uart_port *uport,
 	if (old_state == UART_PM_STATE_UNDEFINED)
 		old_state = UART_PM_STATE_OFF;
 
-	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
+	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) {
+		geni_icc_vote_on(&port->se);
 		geni_se_resources_on(&port->se);
-	else if (new_state == UART_PM_STATE_OFF &&
-			old_state == UART_PM_STATE_ON)
+	} else if (new_state == UART_PM_STATE_OFF &&
+			old_state == UART_PM_STATE_ON) {
 		geni_se_resources_off(&port->se);
+		geni_icc_vote_off(&port->se);
+	}
 }
 
 static const struct uart_ops qcom_geni_console_pops = {
@@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
 			return -ENOMEM;
 	}
 
+	ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
+	if (ret)
+		return ret;
+	/* Set the bus quota to a reasonable value */
+	port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
+		Bps_to_icc(CORE_2X_50_MHZ);
+	port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
+		Bps_to_icc(CORE_2X_100_MHZ);
+	port->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
+	port->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
+
 	port->name = devm_kasprintf(uport->dev, GFP_KERNEL,
 			"qcom_geni_serial_%s%d",
 			uart_console(uport) ? "console" : "uart", uport->line);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
                   ` (5 preceding siblings ...)
  2020-03-31 11:09   ` Akash Asthana
@ 2020-03-31 11:09 ` Akash Asthana
  2020-03-31 11:23     ` Mark Brown
  2020-03-31 19:45     ` Matthias Kaehlcke
  2020-03-31 11:09   ` Akash Asthana
  7 siblings, 2 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Get the interconnect paths for QSPI device and vote according to the
current bus speed of the driver.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
   path handle
 - As per Matthias comment, added error handling for icc_set_bw call

Changes in V3:
 - No Change.

 drivers/spi/spi-qcom-qspi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 3c4f83b..ad48f43 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -2,6 +2,7 @@
 // Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
 
 #include <linux/clk.h>
+#include <linux/interconnect.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -139,7 +140,10 @@ struct qcom_qspi {
 	struct device *dev;
 	struct clk_bulk_data *clks;
 	struct qspi_xfer xfer;
-	/* Lock to protect xfer and IRQ accessed registers */
+	struct icc_path *icc_path_cpu_to_qspi;
+	unsigned int avg_bw_cpu;
+	unsigned int peak_bw_cpu;
+	/* Lock to protect data accessed by IRQs */
 	spinlock_t lock;
 };
 
@@ -241,6 +245,20 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
 		return ret;
 	}
 
+	/*
+	 * Set BW quota for CPU as driver supports FIFO mode only.
+	 * Assume peak bw as twice of avg bw.
+	 */
+	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
+	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
+	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
+		ctrl->peak_bw_cpu);
+	if (ret) {
+		dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
+			__func__);
+		return ret;
+	}
+
 	spin_lock_irqsave(&ctrl->lock, flags);
 
 	/* We are half duplex, so either rx or tx will be set */
@@ -458,6 +476,15 @@ static int qcom_qspi_probe(struct platform_device *pdev)
 	if (ret)
 		goto exit_probe_master_put;
 
+	ctrl->icc_path_cpu_to_qspi = devm_of_icc_get(dev, "qspi-config");
+	if (IS_ERR(ctrl->icc_path_cpu_to_qspi)) {
+		ret = PTR_ERR(ctrl->icc_path_cpu_to_qspi);
+		goto exit_probe_master_put;
+	}
+	/* Put BW vote on CPU path for register access */
+	ctrl->avg_bw_cpu = Bps_to_icc(1000);
+	ctrl->peak_bw_cpu = Bps_to_icc(1000);
+
 	ret = platform_get_irq(pdev, 0);
 	if (ret < 0)
 		goto exit_probe_master_put;
@@ -511,9 +538,17 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
+	int ret;
 
 	clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks);
 
+	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, 0, 0);
+	if (ret) {
+		dev_err_ratelimited(ctrl->dev, "%s: ICC BW remove failed for cpu\n",
+			__func__);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -521,6 +556,15 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
+	int ret;
+
+	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
+		ctrl->peak_bw_cpu);
+	if (ret) {
+		dev_err_ratelimited(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
+			__func__);
+		return ret;
+	}
 
 	return clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 8/8] arm64: dts: sc7180: Add interconnect for QUP and QSPI
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov
  Cc: linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen, Akash Asthana

Add interconnect ports for GENI QUPs and QSPI to set bus capabilities.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
---
Changes in V2:
 - As per Bjorn's comment, ignoring 80 char limit in defining interconnects
   paths.

Changes in V3:
 - No change.

Note: This won't compile without patch@patchwork.kernel.org/patch/11430403
	[arm64: dts: sc7180: Include interconnect definitions]

 arch/arm64/boot/dts/qcom/sc7180.dtsi | 127 +++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 998f101..65d5c85 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -427,6 +427,8 @@
 			#size-cells = <2>;
 			ranges;
 			iommus = <&apps_smmu 0x43 0x0>;
+			interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>;
+			interconnect-names = "qup-core";
 			status = "disabled";
 
 			i2c0: i2c@880000 {
@@ -439,6 +441,11 @@
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -452,6 +459,9 @@
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -463,6 +473,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart0_default>;
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -476,6 +489,11 @@
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -489,6 +507,9 @@
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -500,6 +521,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart1_default>;
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -513,6 +537,11 @@
 				interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -524,6 +553,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart2_default>;
 				interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -537,6 +569,11 @@
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -550,6 +587,9 @@
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -561,6 +601,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart3_default>;
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -574,6 +617,11 @@
 				interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -585,6 +633,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart4_default>;
 				interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -598,6 +649,11 @@
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -611,6 +667,9 @@
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -622,6 +681,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart5_default>;
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 		};
@@ -636,6 +698,8 @@
 			#size-cells = <2>;
 			ranges;
 			iommus = <&apps_smmu 0x4c3 0x0>;
+			interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>;
+			interconnect-names = "qup-core";
 			status = "disabled";
 
 			i2c6: i2c@a80000 {
@@ -648,6 +712,11 @@
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -661,6 +730,9 @@
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -672,6 +744,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart6_default>;
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -685,6 +760,11 @@
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -696,6 +776,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart7_default>;
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -709,6 +792,11 @@
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -722,6 +810,9 @@
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -733,6 +824,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart8_default>;
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -746,6 +840,11 @@
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -757,6 +856,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart9_default>;
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -770,6 +872,11 @@
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -783,6 +890,9 @@
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -794,6 +904,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart10_default>;
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -807,6 +920,11 @@
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -820,6 +938,9 @@
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -831,6 +952,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart11_default>;
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 		};
@@ -1335,6 +1459,9 @@
 			clocks = <&gcc GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
 				 <&gcc GCC_QSPI_CORE_CLK>;
 			clock-names = "iface", "core";
+			interconnects = <&gem_noc MASTER_APPSS_PROC
+					&config_noc SLAVE_QSPI_0>;
+			interconnect-names = "qspi-config";
 			status = "disabled";
 		};
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* [PATCH V3 8/8] arm64: dts: sc7180: Add interconnect for QUP and QSPI
@ 2020-03-31 11:09   ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-03-31 11:09 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, mka-F7+t8E8rja9g9hUCZPvPmw,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw,
	Akash Asthana

Add interconnect ports for GENI QUPs and QSPI to set bus capabilities.

Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
Changes in V2:
 - As per Bjorn's comment, ignoring 80 char limit in defining interconnects
   paths.

Changes in V3:
 - No change.

Note: This won't compile without patch-2CcfMPLixEJWlDyRan3ELWD2FQJk+8+b@public.gmane.org/patch/11430403
	[arm64: dts: sc7180: Include interconnect definitions]

 arch/arm64/boot/dts/qcom/sc7180.dtsi | 127 +++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 998f101..65d5c85 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -427,6 +427,8 @@
 			#size-cells = <2>;
 			ranges;
 			iommus = <&apps_smmu 0x43 0x0>;
+			interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>;
+			interconnect-names = "qup-core";
 			status = "disabled";
 
 			i2c0: i2c@880000 {
@@ -439,6 +441,11 @@
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -452,6 +459,9 @@
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -463,6 +473,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart0_default>;
 				interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -476,6 +489,11 @@
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -489,6 +507,9 @@
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -500,6 +521,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart1_default>;
 				interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -513,6 +537,11 @@
 				interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -524,6 +553,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart2_default>;
 				interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -537,6 +569,11 @@
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -550,6 +587,9 @@
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -561,6 +601,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart3_default>;
 				interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -574,6 +617,11 @@
 				interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -585,6 +633,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart4_default>;
 				interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -598,6 +649,11 @@
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>,
+						<&aggre1_noc MASTER_QUP_0 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -611,6 +667,9 @@
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -622,6 +681,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart5_default>;
 				interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_0 &qup_virt SLAVE_QUP_CORE_0>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_0>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 		};
@@ -636,6 +698,8 @@
 			#size-cells = <2>;
 			ranges;
 			iommus = <&apps_smmu 0x4c3 0x0>;
+			interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>;
+			interconnect-names = "qup-core";
 			status = "disabled";
 
 			i2c6: i2c@a80000 {
@@ -648,6 +712,11 @@
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -661,6 +730,9 @@
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -672,6 +744,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart6_default>;
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -685,6 +760,11 @@
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -696,6 +776,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart7_default>;
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -709,6 +792,11 @@
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -722,6 +810,9 @@
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -733,6 +824,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart8_default>;
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -746,6 +840,11 @@
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -757,6 +856,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart9_default>;
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -770,6 +872,11 @@
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -783,6 +890,9 @@
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -794,6 +904,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart10_default>;
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -807,6 +920,11 @@
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>,
+						<&aggre2_noc MASTER_QUP_1 &mc_virt SLAVE_EBI1>;
+				interconnect-names = "qup-core", "qup-config",
+							"qup-memory";
 				status = "disabled";
 			};
 
@@ -820,6 +938,9 @@
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 
@@ -831,6 +952,9 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&qup_uart11_default>;
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+				interconnects = <&qup_virt MASTER_QUP_CORE_1 &qup_virt SLAVE_QUP_CORE_1>,
+						<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_QUP_1>;
+				interconnect-names = "qup-core", "qup-config";
 				status = "disabled";
 			};
 		};
@@ -1335,6 +1459,9 @@
 			clocks = <&gcc GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
 				 <&gcc GCC_QSPI_CORE_CLK>;
 			clock-names = "iface", "core";
+			interconnects = <&gem_noc MASTER_APPSS_PROC
+					&config_noc SLAVE_QSPI_0>;
+			interconnect-names = "qspi-config";
 			status = "disabled";
 		};
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
@ 2020-03-31 11:23     ` Mark Brown
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Brown @ 2020-03-31 11:23 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

[-- Attachment #1: Type: text/plain, Size: 377 bytes --]

On Tue, Mar 31, 2020 at 04:39:35PM +0530, Akash Asthana wrote:

> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);

I thought you were going to factor this best guess handling of peak
bandwidth out into the core?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
@ 2020-03-31 11:23     ` Mark Brown
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Brown @ 2020-03-31 11:23 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, mka-F7+t8E8rja9g9hUCZPvPmw,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

[-- Attachment #1: Type: text/plain, Size: 377 bytes --]

On Tue, Mar 31, 2020 at 04:39:35PM +0530, Akash Asthana wrote:

> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);

I thought you were going to factor this best guess handling of peak
bandwidth out into the core?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-03-31 17:52     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 17:52 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:30PM +0530, Akash Asthana wrote:
> Add necessary macros and structure variables to support ICC BW
> voting from individual SE drivers.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment dropped enums for ICC paths, given the three
>    paths individual members
> 
> Changes in V3:
>  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>  - Add geni_icc_path structure in common header
> 
>  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>  2 files changed, 134 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 7d622ea..9344c14 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>  }
>  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>  
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr)
> +{
> +	if (icc_core) {
> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> +		if (IS_ERR(se->to_core.path))
> +			return PTR_ERR(se->to_core.path);
> +	}
> +
> +	if (icc_cpu) {
> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> +		if (IS_ERR(se->from_cpu.path))
> +			return PTR_ERR(se->from_cpu.path);
> +	}
> +
> +	if (icc_ddr) {
> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> +		if (IS_ERR(se->to_ddr.path))
> +			return PTR_ERR(se->to_ddr.path);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_get);
> +
> +int geni_icc_vote_on(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {
> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> +			se->to_core.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> +			se->from_cpu.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> +			se->to_ddr.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}


With an array of 'struct geni_icc_path' pointers the above could be
reduced to:

	for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
		if (!se->icc_paths[i])
			continue;

		ret = icc_set_bw(se->icc_paths[i]->path, se->icc_paths[i]->avg_bw,
			se->icc_paths[i]->peak_bw);
		if (ret) {
			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed\n",
						__func__);
			return ret;
		}
	}

similar for geni_icc_vote_off()

It's just a suggestion, looks also good to me as is.

Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-03-31 17:52     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 17:52 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:30PM +0530, Akash Asthana wrote:
> Add necessary macros and structure variables to support ICC BW
> voting from individual SE drivers.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment dropped enums for ICC paths, given the three
>    paths individual members
> 
> Changes in V3:
>  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>  - Add geni_icc_path structure in common header
> 
>  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>  2 files changed, 134 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 7d622ea..9344c14 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>  }
>  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>  
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr)
> +{
> +	if (icc_core) {
> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> +		if (IS_ERR(se->to_core.path))
> +			return PTR_ERR(se->to_core.path);
> +	}
> +
> +	if (icc_cpu) {
> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> +		if (IS_ERR(se->from_cpu.path))
> +			return PTR_ERR(se->from_cpu.path);
> +	}
> +
> +	if (icc_ddr) {
> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> +		if (IS_ERR(se->to_ddr.path))
> +			return PTR_ERR(se->to_ddr.path);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_get);
> +
> +int geni_icc_vote_on(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {
> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> +			se->to_core.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> +			se->from_cpu.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> +			se->to_ddr.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}


With an array of 'struct geni_icc_path' pointers the above could be
reduced to:

	for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
		if (!se->icc_paths[i])
			continue;

		ret = icc_set_bw(se->icc_paths[i]->path, se->icc_paths[i]->avg_bw,
			se->icc_paths[i]->peak_bw);
		if (ret) {
			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed\n",
						__func__);
			return ret;
		}
	}

similar for geni_icc_vote_off()

It's just a suggestion, looks also good to me as is.

Reviewed-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
@ 2020-03-31 18:24     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 18:24 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:31PM +0530, Akash Asthana wrote:
> QUP core clock is shared among all the SE drivers present on particular
> QUP wrapper, the system will reset(unclocked access) if earlycon used after
> QUP core clock is put to 0 from other SE drivers before real console comes
> up.
> 
> As earlycon can't vote for it's QUP core need, to fix this add ICC
> support to common/QUP wrapper driver and put vote for QUP core from
> probe on behalf of earlycon and remove vote during earlycon exit call.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> Reported-by: Matthias Kaehlcke <mka@chromium.org>
> ---
> Change is V3:
>  - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
>    exit function to remove ICC vote for earlyconsole.
>  - Remove suspend/resume hook for geni-se driver as we are no longer
>    removing earlyconsole ICC vote from system suspend, we are removing
>    from earlycon exit.
> 
>  drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
>  drivers/tty/serial/qcom_geni_serial.c |  7 +++++
>  include/linux/qcom-geni-se.h          |  2 ++
>  3 files changed, 60 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 9344c14..d30c282 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -90,8 +90,11 @@ struct geni_wrapper {
>  	struct device *dev;
>  	void __iomem *base;
>  	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
> +	struct geni_icc_path to_core;
>  };
>  
> +struct geni_wrapper *earlycon_wrapper;

should be static

> +
>  #define QUP_HW_VER_REG			0x4
>  
>  /* Common SE registers */
> @@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
>  }
>  EXPORT_SYMBOL(geni_icc_vote_off);
>  
> +void geni_remove_earlycon_icc_vote(void)
> +{
> +	struct geni_wrapper *wrapper = earlycon_wrapper;
> +	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
> +	struct device_node *child;
> +
> +	for_each_child_of_node(parent, child) {
> +		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
> +			wrapper = platform_get_drvdata(of_find_device_by_node(
> +					child));
> +			icc_put(wrapper->to_core.path);
> +			wrapper->to_core.path = NULL;
> +		}
> +	}
> +	of_node_put(parent);
> +
> +	earlycon_wrapper = NULL;
> +}
> +EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);

I didn't know that consoles have an exit handler, this is way nicer than
the miscellaneous triggers we discussed earlier :)

> +
>  static int geni_se_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> +#ifdef CONFIG_SERIAL_EARLYCON
> +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
> +	if (IS_ERR(wrapper->to_core.path))
> +		return PTR_ERR(wrapper->to_core.path);
> +	/*
> +	 * Put minmal BW request on core clocks on behalf of early console.
> +	 * The vote will be removed earlycon exit function.
> +	 *
> +	 * Note: We are putting vote on each QUP wrapper instead only to which
> +	 * earlycon is connected because QUP core clock of different wrapper
> +	 * share same voltage domain. If core1 is put to 0, then core2 will
> +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
> +	 * we touch any of the core clock.
> +	 * core1 = core2 = max(core1, core2)
> +	 */

I don't really understand this part. According to the comment if we vote
(let's say) for core2 but not for core1 then:

core1: 0
core2: GENI_DEFAULT_BW

core1 = core2 = max(core1, core2)
  or
core1 = core2 = max(0, GENI_DEFAULT_BW)

hence

core1 = core2 = GENI_DEFAULT_BW

What am I missing, why is it necessary to vote for both/all?

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
@ 2020-03-31 18:24     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 18:24 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:31PM +0530, Akash Asthana wrote:
> QUP core clock is shared among all the SE drivers present on particular
> QUP wrapper, the system will reset(unclocked access) if earlycon used after
> QUP core clock is put to 0 from other SE drivers before real console comes
> up.
> 
> As earlycon can't vote for it's QUP core need, to fix this add ICC
> support to common/QUP wrapper driver and put vote for QUP core from
> probe on behalf of earlycon and remove vote during earlycon exit call.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Reported-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
> Change is V3:
>  - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
>    exit function to remove ICC vote for earlyconsole.
>  - Remove suspend/resume hook for geni-se driver as we are no longer
>    removing earlyconsole ICC vote from system suspend, we are removing
>    from earlycon exit.
> 
>  drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
>  drivers/tty/serial/qcom_geni_serial.c |  7 +++++
>  include/linux/qcom-geni-se.h          |  2 ++
>  3 files changed, 60 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 9344c14..d30c282 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -90,8 +90,11 @@ struct geni_wrapper {
>  	struct device *dev;
>  	void __iomem *base;
>  	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
> +	struct geni_icc_path to_core;
>  };
>  
> +struct geni_wrapper *earlycon_wrapper;

should be static

> +
>  #define QUP_HW_VER_REG			0x4
>  
>  /* Common SE registers */
> @@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
>  }
>  EXPORT_SYMBOL(geni_icc_vote_off);
>  
> +void geni_remove_earlycon_icc_vote(void)
> +{
> +	struct geni_wrapper *wrapper = earlycon_wrapper;
> +	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
> +	struct device_node *child;
> +
> +	for_each_child_of_node(parent, child) {
> +		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
> +			wrapper = platform_get_drvdata(of_find_device_by_node(
> +					child));
> +			icc_put(wrapper->to_core.path);
> +			wrapper->to_core.path = NULL;
> +		}
> +	}
> +	of_node_put(parent);
> +
> +	earlycon_wrapper = NULL;
> +}
> +EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);

I didn't know that consoles have an exit handler, this is way nicer than
the miscellaneous triggers we discussed earlier :)

> +
>  static int geni_se_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> +#ifdef CONFIG_SERIAL_EARLYCON
> +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
> +	if (IS_ERR(wrapper->to_core.path))
> +		return PTR_ERR(wrapper->to_core.path);
> +	/*
> +	 * Put minmal BW request on core clocks on behalf of early console.
> +	 * The vote will be removed earlycon exit function.
> +	 *
> +	 * Note: We are putting vote on each QUP wrapper instead only to which
> +	 * earlycon is connected because QUP core clock of different wrapper
> +	 * share same voltage domain. If core1 is put to 0, then core2 will
> +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
> +	 * we touch any of the core clock.
> +	 * core1 = core2 = max(core1, core2)
> +	 */

I don't really understand this part. According to the comment if we vote
(let's say) for core2 but not for core1 then:

core1: 0
core2: GENI_DEFAULT_BW

core1 = core2 = max(core1, core2)
  or
core1 = core2 = max(0, GENI_DEFAULT_BW)

hence

core1 = core2 = GENI_DEFAULT_BW

What am I missing, why is it necessary to vote for both/all?

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

* Re: [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support
@ 2020-03-31 18:49     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 18:49 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:32PM +0530, Akash Asthana wrote:
> Get the interconnect paths for I2C based Serial Engine device
> and vote according to the bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_i2c_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias comment, use common library APIs defined in geni-se
>    driver for ICC functionality.
> 
>  drivers/i2c/busses/i2c-qcom-geni.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
> index 18d1e4f..373c2ca 100644
> --- a/drivers/i2c/busses/i2c-qcom-geni.c
> +++ b/drivers/i2c/busses/i2c-qcom-geni.c
> @@ -557,6 +557,26 @@ static int geni_i2c_probe(struct platform_device *pdev)
>  	gi2c->adap.dev.of_node = dev->of_node;
>  	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
>  
> +	ret = geni_icc_get(&gi2c->se, "qup-core", "qup-config", "qup-memory");
> +	if (ret)
> +		return ret;
> +	/*
> +	 * Set the bus quota for core and cpu to a reasonable value for
> +	 * register access.
> +	 * Set quota for DDR based on bus speed, assume peak requirement
> +	 * as twice of avg bw.
> +	 */
> +	gi2c->se.to_core.avg_bw = GENI_DEFAULT_BW;
> +	gi2c->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
> +	gi2c->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
> +	gi2c->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
> +	gi2c->se.to_ddr.avg_bw = Bps_to_icc(gi2c->clk_freq_out);
> +	gi2c->se.to_ddr.peak_bw = Bps_to_icc(2 * gi2c->clk_freq_out);
> +
> +	ret = geni_icc_vote_on(&gi2c->se);
> +	if (ret)
> +		return ret;
> +
>  	ret = geni_se_resources_on(&gi2c->se);
>  	if (ret) {
>  		dev_err(dev, "Error turning on resources %d\n", ret);

I think you need to call geni_icc_vote_off() here and in other error paths.

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

* Re: [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support
@ 2020-03-31 18:49     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 18:49 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:32PM +0530, Akash Asthana wrote:
> Get the interconnect paths for I2C based Serial Engine device
> and vote according to the bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_i2c_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias comment, use common library APIs defined in geni-se
>    driver for ICC functionality.
> 
>  drivers/i2c/busses/i2c-qcom-geni.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
> index 18d1e4f..373c2ca 100644
> --- a/drivers/i2c/busses/i2c-qcom-geni.c
> +++ b/drivers/i2c/busses/i2c-qcom-geni.c
> @@ -557,6 +557,26 @@ static int geni_i2c_probe(struct platform_device *pdev)
>  	gi2c->adap.dev.of_node = dev->of_node;
>  	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
>  
> +	ret = geni_icc_get(&gi2c->se, "qup-core", "qup-config", "qup-memory");
> +	if (ret)
> +		return ret;
> +	/*
> +	 * Set the bus quota for core and cpu to a reasonable value for
> +	 * register access.
> +	 * Set quota for DDR based on bus speed, assume peak requirement
> +	 * as twice of avg bw.
> +	 */
> +	gi2c->se.to_core.avg_bw = GENI_DEFAULT_BW;
> +	gi2c->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
> +	gi2c->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
> +	gi2c->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
> +	gi2c->se.to_ddr.avg_bw = Bps_to_icc(gi2c->clk_freq_out);
> +	gi2c->se.to_ddr.peak_bw = Bps_to_icc(2 * gi2c->clk_freq_out);
> +
> +	ret = geni_icc_vote_on(&gi2c->se);
> +	if (ret)
> +		return ret;
> +
>  	ret = geni_se_resources_on(&gi2c->se);
>  	if (ret) {
>  		dev_err(dev, "Error turning on resources %d\n", ret);

I think you need to call geni_icc_vote_off() here and in other error paths.

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

* Re: [PATCH V3 5/8] spi: spi-geni-qcom: Add interconnect support
@ 2020-03-31 19:02     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:02 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

On Tue, Mar 31, 2020 at 04:39:33PM +0530, Akash Asthana wrote:
> Get the interconnect paths for SPI based Serial Engine device
> and vote according to the current bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_spi_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias's comment, use helper ICC function from geni-se driver.
> 
>  drivers/spi/spi-geni-qcom.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
> index c397242..f1dae2d 100644
> --- a/drivers/spi/spi-geni-qcom.c
> +++ b/drivers/spi/spi-geni-qcom.c
> @@ -234,6 +234,16 @@ static int setup_fifo_params(struct spi_device *spi_slv,
>  		return ret;
>  	}
>  
> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	se->from_cpu.avg_bw = Bps_to_icc(mas->cur_speed_hz);
> +	se->from_cpu.peak_bw = Bps_to_icc(2 * mas->cur_speed_hz);
> +	ret = geni_icc_vote_on(se);
> +	if (ret)
> +		return ret;
> +
>  	clk_sel = idx & CLK_SEL_MSK;
>  	m_clk_cfg = (div << CLK_DIV_SHFT) | SER_CLK_EN;
>  	spi_setup_word_len(mas, spi_slv->mode, spi_slv->bits_per_word);
> @@ -578,6 +588,15 @@ static int spi_geni_probe(struct platform_device *pdev)
>  	spin_lock_init(&mas->lock);
>  	pm_runtime_enable(dev);
>  
> +	ret = geni_icc_get(&mas->se, "qup-core", "qup-config", NULL);
> +	if (ret)
> +		goto spi_geni_probe_runtime_disable;

This fails without providing any hints why, besides the error code.
It might be worth to add error logging to geni_icc_get().

> +	/* Set the bus quota to a reasonable value for register access */
> +	mas->se.to_core.avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
> +	mas->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
> +	mas->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
> +	mas->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
> +
>  	ret = spi_geni_init(mas);
>  	if (ret)
>  		goto spi_geni_probe_runtime_disable;
> @@ -616,14 +635,24 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
>  {
>  	struct spi_master *spi = dev_get_drvdata(dev);
>  	struct spi_geni_master *mas = spi_master_get_devdata(spi);
> +	int ret;
> +
> +	ret = geni_se_resources_off(&mas->se);
> +	if (ret)
> +		return ret;
>  
> -	return geni_se_resources_off(&mas->se);
> +	return geni_icc_vote_off(&mas->se);
>  }
>  
>  static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
>  {
>  	struct spi_master *spi = dev_get_drvdata(dev);
>  	struct spi_geni_master *mas = spi_master_get_devdata(spi);
> +	int ret;
> +
> +	ret = geni_icc_vote_on(&mas->se);
> +	if (ret)
> +		return ret;
>  
>  	return geni_se_resources_on(&mas->se);
>  }

Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

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

* Re: [PATCH V3 5/8] spi: spi-geni-qcom: Add interconnect support
@ 2020-03-31 19:02     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:02 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

On Tue, Mar 31, 2020 at 04:39:33PM +0530, Akash Asthana wrote:
> Get the interconnect paths for SPI based Serial Engine device
> and vote according to the current bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_spi_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias's comment, use helper ICC function from geni-se driver.
> 
>  drivers/spi/spi-geni-qcom.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
> index c397242..f1dae2d 100644
> --- a/drivers/spi/spi-geni-qcom.c
> +++ b/drivers/spi/spi-geni-qcom.c
> @@ -234,6 +234,16 @@ static int setup_fifo_params(struct spi_device *spi_slv,
>  		return ret;
>  	}
>  
> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	se->from_cpu.avg_bw = Bps_to_icc(mas->cur_speed_hz);
> +	se->from_cpu.peak_bw = Bps_to_icc(2 * mas->cur_speed_hz);
> +	ret = geni_icc_vote_on(se);
> +	if (ret)
> +		return ret;
> +
>  	clk_sel = idx & CLK_SEL_MSK;
>  	m_clk_cfg = (div << CLK_DIV_SHFT) | SER_CLK_EN;
>  	spi_setup_word_len(mas, spi_slv->mode, spi_slv->bits_per_word);
> @@ -578,6 +588,15 @@ static int spi_geni_probe(struct platform_device *pdev)
>  	spin_lock_init(&mas->lock);
>  	pm_runtime_enable(dev);
>  
> +	ret = geni_icc_get(&mas->se, "qup-core", "qup-config", NULL);
> +	if (ret)
> +		goto spi_geni_probe_runtime_disable;

This fails without providing any hints why, besides the error code.
It might be worth to add error logging to geni_icc_get().

> +	/* Set the bus quota to a reasonable value for register access */
> +	mas->se.to_core.avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
> +	mas->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
> +	mas->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
> +	mas->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
> +
>  	ret = spi_geni_init(mas);
>  	if (ret)
>  		goto spi_geni_probe_runtime_disable;
> @@ -616,14 +635,24 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
>  {
>  	struct spi_master *spi = dev_get_drvdata(dev);
>  	struct spi_geni_master *mas = spi_master_get_devdata(spi);
> +	int ret;
> +
> +	ret = geni_se_resources_off(&mas->se);
> +	if (ret)
> +		return ret;
>  
> -	return geni_se_resources_off(&mas->se);
> +	return geni_icc_vote_off(&mas->se);
>  }
>  
>  static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
>  {
>  	struct spi_master *spi = dev_get_drvdata(dev);
>  	struct spi_geni_master *mas = spi_master_get_devdata(spi);
> +	int ret;
> +
> +	ret = geni_icc_vote_on(&mas->se);
> +	if (ret)
> +		return ret;
>  
>  	return geni_se_resources_on(&mas->se);
>  }

Reviewed-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

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

* Re: [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
@ 2020-03-31 19:39     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:39 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:34PM +0530, Akash Asthana wrote:
> Get the interconnect paths for Uart based Serial Engine device
> and vote according to the baud rate requirement of the driver.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_serial_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias comment, use common library APIs defined in geni-se
>    driver for ICC functionality.
> 
>  drivers/tty/serial/qcom_geni_serial.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
> index 8c5d97c..2befe72 100644
> --- a/drivers/tty/serial/qcom_geni_serial.c
> +++ b/drivers/tty/serial/qcom_geni_serial.c
> @@ -965,6 +965,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
>  	ser_clk_cfg = SER_CLK_EN;
>  	ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
>  
> +	/*
> +	 * Bump up BW vote on CPU path as driver supports FIFO mode only.
> +	 * Assume peak_bw as twice of avg_bw.
> +	 */
> +	port->se.from_cpu.avg_bw = Bps_to_icc(baud);
> +	port->se.from_cpu.peak_bw = Bps_to_icc(2 * baud);
> +	geni_icc_vote_on(&port->se);
> +
>  	/* parity */
>  	tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
>  	tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
> @@ -1202,11 +1210,14 @@ static void qcom_geni_serial_pm(struct uart_port *uport,
>  	if (old_state == UART_PM_STATE_UNDEFINED)
>  		old_state = UART_PM_STATE_OFF;
>  
> -	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
> +	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) {
> +		geni_icc_vote_on(&port->se);
>  		geni_se_resources_on(&port->se);
> -	else if (new_state == UART_PM_STATE_OFF &&
> -			old_state == UART_PM_STATE_ON)
> +	} else if (new_state == UART_PM_STATE_OFF &&
> +			old_state == UART_PM_STATE_ON) {
>  		geni_se_resources_off(&port->se);
> +		geni_icc_vote_off(&port->se);
> +	}
>  }
>  
>  static const struct uart_ops qcom_geni_console_pops = {
> @@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
>  			return -ENOMEM;
>  	}
>  
> +	ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
> +	if (ret)
> +		return ret;
> +	/* Set the bus quota to a reasonable value */
> +	port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
> +		Bps_to_icc(CORE_2X_50_MHZ);
> +	port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
> +		Bps_to_icc(CORE_2X_100_MHZ);

I'm still unconvinced about the setting of the core bandwidth based on
whether the port is used as console or not. It could possibly break
consoles working at speeds > 115kbs and reserve more bandwidth than
necessary for ports with 'slow' devices.

Why not scale the core bandwidth dynamically? You said earlier that there
is no clear/linear translation of port speed to bandwidth, but you could
use the same logic that is implicitly used here:

	if (baudrate <= 115200) {
		avg_bw = GENI_DEFAULT_BW;
		peak_bw = GENI_DEFAULT_BW;
	} else {
		avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
		peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
	}

This would be more robust, power efficient and future readers of the
code don't have to wonder "why is the console special?" when our
discussions on this will be long forgotten.

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

* Re: [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
@ 2020-03-31 19:39     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:39 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

Hi Akash,

On Tue, Mar 31, 2020 at 04:39:34PM +0530, Akash Asthana wrote:
> Get the interconnect paths for Uart based Serial Engine device
> and vote according to the baud rate requirement of the driver.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, removed se == NULL check from geni_serial_icc_get
>  - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - As per Matthias comment, use common library APIs defined in geni-se
>    driver for ICC functionality.
> 
>  drivers/tty/serial/qcom_geni_serial.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
> index 8c5d97c..2befe72 100644
> --- a/drivers/tty/serial/qcom_geni_serial.c
> +++ b/drivers/tty/serial/qcom_geni_serial.c
> @@ -965,6 +965,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
>  	ser_clk_cfg = SER_CLK_EN;
>  	ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
>  
> +	/*
> +	 * Bump up BW vote on CPU path as driver supports FIFO mode only.
> +	 * Assume peak_bw as twice of avg_bw.
> +	 */
> +	port->se.from_cpu.avg_bw = Bps_to_icc(baud);
> +	port->se.from_cpu.peak_bw = Bps_to_icc(2 * baud);
> +	geni_icc_vote_on(&port->se);
> +
>  	/* parity */
>  	tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
>  	tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
> @@ -1202,11 +1210,14 @@ static void qcom_geni_serial_pm(struct uart_port *uport,
>  	if (old_state == UART_PM_STATE_UNDEFINED)
>  		old_state = UART_PM_STATE_OFF;
>  
> -	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
> +	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) {
> +		geni_icc_vote_on(&port->se);
>  		geni_se_resources_on(&port->se);
> -	else if (new_state == UART_PM_STATE_OFF &&
> -			old_state == UART_PM_STATE_ON)
> +	} else if (new_state == UART_PM_STATE_OFF &&
> +			old_state == UART_PM_STATE_ON) {
>  		geni_se_resources_off(&port->se);
> +		geni_icc_vote_off(&port->se);
> +	}
>  }
>  
>  static const struct uart_ops qcom_geni_console_pops = {
> @@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
>  			return -ENOMEM;
>  	}
>  
> +	ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
> +	if (ret)
> +		return ret;
> +	/* Set the bus quota to a reasonable value */
> +	port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
> +		Bps_to_icc(CORE_2X_50_MHZ);
> +	port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
> +		Bps_to_icc(CORE_2X_100_MHZ);

I'm still unconvinced about the setting of the core bandwidth based on
whether the port is used as console or not. It could possibly break
consoles working at speeds > 115kbs and reserve more bandwidth than
necessary for ports with 'slow' devices.

Why not scale the core bandwidth dynamically? You said earlier that there
is no clear/linear translation of port speed to bandwidth, but you could
use the same logic that is implicitly used here:

	if (baudrate <= 115200) {
		avg_bw = GENI_DEFAULT_BW;
		peak_bw = GENI_DEFAULT_BW;
	} else {
		avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
		peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
	}

This would be more robust, power efficient and future readers of the
code don't have to wonder "why is the console special?" when our
discussions on this will be long forgotten.

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
@ 2020-03-31 19:45     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:45 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

On Tue, Mar 31, 2020 at 04:39:35PM +0530, Akash Asthana wrote:
> Get the interconnect paths for QSPI device and vote according to the
> current bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - No Change.
> 
>  drivers/spi/spi-qcom-qspi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
> index 3c4f83b..ad48f43 100644
> --- a/drivers/spi/spi-qcom-qspi.c
> +++ b/drivers/spi/spi-qcom-qspi.c
> @@ -2,6 +2,7 @@
>  // Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
>  
>  #include <linux/clk.h>
> +#include <linux/interconnect.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/module.h>
> @@ -139,7 +140,10 @@ struct qcom_qspi {
>  	struct device *dev;
>  	struct clk_bulk_data *clks;
>  	struct qspi_xfer xfer;
> -	/* Lock to protect xfer and IRQ accessed registers */
> +	struct icc_path *icc_path_cpu_to_qspi;
> +	unsigned int avg_bw_cpu;
> +	unsigned int peak_bw_cpu;
> +	/* Lock to protect data accessed by IRQs */
>  	spinlock_t lock;
>  };
>  
> @@ -241,6 +245,20 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
> +		ctrl->peak_bw_cpu);
> +	if (ret) {
> +		dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
> +
>  	spin_lock_irqsave(&ctrl->lock, flags);
>  
>  	/* We are half duplex, so either rx or tx will be set */
> @@ -458,6 +476,15 @@ static int qcom_qspi_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto exit_probe_master_put;
>  
> +	ctrl->icc_path_cpu_to_qspi = devm_of_icc_get(dev, "qspi-config");
> +	if (IS_ERR(ctrl->icc_path_cpu_to_qspi)) {
> +		ret = PTR_ERR(ctrl->icc_path_cpu_to_qspi);
> +		goto exit_probe_master_put;
> +	}
> +	/* Put BW vote on CPU path for register access */
> +	ctrl->avg_bw_cpu = Bps_to_icc(1000);
> +	ctrl->peak_bw_cpu = Bps_to_icc(1000);
> +
>  	ret = platform_get_irq(pdev, 0);
>  	if (ret < 0)
>  		goto exit_probe_master_put;
> @@ -511,9 +538,17 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
>  {
>  	struct spi_master *master = dev_get_drvdata(dev);
>  	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
> +	int ret;
>  
>  	clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks);
>  
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, 0, 0);
> +	if (ret) {
> +		dev_err_ratelimited(ctrl->dev, "%s: ICC BW remove failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -521,6 +556,15 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
>  {
>  	struct spi_master *master = dev_get_drvdata(dev);
>  	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
> +	int ret;
> +
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
> +		ctrl->peak_bw_cpu);
> +	if (ret) {
> +		dev_err_ratelimited(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
>  
>  	return clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
>  }

Looks good to me besides Mark's concern about the bandwith calculation logic.

Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
@ 2020-03-31 19:45     ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-03-31 19:45 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

On Tue, Mar 31, 2020 at 04:39:35PM +0530, Akash Asthana wrote:
> Get the interconnect paths for QSPI device and vote according to the
> current bus speed of the driver.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>    path handle
>  - As per Matthias comment, added error handling for icc_set_bw call
> 
> Changes in V3:
>  - No Change.
> 
>  drivers/spi/spi-qcom-qspi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
> index 3c4f83b..ad48f43 100644
> --- a/drivers/spi/spi-qcom-qspi.c
> +++ b/drivers/spi/spi-qcom-qspi.c
> @@ -2,6 +2,7 @@
>  // Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
>  
>  #include <linux/clk.h>
> +#include <linux/interconnect.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/module.h>
> @@ -139,7 +140,10 @@ struct qcom_qspi {
>  	struct device *dev;
>  	struct clk_bulk_data *clks;
>  	struct qspi_xfer xfer;
> -	/* Lock to protect xfer and IRQ accessed registers */
> +	struct icc_path *icc_path_cpu_to_qspi;
> +	unsigned int avg_bw_cpu;
> +	unsigned int peak_bw_cpu;
> +	/* Lock to protect data accessed by IRQs */
>  	spinlock_t lock;
>  };
>  
> @@ -241,6 +245,20 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
>  		return ret;
>  	}
>  
> +	/*
> +	 * Set BW quota for CPU as driver supports FIFO mode only.
> +	 * Assume peak bw as twice of avg bw.
> +	 */
> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
> +		ctrl->peak_bw_cpu);
> +	if (ret) {
> +		dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
> +
>  	spin_lock_irqsave(&ctrl->lock, flags);
>  
>  	/* We are half duplex, so either rx or tx will be set */
> @@ -458,6 +476,15 @@ static int qcom_qspi_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto exit_probe_master_put;
>  
> +	ctrl->icc_path_cpu_to_qspi = devm_of_icc_get(dev, "qspi-config");
> +	if (IS_ERR(ctrl->icc_path_cpu_to_qspi)) {
> +		ret = PTR_ERR(ctrl->icc_path_cpu_to_qspi);
> +		goto exit_probe_master_put;
> +	}
> +	/* Put BW vote on CPU path for register access */
> +	ctrl->avg_bw_cpu = Bps_to_icc(1000);
> +	ctrl->peak_bw_cpu = Bps_to_icc(1000);
> +
>  	ret = platform_get_irq(pdev, 0);
>  	if (ret < 0)
>  		goto exit_probe_master_put;
> @@ -511,9 +538,17 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
>  {
>  	struct spi_master *master = dev_get_drvdata(dev);
>  	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
> +	int ret;
>  
>  	clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks);
>  
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, 0, 0);
> +	if (ret) {
> +		dev_err_ratelimited(ctrl->dev, "%s: ICC BW remove failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -521,6 +556,15 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
>  {
>  	struct spi_master *master = dev_get_drvdata(dev);
>  	struct qcom_qspi *ctrl = spi_master_get_devdata(master);
> +	int ret;
> +
> +	ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, ctrl->avg_bw_cpu,
> +		ctrl->peak_bw_cpu);
> +	if (ret) {
> +		dev_err_ratelimited(ctrl->dev, "%s: ICC BW voting failed for cpu\n",
> +			__func__);
> +		return ret;
> +	}
>  
>  	return clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
>  }

Looks good to me besides Mark's concern about the bandwith calculation logic.

Reviewed-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-03-31 23:32     ` Bjorn Andersson
  0 siblings, 0 replies; 55+ messages in thread
From: Bjorn Andersson @ 2020-03-31 23:32 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, wsa, broonie, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:

> Add necessary macros and structure variables to support ICC BW
> voting from individual SE drivers.
> 
> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment dropped enums for ICC paths, given the three
>    paths individual members
> 
> Changes in V3:
>  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>  - Add geni_icc_path structure in common header
> 
>  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>  2 files changed, 134 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 7d622ea..9344c14 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>  }
>  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>  
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr)
> +{
> +	if (icc_core) {

Afaict it's only this that might be passed as NULL, so please drop these
conditionals (keep the last one).

> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> +		if (IS_ERR(se->to_core.path))

It would be useful to print an error message here (if PTR_ERR(path) !=
-EPROBE_DEFER).

> +			return PTR_ERR(se->to_core.path);
> +	}
> +
> +	if (icc_cpu) {
> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> +		if (IS_ERR(se->from_cpu.path))
> +			return PTR_ERR(se->from_cpu.path);
> +	}
> +
> +	if (icc_ddr) {
> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> +		if (IS_ERR(se->to_ddr.path))
> +			return PTR_ERR(se->to_ddr.path);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_get);
> +
> +int geni_icc_vote_on(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {

icc_set_bw(NULL, ...) is valid and will return 0, so these checks
doesn't add any value.

> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> +			se->to_core.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> +						__func__);

Please drop the __func__, the message is specific enough.

> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> +			se->from_cpu.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> +			se->to_ddr.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_vote_on);
> +
> +int geni_icc_vote_off(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {
> +		ret = icc_set_bw(se->to_core.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_vote_off);

Given that these two functions only switch the bandwidth request between
some value and 0, I really think we should carry a "bool enabled" on the
path and replace these two functions with
icc_bulk_enable()/icc_bulk_disable().

The added benefit of this would be that you call icc_set_bw() instead of
changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
track of them here.

Regards,
Bjorn

> +
>  static int geni_se_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
> index dd46494..a83c86b 100644
> --- a/include/linux/qcom-geni-se.h
> +++ b/include/linux/qcom-geni-se.h
> @@ -6,6 +6,8 @@
>  #ifndef _LINUX_QCOM_GENI_SE
>  #define _LINUX_QCOM_GENI_SE
>  
> +#include <linux/interconnect.h>
> +
>  /* Transfer mode supported by GENI Serial Engines */
>  enum geni_se_xfer_mode {
>  	GENI_SE_INVALID,
> @@ -25,6 +27,12 @@ enum geni_se_protocol_type {
>  struct geni_wrapper;
>  struct clk;
>  
> +struct geni_icc_path {
> +	struct icc_path *path;
> +	unsigned int avg_bw;
> +	unsigned int peak_bw;
> +};
> +
>  /**
>   * struct geni_se - GENI Serial Engine
>   * @base:		Base Address of the Serial Engine's register block
> @@ -33,6 +41,9 @@ struct clk;
>   * @clk:		Handle to the core serial engine clock
>   * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl
>   * @clk_perf_tbl:	Table of clock frequency input to serial engine clock
> + * @to_core:	ICC path structure for geni to core
> + * @from_cpu:	ICC path structure for cpu to geni
> + * @to_ddr:	ICC path structure for geni to ddr
>   */
>  struct geni_se {
>  	void __iomem *base;
> @@ -41,6 +52,9 @@ struct geni_se {
>  	struct clk *clk;
>  	unsigned int num_clk_levels;
>  	unsigned long *clk_perf_tbl;
> +	struct geni_icc_path to_core;
> +	struct geni_icc_path from_cpu;
> +	struct geni_icc_path to_ddr;
>  };
>  
>  /* Common SE registers */
> @@ -229,6 +243,21 @@ struct geni_se {
>  #define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT)
>  #define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK)
>  
> +/*
> + * Define bandwidth thresholds that cause the underlying Core 2X interconnect
> + * clock to run at the named frequency. These baseline values are recommended
> + * by the hardware team, and are not dynamically scaled with GENI bandwidth
> + * beyond basic on/off.
> + */
> +#define CORE_2X_19_2_MHZ		960
> +#define CORE_2X_50_MHZ			2500
> +#define CORE_2X_100_MHZ			5000
> +#define CORE_2X_150_MHZ			7500
> +#define CORE_2X_200_MHZ			10000
> +#define CORE_2X_236_MHZ			16383
> +
> +#define GENI_DEFAULT_BW			Bps_to_icc(1000)
> +
>  #if IS_ENABLED(CONFIG_QCOM_GENI_SE)
>  
>  u32 geni_se_get_qup_hw_version(struct geni_se *se);
> @@ -416,5 +445,12 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
>  void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
>  
>  void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
> +
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr);
> +
> +int geni_icc_vote_on(struct geni_se *se);
> +
> +int geni_icc_vote_off(struct geni_se *se);
>  #endif
>  #endif
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-03-31 23:32     ` Bjorn Andersson
  0 siblings, 0 replies; 55+ messages in thread
From: Bjorn Andersson @ 2020-03-31 23:32 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A, wsa-z923LK4zBo2bacvFa/9K2g,
	broonie-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, mka-F7+t8E8rja9g9hUCZPvPmw,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:

> Add necessary macros and structure variables to support ICC BW
> voting from individual SE drivers.
> 
> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> Changes in V2:
>  - As per Bjorn's comment dropped enums for ICC paths, given the three
>    paths individual members
> 
> Changes in V3:
>  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>  - Add geni_icc_path structure in common header
> 
>  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>  2 files changed, 134 insertions(+)
> 
> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> index 7d622ea..9344c14 100644
> --- a/drivers/soc/qcom/qcom-geni-se.c
> +++ b/drivers/soc/qcom/qcom-geni-se.c
> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>  }
>  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>  
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr)
> +{
> +	if (icc_core) {

Afaict it's only this that might be passed as NULL, so please drop these
conditionals (keep the last one).

> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> +		if (IS_ERR(se->to_core.path))

It would be useful to print an error message here (if PTR_ERR(path) !=
-EPROBE_DEFER).

> +			return PTR_ERR(se->to_core.path);
> +	}
> +
> +	if (icc_cpu) {
> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> +		if (IS_ERR(se->from_cpu.path))
> +			return PTR_ERR(se->from_cpu.path);
> +	}
> +
> +	if (icc_ddr) {
> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> +		if (IS_ERR(se->to_ddr.path))
> +			return PTR_ERR(se->to_ddr.path);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_get);
> +
> +int geni_icc_vote_on(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {

icc_set_bw(NULL, ...) is valid and will return 0, so these checks
doesn't add any value.

> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> +			se->to_core.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> +						__func__);

Please drop the __func__, the message is specific enough.

> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> +			se->from_cpu.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> +			se->to_ddr.peak_bw);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_vote_on);
> +
> +int geni_icc_vote_off(struct geni_se *se)
> +{
> +	int ret;
> +
> +	if (se->to_core.path) {
> +		ret = icc_set_bw(se->to_core.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->from_cpu.path) {
> +		ret = icc_set_bw(se->from_cpu.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	if (se->to_ddr.path) {
> +		ret = icc_set_bw(se->to_ddr.path, 0, 0);
> +		if (ret) {
> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
> +						__func__);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(geni_icc_vote_off);

Given that these two functions only switch the bandwidth request between
some value and 0, I really think we should carry a "bool enabled" on the
path and replace these two functions with
icc_bulk_enable()/icc_bulk_disable().

The added benefit of this would be that you call icc_set_bw() instead of
changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
track of them here.

Regards,
Bjorn

> +
>  static int geni_se_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
> index dd46494..a83c86b 100644
> --- a/include/linux/qcom-geni-se.h
> +++ b/include/linux/qcom-geni-se.h
> @@ -6,6 +6,8 @@
>  #ifndef _LINUX_QCOM_GENI_SE
>  #define _LINUX_QCOM_GENI_SE
>  
> +#include <linux/interconnect.h>
> +
>  /* Transfer mode supported by GENI Serial Engines */
>  enum geni_se_xfer_mode {
>  	GENI_SE_INVALID,
> @@ -25,6 +27,12 @@ enum geni_se_protocol_type {
>  struct geni_wrapper;
>  struct clk;
>  
> +struct geni_icc_path {
> +	struct icc_path *path;
> +	unsigned int avg_bw;
> +	unsigned int peak_bw;
> +};
> +
>  /**
>   * struct geni_se - GENI Serial Engine
>   * @base:		Base Address of the Serial Engine's register block
> @@ -33,6 +41,9 @@ struct clk;
>   * @clk:		Handle to the core serial engine clock
>   * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl
>   * @clk_perf_tbl:	Table of clock frequency input to serial engine clock
> + * @to_core:	ICC path structure for geni to core
> + * @from_cpu:	ICC path structure for cpu to geni
> + * @to_ddr:	ICC path structure for geni to ddr
>   */
>  struct geni_se {
>  	void __iomem *base;
> @@ -41,6 +52,9 @@ struct geni_se {
>  	struct clk *clk;
>  	unsigned int num_clk_levels;
>  	unsigned long *clk_perf_tbl;
> +	struct geni_icc_path to_core;
> +	struct geni_icc_path from_cpu;
> +	struct geni_icc_path to_ddr;
>  };
>  
>  /* Common SE registers */
> @@ -229,6 +243,21 @@ struct geni_se {
>  #define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT)
>  #define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK)
>  
> +/*
> + * Define bandwidth thresholds that cause the underlying Core 2X interconnect
> + * clock to run at the named frequency. These baseline values are recommended
> + * by the hardware team, and are not dynamically scaled with GENI bandwidth
> + * beyond basic on/off.
> + */
> +#define CORE_2X_19_2_MHZ		960
> +#define CORE_2X_50_MHZ			2500
> +#define CORE_2X_100_MHZ			5000
> +#define CORE_2X_150_MHZ			7500
> +#define CORE_2X_200_MHZ			10000
> +#define CORE_2X_236_MHZ			16383
> +
> +#define GENI_DEFAULT_BW			Bps_to_icc(1000)
> +
>  #if IS_ENABLED(CONFIG_QCOM_GENI_SE)
>  
>  u32 geni_se_get_qup_hw_version(struct geni_se *se);
> @@ -416,5 +445,12 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
>  void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
>  
>  void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
> +
> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> +		const char *icc_ddr);
> +
> +int geni_icc_vote_on(struct geni_se *se);
> +
> +int geni_icc_vote_off(struct geni_se *se);
>  #endif
>  #endif
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-03-31 23:32     ` Bjorn Andersson
@ 2020-04-01 16:26       ` Evan Green
  -1 siblings, 0 replies; 55+ messages in thread
From: Evan Green @ 2020-04-01 16:26 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Akash Asthana, Greg Kroah-Hartman, Andy Gross, wsa, Mark Brown,
	Mark Rutland, Rob Herring, Georgi Djakov, linux-i2c, linux-spi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Manu Gautam, linux-arm-msm, linux-serial,
	Matthias Kaehlcke, Doug Anderson

On Tue, Mar 31, 2020 at 4:32 PM Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
>
> On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:
>
> > Add necessary macros and structure variables to support ICC BW
> > voting from individual SE drivers.
> >
> > Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> > ---
> > Changes in V2:
> >  - As per Bjorn's comment dropped enums for ICC paths, given the three
> >    paths individual members
> >
> > Changes in V3:
> >  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
> >  - Add geni_icc_path structure in common header
> >
> >  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
> >  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
> >  2 files changed, 134 insertions(+)
> >
> > diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> > index 7d622ea..9344c14 100644
> > --- a/drivers/soc/qcom/qcom-geni-se.c
> > +++ b/drivers/soc/qcom/qcom-geni-se.c
> > @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
> >  }
> >  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
> >
> > +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> > +             const char *icc_ddr)
> > +{
> > +     if (icc_core) {
>
> Afaict it's only this that might be passed as NULL, so please drop these
> conditionals (keep the last one).
>
> > +             se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> > +             if (IS_ERR(se->to_core.path))
>
> It would be useful to print an error message here (if PTR_ERR(path) !=
> -EPROBE_DEFER).
>
> > +                     return PTR_ERR(se->to_core.path);
> > +     }
> > +
> > +     if (icc_cpu) {
> > +             se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> > +             if (IS_ERR(se->from_cpu.path))
> > +                     return PTR_ERR(se->from_cpu.path);
> > +     }
> > +
> > +     if (icc_ddr) {
> > +             se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> > +             if (IS_ERR(se->to_ddr.path))
> > +                     return PTR_ERR(se->to_ddr.path);
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_get);
> > +
> > +int geni_icc_vote_on(struct geni_se *se)
> > +{
> > +     int ret;
> > +
> > +     if (se->to_core.path) {
>
> icc_set_bw(NULL, ...) is valid and will return 0, so these checks
> doesn't add any value.
>
> > +             ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> > +                     se->to_core.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> > +                                             __func__);
>
> Please drop the __func__, the message is specific enough.
>
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->from_cpu.path) {
> > +             ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> > +                     se->from_cpu.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->to_ddr.path) {
> > +             ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> > +                     se->to_ddr.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_vote_on);
> > +
> > +int geni_icc_vote_off(struct geni_se *se)
> > +{
> > +     int ret;
> > +
> > +     if (se->to_core.path) {
> > +             ret = icc_set_bw(se->to_core.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->from_cpu.path) {
> > +             ret = icc_set_bw(se->from_cpu.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->to_ddr.path) {
> > +             ret = icc_set_bw(se->to_ddr.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_vote_off);
>
> Given that these two functions only switch the bandwidth request between
> some value and 0, I really think we should carry a "bool enabled" on the
> path and replace these two functions with
> icc_bulk_enable()/icc_bulk_disable().
>
> The added benefit of this would be that you call icc_set_bw() instead of
> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
> track of them here.

Yes yes! I had the same thought here [1].

Georgi, what do you think?
-Evan

[1] https://lore.kernel.org/linux-arm-msm/CAE=gft58QsgTCUHMHKJhcM9ZxAeMiY16CrbNv2HaTCRqwtmt7A@mail.gmail.com/

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-04-01 16:26       ` Evan Green
  0 siblings, 0 replies; 55+ messages in thread
From: Evan Green @ 2020-04-01 16:26 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Akash Asthana, Greg Kroah-Hartman, Andy Gross, wsa, Mark Brown,
	Mark Rutland, Rob Herring, Georgi Djakov, linux-i2c, linux-spi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Manu Gautam, linux-arm-msm, linux-serial,
	Matthias Kaehlcke, Doug Anderson

On Tue, Mar 31, 2020 at 4:32 PM Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
>
> On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:
>
> > Add necessary macros and structure variables to support ICC BW
> > voting from individual SE drivers.
> >
> > Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> > ---
> > Changes in V2:
> >  - As per Bjorn's comment dropped enums for ICC paths, given the three
> >    paths individual members
> >
> > Changes in V3:
> >  - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
> >  - Add geni_icc_path structure in common header
> >
> >  drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
> >  include/linux/qcom-geni-se.h    | 36 +++++++++++++++
> >  2 files changed, 134 insertions(+)
> >
> > diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> > index 7d622ea..9344c14 100644
> > --- a/drivers/soc/qcom/qcom-geni-se.c
> > +++ b/drivers/soc/qcom/qcom-geni-se.c
> > @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
> >  }
> >  EXPORT_SYMBOL(geni_se_rx_dma_unprep);
> >
> > +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> > +             const char *icc_ddr)
> > +{
> > +     if (icc_core) {
>
> Afaict it's only this that might be passed as NULL, so please drop these
> conditionals (keep the last one).
>
> > +             se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
> > +             if (IS_ERR(se->to_core.path))
>
> It would be useful to print an error message here (if PTR_ERR(path) !=
> -EPROBE_DEFER).
>
> > +                     return PTR_ERR(se->to_core.path);
> > +     }
> > +
> > +     if (icc_cpu) {
> > +             se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
> > +             if (IS_ERR(se->from_cpu.path))
> > +                     return PTR_ERR(se->from_cpu.path);
> > +     }
> > +
> > +     if (icc_ddr) {
> > +             se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
> > +             if (IS_ERR(se->to_ddr.path))
> > +                     return PTR_ERR(se->to_ddr.path);
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_get);
> > +
> > +int geni_icc_vote_on(struct geni_se *se)
> > +{
> > +     int ret;
> > +
> > +     if (se->to_core.path) {
>
> icc_set_bw(NULL, ...) is valid and will return 0, so these checks
> doesn't add any value.
>
> > +             ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
> > +                     se->to_core.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
> > +                                             __func__);
>
> Please drop the __func__, the message is specific enough.
>
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->from_cpu.path) {
> > +             ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
> > +                     se->from_cpu.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->to_ddr.path) {
> > +             ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
> > +                     se->to_ddr.peak_bw);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_vote_on);
> > +
> > +int geni_icc_vote_off(struct geni_se *se)
> > +{
> > +     int ret;
> > +
> > +     if (se->to_core.path) {
> > +             ret = icc_set_bw(se->to_core.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->from_cpu.path) {
> > +             ret = icc_set_bw(se->from_cpu.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     if (se->to_ddr.path) {
> > +             ret = icc_set_bw(se->to_ddr.path, 0, 0);
> > +             if (ret) {
> > +                     dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
> > +                                             __func__);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(geni_icc_vote_off);
>
> Given that these two functions only switch the bandwidth request between
> some value and 0, I really think we should carry a "bool enabled" on the
> path and replace these two functions with
> icc_bulk_enable()/icc_bulk_disable().
>
> The added benefit of this would be that you call icc_set_bw() instead of
> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
> track of them here.

Yes yes! I had the same thought here [1].

Georgi, what do you think?
-Evan

[1] https://lore.kernel.org/linux-arm-msm/CAE=gft58QsgTCUHMHKJhcM9ZxAeMiY16CrbNv2HaTCRqwtmt7A@mail.gmail.com/

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
@ 2020-04-01 19:46       ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-04-01 19:46 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

On Tue, Mar 31, 2020 at 11:24:57AM -0700, Matthias Kaehlcke wrote:
> Hi Akash,
> 
> On Tue, Mar 31, 2020 at 04:39:31PM +0530, Akash Asthana wrote:
> > QUP core clock is shared among all the SE drivers present on particular
> > QUP wrapper, the system will reset(unclocked access) if earlycon used after
> > QUP core clock is put to 0 from other SE drivers before real console comes
> > up.
> > 
> > As earlycon can't vote for it's QUP core need, to fix this add ICC
> > support to common/QUP wrapper driver and put vote for QUP core from
> > probe on behalf of earlycon and remove vote during earlycon exit call.
> > 
> > Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> > Reported-by: Matthias Kaehlcke <mka@chromium.org>
> > ---
> > Change is V3:
> >  - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
> >    exit function to remove ICC vote for earlyconsole.
> >  - Remove suspend/resume hook for geni-se driver as we are no longer
> >    removing earlyconsole ICC vote from system suspend, we are removing
> >    from earlycon exit.
> > 
> >  drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
> >  drivers/tty/serial/qcom_geni_serial.c |  7 +++++
> >  include/linux/qcom-geni-se.h          |  2 ++
> >  3 files changed, 60 insertions(+)
> > 
> > diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> > index 9344c14..d30c282 100644
> > --- a/drivers/soc/qcom/qcom-geni-se.c
> > +++ b/drivers/soc/qcom/qcom-geni-se.c
> > @@ -90,8 +90,11 @@ struct geni_wrapper {
> >  	struct device *dev;
> >  	void __iomem *base;
> >  	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
> > +	struct geni_icc_path to_core;
> >  };
> >  
> > +struct geni_wrapper *earlycon_wrapper;
> 
> should be static
> 
> > +
> >  #define QUP_HW_VER_REG			0x4
> >  
> >  /* Common SE registers */
> > @@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
> >  }
> >  EXPORT_SYMBOL(geni_icc_vote_off);
> >  
> > +void geni_remove_earlycon_icc_vote(void)
> > +{
> > +	struct geni_wrapper *wrapper = earlycon_wrapper;
> > +	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
> > +	struct device_node *child;
> > +
> > +	for_each_child_of_node(parent, child) {
> > +		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
> > +			wrapper = platform_get_drvdata(of_find_device_by_node(
> > +					child));
> > +			icc_put(wrapper->to_core.path);
> > +			wrapper->to_core.path = NULL;
> > +		}
> > +	}
> > +	of_node_put(parent);
> > +
> > +	earlycon_wrapper = NULL;
> > +}
> > +EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
> 
> I didn't know that consoles have an exit handler, this is way nicer than
> the miscellaneous triggers we discussed earlier :)

No wonder I 'missed' this when looking at the console code for possible
triggers, it is brand new and as of now only exists in -next:

commit ed31685c96e18f773ca11dd1a637974d62130673
Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date:   Mon Feb 3 15:31:30 2020 +0200

    console: Introduce ->exit() callback


sharp timing!

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
@ 2020-04-01 19:46       ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-04-01 19:46 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

On Tue, Mar 31, 2020 at 11:24:57AM -0700, Matthias Kaehlcke wrote:
> Hi Akash,
> 
> On Tue, Mar 31, 2020 at 04:39:31PM +0530, Akash Asthana wrote:
> > QUP core clock is shared among all the SE drivers present on particular
> > QUP wrapper, the system will reset(unclocked access) if earlycon used after
> > QUP core clock is put to 0 from other SE drivers before real console comes
> > up.
> > 
> > As earlycon can't vote for it's QUP core need, to fix this add ICC
> > support to common/QUP wrapper driver and put vote for QUP core from
> > probe on behalf of earlycon and remove vote during earlycon exit call.
> > 
> > Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> > Reported-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> > ---
> > Change is V3:
> >  - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
> >    exit function to remove ICC vote for earlyconsole.
> >  - Remove suspend/resume hook for geni-se driver as we are no longer
> >    removing earlyconsole ICC vote from system suspend, we are removing
> >    from earlycon exit.
> > 
> >  drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
> >  drivers/tty/serial/qcom_geni_serial.c |  7 +++++
> >  include/linux/qcom-geni-se.h          |  2 ++
> >  3 files changed, 60 insertions(+)
> > 
> > diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> > index 9344c14..d30c282 100644
> > --- a/drivers/soc/qcom/qcom-geni-se.c
> > +++ b/drivers/soc/qcom/qcom-geni-se.c
> > @@ -90,8 +90,11 @@ struct geni_wrapper {
> >  	struct device *dev;
> >  	void __iomem *base;
> >  	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
> > +	struct geni_icc_path to_core;
> >  };
> >  
> > +struct geni_wrapper *earlycon_wrapper;
> 
> should be static
> 
> > +
> >  #define QUP_HW_VER_REG			0x4
> >  
> >  /* Common SE registers */
> > @@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
> >  }
> >  EXPORT_SYMBOL(geni_icc_vote_off);
> >  
> > +void geni_remove_earlycon_icc_vote(void)
> > +{
> > +	struct geni_wrapper *wrapper = earlycon_wrapper;
> > +	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
> > +	struct device_node *child;
> > +
> > +	for_each_child_of_node(parent, child) {
> > +		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
> > +			wrapper = platform_get_drvdata(of_find_device_by_node(
> > +					child));
> > +			icc_put(wrapper->to_core.path);
> > +			wrapper->to_core.path = NULL;
> > +		}
> > +	}
> > +	of_node_put(parent);
> > +
> > +	earlycon_wrapper = NULL;
> > +}
> > +EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
> 
> I didn't know that consoles have an exit handler, this is way nicer than
> the miscellaneous triggers we discussed earlier :)

No wonder I 'missed' this when looking at the console code for possible
triggers, it is brand new and as of now only exists in -next:

commit ed31685c96e18f773ca11dd1a637974d62130673
Author: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Date:   Mon Feb 3 15:31:30 2020 +0200

    console: Introduce ->exit() callback


sharp timing!

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-04-02 13:46       ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-02 13:46 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,

On 3/31/2020 11:22 PM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Mar 31, 2020 at 04:39:30PM +0530, Akash Asthana wrote:
>> Add necessary macros and structure variables to support ICC BW
>> voting from individual SE drivers.
>>
>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>> ---
>> Changes in V2:
>>   - As per Bjorn's comment dropped enums for ICC paths, given the three
>>     paths individual members
>>
>> Changes in V3:
>>   - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>>   - Add geni_icc_path structure in common header
>>
>>   drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>>   include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>>   2 files changed, 134 insertions(+)
>>
>> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
>> index 7d622ea..9344c14 100644
>> --- a/drivers/soc/qcom/qcom-geni-se.c
>> +++ b/drivers/soc/qcom/qcom-geni-se.c
>> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>>   }
>>   EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>>   
>> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
>> +		const char *icc_ddr)
>> +{
>> +	if (icc_core) {
>> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
>> +		if (IS_ERR(se->to_core.path))
>> +			return PTR_ERR(se->to_core.path);
>> +	}
>> +
>> +	if (icc_cpu) {
>> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
>> +		if (IS_ERR(se->from_cpu.path))
>> +			return PTR_ERR(se->from_cpu.path);
>> +	}
>> +
>> +	if (icc_ddr) {
>> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
>> +		if (IS_ERR(se->to_ddr.path))
>> +			return PTR_ERR(se->to_ddr.path);
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_get);
>> +
>> +int geni_icc_vote_on(struct geni_se *se)
>> +{
>> +	int ret;
>> +
>> +	if (se->to_core.path) {
>> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
>> +			se->to_core.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->from_cpu.path) {
>> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
>> +			se->from_cpu.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->to_ddr.path) {
>> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
>> +			se->to_ddr.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>
> With an array of 'struct geni_icc_path' pointers the above could be
> reduced to:
>
> 	for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
> 		if (!se->icc_paths[i])
> 			continue;
>
> 		ret = icc_set_bw(se->icc_paths[i]->path, se->icc_paths[i]->avg_bw,
> 			se->icc_paths[i]->peak_bw);
> 		if (ret) {
> 			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed\n",
> 						__func__);
> 			return ret;
> 		}
> 	}
>
> similar for geni_icc_vote_off()
>
> It's just a suggestion, looks also good to me as is.

I thought giving individual path name will increase readability. But 
that doesn't seems to be adding much value on cost of repeated code.

So, I will make the suggested change in next version.

Thanks,

Akash

>
> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
@ 2020-04-02 13:46       ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-02 13:46 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	agross-DgEjT+Ai2ygdnm+yROfE0A,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	wsa-z923LK4zBo2bacvFa/9K2g, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, swboyd-F7+t8E8rja9g9hUCZPvPmw,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw, evgreen-F7+t8E8rja9g9hUCZPvPmw

Hi Matthias,

On 3/31/2020 11:22 PM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Mar 31, 2020 at 04:39:30PM +0530, Akash Asthana wrote:
>> Add necessary macros and structure variables to support ICC BW
>> voting from individual SE drivers.
>>
>> Signed-off-by: Akash Asthana <akashast-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> ---
>> Changes in V2:
>>   - As per Bjorn's comment dropped enums for ICC paths, given the three
>>     paths individual members
>>
>> Changes in V3:
>>   - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>>   - Add geni_icc_path structure in common header
>>
>>   drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>>   include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>>   2 files changed, 134 insertions(+)
>>
>> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
>> index 7d622ea..9344c14 100644
>> --- a/drivers/soc/qcom/qcom-geni-se.c
>> +++ b/drivers/soc/qcom/qcom-geni-se.c
>> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>>   }
>>   EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>>   
>> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
>> +		const char *icc_ddr)
>> +{
>> +	if (icc_core) {
>> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
>> +		if (IS_ERR(se->to_core.path))
>> +			return PTR_ERR(se->to_core.path);
>> +	}
>> +
>> +	if (icc_cpu) {
>> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
>> +		if (IS_ERR(se->from_cpu.path))
>> +			return PTR_ERR(se->from_cpu.path);
>> +	}
>> +
>> +	if (icc_ddr) {
>> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
>> +		if (IS_ERR(se->to_ddr.path))
>> +			return PTR_ERR(se->to_ddr.path);
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_get);
>> +
>> +int geni_icc_vote_on(struct geni_se *se)
>> +{
>> +	int ret;
>> +
>> +	if (se->to_core.path) {
>> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
>> +			se->to_core.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->from_cpu.path) {
>> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
>> +			se->from_cpu.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->to_ddr.path) {
>> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
>> +			se->to_ddr.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>
> With an array of 'struct geni_icc_path' pointers the above could be
> reduced to:
>
> 	for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
> 		if (!se->icc_paths[i])
> 			continue;
>
> 		ret = icc_set_bw(se->icc_paths[i]->path, se->icc_paths[i]->avg_bw,
> 			se->icc_paths[i]->peak_bw);
> 		if (ret) {
> 			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed\n",
> 						__func__);
> 			return ret;
> 		}
> 	}
>
> similar for geni_icc_vote_off()
>
> It's just a suggestion, looks also good to me as is.

I thought giving individual path name will increase readability. But 
that doesn't seems to be adding much value on cost of repeated code.

So, I will make the suggested change in next version.

Thanks,

Akash

>
> Reviewed-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-03-31 23:32     ` Bjorn Andersson
  (?)
  (?)
@ 2020-04-07  6:45     ` Akash Asthana
  2020-04-07 22:07       ` Bjorn Andersson
  -1 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  6:45 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: gregkh, agross, wsa, broonie, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

Hi Bjorn,

On 4/1/2020 5:02 AM, Bjorn Andersson wrote:
> On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:
>
>> Add necessary macros and structure variables to support ICC BW
>> voting from individual SE drivers.
>>
>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>> ---
>> Changes in V2:
>>   - As per Bjorn's comment dropped enums for ICC paths, given the three
>>     paths individual members
>>
>> Changes in V3:
>>   - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>>   - Add geni_icc_path structure in common header
>>
>>   drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>>   include/linux/qcom-geni-se.h    | 36 +++++++++++++++
>>   2 files changed, 134 insertions(+)
>>
>> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
>> index 7d622ea..9344c14 100644
>> --- a/drivers/soc/qcom/qcom-geni-se.c
>> +++ b/drivers/soc/qcom/qcom-geni-se.c
>> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>>   }
>>   EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>>   
>> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
>> +		const char *icc_ddr)
>> +{
>> +	if (icc_core) {
> Afaict it's only this that might be passed as NULL, so please drop these
> conditionals (keep the last one).
IIUC you're suggesting to drop if (icc_core/cpu) but keep if (icc_ddr) ?
>
>> +		se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
>> +		if (IS_ERR(se->to_core.path))
> It would be useful to print an error message here (if PTR_ERR(path) !=
> -EPROBE_DEFER).
okay
>
>> +			return PTR_ERR(se->to_core.path);
>> +	}
>> +
>> +	if (icc_cpu) {
>> +		se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
>> +		if (IS_ERR(se->from_cpu.path))
>> +			return PTR_ERR(se->from_cpu.path);
>> +	}
>> +
>> +	if (icc_ddr) {
>> +		se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
>> +		if (IS_ERR(se->to_ddr.path))
>> +			return PTR_ERR(se->to_ddr.path);
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_get);
>> +
>> +int geni_icc_vote_on(struct geni_se *se)
>> +{
>> +	int ret;
>> +
>> +	if (se->to_core.path) {
> icc_set_bw(NULL, ...) is valid and will return 0, so these checks
> doesn't add any value.
Yeah, ok
>
>> +		ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
>> +			se->to_core.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
>> +						__func__);
> Please drop the __func__, the message is specific enough.

ok

Regards,

Akash

>
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->from_cpu.path) {
>> +		ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
>> +			se->from_cpu.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->to_ddr.path) {
>> +		ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
>> +			se->to_ddr.peak_bw);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_vote_on);
>> +
>> +int geni_icc_vote_off(struct geni_se *se)
>> +{
>> +	int ret;
>> +
>> +	if (se->to_core.path) {
>> +		ret = icc_set_bw(se->to_core.path, 0, 0);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for core\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->from_cpu.path) {
>> +		ret = icc_set_bw(se->from_cpu.path, 0, 0);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for cpu\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	if (se->to_ddr.path) {
>> +		ret = icc_set_bw(se->to_ddr.path, 0, 0);
>> +		if (ret) {
>> +			dev_err_ratelimited(se->dev, "%s: ICC BW remove failed for ddr\n",
>> +						__func__);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_vote_off);
> Given that these two functions only switch the bandwidth request between
> some value and 0, I really think we should carry a "bool enabled" on the
> path and replace these two functions with
> icc_bulk_enable()/icc_bulk_disable().
>
> The added benefit of this would be that you call icc_set_bw() instead of
> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
> track of them here.
>
> Regards,
> Bjorn
>> +
>>   static int geni_se_probe(struct platform_device *pdev)
>>   {
>>   	struct device *dev = &pdev->dev;
>> diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
>> index dd46494..a83c86b 100644
>> --- a/include/linux/qcom-geni-se.h
>> +++ b/include/linux/qcom-geni-se.h
>> @@ -6,6 +6,8 @@
>>   #ifndef _LINUX_QCOM_GENI_SE
>>   #define _LINUX_QCOM_GENI_SE
>>   
>> +#include <linux/interconnect.h>
>> +
>>   /* Transfer mode supported by GENI Serial Engines */
>>   enum geni_se_xfer_mode {
>>   	GENI_SE_INVALID,
>> @@ -25,6 +27,12 @@ enum geni_se_protocol_type {
>>   struct geni_wrapper;
>>   struct clk;
>>   
>> +struct geni_icc_path {
>> +	struct icc_path *path;
>> +	unsigned int avg_bw;
>> +	unsigned int peak_bw;
>> +};
>> +
>>   /**
>>    * struct geni_se - GENI Serial Engine
>>    * @base:		Base Address of the Serial Engine's register block
>> @@ -33,6 +41,9 @@ struct clk;
>>    * @clk:		Handle to the core serial engine clock
>>    * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl
>>    * @clk_perf_tbl:	Table of clock frequency input to serial engine clock
>> + * @to_core:	ICC path structure for geni to core
>> + * @from_cpu:	ICC path structure for cpu to geni
>> + * @to_ddr:	ICC path structure for geni to ddr
>>    */
>>   struct geni_se {
>>   	void __iomem *base;
>> @@ -41,6 +52,9 @@ struct geni_se {
>>   	struct clk *clk;
>>   	unsigned int num_clk_levels;
>>   	unsigned long *clk_perf_tbl;
>> +	struct geni_icc_path to_core;
>> +	struct geni_icc_path from_cpu;
>> +	struct geni_icc_path to_ddr;
>>   };
>>   
>>   /* Common SE registers */
>> @@ -229,6 +243,21 @@ struct geni_se {
>>   #define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT)
>>   #define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK)
>>   
>> +/*
>> + * Define bandwidth thresholds that cause the underlying Core 2X interconnect
>> + * clock to run at the named frequency. These baseline values are recommended
>> + * by the hardware team, and are not dynamically scaled with GENI bandwidth
>> + * beyond basic on/off.
>> + */
>> +#define CORE_2X_19_2_MHZ		960
>> +#define CORE_2X_50_MHZ			2500
>> +#define CORE_2X_100_MHZ			5000
>> +#define CORE_2X_150_MHZ			7500
>> +#define CORE_2X_200_MHZ			10000
>> +#define CORE_2X_236_MHZ			16383
>> +
>> +#define GENI_DEFAULT_BW			Bps_to_icc(1000)
>> +
>>   #if IS_ENABLED(CONFIG_QCOM_GENI_SE)
>>   
>>   u32 geni_se_get_qup_hw_version(struct geni_se *se);
>> @@ -416,5 +445,12 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
>>   void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
>>   
>>   void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
>> +
>> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
>> +		const char *icc_ddr);
>> +
>> +int geni_icc_vote_on(struct geni_se *se);
>> +
>> +int geni_icc_vote_off(struct geni_se *se);
>>   #endif
>>   #endif
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-04-01 16:26       ` Evan Green
  (?)
@ 2020-04-07  6:46       ` Akash Asthana
  2020-04-07  9:58         ` Georgi Djakov
  -1 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  6:46 UTC (permalink / raw)
  To: Evan Green, Bjorn Andersson
  Cc: Greg Kroah-Hartman, Andy Gross, wsa, Mark Brown, Mark Rutland,
	Rob Herring, Georgi Djakov, linux-i2c, linux-spi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Manu Gautam, linux-arm-msm, linux-serial,
	Matthias Kaehlcke, Doug Anderson

Hi Bjorn, Evan,

>> Given that these two functions only switch the bandwidth request between
>> some value and 0, I really think we should carry a "bool enabled" on the
>> path and replace these two functions with
>> icc_bulk_enable()/icc_bulk_disable().
So, if above is implementation "bool enabled" on path can be used 
directly in aggregation of ICC votes on particular node without using 
icc_set_bw call, if yes then I am not aware how? or we'll be using 
icc_set_bw API indirectly inside icc_bulk APIs?
>> The added benefit of this would be that you call icc_set_bw() instead of
>> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
>> track of them here.

Ok IIUC, we need to call icc_set_bw() from GENI driver only if we change 
(avg_bw | peak_bw)?

Regards,

Akash

> Yes yes! I had the same thought here [1].
>
> Georgi, what do you think?
> -Evan
>
> [1] https://lore.kernel.org/linux-arm-msm/CAE=gft58QsgTCUHMHKJhcM9ZxAeMiY16CrbNv2HaTCRqwtmt7A@mail.gmail.com/

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-04-01 19:46       ` Matthias Kaehlcke
  (?)
@ 2020-04-07  6:52       ` Akash Asthana
  -1 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  6:52 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias

On 4/2/2020 1:16 AM, Matthias Kaehlcke wrote:
> On Tue, Mar 31, 2020 at 11:24:57AM -0700, Matthias Kaehlcke wrote:
>> Hi Akash,
>>
>> On Tue, Mar 31, 2020 at 04:39:31PM +0530, Akash Asthana wrote:
>>> QUP core clock is shared among all the SE drivers present on particular
>>> QUP wrapper, the system will reset(unclocked access) if earlycon used after
>>> QUP core clock is put to 0 from other SE drivers before real console comes
>>> up.
>>>
>>> As earlycon can't vote for it's QUP core need, to fix this add ICC
>>> support to common/QUP wrapper driver and put vote for QUP core from
>>> probe on behalf of earlycon and remove vote during earlycon exit call.
>>>
>>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>>> Reported-by: Matthias Kaehlcke <mka@chromium.org>
>>> ---
>>> Change is V3:
>>>   - Add geni_remove_earlycon_icc_vote API that will be used by earlycon
>>>     exit function to remove ICC vote for earlyconsole.
>>>   - Remove suspend/resume hook for geni-se driver as we are no longer
>>>     removing earlyconsole ICC vote from system suspend, we are removing
>>>     from earlycon exit.
>>>
>>>   drivers/soc/qcom/qcom-geni-se.c       | 51 +++++++++++++++++++++++++++++++++++
>>>   drivers/tty/serial/qcom_geni_serial.c |  7 +++++
>>>   include/linux/qcom-geni-se.h          |  2 ++
>>>   3 files changed, 60 insertions(+)
>>>
>>> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
>>> index 9344c14..d30c282 100644
>>> --- a/drivers/soc/qcom/qcom-geni-se.c
>>> +++ b/drivers/soc/qcom/qcom-geni-se.c
>>> @@ -90,8 +90,11 @@ struct geni_wrapper {
>>>   	struct device *dev;
>>>   	void __iomem *base;
>>>   	struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
>>> +	struct geni_icc_path to_core;
>>>   };
>>>   
>>> +struct geni_wrapper *earlycon_wrapper;
>> should be static
Yeah ok, I missed it.
>>
>>> +
>>>   #define QUP_HW_VER_REG			0x4
>>>   
>>>   /* Common SE registers */
>>> @@ -818,6 +821,26 @@ int geni_icc_vote_off(struct geni_se *se)
>>>   }
>>>   EXPORT_SYMBOL(geni_icc_vote_off);
>>>   
>>> +void geni_remove_earlycon_icc_vote(void)
>>> +{
>>> +	struct geni_wrapper *wrapper = earlycon_wrapper;
>>> +	struct device_node *parent = of_get_next_parent(wrapper->dev->of_node);
>>> +	struct device_node *child;
>>> +
>>> +	for_each_child_of_node(parent, child) {
>>> +		if (of_device_is_compatible(child, "qcom,geni-se-qup")) {
>>> +			wrapper = platform_get_drvdata(of_find_device_by_node(
>>> +					child));
>>> +			icc_put(wrapper->to_core.path);
>>> +			wrapper->to_core.path = NULL;
>>> +		}
>>> +	}
>>> +	of_node_put(parent);
>>> +
>>> +	earlycon_wrapper = NULL;
>>> +}
>>> +EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
>> I didn't know that consoles have an exit handler, this is way nicer than
>> the miscellaneous triggers we discussed earlier :)
> No wonder I 'missed' this when looking at the console code for possible
> triggers, it is brand new and as of now only exists in -next:
>
> commit ed31685c96e18f773ca11dd1a637974d62130673
> Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Date:   Mon Feb 3 15:31:30 2020 +0200
>
>      console: Introduce ->exit() callback
>
>
> sharp timing!

Yeah this is added recently, even I was not aware of it, Bjorn suggested 
me to use this. Indeed sharp timing!  :)

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support
  2020-03-31 18:49     ` Matthias Kaehlcke
  (?)
@ 2020-04-07  7:04     ` Akash Asthana
  -1 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  7:04 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi  Matthias,

On 4/1/2020 12:19 AM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Mar 31, 2020 at 04:39:32PM +0530, Akash Asthana wrote:
>> Get the interconnect paths for I2C based Serial Engine device
>> and vote according to the bus speed of the driver.
>>
>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>> ---
>> Changes in V2:
>>   - As per Bjorn's comment, removed se == NULL check from geni_i2c_icc_get
>>   - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>>   - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>>     path handle
>>   - As per Matthias comment, added error handling for icc_set_bw call
>>
>> Changes in V3:
>>   - As per Matthias comment, use common library APIs defined in geni-se
>>     driver for ICC functionality.
>>
>>   drivers/i2c/busses/i2c-qcom-geni.c | 30 +++++++++++++++++++++++++++++-
>>   1 file changed, 29 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
>> index 18d1e4f..373c2ca 100644
>> --- a/drivers/i2c/busses/i2c-qcom-geni.c
>> +++ b/drivers/i2c/busses/i2c-qcom-geni.c
>> @@ -557,6 +557,26 @@ static int geni_i2c_probe(struct platform_device *pdev)
>>   	gi2c->adap.dev.of_node = dev->of_node;
>>   	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
>>   
>> +	ret = geni_icc_get(&gi2c->se, "qup-core", "qup-config", "qup-memory");
>> +	if (ret)
>> +		return ret;
>> +	/*
>> +	 * Set the bus quota for core and cpu to a reasonable value for
>> +	 * register access.
>> +	 * Set quota for DDR based on bus speed, assume peak requirement
>> +	 * as twice of avg bw.
>> +	 */
>> +	gi2c->se.to_core.avg_bw = GENI_DEFAULT_BW;
>> +	gi2c->se.to_core.peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
>> +	gi2c->se.from_cpu.avg_bw = GENI_DEFAULT_BW;
>> +	gi2c->se.from_cpu.peak_bw = GENI_DEFAULT_BW;
>> +	gi2c->se.to_ddr.avg_bw = Bps_to_icc(gi2c->clk_freq_out);
>> +	gi2c->se.to_ddr.peak_bw = Bps_to_icc(2 * gi2c->clk_freq_out);
>> +
>> +	ret = geni_icc_vote_on(&gi2c->se);
>> +	if (ret)
>> +		return ret;
>> +
>>   	ret = geni_se_resources_on(&gi2c->se);
>>   	if (ret) {
>>   		dev_err(dev, "Error turning on resources %d\n", ret);
> I think you need to call geni_icc_vote_off() here and in other error paths.

No need to add geni_icc_vote_off() on error paths because we are using 
devm_of_icc_get to get ICC path handle.

If we are going to fail probe then "devm_icc_release---->icc_put" will 
set votes to 0 on each path. https://patchwork.kernel.org/patch/11467507/

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 5/8] spi: spi-geni-qcom: Add interconnect support
  2020-03-31 19:02     ` Matthias Kaehlcke
  (?)
@ 2020-04-07  7:11     ` Akash Asthana
  -1 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  7:11 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,

>>   
>> +	ret = geni_icc_get(&mas->se, "qup-core", "qup-config", NULL);
>> +	if (ret)
>> +		goto spi_geni_probe_runtime_disable;
> This fails without providing any hints why, besides the error code.
> It might be worth to add error logging to geni_icc_get().
>
As per Bjorn's comment, I will add error logs inside geni_icc_get API 
incase it returns something other than -EPROBE_DEFER . 
https://patchwork.kernel.org/patch/11467511/

regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
  2020-03-31 19:39     ` Matthias Kaehlcke
  (?)
@ 2020-04-07  9:19     ` Akash Asthana
  2020-04-07  9:40       ` Akash Asthana
  -1 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  9:19 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,

On 4/1/2020 1:09 AM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Mar 31, 2020 at 04:39:34PM +0530, Akash Asthana wrote:
>> Get the interconnect paths for Uart based Serial Engine device
>> and vote according to the baud rate requirement of the driver.
>>
>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>> ---
>> Changes in V2:
>>   - As per Bjorn's comment, removed se == NULL check from geni_serial_icc_get
>>   - As per Bjorn's comment, removed code to set se->icc_path* to NULL in failure
>>   - As per Bjorn's comment, introduced and using devm_of_icc_get API for getting
>>     path handle
>>   - As per Matthias comment, added error handling for icc_set_bw call
>>
>> Changes in V3:
>>   - As per Matthias comment, use common library APIs defined in geni-se
>>     driver for ICC functionality.
>>
>>   drivers/tty/serial/qcom_geni_serial.c | 28 +++++++++++++++++++++++++---
>>   1 file changed, 25 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
>> index 8c5d97c..2befe72 100644
>> --- a/drivers/tty/serial/qcom_geni_serial.c
>> +++ b/drivers/tty/serial/qcom_geni_serial.c
>> @@ -965,6 +965,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
>>   	ser_clk_cfg = SER_CLK_EN;
>>   	ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
>>   
>> +	/*
>> +	 * Bump up BW vote on CPU path as driver supports FIFO mode only.
>> +	 * Assume peak_bw as twice of avg_bw.
>> +	 */
>> +	port->se.from_cpu.avg_bw = Bps_to_icc(baud);
>> +	port->se.from_cpu.peak_bw = Bps_to_icc(2 * baud);
>> +	geni_icc_vote_on(&port->se);
>> +
>>   	/* parity */
>>   	tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
>>   	tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
>> @@ -1202,11 +1210,14 @@ static void qcom_geni_serial_pm(struct uart_port *uport,
>>   	if (old_state == UART_PM_STATE_UNDEFINED)
>>   		old_state = UART_PM_STATE_OFF;
>>   
>> -	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
>> +	if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) {
>> +		geni_icc_vote_on(&port->se);
>>   		geni_se_resources_on(&port->se);
>> -	else if (new_state == UART_PM_STATE_OFF &&
>> -			old_state == UART_PM_STATE_ON)
>> +	} else if (new_state == UART_PM_STATE_OFF &&
>> +			old_state == UART_PM_STATE_ON) {
>>   		geni_se_resources_off(&port->se);
>> +		geni_icc_vote_off(&port->se);
>> +	}
>>   }
>>   
>>   static const struct uart_ops qcom_geni_console_pops = {
>> @@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
>>   			return -ENOMEM;
>>   	}
>>   
>> +	ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
>> +	if (ret)
>> +		return ret;
>> +	/* Set the bus quota to a reasonable value */
>> +	port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
>> +		Bps_to_icc(CORE_2X_50_MHZ);
>> +	port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
>> +		Bps_to_icc(CORE_2X_100_MHZ);
> I'm still unconvinced about the setting of the core bandwidth based on
> whether the port is used as console or not. It could possibly break
> consoles working at speeds > 115kbs and reserve more bandwidth than
> necessary for ports with 'slow' devices.
>
> Why not scale the core bandwidth dynamically? You said earlier that there
> is no clear/linear translation of port speed to bandwidth, but you could
> use the same logic that is implicitly used here:
>
> 	if (baudrate <= 115200) {
> 		avg_bw = GENI_DEFAULT_BW;
> 		peak_bw = GENI_DEFAULT_BW;
> 	} else {
> 		avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
> 		peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
> 	}
>
> This would be more robust, power efficient and future readers of the
> code don't have to wonder "why is the console special?" when our
> discussions on this will be long forgotten.

Okay, I will add this piece of code in set_termios call of the driver 
because I don't have baudrate information during probe. It covers the 
console case mentioned in probe function.

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 6/8] tty: serial: qcom_geni_serial: Add interconnect support
  2020-04-07  9:19     ` Akash Asthana
@ 2020-04-07  9:40       ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  9:40 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,


>>>     static const struct uart_ops qcom_geni_console_pops = {
>>> @@ -1304,6 +1315,17 @@ static int qcom_geni_serial_probe(struct 
>>> platform_device *pdev)
>>>               return -ENOMEM;
>>>       }
>>>   +    ret = geni_icc_get(&port->se, "qup-core", "qup-config", NULL);
>>> +    if (ret)
>>> +        return ret;
>>> +    /* Set the bus quota to a reasonable value */
>>> +    port->se.to_core.avg_bw = console ? GENI_DEFAULT_BW :
>>> +        Bps_to_icc(CORE_2X_50_MHZ);
>>> +    port->se.to_core.peak_bw = console ? GENI_DEFAULT_BW :
>>> +        Bps_to_icc(CORE_2X_100_MHZ);
>> I'm still unconvinced about the setting of the core bandwidth based on
>> whether the port is used as console or not. It could possibly break
>> consoles working at speeds > 115kbs and reserve more bandwidth than
>> necessary for ports with 'slow' devices.
>>
>> Why not scale the core bandwidth dynamically? You said earlier that 
>> there
>> is no clear/linear translation of port speed to bandwidth, but you could
>> use the same logic that is implicitly used here:
>>
>>     if (baudrate <= 115200) {
>>         avg_bw = GENI_DEFAULT_BW;
>>         peak_bw = GENI_DEFAULT_BW;

I will make peak_bw = 2 * DEFAULT  to generalize this logic and will 
factor it out in common driver.

Anyway with  peak_bw = GENI_DEFAULT_BW or 2 * GENI_DEFAULT_BW core clock 
is going to tick at 50 MHz.

9600(19.2 MHz) < GENI_DEFAULT_BW, 2 * GENI_DEFAULT_BW < 2500(50 MHz).


Regards,

Akash

>>     } else {
>>         avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
>>         peak_bw = Bps_to_icc(CORE_2X_100_MHZ);
>>     }
>>
>> This would be more robust, power efficient and future readers of the
>> code don't have to wonder "why is the console special?" when our
>> discussions on this will be long forgotten.
>
> Okay, I will add this piece of code in set_termios call of the driver 
> because I don't have baudrate information during probe. It covers the 
> console case mentioned in probe function.
>
> Regards,
>
> Akash
>
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-03-31 11:23     ` Mark Brown
  (?)
@ 2020-04-07  9:54     ` Akash Asthana
  2020-04-07 10:55       ` Mark Brown
  -1 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-07  9:54 UTC (permalink / raw)
  To: Mark Brown
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

Hi Mark,

On 3/31/2020 4:53 PM, Mark Brown wrote:
> On Tue, Mar 31, 2020 at 04:39:35PM +0530, Akash Asthana wrote:
>
>> +	/*
>> +	 * Set BW quota for CPU as driver supports FIFO mode only.
>> +	 * Assume peak bw as twice of avg bw.
>> +	 */
>> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
>> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
> I thought you were going to factor this best guess handling of peak
> bandwidth out into the core?

I can centralize this for SPI, I2C and UART  in Common driver(QUP 
wrapper) but still for QSPI I have to keep this piece of code as is 
because It is not child of QUP wrapper(it doesn't use common code).

I am not sure whether I can move this " Assume peak_bw as twice of 
avg_bw if nothing is mentioned explicitly" to ICC core because the 
factor of 2 is chosen randomly by me.

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-04-07  6:46       ` Akash Asthana
@ 2020-04-07  9:58         ` Georgi Djakov
  2020-04-08 11:13           ` Akash Asthana
  0 siblings, 1 reply; 55+ messages in thread
From: Georgi Djakov @ 2020-04-07  9:58 UTC (permalink / raw)
  To: Akash Asthana, Evan Green, Bjorn Andersson
  Cc: Greg Kroah-Hartman, Andy Gross, wsa, Mark Brown, Mark Rutland,
	Rob Herring, linux-i2c, linux-spi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Manu Gautam, linux-arm-msm, linux-serial,
	Matthias Kaehlcke, Doug Anderson

Hi,

On 4/7/20 09:46, Akash Asthana wrote:
> Hi Bjorn, Evan,
> 
>>> Given that these two functions only switch the bandwidth request between
>>> some value and 0, I really think we should carry a "bool enabled" on the
>>> path and replace these two functions with
>>> icc_bulk_enable()/icc_bulk_disable().
> So, if above is implementation "bool enabled" on path can be used directly in
> aggregation of ICC votes on particular node without using icc_set_bw call, if
> yes then I am not aware how? or we'll be using icc_set_bw API indirectly inside
> icc_bulk APIs?

If there is a repeated pattern to switch between some bandwidth value and zero,
it really makes sense to introduce such functions in the framework core. I think
that this might be very useful especially for suspend and resume cases.
Something like icc_{enable,disable}(struct icc_path *path) functions and also
the bulk versions, that will flag the path as disabled, re-aggregate and do
icc_set_bw().

>>> The added benefit of this would be that you call icc_set_bw() instead of
>>> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
>>> track of them here.
> 
> Ok IIUC, we need to call icc_set_bw() from GENI driver only if we change (avg_bw
> | peak_bw)?

Yes, exactly.

Thanks,
Georgi

> 
> Regards,
> 
> Akash
> 
>> Yes yes! I had the same thought here [1].
>>
>> Georgi, what do you think?
>> -Evan
>>
>> [1]
>> https://lore.kernel.org/linux-arm-msm/CAE=gft58QsgTCUHMHKJhcM9ZxAeMiY16CrbNv2HaTCRqwtmt7A@mail.gmail.com/
>>
> 

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-04-07  9:54     ` Akash Asthana
@ 2020-04-07 10:55       ` Mark Brown
  2020-04-08 12:17         ` Akash Asthana
  0 siblings, 1 reply; 55+ messages in thread
From: Mark Brown @ 2020-04-07 10:55 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

[-- Attachment #1: Type: text/plain, Size: 845 bytes --]

On Tue, Apr 07, 2020 at 03:24:42PM +0530, Akash Asthana wrote:
> On 3/31/2020 4:53 PM, Mark Brown wrote:

> > > +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
> > > +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);

> > I thought you were going to factor this best guess handling of peak
> > bandwidth out into the core?

> I can centralize this for SPI, I2C and UART  in Common driver(QUP wrapper)
> but still for QSPI I have to keep this piece of code as is because It is not
> child of QUP wrapper(it doesn't use common code).

Why not?

> I am not sure whether I can move this " Assume peak_bw as twice of avg_bw if
> nothing is mentioned explicitly" to ICC core because the factor of 2 is
> chosen randomly by me.

That's the whole point - if this is just a random number then we may as
well at least be consistently random.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-03-31 18:24     ` Matthias Kaehlcke
  (?)
  (?)
@ 2020-04-07 11:34     ` Akash Asthana
  2020-04-07 17:26       ` Matthias Kaehlcke
  -1 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-07 11:34 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,


>>   static int geni_se_probe(struct platform_device *pdev)
>>   {
>>   	struct device *dev = &pdev->dev;
>> @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
>>   		}
>>   	}
>>   
>> +#ifdef CONFIG_SERIAL_EARLYCON
>> +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
>> +	if (IS_ERR(wrapper->to_core.path))
>> +		return PTR_ERR(wrapper->to_core.path);
>> +	/*
>> +	 * Put minmal BW request on core clocks on behalf of early console.
>> +	 * The vote will be removed earlycon exit function.
>> +	 *
>> +	 * Note: We are putting vote on each QUP wrapper instead only to which
>> +	 * earlycon is connected because QUP core clock of different wrapper
>> +	 * share same voltage domain. If core1 is put to 0, then core2 will
>> +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
>> +	 * we touch any of the core clock.
>> +	 * core1 = core2 = max(core1, core2)
>> +	 */
> I don't really understand this part. According to the comment if we vote
> (let's say) for core2 but not for core1 then:
>
> core1: 0
> core2: GENI_DEFAULT_BW
>
> core1 = core2 = max(core1, core2)
>    or
> core1 = core2 = max(0, GENI_DEFAULT_BW)
>
> hence
>
> core1 = core2 = GENI_DEFAULT_BW
>
> What am I missing, why is it necessary to vote for both/all?
say core1 is for earlycon usecase

There is common switch to control both the QUP core clock. I guess most 
appropriate description would be     switch = max(vote_on_core1, 
vote_on_core2) + default_vote.

During early bootup, vote_on_core1 = 0, vote_on_core2 = 0;

As earlycon was working even without voting it's core need because there 
was some default vote present on the core switch by ICC during bootup.

So if any child(say SPI) of other QUP wrapper resumed and suspended 
before earlycon wrapper comes up. This will make core clock to run at 
zero and will cause NOC issue because vote_on_core1 = 0, vote_on_core2 = 
0; and it seems default votes from core switch is removed  ASA it's 
voted on any core.

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-04-07 11:34     ` Akash Asthana
@ 2020-04-07 17:26       ` Matthias Kaehlcke
  2020-04-08 11:38         ` Akash Asthana
  0 siblings, 1 reply; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-04-07 17:26 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Akash,

On Tue, Apr 07, 2020 at 05:04:17PM +0530, Akash Asthana wrote:
> Hi Matthias,
> 
> 
> > >   static int geni_se_probe(struct platform_device *pdev)
> > >   {
> > >   	struct device *dev = &pdev->dev;
> > > @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
> > >   		}
> > >   	}
> > > +#ifdef CONFIG_SERIAL_EARLYCON
> > > +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
> > > +	if (IS_ERR(wrapper->to_core.path))
> > > +		return PTR_ERR(wrapper->to_core.path);
> > > +	/*
> > > +	 * Put minmal BW request on core clocks on behalf of early console.
> > > +	 * The vote will be removed earlycon exit function.
> > > +	 *
> > > +	 * Note: We are putting vote on each QUP wrapper instead only to which
> > > +	 * earlycon is connected because QUP core clock of different wrapper
> > > +	 * share same voltage domain. If core1 is put to 0, then core2 will
> > > +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
> > > +	 * we touch any of the core clock.
> > > +	 * core1 = core2 = max(core1, core2)
> > > +	 */
> > I don't really understand this part. According to the comment if we vote
> > (let's say) for core2 but not for core1 then:
> > 
> > core1: 0
> > core2: GENI_DEFAULT_BW
> > 
> > core1 = core2 = max(core1, core2)
> >    or
> > core1 = core2 = max(0, GENI_DEFAULT_BW)
> > 
> > hence
> > 
> > core1 = core2 = GENI_DEFAULT_BW
> > 
> > What am I missing, why is it necessary to vote for both/all?
> say core1 is for earlycon usecase
> 
> There is common switch to control both the QUP core clock. I guess most
> appropriate description would be     switch = max(vote_on_core1,
> vote_on_core2) + default_vote.
> 
> During early bootup, vote_on_core1 = 0, vote_on_core2 = 0;
> 
> As earlycon was working even without voting it's core need because there was
> some default vote present on the core switch by ICC during bootup.
> 
> So if any child(say SPI) of other QUP wrapper resumed and suspended before
> earlycon wrapper comes up. This will make core clock to run at zero and will
> cause NOC issue because vote_on_core1 = 0, vote_on_core2 = 0; and it seems
> default votes from core switch is removed  ASA it's voted on any core.

Thanks for the explication!

You are probably totally right, but for some reason my brain still resists
to get it ...

With the above my current interpretation is (assuming earlycon only votes on
core1):

                      core1   core2  default  switch
early boot              0       0        1       1
SPI resume (core2)      0       1        0       1
SPI suspend (core2)     0       0        0       0
earlycon init 		1	0        0       1


What is wrong in the above table?

Thanks for bearing with me :)

Matthias

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-04-07  6:45     ` Akash Asthana
@ 2020-04-07 22:07       ` Bjorn Andersson
  0 siblings, 0 replies; 55+ messages in thread
From: Bjorn Andersson @ 2020-04-07 22:07 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, wsa, broonie, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

On Mon 06 Apr 23:45 PDT 2020, Akash Asthana wrote:

> Hi Bjorn,
> 
> On 4/1/2020 5:02 AM, Bjorn Andersson wrote:
> > On Tue 31 Mar 04:09 PDT 2020, Akash Asthana wrote:
> > 
> > > Add necessary macros and structure variables to support ICC BW
> > > voting from individual SE drivers.
> > > 
> > > Signed-off-by: Akash Asthana <akashast@codeaurora.org>
> > > ---
> > > Changes in V2:
> > >   - As per Bjorn's comment dropped enums for ICC paths, given the three
> > >     paths individual members
> > > 
> > > Changes in V3:
> > >   - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
> > >   - Add geni_icc_path structure in common header
> > > 
> > >   drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
> > >   include/linux/qcom-geni-se.h    | 36 +++++++++++++++
> > >   2 files changed, 134 insertions(+)
> > > 
> > > diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
> > > index 7d622ea..9344c14 100644
> > > --- a/drivers/soc/qcom/qcom-geni-se.c
> > > +++ b/drivers/soc/qcom/qcom-geni-se.c
> > > @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
> > >   }
> > >   EXPORT_SYMBOL(geni_se_rx_dma_unprep);
> > > +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
> > > +		const char *icc_ddr)
> > > +{
> > > +	if (icc_core) {
> > Afaict it's only this that might be passed as NULL, so please drop these
> > conditionals (keep the last one).
> IIUC you're suggesting to drop if (icc_core/cpu) but keep if (icc_ddr) ?

Correct

Thanks,
Bjorn

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

* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
  2020-04-07  9:58         ` Georgi Djakov
@ 2020-04-08 11:13           ` Akash Asthana
  0 siblings, 0 replies; 55+ messages in thread
From: Akash Asthana @ 2020-04-08 11:13 UTC (permalink / raw)
  To: Georgi Djakov, Evan Green, Bjorn Andersson
  Cc: Greg Kroah-Hartman, Andy Gross, wsa, Mark Brown, Mark Rutland,
	Rob Herring, linux-i2c, linux-spi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Manu Gautam, linux-arm-msm, linux-serial,
	Matthias Kaehlcke, Doug Anderson

Hi Georgi, Bjorn, Evan,

On 4/7/2020 3:28 PM, Georgi Djakov wrote:
> Hi,
>
> On 4/7/20 09:46, Akash Asthana wrote:
>> Hi Bjorn, Evan,
>>
>>>> Given that these two functions only switch the bandwidth request between
>>>> some value and 0, I really think we should carry a "bool enabled" on the
>>>> path and replace these two functions with
>>>> icc_bulk_enable()/icc_bulk_disable().
>> So, if above is implementation "bool enabled" on path can be used directly in
>> aggregation of ICC votes on particular node without using icc_set_bw call, if
>> yes then I am not aware how? or we'll be using icc_set_bw API indirectly inside
>> icc_bulk APIs?
> If there is a repeated pattern to switch between some bandwidth value and zero,
> it really makes sense to introduce such functions in the framework core. I think
> that this might be very useful especially for suspend and resume cases.
> Something like icc_{enable,disable}(struct icc_path *path) functions and also
> the bulk versions, that will flag the path as disabled, re-aggregate and do
> icc_set_bw().

This appears to be a non-trivial change to ICC core, as my understanding 
of ICC core is limited as of now hence, I am not very clear of the 
implementation of icc_bulk APIs.

Will it be okay if I keep geni_icc_vote_on/off API as 
is@https://patchwork.kernel.org/patch/11467511/ for now and later will 
switch to icc_bulk once it's introduced in ICC core.

Regards,

Akash

>>>> The added benefit of this would be that you call icc_set_bw() instead of
>>>> changing the geni_icc_path->{avg_bw,peak_bw} and don't need to keep
>>>> track of them here.
>> Ok IIUC, we need to call icc_set_bw() from GENI driver only if we change (avg_bw
>> | peak_bw)?
> Yes, exactly.
>
> Thanks,
> Georgi
>
>> Regards,
>>
>> Akash
>>
>>> Yes yes! I had the same thought here [1].
>>>
>>> Georgi, what do you think?
>>> -Evan
>>>
>>> [1]
>>> https://lore.kernel.org/linux-arm-msm/CAE=gft58QsgTCUHMHKJhcM9ZxAeMiY16CrbNv2HaTCRqwtmt7A@mail.gmail.com/
>>>
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-04-07 17:26       ` Matthias Kaehlcke
@ 2020-04-08 11:38         ` Akash Asthana
  2020-04-08 17:09           ` Matthias Kaehlcke
  0 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-08 11:38 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

Hi Matthias,

On 4/7/2020 10:56 PM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Apr 07, 2020 at 05:04:17PM +0530, Akash Asthana wrote:
>> Hi Matthias,
>>
>>
>>>>    static int geni_se_probe(struct platform_device *pdev)
>>>>    {
>>>>    	struct device *dev = &pdev->dev;
>>>> @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
>>>>    		}
>>>>    	}
>>>> +#ifdef CONFIG_SERIAL_EARLYCON
>>>> +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
>>>> +	if (IS_ERR(wrapper->to_core.path))
>>>> +		return PTR_ERR(wrapper->to_core.path);
>>>> +	/*
>>>> +	 * Put minmal BW request on core clocks on behalf of early console.
>>>> +	 * The vote will be removed earlycon exit function.
>>>> +	 *
>>>> +	 * Note: We are putting vote on each QUP wrapper instead only to which
>>>> +	 * earlycon is connected because QUP core clock of different wrapper
>>>> +	 * share same voltage domain. If core1 is put to 0, then core2 will
>>>> +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
>>>> +	 * we touch any of the core clock.
>>>> +	 * core1 = core2 = max(core1, core2)
>>>> +	 */
>>> I don't really understand this part. According to the comment if we vote
>>> (let's say) for core2 but not for core1 then:
>>>
>>> core1: 0
>>> core2: GENI_DEFAULT_BW
>>>
>>> core1 = core2 = max(core1, core2)
>>>     or
>>> core1 = core2 = max(0, GENI_DEFAULT_BW)
>>>
>>> hence
>>>
>>> core1 = core2 = GENI_DEFAULT_BW
>>>
>>> What am I missing, why is it necessary to vote for both/all?
>> say core1 is for earlycon usecase
>>
>> There is common switch to control both the QUP core clock. I guess most
>> appropriate description would be     switch = max(vote_on_core1,
>> vote_on_core2) + default_vote.
>>
>> During early bootup, vote_on_core1 = 0, vote_on_core2 = 0;
>>
>> As earlycon was working even without voting it's core need because there was
>> some default vote present on the core switch by ICC during bootup.
>>
>> So if any child(say SPI) of other QUP wrapper resumed and suspended before
>> earlycon wrapper comes up. This will make core clock to run at zero and will
>> cause NOC issue because vote_on_core1 = 0, vote_on_core2 = 0; and it seems
>> default votes from core switch is removed  ASA it's voted on any core.
> Thanks for the explication!
>
> You are probably totally right, but for some reason my brain still resists
> to get it ...
>
> With the above my current interpretation is (assuming earlycon only votes on
> core1):
>
>                        core1   core2  default  switch
> early boot              0       0        1       1
> SPI resume (core2)      0       1        0       1
> SPI suspend (core2)     0       0        0       0
> earlycon init 		1	0        0       1
>
>
> What is wrong in the above table?
>
> Thanks for bearing with me :)
NP :)

I guess you meant QUP WRAPPER 1 probe by "earlycon init".

                       core1   core2  default  switch	Time
early boot              0       0        1       1	0s
SPI resume (core2)      0       1        0       1	3.2s
SPI suspend (core2)     0       0        0       0	3.3s
QUP WRAPPER 1(probe)	1	0        0       1	5s (say)

So switch is at 0 in time interval [3.3, 5] that will make core clock to run at 0.
If we use earlycon during this time interval it will reset the board.

Did above answered the query?

Regards,
Akash

>
> Matthias

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-04-07 10:55       ` Mark Brown
@ 2020-04-08 12:17         ` Akash Asthana
  2020-04-09 13:17           ` Georgi Djakov
  0 siblings, 1 reply; 55+ messages in thread
From: Akash Asthana @ 2020-04-08 12:17 UTC (permalink / raw)
  To: Mark Brown
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd, mgautam,
	linux-arm-msm, linux-serial, mka, dianders, evgreen

Hi Mark, Evan, Georgi,

On 4/7/2020 4:25 PM, Mark Brown wrote:
> On Tue, Apr 07, 2020 at 03:24:42PM +0530, Akash Asthana wrote:
>> On 3/31/2020 4:53 PM, Mark Brown wrote:
>>>> +	ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
>>>> +	ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
>>> I thought you were going to factor this best guess handling of peak
>>> bandwidth out into the core?
>> I can centralize this for SPI, I2C and UART  in Common driver(QUP wrapper)
>> but still for QSPI I have to keep this piece of code as is because It is not
>> child of QUP wrapper(it doesn't use common code).
> Why not?
>
>> I am not sure whether I can move this " Assume peak_bw as twice of avg_bw if
>> nothing is mentioned explicitly" to ICC core because the factor of 2 is
>> chosen randomly by me.
> That's the whole point - if this is just a random number then we may as
> well at least be consistently random.

Can we centralize below logic of peak_bw selection for all the clients 
to ICC core?

"Assume peak_bw requirement as twice of avg_bw, if it is not mentioned 
explicitly"

===========================================================================
int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
{
         struct icc_node *node;
         u32 old_avg, old_peak;
         size_t i;
         int ret;

         if (!path)
                 return 0;

         if (WARN_ON(IS_ERR(path) || !path->num_nodes))
                 return -EINVAL;

+       /*
+        * Assume peak_bw requirement as twice of avg_bw, if it is not
+        * mentioned explicitly
+        */
+       peak_bw = peak_bw ? peak_bw : 2 * avg_bw;
===========================================================================

In case if some client really don't want to put peak requirement they 
can pass avg_bw = peak_bw. As peak_bw <= avg_bw is kind of no-ops.

Regards,

Akash

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project

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

* Re: [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash
  2020-04-08 11:38         ` Akash Asthana
@ 2020-04-08 17:09           ` Matthias Kaehlcke
  0 siblings, 0 replies; 55+ messages in thread
From: Matthias Kaehlcke @ 2020-04-08 17:09 UTC (permalink / raw)
  To: Akash Asthana
  Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
	robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, dianders, evgreen

On Wed, Apr 08, 2020 at 05:08:01PM +0530, Akash Asthana wrote:
> Hi Matthias,
> 
> On 4/7/2020 10:56 PM, Matthias Kaehlcke wrote:
> > Hi Akash,
> > 
> > On Tue, Apr 07, 2020 at 05:04:17PM +0530, Akash Asthana wrote:
> > > Hi Matthias,
> > > 
> > > 
> > > > >    static int geni_se_probe(struct platform_device *pdev)
> > > > >    {
> > > > >    	struct device *dev = &pdev->dev;
> > > > > @@ -845,6 +868,34 @@ static int geni_se_probe(struct platform_device *pdev)
> > > > >    		}
> > > > >    	}
> > > > > +#ifdef CONFIG_SERIAL_EARLYCON
> > > > > +	wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
> > > > > +	if (IS_ERR(wrapper->to_core.path))
> > > > > +		return PTR_ERR(wrapper->to_core.path);
> > > > > +	/*
> > > > > +	 * Put minmal BW request on core clocks on behalf of early console.
> > > > > +	 * The vote will be removed earlycon exit function.
> > > > > +	 *
> > > > > +	 * Note: We are putting vote on each QUP wrapper instead only to which
> > > > > +	 * earlycon is connected because QUP core clock of different wrapper
> > > > > +	 * share same voltage domain. If core1 is put to 0, then core2 will
> > > > > +	 * also run at 0, if not voted. Default ICC vote will be removed ASA
> > > > > +	 * we touch any of the core clock.
> > > > > +	 * core1 = core2 = max(core1, core2)
> > > > > +	 */
> > > > I don't really understand this part. According to the comment if we vote
> > > > (let's say) for core2 but not for core1 then:
> > > > 
> > > > core1: 0
> > > > core2: GENI_DEFAULT_BW
> > > > 
> > > > core1 = core2 = max(core1, core2)
> > > >     or
> > > > core1 = core2 = max(0, GENI_DEFAULT_BW)
> > > > 
> > > > hence
> > > > 
> > > > core1 = core2 = GENI_DEFAULT_BW
> > > > 
> > > > What am I missing, why is it necessary to vote for both/all?
> > > say core1 is for earlycon usecase
> > > 
> > > There is common switch to control both the QUP core clock. I guess most
> > > appropriate description would be     switch = max(vote_on_core1,
> > > vote_on_core2) + default_vote.
> > > 
> > > During early bootup, vote_on_core1 = 0, vote_on_core2 = 0;
> > > 
> > > As earlycon was working even without voting it's core need because there was
> > > some default vote present on the core switch by ICC during bootup.
> > > 
> > > So if any child(say SPI) of other QUP wrapper resumed and suspended before
> > > earlycon wrapper comes up. This will make core clock to run at zero and will
> > > cause NOC issue because vote_on_core1 = 0, vote_on_core2 = 0; and it seems
> > > default votes from core switch is removed  ASA it's voted on any core.
> > Thanks for the explication!
> > 
> > You are probably totally right, but for some reason my brain still resists
> > to get it ...
> > 
> > With the above my current interpretation is (assuming earlycon only votes on
> > core1):
> > 
> >                        core1   core2  default  switch
> > early boot              0       0        1       1
> > SPI resume (core2)      0       1        0       1
> > SPI suspend (core2)     0       0        0       0
> > earlycon init 		1	0        0       1
> > 
> > 
> > What is wrong in the above table?
> > 
> > Thanks for bearing with me :)
> NP :)
> 
> I guess you meant QUP WRAPPER 1 probe by "earlycon init".
> 
>                       core1   core2  default  switch	Time
> early boot              0       0        1       1	0s
> SPI resume (core2)      0       1        0       1	3.2s
> SPI suspend (core2)     0       0        0       0	3.3s
> QUP WRAPPER 1(probe)	1	0        0       1	5s (say)
> 
> So switch is at 0 in time interval [3.3, 5] that will make core clock to run at 0.
> If we use earlycon during this time interval it will reset the board.
> 
> Did above answered the query?

now it finally made 'click', thanks :)

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-04-08 12:17         ` Akash Asthana
@ 2020-04-09 13:17           ` Georgi Djakov
  2020-04-09 13:20             ` Mark Brown
       [not found]             ` <eca0e6a7-effe-022c-e90e-c0672991251d@codeaurora.org>
  0 siblings, 2 replies; 55+ messages in thread
From: Georgi Djakov @ 2020-04-09 13:17 UTC (permalink / raw)
  To: Akash Asthana, Mark Brown
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen

Hi Akash,

On 4/8/20 15:17, Akash Asthana wrote:
> Hi Mark, Evan, Georgi,
> 
> On 4/7/2020 4:25 PM, Mark Brown wrote:
>> On Tue, Apr 07, 2020 at 03:24:42PM +0530, Akash Asthana wrote:
>>> On 3/31/2020 4:53 PM, Mark Brown wrote:
>>>>> +    ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
>>>>> +    ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
>>>> I thought you were going to factor this best guess handling of peak
>>>> bandwidth out into the core?
>>> I can centralize this for SPI, I2C and UART  in Common driver(QUP wrapper)
>>> but still for QSPI I have to keep this piece of code as is because It is not
>>> child of QUP wrapper(it doesn't use common code).
>> Why not?
>>
>>> I am not sure whether I can move this " Assume peak_bw as twice of avg_bw if
>>> nothing is mentioned explicitly" to ICC core because the factor of 2 is
>>> chosen randomly by me.
>> That's the whole point - if this is just a random number then we may as
>> well at least be consistently random.
> 
> Can we centralize below logic of peak_bw selection for all the clients to ICC core?

I don't think this is a good idea for now, because this is very hardware
specific. A scaling factor that works for one client might not work for another.

My questions here is how did you decide on this "multiply by two"? I can imagine
that the traffic can be bursty on some interfaces, but is the factor here really
a "random number" or is this based on some data patterns or performance
analysis?

Thanks,
Georgi

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-04-09 13:17           ` Georgi Djakov
@ 2020-04-09 13:20             ` Mark Brown
  2020-04-15 10:34               ` Georgi Djakov
       [not found]             ` <eca0e6a7-effe-022c-e90e-c0672991251d@codeaurora.org>
  1 sibling, 1 reply; 55+ messages in thread
From: Mark Brown @ 2020-04-09 13:20 UTC (permalink / raw)
  To: Georgi Djakov
  Cc: Akash Asthana, gregkh, agross, bjorn.andersson, wsa,
	mark.rutland, robh+dt, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, mka, dianders, evgreen

[-- Attachment #1: Type: text/plain, Size: 867 bytes --]

On Thu, Apr 09, 2020 at 04:17:22PM +0300, Georgi Djakov wrote:
> On 4/8/20 15:17, Akash Asthana wrote:

> > Can we centralize below logic of peak_bw selection for all the clients to ICC core?

> I don't think this is a good idea for now, because this is very hardware
> specific. A scaling factor that works for one client might not work for another.

AIUI a driver can always override the setting if it's got a better idea.

> My questions here is how did you decide on this "multiply by two"? I can imagine
> that the traffic can be bursty on some interfaces, but is the factor here really
> a "random number" or is this based on some data patterns or performance
> analysis?

The reason I'm pushing for this to go into the core is that the numbers
seem to be just made up and not device specific at all (or at least
there's a lot of devices with the same values).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
  2020-04-09 13:20             ` Mark Brown
@ 2020-04-15 10:34               ` Georgi Djakov
  0 siblings, 0 replies; 55+ messages in thread
From: Georgi Djakov @ 2020-04-15 10:34 UTC (permalink / raw)
  To: Mark Brown
  Cc: Akash Asthana, gregkh, agross, bjorn.andersson, wsa,
	mark.rutland, robh+dt, linux-i2c, linux-spi, devicetree, swboyd,
	mgautam, linux-arm-msm, linux-serial, mka, dianders, evgreen

Hi,

On 4/9/20 16:20, Mark Brown wrote:
> On Thu, Apr 09, 2020 at 04:17:22PM +0300, Georgi Djakov wrote:
>> On 4/8/20 15:17, Akash Asthana wrote:
> 
>>> Can we centralize below logic of peak_bw selection for all the clients to ICC core?
> 
>> I don't think this is a good idea for now, because this is very hardware
>> specific. A scaling factor that works for one client might not work for another.
> 
> AIUI a driver can always override the setting if it's got a better idea.

True.

>> My questions here is how did you decide on this "multiply by two"? I can imagine
>> that the traffic can be bursty on some interfaces, but is the factor here really
>> a "random number" or is this based on some data patterns or performance
>> analysis?
> 
> The reason I'm pushing for this to go into the core is that the numbers
> seem to be just made up and not device specific at all (or at least
> there's a lot of devices with the same values).

I might be a bit too cautious here, but the main question is what this common
number should be then. Maybe the numbers are not device specific, but
communication interface/bus specific? I would rather make the peak 30% higher
than the average, but for low speed interfaces i guess the factor of two should
also be fine?

Thanks,
Georgi

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

* Re: [PATCH V3 7/8] spi: spi-qcom-qspi: Add interconnect support
       [not found]             ` <eca0e6a7-effe-022c-e90e-c0672991251d@codeaurora.org>
@ 2020-04-15 10:54               ` Georgi Djakov
  0 siblings, 0 replies; 55+ messages in thread
From: Georgi Djakov @ 2020-04-15 10:54 UTC (permalink / raw)
  To: Akash Asthana, Mark Brown
  Cc: gregkh, agross, bjorn.andersson, wsa, mark.rutland, robh+dt,
	linux-i2c, linux-spi, devicetree, swboyd, mgautam, linux-arm-msm,
	linux-serial, mka, dianders, evgreen

Hi Akash,

On 4/10/20 10:31, Akash Asthana wrote:
> Hi Georgi,
> 
> On 4/9/2020 6:47 PM, Georgi Djakov wrote:
>> Hi Akash,
>>
>> On 4/8/20 15:17, Akash Asthana wrote:
>>> Hi Mark, Evan, Georgi,
>>>
>>> On 4/7/2020 4:25 PM, Mark Brown wrote:
>>>> On Tue, Apr 07, 2020 at 03:24:42PM +0530, Akash Asthana wrote:
>>>>> On 3/31/2020 4:53 PM, Mark Brown wrote:
>>>>>>> +    ctrl->avg_bw_cpu = Bps_to_icc(speed_hz);
>>>>>>> +    ctrl->peak_bw_cpu = Bps_to_icc(2 * speed_hz);
>>>>>> I thought you were going to factor this best guess handling of peak
>>>>>> bandwidth out into the core?
>>>>> I can centralize this for SPI, I2C and UART  in Common driver(QUP wrapper)
>>>>> but still for QSPI I have to keep this piece of code as is because It is not
>>>>> child of QUP wrapper(it doesn't use common code).
>>>> Why not?
>>>>
>>>>> I am not sure whether I can move this " Assume peak_bw as twice of avg_bw if
>>>>> nothing is mentioned explicitly" to ICC core because the factor of 2 is
>>>>> chosen randomly by me.
>>>> That's the whole point - if this is just a random number then we may as
>>>> well at least be consistently random.
>>> Can we centralize below logic of peak_bw selection for all the clients to ICC core?
>> I don't think this is a good idea for now, because this is very hardware
>> specific. A scaling factor that works for one client might not work for another.
>>
>> My questions here is how did you decide on this "multiply by two"? I can imagine
>> that the traffic can be bursty on some interfaces, but is the factor here really
>> a "random number" or is this based on some data patterns or performance
>> analysis?
> 
> Factor of 2 is random number.
> 
> We are taking care of actual throughput requirement in avg_bw vote and
> the intention of putting peak as twice of avg is to ensure that if high
> speed peripherals(ex:USB) removes their votes, we shouldn't see any
> latency issue because of other ICC client who don't vote for their BW
> requirement or *actual* BW requirement.

Thanks for clarifying, but is this latency a confirmed issue on real hardware?
I guess voting for twice as average will work, but still wondering wouldn't
it be more appropriate to handle it in the interconnect platform driver instead?
Also why is the other client not voting, can we fix it?

Thanks,
Georgi

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

end of thread, other threads:[~2020-04-15 10:54 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-31 11:09 [PATCH V3 0/8] Add interconnect support to QSPI and QUP drivers Akash Asthana
2020-03-31 11:09 ` [PATCH V3 1/8] interconnect: Add devm_of_icc_get() as exported API for users Akash Asthana
2020-03-31 11:09   ` Akash Asthana
2020-03-31 11:09 ` [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting Akash Asthana
2020-03-31 17:52   ` Matthias Kaehlcke
2020-03-31 17:52     ` Matthias Kaehlcke
2020-04-02 13:46     ` Akash Asthana
2020-04-02 13:46       ` Akash Asthana
2020-03-31 23:32   ` Bjorn Andersson
2020-03-31 23:32     ` Bjorn Andersson
2020-04-01 16:26     ` Evan Green
2020-04-01 16:26       ` Evan Green
2020-04-07  6:46       ` Akash Asthana
2020-04-07  9:58         ` Georgi Djakov
2020-04-08 11:13           ` Akash Asthana
2020-04-07  6:45     ` Akash Asthana
2020-04-07 22:07       ` Bjorn Andersson
2020-03-31 11:09 ` [PATCH V3 3/8] soc: qcom-geni-se: Add interconnect support to fix earlycon crash Akash Asthana
2020-03-31 18:24   ` Matthias Kaehlcke
2020-03-31 18:24     ` Matthias Kaehlcke
2020-04-01 19:46     ` Matthias Kaehlcke
2020-04-01 19:46       ` Matthias Kaehlcke
2020-04-07  6:52       ` Akash Asthana
2020-04-07 11:34     ` Akash Asthana
2020-04-07 17:26       ` Matthias Kaehlcke
2020-04-08 11:38         ` Akash Asthana
2020-04-08 17:09           ` Matthias Kaehlcke
2020-03-31 11:09 ` [PATCH V3 4/8] i2c: i2c-qcom-geni: Add interconnect support Akash Asthana
2020-03-31 18:49   ` Matthias Kaehlcke
2020-03-31 18:49     ` Matthias Kaehlcke
2020-04-07  7:04     ` Akash Asthana
2020-03-31 11:09 ` [PATCH V3 5/8] spi: spi-geni-qcom: " Akash Asthana
2020-03-31 19:02   ` Matthias Kaehlcke
2020-03-31 19:02     ` Matthias Kaehlcke
2020-04-07  7:11     ` Akash Asthana
2020-03-31 11:09 ` [PATCH V3 6/8] tty: serial: qcom_geni_serial: " Akash Asthana
2020-03-31 11:09   ` Akash Asthana
2020-03-31 19:39   ` Matthias Kaehlcke
2020-03-31 19:39     ` Matthias Kaehlcke
2020-04-07  9:19     ` Akash Asthana
2020-04-07  9:40       ` Akash Asthana
2020-03-31 11:09 ` [PATCH V3 7/8] spi: spi-qcom-qspi: " Akash Asthana
2020-03-31 11:23   ` Mark Brown
2020-03-31 11:23     ` Mark Brown
2020-04-07  9:54     ` Akash Asthana
2020-04-07 10:55       ` Mark Brown
2020-04-08 12:17         ` Akash Asthana
2020-04-09 13:17           ` Georgi Djakov
2020-04-09 13:20             ` Mark Brown
2020-04-15 10:34               ` Georgi Djakov
     [not found]             ` <eca0e6a7-effe-022c-e90e-c0672991251d@codeaurora.org>
2020-04-15 10:54               ` Georgi Djakov
2020-03-31 19:45   ` Matthias Kaehlcke
2020-03-31 19:45     ` Matthias Kaehlcke
2020-03-31 11:09 ` [PATCH V3 8/8] arm64: dts: sc7180: Add interconnect for QUP and QSPI Akash Asthana
2020-03-31 11:09   ` Akash Asthana

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.