linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/14] ti-sysc changes to probe devices with dts data only
@ 2019-03-25 21:58 Tony Lindgren
  2019-03-25 21:58 ` [PATCH 01/14] bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated Tony Lindgren
                   ` (13 more replies)
  0 siblings, 14 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

Hi all,

Here are some ti-sysc interconnect target module changes that allow
dropping legacy platform data for many devices in favor of devicetree
provided data.

This series depends on patch series "[PATCH 0/7] omap changes to
allocate struct omap_hwmod dynamically".

I'll be posting patches separately to drop platform data. Meanwhile,
the easiest way to test this series is to just temporarily comment
out selected platform data entries one driver at a time. This can be
done in the SoC specific struct omap_hwmod_ocp_if array at the end of
the arch/arm/mach-omap2/omap_hwmod_*_data.c files.

Note that we are not yet handling all the quirks yet listed in
arch/arm/mach-omap2/omap_hwmod.h in "omap_hwmod.flags definitions".
We currently do not yet handle quirks for devices with:

HWMOD_NO_OCP_AUTOIDLE
HWMOD_NO_IDLEST
HWMOD_BLOCK_WFI
HWMOD_FORCE_MSTANDBY
HWMOD_RECONFIG_IO_CHAIN
HWMOD_CLKDM_NOAUTO

I'll be posting patches for these later on as needed.

Regards,

Tony


Tony Lindgren (14):
  bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated
  bus: ti-sysc: Handle missed no-idle property in addition to
    no-idle-on-init
  bus: ti-sysc: Make functions static
  bus: ti-sysc: Move legacy platform data idling into separate functions
  bus: ti-sysc: Add separate functions for handling clocks
  bus: ti-sysc: Enable all clocks directly during init to read revision
  bus: ti-sysc: Allocate mdata as needed and do platform data based init
    later
  bus: ti-sysc: Manage clocks for the interconnect target module in all
    cases
  bus: ti-sysc: Move rstctrl reset to happen later
  bus: ti-sysc: Add support for early quirks based on register address
  bus: ti-sysc: Add quirk handling for external optional functional
    clock
  bus: ti-sysc: Pass clockactivity quirk to platform functions
  bus: ti-sysc: Handle swsup idle mode quirks
  bus: ti-sysc: Detect DMIC for debugging

 .../devicetree/bindings/bus/ti-sysc.txt       |   2 +
 arch/arm/mach-omap2/omap_hwmod.c              |  10 +
 drivers/bus/ti-sysc.c                         | 537 ++++++++++++++----
 include/linux/platform_data/ti-sysc.h         |   9 +-
 4 files changed, 438 insertions(+), 120 deletions(-)

-- 
2.21.0

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

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

* [PATCH 01/14] bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init Tony Lindgren
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

If we return early before ddata->clocks have been allocated we will get a
NULL pointer dereference in sysc_unprepare(). Let's fix this by returning
early when no clocks are allocated.

Fixes: 0eecc636e5a2 ("bus: ti-sysc: Add minimal TI sysc interconnect target driver")
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -1331,6 +1331,9 @@ static void sysc_unprepare(struct sysc *ddata)
 {
 	int i;
 
+	if (!ddata->clocks)
+		return;
+
 	for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
 		if (!IS_ERR_OR_NULL(ddata->clocks[i]))
 			clk_unprepare(ddata->clocks[i]);
-- 
2.21.0

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

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

* [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
  2019-03-25 21:58 ` [PATCH 01/14] bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-31  6:41   ` Rob Herring
  2019-03-25 21:58 ` [PATCH 03/14] bus: ti-sysc: Make functions static Tony Lindgren
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, devicetree, Faiz Abbas, Keerthy,
	Rob Herring, linux-arm-kernel, Roger Quadros

We have ti,no-idle in use in addition to ti,no-idle-on-init but we're
missing handling for it in the ti-sysc interconnect target module driver.

Let's also group the idle defines together and update the binding
documentation for it.

Cc: Rob Herring <robh@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 Documentation/devicetree/bindings/bus/ti-sysc.txt | 2 ++
 arch/arm/mach-omap2/omap_hwmod.c                  | 2 ++
 drivers/bus/ti-sysc.c                             | 5 ++++-
 include/linux/platform_data/ti-sysc.h             | 5 +++--
 4 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/bus/ti-sysc.txt b/Documentation/devicetree/bindings/bus/ti-sysc.txt
--- a/Documentation/devicetree/bindings/bus/ti-sysc.txt
+++ b/Documentation/devicetree/bindings/bus/ti-sysc.txt
@@ -94,6 +94,8 @@ Optional properties:
 
 - ti,no-idle-on-init	interconnect target module should not be idled at init
 
+- ti,no-idle		interconnect target module should not be idled
+
 Example: Single instance of MUSB controller on omap4 using interconnect ranges
 using offsets from l4_cfg second segment (0x4a000000 + 0x80000 = 0x4a0ab000):
 
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3675,6 +3675,8 @@ int omap_hwmod_init_module(struct device *dev,
 	if (error)
 		return error;
 
+	if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE)
+		oh->flags |= HWMOD_NO_IDLE;
 	if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT)
 		oh->flags |= HWMOD_INIT_NO_IDLE;
 	if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -920,7 +920,8 @@ static int sysc_init_module(struct sysc *ddata)
 {
 	int error;
 
-	if (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE_ON_INIT) {
+	if (ddata->cfg.quirks &
+	    (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT)) {
 		ddata->revision = sysc_read_revision(ddata);
 		goto rev_quirks;
 	}
@@ -1281,6 +1282,8 @@ static const struct sysc_dts_quirk sysc_dts_quirks[] = {
 	  .mask = SYSC_QUIRK_NO_IDLE_ON_INIT, },
 	{ .name = "ti,no-reset-on-init",
 	  .mask = SYSC_QUIRK_NO_RESET_ON_INIT, },
+	{ .name = "ti,no-idle",
+	  .mask = SYSC_QUIRK_NO_IDLE, },
 };
 
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h
--- a/include/linux/platform_data/ti-sysc.h
+++ b/include/linux/platform_data/ti-sysc.h
@@ -46,8 +46,9 @@ struct sysc_regbits {
 	s8 emufree_shift;
 };
 
-#define SYSC_QUIRK_LEGACY_IDLE		BIT(8)
-#define SYSC_QUIRK_RESET_STATUS		BIT(7)
+#define SYSC_QUIRK_LEGACY_IDLE		BIT(9)
+#define SYSC_QUIRK_RESET_STATUS		BIT(8)
+#define SYSC_QUIRK_NO_IDLE		BIT(7)
 #define SYSC_QUIRK_NO_IDLE_ON_INIT	BIT(6)
 #define SYSC_QUIRK_NO_RESET_ON_INIT	BIT(5)
 #define SYSC_QUIRK_OPT_CLKS_NEEDED	BIT(4)
-- 
2.21.0

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

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

* [PATCH 03/14] bus: ti-sysc: Make functions static
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
  2019-03-25 21:58 ` [PATCH 01/14] bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated Tony Lindgren
  2019-03-25 21:58 ` [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 04/14] bus: ti-sysc: Move legacy platform data idling into separate functions Tony Lindgren
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

We can make sysc_write() and sysc_child_pm_domain static as noted by
sparse.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -94,7 +94,7 @@ struct sysc {
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
 				  bool is_child);
 
-void sysc_write(struct sysc *ddata, int offset, u32 value)
+static void sysc_write(struct sysc *ddata, int offset, u32 value)
 {
 	writel_relaxed(value, ddata->module_va + offset);
 }
@@ -1209,7 +1209,7 @@ static int sysc_child_resume_noirq(struct device *dev)
 }
 #endif
 
-struct dev_pm_domain sysc_child_pm_domain = {
+static struct dev_pm_domain sysc_child_pm_domain = {
 	.ops = {
 		SET_RUNTIME_PM_OPS(sysc_child_runtime_suspend,
 				   sysc_child_runtime_resume,
-- 
2.21.0

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

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

* [PATCH 04/14] bus: ti-sysc: Move legacy platform data idling into separate functions
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (2 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 03/14] bus: ti-sysc: Make functions static Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks Tony Lindgren
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

Let's move the legacy idle and enable into separate functions to simplify
PM runtime functions a bit.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 78 +++++++++++++++++++++++++++----------------
 1 file changed, 50 insertions(+), 28 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -622,9 +622,50 @@ static void sysc_show_registers(struct sysc *ddata)
 		buf);
 }
 
-static int __maybe_unused sysc_runtime_suspend(struct device *dev)
+static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev,
+						      struct sysc *ddata)
+{
+	struct ti_sysc_platform_data *pdata;
+	int error;
+
+	pdata = dev_get_platdata(ddata->dev);
+	if (!pdata)
+		return 0;
+
+	if (!pdata->idle_module)
+		return -ENODEV;
+
+	error = pdata->idle_module(dev, &ddata->cookie);
+	if (error)
+		dev_err(dev, "%s: could not idle: %i\n",
+			__func__, error);
+
+	return 0;
+}
+
+static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
+						     struct sysc *ddata)
 {
 	struct ti_sysc_platform_data *pdata;
+	int error;
+
+	pdata = dev_get_platdata(ddata->dev);
+	if (!pdata)
+		return 0;
+
+	if (!pdata->enable_module)
+		return -ENODEV;
+
+	error = pdata->enable_module(dev, &ddata->cookie);
+	if (error)
+		dev_err(dev, "%s: could not enable: %i\n",
+			__func__, error);
+
+	return 0;
+}
+
+static int __maybe_unused sysc_runtime_suspend(struct device *dev)
+{
 	struct sysc *ddata;
 	int error = 0, i;
 
@@ -634,19 +675,11 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 		return 0;
 
 	if (ddata->legacy_mode) {
-		pdata = dev_get_platdata(ddata->dev);
-		if (!pdata)
-			return 0;
-
-		if (!pdata->idle_module)
-			return -ENODEV;
-
-		error = pdata->idle_module(dev, &ddata->cookie);
-		if (error)
-			dev_err(dev, "%s: could not idle: %i\n",
-				__func__, error);
+		error = sysc_runtime_suspend_legacy(dev, ddata);
+		if (!error)
+			ddata->enabled = false;
 
-		goto idled;
+		return error;
 	}
 
 	for (i = 0; i < ddata->nr_clocks; i++) {
@@ -659,7 +692,6 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 		clk_disable(ddata->clocks[i]);
 	}
 
-idled:
 	ddata->enabled = false;
 
 	return error;
@@ -667,7 +699,6 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 
 static int __maybe_unused sysc_runtime_resume(struct device *dev)
 {
-	struct ti_sysc_platform_data *pdata;
 	struct sysc *ddata;
 	int error = 0, i;
 
@@ -677,19 +708,11 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 		return 0;
 
 	if (ddata->legacy_mode) {
-		pdata = dev_get_platdata(ddata->dev);
-		if (!pdata)
-			return 0;
+		error = sysc_runtime_resume_legacy(dev, ddata);
+		if (!error)
+			ddata->enabled = true;
 
-		if (!pdata->enable_module)
-			return -ENODEV;
-
-		error = pdata->enable_module(dev, &ddata->cookie);
-		if (error)
-			dev_err(dev, "%s: could not enable: %i\n",
-				__func__, error);
-
-		goto awake;
+		return error;
 	}
 
 	for (i = 0; i < ddata->nr_clocks; i++) {
@@ -704,7 +727,6 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 			return error;
 	}
 
-awake:
 	ddata->enabled = true;
 
 	return error;
-- 
2.21.0

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

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

* [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (3 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 04/14] bus: ti-sysc: Move legacy platform data idling into separate functions Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-04-03 18:00   ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 06/14] bus: ti-sysc: Enable all clocks directly during init to read revision Tony Lindgren
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

At least McPDM module depends on an external optional clock to be
usable. To make handling of the McPDM clock easier in the following
patches, let's add separate functions for handling the main clocks
and the optional clocks.

Let's also add error handling to shut down already enabled clocks
while at it.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 141 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 123 insertions(+), 18 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -231,6 +231,112 @@ static int sysc_get_clocks(struct sysc *ddata)
 	return 0;
 }
 
+static int sysc_enable_main_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i, error;
+
+	if (!ddata->clocks)
+		return 0;
+
+	for (i = 0; i < SYSC_OPTFCK0; i++) {
+		clock = ddata->clocks[i];
+
+		/* Main clocks may not have ick */
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		error = clk_enable(clock);
+		if (error)
+			goto err_disable;
+	}
+
+	return 0;
+
+err_disable:
+	for (; i >= 0; i--) {
+		clock = ddata->clocks[i];
+
+		/* Main clocks may not have ick */
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+
+	return error;
+}
+
+static void sysc_disable_main_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i;
+
+	if (!ddata->clocks)
+		return;
+
+	for (i = 0; i < SYSC_OPTFCK0; i++) {
+		clock = ddata->clocks[i];
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+}
+
+static int sysc_enable_opt_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i, error;
+
+	if (!ddata->clocks)
+		return 0;
+
+	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+		clock = ddata->clocks[i];
+
+		/* Assume no holes for opt clocks */
+		if (IS_ERR_OR_NULL(clock))
+			return 0;
+
+		error = clk_enable(clock);
+		if (error)
+			goto err_disable;
+	}
+
+	return 0;
+
+err_disable:
+	for (; i >= 0; i--) {
+		clock = ddata->clocks[i];
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+
+	return error;
+}
+
+static void sysc_disable_opt_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i;
+
+	if (!ddata->clocks)
+		return;
+
+	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+		clock = ddata->clocks[i];
+
+		/* Assume no holes for opt clocks */
+		if (IS_ERR_OR_NULL(clock))
+			return;
+
+		clk_disable(clock);
+	}
+}
+
 /**
  * sysc_init_resets - reset module on init
  * @ddata: device driver data
@@ -667,7 +773,7 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
 static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 {
 	struct sysc *ddata;
-	int error = 0, i;
+	int error = 0;
 
 	ddata = dev_get_drvdata(dev);
 
@@ -682,15 +788,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 		return error;
 	}
 
-	for (i = 0; i < ddata->nr_clocks; i++) {
-		if (IS_ERR_OR_NULL(ddata->clocks[i]))
-			continue;
+	sysc_disable_main_clocks(ddata);
 
-		if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-			break;
-
-		clk_disable(ddata->clocks[i]);
-	}
+	if (sysc_opt_clks_needed(ddata))
+		sysc_disable_opt_clocks(ddata);
 
 	ddata->enabled = false;
 
@@ -700,7 +801,7 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 static int __maybe_unused sysc_runtime_resume(struct device *dev)
 {
 	struct sysc *ddata;
-	int error = 0, i;
+	int error = 0;
 
 	ddata = dev_get_drvdata(dev);
 
@@ -715,20 +816,24 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 		return error;
 	}
 
-	for (i = 0; i < ddata->nr_clocks; i++) {
-		if (IS_ERR_OR_NULL(ddata->clocks[i]))
-			continue;
-
-		if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-			break;
-
-		error = clk_enable(ddata->clocks[i]);
+	if (sysc_opt_clks_needed(ddata)) {
+		error = sysc_enable_opt_clocks(ddata);
 		if (error)
 			return error;
 	}
 
+	error = sysc_enable_main_clocks(ddata);
+	if (error)
+		goto err_main_clocks;
+
 	ddata->enabled = true;
 
+	return 0;
+
+err_main_clocks:
+	if (sysc_opt_clks_needed(ddata))
+		sysc_disable_opt_clocks(ddata);
+
 	return error;
 }
 
-- 
2.21.0

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

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

* [PATCH 06/14] bus: ti-sysc: Enable all clocks directly during init to read revision
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (4 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 07/14] bus: ti-sysc: Allocate mdata as needed and do platform data based init later Tony Lindgren
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

The first thing we want to do is just read the module revision register to
be able to configure the module specific quirks and configure the module
registers.

As the interconnect target module may not yet be properly configured and
may need a reset first, we don't want to use pm_runtime_get() at this
point.

To read the revision register, let's just enable the all the clocks for
the interconnect target module during init even if the optional clocks
are not needed. That way we can read the revision register to configure
the quirks needed for PM runtime.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 50 ++++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -1042,39 +1042,45 @@ static int sysc_reset(struct sysc *ddata)
 				  100, MAX_MODULE_SOFTRESET_WAIT);
 }
 
-/* At this point the module is configured enough to read the revision */
+/*
+ * At this point the module is configured enough to read the revision but
+ * module may not be completely configured yet to use PM runtime. Enable
+ * all clocks directly during init to configure the quirks needed for PM
+ * runtime based on the revision register.
+ */
 static int sysc_init_module(struct sysc *ddata)
 {
-	int error;
+	int error = 0;
+	bool manage_clocks = true;
 
 	if (ddata->cfg.quirks &
-	    (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT)) {
-		ddata->revision = sysc_read_revision(ddata);
-		goto rev_quirks;
-	}
+	    (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))
+		manage_clocks = false;
 
-	error = pm_runtime_get_sync(ddata->dev);
-	if (error < 0) {
-		pm_runtime_put_noidle(ddata->dev);
+	if (manage_clocks) {
+		error = sysc_enable_opt_clocks(ddata);
+		if (error)
+			return error;
 
-		return 0;
+		error = sysc_enable_main_clocks(ddata);
+		if (error)
+			goto err_opt_clocks;
 	}
 
+	ddata->revision = sysc_read_revision(ddata);
+	sysc_init_revision_quirks(ddata);
+
 	error = sysc_reset(ddata);
-	if (error) {
+	if (error)
 		dev_err(ddata->dev, "Reset failed with %d\n", error);
-		pm_runtime_put_sync(ddata->dev);
 
-		return error;
-	}
-
-	ddata->revision = sysc_read_revision(ddata);
-	pm_runtime_put_sync(ddata->dev);
-
-rev_quirks:
-	sysc_init_revision_quirks(ddata);
+	if (manage_clocks)
+		sysc_disable_main_clocks(ddata);
+err_opt_clocks:
+	if (manage_clocks)
+		sysc_disable_opt_clocks(ddata);
 
-	return 0;
+	return error;
 }
 
 static int sysc_init_sysc_mask(struct sysc *ddata)
@@ -1812,11 +1818,11 @@ static int sysc_probe(struct platform_device *pdev)
 	if (error)
 		return error;
 
-	pm_runtime_enable(ddata->dev);
 	error = sysc_init_module(ddata);
 	if (error)
 		goto unprepare;
 
+	pm_runtime_enable(ddata->dev);
 	error = pm_runtime_get_sync(ddata->dev);
 	if (error < 0) {
 		pm_runtime_put_noidle(ddata->dev);
-- 
2.21.0

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

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

* [PATCH 07/14] bus: ti-sysc: Allocate mdata as needed and do platform data based init later
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (5 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 06/14] bus: ti-sysc: Enable all clocks directly during init to read revision Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 08/14] bus: ti-sysc: Manage clocks for the interconnect target module in all cases Tony Lindgren
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

The platform data based init functions typically reset the interconnect
target module configure the registers. As we may need the interconnect
target module specific quirks configured based on the revision register,
we want to move the platform data based init to happen later.

Let's allocate mdata as needed so it's available for sysc_legacy_init()
that we call with module clocks enabled from sysc_init_module().

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 54 +++++++++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -75,6 +75,7 @@ struct sysc {
 	u32 module_size;
 	void __iomem *module_va;
 	int offsets[SYSC_MAX_REGS];
+	struct ti_sysc_module_data *mdata;
 	struct clk **clocks;
 	const char **clock_roles;
 	int nr_clocks;
@@ -1012,6 +1013,26 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
 	}
 }
 
+/*
+ * Note that pdata->init_module() typically does a reset first. After
+ * pdata->init_module() is done, PM runtime can be used for the interconnect
+ * target module.
+ */
+static int sysc_legacy_init(struct sysc *ddata)
+{
+	struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
+	int error;
+
+	if (!ddata->legacy_mode || !pdata || !pdata->init_module)
+		return 0;
+
+	error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie);
+	if (error == -EEXIST)
+		error = 0;
+
+	return error;
+}
+
 static int sysc_reset(struct sysc *ddata)
 {
 	int offset = ddata->offsets[SYSC_SYSCONFIG];
@@ -1070,10 +1091,15 @@ static int sysc_init_module(struct sysc *ddata)
 	ddata->revision = sysc_read_revision(ddata);
 	sysc_init_revision_quirks(ddata);
 
+	error = sysc_legacy_init(ddata);
+	if (error)
+		goto err_main_clocks;
+
 	error = sysc_reset(ddata);
 	if (error)
 		dev_err(ddata->dev, "Reset failed with %d\n", error);
 
+err_main_clocks:
 	if (manage_clocks)
 		sysc_disable_main_clocks(ddata);
 err_opt_clocks:
@@ -1715,28 +1741,26 @@ static const struct sysc_capabilities sysc_dra7_mcan = {
 static int sysc_init_pdata(struct sysc *ddata)
 {
 	struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
-	struct ti_sysc_module_data mdata;
-	int error = 0;
+	struct ti_sysc_module_data *mdata;
 
 	if (!pdata || !ddata->legacy_mode)
 		return 0;
 
-	mdata.name = ddata->legacy_mode;
-	mdata.module_pa = ddata->module_pa;
-	mdata.module_size = ddata->module_size;
-	mdata.offsets = ddata->offsets;
-	mdata.nr_offsets = SYSC_MAX_REGS;
-	mdata.cap = ddata->cap;
-	mdata.cfg = &ddata->cfg;
+	mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL);
+	if (!mdata)
+		return -ENOMEM;
 
-	if (!pdata->init_module)
-		return -ENODEV;
+	mdata->name = ddata->legacy_mode;
+	mdata->module_pa = ddata->module_pa;
+	mdata->module_size = ddata->module_size;
+	mdata->offsets = ddata->offsets;
+	mdata->nr_offsets = SYSC_MAX_REGS;
+	mdata->cap = ddata->cap;
+	mdata->cfg = &ddata->cfg;
 
-	error = pdata->init_module(ddata->dev, &mdata, &ddata->cookie);
-	if (error == -EEXIST)
-		error = 0;
+	ddata->mdata = mdata;
 
-	return error;
+	return 0;
 }
 
 static int sysc_init_match(struct sysc *ddata)
-- 
2.21.0

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

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

* [PATCH 08/14] bus: ti-sysc: Manage clocks for the interconnect target module in all cases
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (6 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 07/14] bus: ti-sysc: Allocate mdata as needed and do platform data based init later Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later Tony Lindgren
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

We are currently not managing interconnect target module clocks in the
for legacy platform data based case. This causes a problem for using the
platform data based functions when dropping the platform data for the
interconnect target module configuration.

To avoid a situation where we need to populate the main and optional
clocks also for the platform data based functions, let's just manage the
clocks directly in ti-sysc driver. This means that until the interconnect
target module confugration platform data is dropped our use count for
clk_enable() will be 2 instead of 1.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -783,10 +783,8 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 
 	if (ddata->legacy_mode) {
 		error = sysc_runtime_suspend_legacy(dev, ddata);
-		if (!error)
-			ddata->enabled = false;
-
-		return error;
+		if (error)
+			return error;
 	}
 
 	sysc_disable_main_clocks(ddata);
@@ -809,14 +807,6 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 	if (ddata->enabled)
 		return 0;
 
-	if (ddata->legacy_mode) {
-		error = sysc_runtime_resume_legacy(dev, ddata);
-		if (!error)
-			ddata->enabled = true;
-
-		return error;
-	}
-
 	if (sysc_opt_clks_needed(ddata)) {
 		error = sysc_enable_opt_clocks(ddata);
 		if (error)
@@ -825,13 +815,21 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 
 	error = sysc_enable_main_clocks(ddata);
 	if (error)
-		goto err_main_clocks;
+		goto err_opt_clocks;
+
+	if (ddata->legacy_mode) {
+		error = sysc_runtime_resume_legacy(dev, ddata);
+		if (error)
+			goto err_main_clocks;
+	}
 
 	ddata->enabled = true;
 
 	return 0;
 
 err_main_clocks:
+	sysc_disable_main_clocks(ddata);
+err_opt_clocks:
 	if (sysc_opt_clks_needed(ddata))
 		sysc_disable_opt_clocks(ddata);
 
-- 
2.21.0

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

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

* [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (7 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 08/14] bus: ti-sysc: Manage clocks for the interconnect target module in all cases Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-26 23:13   ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 10/14] bus: ti-sysc: Add support for early quirks based on register address Tony Lindgren
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

We should not do the reset until the clocks are enabled. Let's only init
restctrl in sysc_init_resets() and do the reset later on in sysc_reset().

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 61 ++++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 24 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -339,38 +339,18 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
 }
 
 /**
- * sysc_init_resets - reset module on init
+ * sysc_init_resets - init rstctrl reset line if configured
  * @ddata: device driver data
  *
- * A module can have both OCP softreset control and external rstctrl.
- * If more complicated rstctrl resets are needed, please handle these
- * directly from the child device driver and map only the module reset
- * for the parent interconnect target module device.
- *
- * Automatic reset of the module on init can be skipped with the
- * "ti,no-reset-on-init" device tree property.
+ * See sysc_rstctrl_reset_deassert().
  */
 static int sysc_init_resets(struct sysc *ddata)
 {
-	int error;
-
 	ddata->rsts =
 		devm_reset_control_array_get_optional_exclusive(ddata->dev);
 	if (IS_ERR(ddata->rsts))
 		return PTR_ERR(ddata->rsts);
 
-	if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
-		goto deassert;
-
-	error = reset_control_assert(ddata->rsts);
-	if (error)
-		return error;
-
-deassert:
-	error = reset_control_deassert(ddata->rsts);
-	if (error)
-		return error;
-
 	return 0;
 }
 
@@ -1031,14 +1011,47 @@ static int sysc_legacy_init(struct sysc *ddata)
 	return error;
 }
 
+/**
+ * sysc_rstctrl_reset_deassert - deassert rstctrl reset
+ * @ddata: device driver data
+ * @reset: reset before deassert
+ *
+ * A module can have both OCP softreset control and external rstctrl.
+ * If more complicated rstctrl resets are needed, please handle these
+ * directly from the child device driver and map only the module reset
+ * for the parent interconnect target module device.
+ *
+ * Automatic reset of the module on init can be skipped with the
+ * "ti,no-reset-on-init" device tree property.
+ */
+static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
+{
+	int error;
+
+	if (!ddata->rsts)
+		return 0;
+
+	if (reset) {
+		error = reset_control_assert(ddata->rsts);
+		if (error)
+			return error;
+	}
+
+	return reset_control_deassert(ddata->rsts);
+}
+
 static int sysc_reset(struct sysc *ddata)
 {
 	int offset = ddata->offsets[SYSC_SYSCONFIG];
-	int val;
+	int error, val;
 
 	if (ddata->legacy_mode || offset < 0 ||
 	    ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
-		return 0;
+		return sysc_rstctrl_reset_deassert(ddata, false);
+
+	error = sysc_rstctrl_reset_deassert(ddata, true);
+	if (error)
+		return error;
 
 	/*
 	 * Currently only support reset status in sysstatus.
-- 
2.21.0

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

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

* [PATCH 10/14] bus: ti-sysc: Add support for early quirks based on register address
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (8 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock Tony Lindgren
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

At least mcpdm needs an optional external clock enabled to function and
this clock typically comes from the PMIC. We can detect mcpdm based on
the interconnect target module address and set a quirk flag early.

To do this, let's initialize the clocks a bit later and add a new
function for sysc_init_early_quirks(). Note that we cannot yet enable
the early quirks for mcpdm until the optional external clocks are
handled in the in the following patch.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 46 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -959,6 +959,42 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 #endif
 };
 
+/*
+ * Early quirks based on module base and register offsets only that are
+ * needed before the module revision can be read
+ */
+static void sysc_init_early_quirks(struct sysc *ddata)
+{
+	const struct sysc_revision_quirk *q;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sysc_revision_quirks); i++) {
+		q = &sysc_revision_quirks[i];
+
+		if (!q->base)
+			continue;
+
+		if (q->base != ddata->module_pa)
+			continue;
+
+		if (q->rev_offset >= 0 &&
+		    q->rev_offset != ddata->offsets[SYSC_REVISION])
+			continue;
+
+		if (q->sysc_offset >= 0 &&
+		    q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
+			continue;
+
+		if (q->syss_offset >= 0 &&
+		    q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
+			continue;
+
+		ddata->name = q->name;
+		ddata->cfg.quirks |= q->quirks;
+	}
+}
+
+/* Quirks that also consider the revision register value */
 static void sysc_init_revision_quirks(struct sysc *ddata)
 {
 	const struct sysc_revision_quirk *q;
@@ -1825,10 +1861,6 @@ static int sysc_probe(struct platform_device *pdev)
 	if (error)
 		goto unprepare;
 
-	error = sysc_get_clocks(ddata);
-	if (error)
-		return error;
-
 	error = sysc_map_and_check_registers(ddata);
 	if (error)
 		goto unprepare;
@@ -1849,6 +1881,12 @@ static int sysc_probe(struct platform_device *pdev)
 	if (error)
 		goto unprepare;
 
+	sysc_init_early_quirks(ddata);
+
+	error = sysc_get_clocks(ddata);
+	if (error)
+		return error;
+
 	error = sysc_init_resets(ddata);
 	if (error)
 		return error;
-- 
2.21.0

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

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

* [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (9 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 10/14] bus: ti-sysc: Add support for early quirks based on register address Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-04-08 16:51   ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 12/14] bus: ti-sysc: Pass clockactivity quirk to platform functions Tony Lindgren
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

We cannot access mcpdm registers at all unless there is an optional pdmclk
configured. As this is currently only needed for mcpdm, let's check for
mcpdm in sysc_get_clocks(). If it turns out to be needed for other modules
too, we can add more flags to the quirks table for this.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c                 | 90 ++++++++++++++++++++++++++-
 include/linux/platform_data/ti-sysc.h |  1 +
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -47,7 +47,10 @@ enum sysc_clocks {
 	SYSC_MAX_CLOCKS,
 };
 
-static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", };
+static const char * const clock_names[SYSC_MAX_CLOCKS] = {
+	"fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4",
+	"opt5", "opt6", "opt7",
+};
 
 #define SYSC_IDLEMODE_MASK		3
 #define SYSC_CLOCKACTIVITY_MASK		3
@@ -129,6 +132,81 @@ static u32 sysc_read_revision(struct sysc *ddata)
 	return sysc_read(ddata, offset);
 }
 
+static int sysc_add_named_clock_from_child(struct sysc *ddata,
+					   const char *name,
+					   const char *optfck_name)
+{
+	struct device_node *np = ddata->dev->of_node;
+	struct device_node *child;
+	struct clk_lookup *cl;
+	struct clk *clock;
+	const char *n;
+
+	if (name)
+		n = name;
+	else
+		n = optfck_name;
+
+	/* Does the clock alias already exist? */
+	clock = of_clk_get_by_name(np, n);
+	if (!IS_ERR(clock)) {
+		clk_put(clock);
+
+		return 0;
+	}
+
+	child = of_get_next_available_child(np, NULL);
+	if (!child)
+		return -ENODEV;
+
+	clock = devm_get_clk_from_child(ddata->dev, child, name);
+	if (IS_ERR(clock))
+		return PTR_ERR(clock);
+
+	/*
+	 * Use clkdev_add() instead of clkdev_alloc() to avoid the MAX_DEV_ID
+	 * limit for clk_get(). If cl ever needs to be freed, it should be done
+	 * with clkdev_drop().
+	 */
+	cl = kcalloc(1, sizeof(*cl), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+
+	cl->con_id = n;
+	cl->dev_id = dev_name(ddata->dev);
+	cl->clk = clock;
+	clkdev_add(cl);
+
+	clk_put(clock);
+
+	return 0;
+}
+
+static int sysc_init_ext_opt_clock(struct sysc *ddata, const char *name)
+{
+	const char *optfck_name;
+	int error, index;
+
+	if (ddata->nr_clocks < SYSC_OPTFCK0)
+		index = SYSC_OPTFCK0;
+	else
+		index = ddata->nr_clocks;
+
+	if (name)
+		optfck_name = name;
+	else
+		optfck_name = clock_names[index];
+
+	error = sysc_add_named_clock_from_child(ddata, name, optfck_name);
+	if (error)
+		return error;
+
+	ddata->clock_roles[index] = optfck_name;
+	ddata->nr_clocks++;
+
+	return 0;
+}
+
 static int sysc_get_one_clock(struct sysc *ddata, const char *name)
 {
 	int error, i, index = -ENODEV;
@@ -200,6 +278,12 @@ static int sysc_get_clocks(struct sysc *ddata)
 	if (ddata->nr_clocks < 1)
 		return 0;
 
+	if ((ddata->cfg.quirks & SYSC_QUIRK_EXT_OPT_CLOCK)) {
+		error = sysc_init_ext_opt_clock(ddata, NULL);
+		if (error)
+			return error;
+	}
+
 	if (ddata->nr_clocks > SYSC_MAX_CLOCKS) {
 		dev_err(ddata->dev, "too many clocks for %pOF\n", np);
 
@@ -901,6 +985,10 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
 		   SYSC_QUIRK_LEGACY_IDLE),
 
+	/* Quirks that need to be set based on the module address */
+	SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,
+		   SYSC_QUIRK_EXT_OPT_CLOCK),
+
 #ifdef DEBUG
 	SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
 	SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h
--- a/include/linux/platform_data/ti-sysc.h
+++ b/include/linux/platform_data/ti-sysc.h
@@ -46,6 +46,7 @@ struct sysc_regbits {
 	s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_EXT_OPT_CLOCK	BIT(10)
 #define SYSC_QUIRK_LEGACY_IDLE		BIT(9)
 #define SYSC_QUIRK_RESET_STATUS		BIT(8)
 #define SYSC_QUIRK_NO_IDLE		BIT(7)
-- 
2.21.0

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

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

* [PATCH 12/14] bus: ti-sysc: Pass clockactivity quirk to platform functions
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (10 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 13/14] bus: ti-sysc: Handle swsup idle mode quirks Tony Lindgren
  2019-03-25 21:58 ` [PATCH 14/14] bus: ti-sysc: Detect DMIC for debugging Tony Lindgren
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

We already have the clockactivity quirk set for some modules like i2c,
timers and smartreflex. But we're not passing it to the platform functions
yet. Let's start doing that in preparation of dropping interconnect target
module platform data in favor of device tree based data.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/omap_hwmod.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3681,6 +3681,8 @@ int omap_hwmod_init_module(struct device *dev,
 		oh->flags |= HWMOD_INIT_NO_IDLE;
 	if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
 		oh->flags |= HWMOD_INIT_NO_RESET;
+	if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT)
+		oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT;
 
 	error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
 					rev_offs, sysc_offs, syss_offs,
-- 
2.21.0

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

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

* [PATCH 13/14] bus: ti-sysc: Handle swsup idle mode quirks
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (11 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 12/14] bus: ti-sysc: Pass clockactivity quirk to platform functions Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  2019-03-25 21:58 ` [PATCH 14/14] bus: ti-sysc: Detect DMIC for debugging Tony Lindgren
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

In preparation of dropping interconnect target module platform data in
favor of devicetree based data, we must pass swsup idle quirks to the
platform data functions.

For now, let's only tag the UART modules with the SWSUP_SIDLE_ACT quirk.
The other modules will get tagged with swsup quirks as we drop the
platform data and test the changes.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/omap_hwmod.c      | 6 ++++++
 drivers/bus/ti-sysc.c                 | 6 +++---
 include/linux/platform_data/ti-sysc.h | 3 +++
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3683,6 +3683,12 @@ int omap_hwmod_init_module(struct device *dev,
 		oh->flags |= HWMOD_INIT_NO_RESET;
 	if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT)
 		oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT;
+	if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE)
+		oh->flags |= HWMOD_SWSUP_SIDLE;
+	if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT)
+		oh->flags |= HWMOD_SWSUP_SIDLE_ACT;
+	if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
+		oh->flags |= HWMOD_SWSUP_MSTANDBY;
 
 	error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
 					rev_offs, sysc_offs, syss_offs,
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -978,12 +978,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 	SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
 		   0),
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
-		   SYSC_QUIRK_LEGACY_IDLE),
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 	/* Uarts on omap4 and later */
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
-		   SYSC_QUIRK_LEGACY_IDLE),
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
-		   SYSC_QUIRK_LEGACY_IDLE),
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 
 	/* Quirks that need to be set based on the module address */
 	SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h
--- a/include/linux/platform_data/ti-sysc.h
+++ b/include/linux/platform_data/ti-sysc.h
@@ -46,6 +46,9 @@ struct sysc_regbits {
 	s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_SWSUP_MSTANDBY	BIT(13)
+#define SYSC_QUIRK_SWSUP_SIDLE_ACT	BIT(12)
+#define SYSC_QUIRK_SWSUP_SIDLE		BIT(11)
 #define SYSC_QUIRK_EXT_OPT_CLOCK	BIT(10)
 #define SYSC_QUIRK_LEGACY_IDLE		BIT(9)
 #define SYSC_QUIRK_RESET_STATUS		BIT(8)
-- 
2.21.0

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

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

* [PATCH 14/14] bus: ti-sysc: Detect DMIC for debugging
  2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
                   ` (12 preceding siblings ...)
  2019-03-25 21:58 ` [PATCH 13/14] bus: ti-sysc: Handle swsup idle mode quirks Tony Lindgren
@ 2019-03-25 21:58 ` Tony Lindgren
  13 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-25 21:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

Detect DMIC to see what we have connected if config DEBUG is enabled.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -999,6 +999,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 		   0xffff00f0, 0),
 	SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
 	SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0),
+	SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
 	SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
 	SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
 	SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
-- 
2.21.0

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

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

* Re: [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-25 21:58 ` [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later Tony Lindgren
@ 2019-03-26 23:13   ` Tony Lindgren
  2019-03-26 23:22     ` Suman Anna
  0 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-26 23:13 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

* Tony Lindgren <tony@atomide.com> [190325 22:00]:
> We should not do the reset until the clocks are enabled. Let's only init
> restctrl in sysc_init_resets() and do the reset later on in sysc_reset().
...

>  static int sysc_reset(struct sysc *ddata)
>  {
>  	int offset = ddata->offsets[SYSC_SYSCONFIG];
> -	int val;
> +	int error, val;
>  
>  	if (ddata->legacy_mode || offset < 0 ||
>  	    ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
> -		return 0;
> +		return sysc_rstctrl_reset_deassert(ddata, false);
> +
> +	error = sysc_rstctrl_reset_deassert(ddata, true);
> +	if (error)
> +		return error;

This change is wrong, we need to deassert rstctrl reset before
we enable clocks, not after. Updated version below.

Regards,

Tony

8< --------------------
From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Thu, 21 Mar 2019 11:00:21 -0700
Subject: [PATCH] bus: ti-sysc: Move rstctrl reset to happen later

We can do the rsstctrl a bit later, but need to deassert rstctrl reset
before the clocks are enabled if asserted. Let's only init restctrl
in sysc_init_resets() and do the reset later on just before we enable
the device clocks.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 61 +++++++++++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -339,38 +339,18 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
 }
 
 /**
- * sysc_init_resets - reset module on init
+ * sysc_init_resets - init rstctrl reset line if configured
  * @ddata: device driver data
  *
- * A module can have both OCP softreset control and external rstctrl.
- * If more complicated rstctrl resets are needed, please handle these
- * directly from the child device driver and map only the module reset
- * for the parent interconnect target module device.
- *
- * Automatic reset of the module on init can be skipped with the
- * "ti,no-reset-on-init" device tree property.
+ * See sysc_rstctrl_reset_deassert().
  */
 static int sysc_init_resets(struct sysc *ddata)
 {
-	int error;
-
 	ddata->rsts =
 		devm_reset_control_array_get_optional_exclusive(ddata->dev);
 	if (IS_ERR(ddata->rsts))
 		return PTR_ERR(ddata->rsts);
 
-	if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
-		goto deassert;
-
-	error = reset_control_assert(ddata->rsts);
-	if (error)
-		return error;
-
-deassert:
-	error = reset_control_deassert(ddata->rsts);
-	if (error)
-		return error;
-
 	return 0;
 }
 
@@ -1031,6 +1011,35 @@ static int sysc_legacy_init(struct sysc *ddata)
 	return error;
 }
 
+/**
+ * sysc_rstctrl_reset_deassert - deassert rstctrl reset
+ * @ddata: device driver data
+ * @reset: reset before deassert
+ *
+ * A module can have both OCP softreset control and external rstctrl.
+ * If more complicated rstctrl resets are needed, please handle these
+ * directly from the child device driver and map only the module reset
+ * for the parent interconnect target module device.
+ *
+ * Automatic reset of the module on init can be skipped with the
+ * "ti,no-reset-on-init" device tree property.
+ */
+static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
+{
+	int error;
+
+	if (!ddata->rsts)
+		return 0;
+
+	if (reset) {
+		error = reset_control_assert(ddata->rsts);
+		if (error)
+			return error;
+	}
+
+	return reset_control_deassert(ddata->rsts);
+}
+
 static int sysc_reset(struct sysc *ddata)
 {
 	int offset = ddata->offsets[SYSC_SYSCONFIG];
@@ -1071,6 +1080,14 @@ static int sysc_init_module(struct sysc *ddata)
 {
 	int error = 0;
 	bool manage_clocks = true;
+	bool reset = true;
+
+	if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+		reset = false;
+
+	error = sysc_rstctrl_reset_deassert(ddata, reset);
+	if (error)
+		return error;
 
 	if (ddata->cfg.quirks &
 	    (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))
-- 
2.21.0

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

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

* Re: [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-26 23:13   ` Tony Lindgren
@ 2019-03-26 23:22     ` Suman Anna
  2019-03-26 23:40       ` Tony Lindgren
  0 siblings, 1 reply; 23+ messages in thread
From: Suman Anna @ 2019-03-26 23:22 UTC (permalink / raw)
  To: Tony Lindgren, linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

Hi Tony,

On 3/26/19 6:13 PM, Tony Lindgren wrote:
> * Tony Lindgren <tony@atomide.com> [190325 22:00]:
>> We should not do the reset until the clocks are enabled. Let's only init
>> restctrl in sysc_init_resets() and do the reset later on in sysc_reset().
> ...
> 
>>  static int sysc_reset(struct sysc *ddata)
>>  {
>>  	int offset = ddata->offsets[SYSC_SYSCONFIG];
>> -	int val;
>> +	int error, val;
>>  
>>  	if (ddata->legacy_mode || offset < 0 ||
>>  	    ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
>> -		return 0;
>> +		return sysc_rstctrl_reset_deassert(ddata, false);
>> +
>> +	error = sysc_rstctrl_reset_deassert(ddata, true);
>> +	if (error)
>> +		return error;
> 
> This change is wrong, we need to deassert rstctrl reset before
> we enable clocks, not after. Updated version below.

Hmm, are you envisioning the SYSC reset (OCP SoftReset) here or the PRCM
RSTCTRL hardresets here? The latter in general requires the clocks to be
running first (module won't be in ready status until you deassert the
hardresets with clocks running). You can look up the Warm-reset or
Cold-reset sequences in the TRMs for any of the processors.

I am working on preparing the next version of PRUSS patches with ti-sysc
on AM33xx/AM437x/AM57xx platforms, so will pick up these patches for my
testing.

regards
Suman

> 
> Regards,
> 
> Tony
> 
> 8< --------------------
> From tony Mon Sep 17 00:00:00 2001
> From: Tony Lindgren <tony@atomide.com>
> Date: Thu, 21 Mar 2019 11:00:21 -0700
> Subject: [PATCH] bus: ti-sysc: Move rstctrl reset to happen later
> 
> We can do the rsstctrl a bit later, but need to deassert rstctrl reset
> before the clocks are enabled if asserted. Let's only init restctrl
> in sysc_init_resets() and do the reset later on just before we enable
> the device clocks.
> 
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  drivers/bus/ti-sysc.c | 61 +++++++++++++++++++++++++++----------------
>  1 file changed, 39 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
> --- a/drivers/bus/ti-sysc.c
> +++ b/drivers/bus/ti-sysc.c
> @@ -339,38 +339,18 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
>  }
>  
>  /**
> - * sysc_init_resets - reset module on init
> + * sysc_init_resets - init rstctrl reset line if configured
>   * @ddata: device driver data
>   *
> - * A module can have both OCP softreset control and external rstctrl.
> - * If more complicated rstctrl resets are needed, please handle these
> - * directly from the child device driver and map only the module reset
> - * for the parent interconnect target module device.
> - *
> - * Automatic reset of the module on init can be skipped with the
> - * "ti,no-reset-on-init" device tree property.
> + * See sysc_rstctrl_reset_deassert().
>   */
>  static int sysc_init_resets(struct sysc *ddata)
>  {
> -	int error;
> -
>  	ddata->rsts =
>  		devm_reset_control_array_get_optional_exclusive(ddata->dev);
>  	if (IS_ERR(ddata->rsts))
>  		return PTR_ERR(ddata->rsts);
>  
> -	if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
> -		goto deassert;
> -
> -	error = reset_control_assert(ddata->rsts);
> -	if (error)
> -		return error;
> -
> -deassert:
> -	error = reset_control_deassert(ddata->rsts);
> -	if (error)
> -		return error;
> -
>  	return 0;
>  }
>  
> @@ -1031,6 +1011,35 @@ static int sysc_legacy_init(struct sysc *ddata)
>  	return error;
>  }
>  
> +/**
> + * sysc_rstctrl_reset_deassert - deassert rstctrl reset
> + * @ddata: device driver data
> + * @reset: reset before deassert
> + *
> + * A module can have both OCP softreset control and external rstctrl.
> + * If more complicated rstctrl resets are needed, please handle these
> + * directly from the child device driver and map only the module reset
> + * for the parent interconnect target module device.
> + *
> + * Automatic reset of the module on init can be skipped with the
> + * "ti,no-reset-on-init" device tree property.
> + */
> +static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
> +{
> +	int error;
> +
> +	if (!ddata->rsts)
> +		return 0;
> +
> +	if (reset) {
> +		error = reset_control_assert(ddata->rsts);
> +		if (error)
> +			return error;
> +	}
> +
> +	return reset_control_deassert(ddata->rsts);
> +}
> +
>  static int sysc_reset(struct sysc *ddata)
>  {
>  	int offset = ddata->offsets[SYSC_SYSCONFIG];
> @@ -1071,6 +1080,14 @@ static int sysc_init_module(struct sysc *ddata)
>  {
>  	int error = 0;
>  	bool manage_clocks = true;
> +	bool reset = true;
> +
> +	if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
> +		reset = false;
> +
> +	error = sysc_rstctrl_reset_deassert(ddata, reset);
> +	if (error)
> +		return error;
>  
>  	if (ddata->cfg.quirks &
>  	    (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))
> 


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

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

* Re: [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-26 23:22     ` Suman Anna
@ 2019-03-26 23:40       ` Tony Lindgren
  2019-03-27 16:27         ` Suman Anna
  0 siblings, 1 reply; 23+ messages in thread
From: Tony Lindgren @ 2019-03-26 23:40 UTC (permalink / raw)
  To: Suman Anna
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Keerthy, linux-kernel,
	Peter Ujfalusi, Faiz Abbas, Greg Kroah-Hartman, linux-omap,
	linux-arm-kernel, Roger Quadros

Hi,

* Suman Anna <s-anna@ti.com> [190326 23:22]:
> On 3/26/19 6:13 PM, Tony Lindgren wrote:
> Hmm, are you envisioning the SYSC reset (OCP SoftReset) here or the PRCM
> RSTCTRL hardresets here? The latter in general requires the clocks to be
> running first (module won't be in ready status until you deassert the
> hardresets with clocks running). You can look up the Warm-reset or
> Cold-reset sequences in the TRMs for any of the processors.

That's for rstctrl. I just did a quick test with my earlier
reset-simple patch and I noticed sgx on am33xx produces a
clock error unless we deassert it's rstrctrl before enabling
clocks first:

gfx-l3-clkctrl:0004:0: failed to enable

> I am working on preparing the next version of PRUSS patches with ti-sysc
> on AM33xx/AM437x/AM57xx platforms, so will pick up these patches for my
> testing.

OK great, yes please check and test with your rstctrl use case.
I guess you still need to use the reset-simple patch for now
until we have a proper prm rstctrl driver.

Note that you probably also want to leave out the struct
omap_hwmod data from omap_hwmod_*_data.c files with rstctrl
entries.

Regards,

Tony

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

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

* Re: [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-26 23:40       ` Tony Lindgren
@ 2019-03-27 16:27         ` Suman Anna
  2019-03-27 18:37           ` Tony Lindgren
  0 siblings, 1 reply; 23+ messages in thread
From: Suman Anna @ 2019-03-27 16:27 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Keerthy, linux-kernel,
	Peter Ujfalusi, Faiz Abbas, Greg Kroah-Hartman, linux-omap,
	linux-arm-kernel, Roger Quadros

Hi Tony,

On 3/26/19 6:40 PM, Tony Lindgren wrote:
> Hi,
> 
> * Suman Anna <s-anna@ti.com> [190326 23:22]:
>> On 3/26/19 6:13 PM, Tony Lindgren wrote:
>> Hmm, are you envisioning the SYSC reset (OCP SoftReset) here or the PRCM
>> RSTCTRL hardresets here? The latter in general requires the clocks to be
>> running first (module won't be in ready status until you deassert the
>> hardresets with clocks running). You can look up the Warm-reset or
>> Cold-reset sequences in the TRMs for any of the processors.
> 
> That's for rstctrl. I just did a quick test with my earlier
> reset-simple patch and I noticed sgx on am33xx produces a
> clock error unless we deassert it's rstrctrl before enabling
> clocks first:
> 
> gfx-l3-clkctrl:0004:0: failed to enable

Yeah, and I see a similar one across the other modules controlled by
RSTCTRL bits for me as well - MMUs, PRUSS etc. This is because you can
only check the module ready status in _omap4_clkctrl_clk_enable() only
both after the clocks are turned on and resets are deasserted. That
check will always fail with rstctrl asserted. The omap_hwmod code does
use the reset status checks for bailing out, but that stuff is not
present in clkctrl code and can only be achieved by adding a
CLKF_NO_IDLEST (somewhat misnamed) to the corresponding clkctrl atm.

See [1] for AM33xx SGX. I will be posting some of these once I check the
behavior.

> 
>> I am working on preparing the next version of PRUSS patches with ti-sysc
>> on AM33xx/AM437x/AM57xx platforms, so will pick up these patches for my
>> testing.
> 
> OK great, yes please check and test with your rstctrl use case.
> I guess you still need to use the reset-simple patch for now
> until we have a proper prm rstctrl driver.
> 
> Note that you probably also want to leave out the struct
> omap_hwmod data from omap_hwmod_*_data.c files with rstctrl
> entries.

You mean no hwmod entries at all, or hwmod entries with no rstctrl data?

regards
Suman

[1]
http://git.ti.com/gitweb/?p=ti-linux-kernel/ti-linux-kernel.git;a=commitdiff;h=536d660714e98bdb7f96e5990a095283e52e4d8a



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

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

* Re: [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later
  2019-03-27 16:27         ` Suman Anna
@ 2019-03-27 18:37           ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-03-27 18:37 UTC (permalink / raw)
  To: Suman Anna
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Keerthy, linux-kernel,
	Peter Ujfalusi, Faiz Abbas, Greg Kroah-Hartman, linux-omap,
	linux-arm-kernel, Roger Quadros

* Suman Anna <s-anna@ti.com> [190327 16:27]:
> On 3/26/19 6:40 PM, Tony Lindgren wrote:
> > That's for rstctrl. I just did a quick test with my earlier
> > reset-simple patch and I noticed sgx on am33xx produces a
> > clock error unless we deassert it's rstrctrl before enabling
> > clocks first:
> > 
> > gfx-l3-clkctrl:0004:0: failed to enable
> 
> Yeah, and I see a similar one across the other modules controlled by
> RSTCTRL bits for me as well - MMUs, PRUSS etc. This is because you can
> only check the module ready status in _omap4_clkctrl_clk_enable() only
> both after the clocks are turned on and resets are deasserted. That
> check will always fail with rstctrl asserted. The omap_hwmod code does
> use the reset status checks for bailing out, but that stuff is not
> present in clkctrl code and can only be achieved by adding a
> CLKF_NO_IDLEST (somewhat misnamed) to the corresponding clkctrl atm.

Sounds like on ti-sysc init we should just deassert the rstctrl if
asserted, then enable clocks, and then read the revision.

Then if we actually need to toggle rstctrl reset, that can be added
with later patches. But with reset driver, the device IP handling
device driver(s) should probably manage the rstctrl bits directly.

> See [1] for AM33xx SGX. I will be posting some of these once I check the
> behavior.

Yeah OK sounds like we can avoid those issues by deasserting the
module related rstctrl bit before enabling the clocks. Then
deal with resets later if needed.

> > Note that you probably also want to leave out the struct
> > omap_hwmod data from omap_hwmod_*_data.c files with rstctrl
> > entries.
> 
> You mean no hwmod entries at all, or hwmod entries with no rstctrl data?

Except for the lack of rstctrl reset driver, struct hwmod_data
entries should only be needed for the few cases where we're not
yet handling some oh->flags quirks. I think most of the remaining
unhandled quirks are for omap2 and 3.

Regards,

Tony


> [1]
> http://git.ti.com/gitweb/?p=ti-linux-kernel/ti-linux-kernel.git;a=commitdiff;h=536d660714e98bdb7f96e5990a095283e52e4d8a
> 
> 

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

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

* Re: [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init
  2019-03-25 21:58 ` [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init Tony Lindgren
@ 2019-03-31  6:41   ` Rob Herring
  0 siblings, 0 replies; 23+ messages in thread
From: Rob Herring @ 2019-03-31  6:41 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Nishanth Menon, Tero Kristo, ,
	Dave Gerlach, Keerthy, linux-kernel, Peter Ujfalusi, devicetree,
	Faiz Abbas, Greg Kroah-Hartman, linux-omap, linux-arm-kernel,
	Roger Quadros

On Mon, 25 Mar 2019 14:58:37 -0700, Tony Lindgren wrote:
> We have ti,no-idle in use in addition to ti,no-idle-on-init but we're
> missing handling for it in the ti-sysc interconnect target module driver.
> 
> Let's also group the idle defines together and update the binding
> documentation for it.
> 
> Cc: Rob Herring <robh@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  Documentation/devicetree/bindings/bus/ti-sysc.txt | 2 ++
>  arch/arm/mach-omap2/omap_hwmod.c                  | 2 ++
>  drivers/bus/ti-sysc.c                             | 5 ++++-
>  include/linux/platform_data/ti-sysc.h             | 5 +++--
>  4 files changed, 11 insertions(+), 3 deletions(-)
> 

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


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

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

* Re: [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks
  2019-03-25 21:58 ` [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks Tony Lindgren
@ 2019-04-03 18:00   ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-04-03 18:00 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

* Tony Lindgren <tony@atomide.com> [190325 22:00]:
> Let's also add error handling to shut down already enabled clocks
> while at it.
...

> --- a/drivers/bus/ti-sysc.c
> +++ b/drivers/bus/ti-sysc.c
> +err_disable:
> +	for (; i >= 0; i--) {
> +		clock = ddata->clocks[i];
> +
> +		/* Main clocks may not have ick */
> +		if (IS_ERR_OR_NULL(clock))
> +			continue;
> +
> +		clk_disable(clock);
> +	}
> +
> +	return error;
> +}

We need to ignore the current clock on error above
and use for (i--; i >= 0; i--) instead. The same for
sysc_enable_opt_clocks().

Updated patch below.

Regards,

Tony

8< --------------------
From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Thu, 21 Mar 2019 11:00:21 -0700
Subject: [PATCH] bus: ti-sysc: Add separate functions for handling clocks

At least McPDM module depends on an external optional clock to be
usable. To make handling of the McPDM clock easier in the following
patches, let's add separate functions for handling the main clocks
and the optional clocks.

Let's also add error handling to shut down already enabled clocks
while at it.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c | 141 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 123 insertions(+), 18 deletions(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -231,6 +231,112 @@ static int sysc_get_clocks(struct sysc *ddata)
 	return 0;
 }
 
+static int sysc_enable_main_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i, error;
+
+	if (!ddata->clocks)
+		return 0;
+
+	for (i = 0; i < SYSC_OPTFCK0; i++) {
+		clock = ddata->clocks[i];
+
+		/* Main clocks may not have ick */
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		error = clk_enable(clock);
+		if (error)
+			goto err_disable;
+	}
+
+	return 0;
+
+err_disable:
+	for (i--; i >= 0; i--) {
+		clock = ddata->clocks[i];
+
+		/* Main clocks may not have ick */
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+
+	return error;
+}
+
+static void sysc_disable_main_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i;
+
+	if (!ddata->clocks)
+		return;
+
+	for (i = 0; i < SYSC_OPTFCK0; i++) {
+		clock = ddata->clocks[i];
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+}
+
+static int sysc_enable_opt_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i, error;
+
+	if (!ddata->clocks)
+		return 0;
+
+	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+		clock = ddata->clocks[i];
+
+		/* Assume no holes for opt clocks */
+		if (IS_ERR_OR_NULL(clock))
+			return 0;
+
+		error = clk_enable(clock);
+		if (error)
+			goto err_disable;
+	}
+
+	return 0;
+
+err_disable:
+	for (i--; i >= 0; i--) {
+		clock = ddata->clocks[i];
+		if (IS_ERR_OR_NULL(clock))
+			continue;
+
+		clk_disable(clock);
+	}
+
+	return error;
+}
+
+static void sysc_disable_opt_clocks(struct sysc *ddata)
+{
+	struct clk *clock;
+	int i;
+
+	if (!ddata->clocks)
+		return;
+
+	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+		clock = ddata->clocks[i];
+
+		/* Assume no holes for opt clocks */
+		if (IS_ERR_OR_NULL(clock))
+			return;
+
+		clk_disable(clock);
+	}
+}
+
 /**
  * sysc_init_resets - reset module on init
  * @ddata: device driver data
@@ -667,7 +773,7 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
 static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 {
 	struct sysc *ddata;
-	int error = 0, i;
+	int error = 0;
 
 	ddata = dev_get_drvdata(dev);
 
@@ -682,15 +788,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 		return error;
 	}
 
-	for (i = 0; i < ddata->nr_clocks; i++) {
-		if (IS_ERR_OR_NULL(ddata->clocks[i]))
-			continue;
+	sysc_disable_main_clocks(ddata);
 
-		if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-			break;
-
-		clk_disable(ddata->clocks[i]);
-	}
+	if (sysc_opt_clks_needed(ddata))
+		sysc_disable_opt_clocks(ddata);
 
 	ddata->enabled = false;
 
@@ -700,7 +801,7 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
 static int __maybe_unused sysc_runtime_resume(struct device *dev)
 {
 	struct sysc *ddata;
-	int error = 0, i;
+	int error = 0;
 
 	ddata = dev_get_drvdata(dev);
 
@@ -715,20 +816,24 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
 		return error;
 	}
 
-	for (i = 0; i < ddata->nr_clocks; i++) {
-		if (IS_ERR_OR_NULL(ddata->clocks[i]))
-			continue;
-
-		if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-			break;
-
-		error = clk_enable(ddata->clocks[i]);
+	if (sysc_opt_clks_needed(ddata)) {
+		error = sysc_enable_opt_clocks(ddata);
 		if (error)
 			return error;
 	}
 
+	error = sysc_enable_main_clocks(ddata);
+	if (error)
+		goto err_main_clocks;
+
 	ddata->enabled = true;
 
+	return 0;
+
+err_main_clocks:
+	if (sysc_opt_clks_needed(ddata))
+		sysc_disable_opt_clocks(ddata);
+
 	return error;
 }
 
-- 
2.21.0

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

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

* Re: [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock
  2019-03-25 21:58 ` [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock Tony Lindgren
@ 2019-04-08 16:51   ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2019-04-08 16:51 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Tero Kristo, Dave Gerlach, Greg Kroah-Hartman,
	linux-kernel, Peter Ujfalusi, Faiz Abbas, Keerthy,
	linux-arm-kernel, Roger Quadros

* Tony Lindgren <tony@atomide.com> [190325 22:00]:
> @@ -200,6 +278,12 @@ static int sysc_get_clocks(struct sysc *ddata)
>  	if (ddata->nr_clocks < 1)
>  		return 0;
>  
> +	if ((ddata->cfg.quirks & SYSC_QUIRK_EXT_OPT_CLOCK)) {
> +		error = sysc_init_ext_opt_clock(ddata, NULL);
> +		if (error)
> +			return error;
> +	}
> +

After some more testing with mcpdm, these flags are not enough
for dropping the platform data. We need to use the same flags
as in platform data, and add SYSC_QUIRK_NO_RESET_ON_INIT and
SYSC_QUIRK_SWSUP_SIDLE to avoid patching this again. Updated
patch below.

Regards,

Tony

8< ----------------------
From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Thu, 21 Mar 2019 11:00:21 -0700
Subject: [PATCH] bus: ti-sysc: Add quirk handling for external optional
 functional clock

We cannot access mcpdm registers at all unless there is an optional pdmclk
configured. As this is currently only needed for mcpdm, let's check for
mcpdm in sysc_get_clocks(). If it turns out to be needed for other modules
too, we can add more flags to the quirks table for this.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/bus/ti-sysc.c                 | 91 ++++++++++++++++++++++++++-
 include/linux/platform_data/ti-sysc.h |  1 +
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -47,7 +47,10 @@ enum sysc_clocks {
 	SYSC_MAX_CLOCKS,
 };
 
-static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", };
+static const char * const clock_names[SYSC_MAX_CLOCKS] = {
+	"fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4",
+	"opt5", "opt6", "opt7",
+};
 
 #define SYSC_IDLEMODE_MASK		3
 #define SYSC_CLOCKACTIVITY_MASK		3
@@ -129,6 +132,81 @@ static u32 sysc_read_revision(struct sysc *ddata)
 	return sysc_read(ddata, offset);
 }
 
+static int sysc_add_named_clock_from_child(struct sysc *ddata,
+					   const char *name,
+					   const char *optfck_name)
+{
+	struct device_node *np = ddata->dev->of_node;
+	struct device_node *child;
+	struct clk_lookup *cl;
+	struct clk *clock;
+	const char *n;
+
+	if (name)
+		n = name;
+	else
+		n = optfck_name;
+
+	/* Does the clock alias already exist? */
+	clock = of_clk_get_by_name(np, n);
+	if (!IS_ERR(clock)) {
+		clk_put(clock);
+
+		return 0;
+	}
+
+	child = of_get_next_available_child(np, NULL);
+	if (!child)
+		return -ENODEV;
+
+	clock = devm_get_clk_from_child(ddata->dev, child, name);
+	if (IS_ERR(clock))
+		return PTR_ERR(clock);
+
+	/*
+	 * Use clkdev_add() instead of clkdev_alloc() to avoid the MAX_DEV_ID
+	 * limit for clk_get(). If cl ever needs to be freed, it should be done
+	 * with clkdev_drop().
+	 */
+	cl = kcalloc(1, sizeof(*cl), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+
+	cl->con_id = n;
+	cl->dev_id = dev_name(ddata->dev);
+	cl->clk = clock;
+	clkdev_add(cl);
+
+	clk_put(clock);
+
+	return 0;
+}
+
+static int sysc_init_ext_opt_clock(struct sysc *ddata, const char *name)
+{
+	const char *optfck_name;
+	int error, index;
+
+	if (ddata->nr_clocks < SYSC_OPTFCK0)
+		index = SYSC_OPTFCK0;
+	else
+		index = ddata->nr_clocks;
+
+	if (name)
+		optfck_name = name;
+	else
+		optfck_name = clock_names[index];
+
+	error = sysc_add_named_clock_from_child(ddata, name, optfck_name);
+	if (error)
+		return error;
+
+	ddata->clock_roles[index] = optfck_name;
+	ddata->nr_clocks++;
+
+	return 0;
+}
+
 static int sysc_get_one_clock(struct sysc *ddata, const char *name)
 {
 	int error, i, index = -ENODEV;
@@ -200,6 +278,12 @@ static int sysc_get_clocks(struct sysc *ddata)
 	if (ddata->nr_clocks < 1)
 		return 0;
 
+	if ((ddata->cfg.quirks & SYSC_QUIRK_EXT_OPT_CLOCK)) {
+		error = sysc_init_ext_opt_clock(ddata, NULL);
+		if (error)
+			return error;
+	}
+
 	if (ddata->nr_clocks > SYSC_MAX_CLOCKS) {
 		dev_err(ddata->dev, "too many clocks for %pOF\n", np);
 
@@ -901,6 +985,11 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
 		   SYSC_QUIRK_LEGACY_IDLE),
 
+	/* Quirks that need to be set based on the module address */
+	SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,
+		   SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
+		   SYSC_QUIRK_SWSUP_SIDLE),
+
 #ifdef DEBUG
 	SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
 	SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h
--- a/include/linux/platform_data/ti-sysc.h
+++ b/include/linux/platform_data/ti-sysc.h
@@ -46,6 +46,7 @@ struct sysc_regbits {
 	s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_EXT_OPT_CLOCK	BIT(10)
 #define SYSC_QUIRK_LEGACY_IDLE		BIT(9)
 #define SYSC_QUIRK_RESET_STATUS		BIT(8)
 #define SYSC_QUIRK_NO_IDLE		BIT(7)
-- 
2.21.0

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

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

end of thread, other threads:[~2019-04-08 16:51 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-25 21:58 [PATCH 00/14] ti-sysc changes to probe devices with dts data only Tony Lindgren
2019-03-25 21:58 ` [PATCH 01/14] bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated Tony Lindgren
2019-03-25 21:58 ` [PATCH 02/14] bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init Tony Lindgren
2019-03-31  6:41   ` Rob Herring
2019-03-25 21:58 ` [PATCH 03/14] bus: ti-sysc: Make functions static Tony Lindgren
2019-03-25 21:58 ` [PATCH 04/14] bus: ti-sysc: Move legacy platform data idling into separate functions Tony Lindgren
2019-03-25 21:58 ` [PATCH 05/14] bus: ti-sysc: Add separate functions for handling clocks Tony Lindgren
2019-04-03 18:00   ` Tony Lindgren
2019-03-25 21:58 ` [PATCH 06/14] bus: ti-sysc: Enable all clocks directly during init to read revision Tony Lindgren
2019-03-25 21:58 ` [PATCH 07/14] bus: ti-sysc: Allocate mdata as needed and do platform data based init later Tony Lindgren
2019-03-25 21:58 ` [PATCH 08/14] bus: ti-sysc: Manage clocks for the interconnect target module in all cases Tony Lindgren
2019-03-25 21:58 ` [PATCH 09/14] bus: ti-sysc: Move rstctrl reset to happen later Tony Lindgren
2019-03-26 23:13   ` Tony Lindgren
2019-03-26 23:22     ` Suman Anna
2019-03-26 23:40       ` Tony Lindgren
2019-03-27 16:27         ` Suman Anna
2019-03-27 18:37           ` Tony Lindgren
2019-03-25 21:58 ` [PATCH 10/14] bus: ti-sysc: Add support for early quirks based on register address Tony Lindgren
2019-03-25 21:58 ` [PATCH 11/14] bus: ti-sysc: Add quirk handling for external optional functional clock Tony Lindgren
2019-04-08 16:51   ` Tony Lindgren
2019-03-25 21:58 ` [PATCH 12/14] bus: ti-sysc: Pass clockactivity quirk to platform functions Tony Lindgren
2019-03-25 21:58 ` [PATCH 13/14] bus: ti-sysc: Handle swsup idle mode quirks Tony Lindgren
2019-03-25 21:58 ` [PATCH 14/14] bus: ti-sysc: Detect DMIC for debugging Tony Lindgren

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