linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] introduce support for early platform drivers
@ 2018-05-11 16:20 Bartosz Golaszewski
  2018-05-11 16:20 ` [PATCH 01/12] platform/early: add a new field to struct device Bartosz Golaszewski
                   ` (13 more replies)
  0 siblings, 14 replies; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

This series is a follow-up to the RFC[1] posted a couple days ago.

NOTE: this series applies on top of my recent patches[2] that move the previous
implementation of early platform devices to arch/sh.

Problem:

Certain class of devices, such as timers, certain clock drivers and irq chip
drivers need to be probed early in the boot sequence. The currently preferred
approach is using one of the OF_DECLARE() macros. This however does not create
a platform device which has many drawbacks - such as not being able to use
devres routines, dev_ log functions or no way of deferring the init OF function
if some other resources are missing.

For drivers that use both platform drivers and OF_DECLARE the situation is even
more complicated as the code needs to take into account that there can possibly
be no struct device present. For a specific use case that we're having problems
with, please refer to the recent DaVinci common-clock conversion patches and
the nasty workaround that this problem implies[3].

We also used to have an early platform drivers implementation but they were not
integrated with the linux device model at all - they merely used the same data
structures. The users could not use devres, defer probe and the early devices
never became actual platform devices later on.

Proposed solution:

This series aims at solving this problem by (re-)introducing the concept of
early platform drivers and devices - this time however in a way that seamlessly
integrates with the existing platform drivers and also offers device-tree
support.

The idea is to provide a way for users to probe devices early, while already
being able to use devres, devices resources and properties and also deferred
probing.

New structures are introduced: the early platform driver contains the
early_probe callback which has the same signature as regular platform_device
probe. This callback is called early on. The user can have both the early and
regular probe speficied or only one of them and they both receive the same
platform device object as argument. Any device data allocated early will be
carried over to the normal probe.

The architecture code is responsible for calling early_platform_start() in
which the early drivers will be registered and devices populated from DT.

Once the device and kobject mechanisms are ready, all early drivers and devices
will be converted into real platform drivers and devices. Also: if any of the
early platform registration functions will be called once early initialization
is done, these functions will work like regular platform_device/driver ones.

Patches 1-9/12 introduce changes to existing code that are necessary before
adding support for early drivers. Patch 10/12 contains the new framwork in an
isolated file which can be compiled only if needed by the architecture.

Patch 11/12 contains a dummy early platform driver that serves as a code
example and can be used for simple testing.

The last patch finally makes the of/platform code aware of early platform
drivers.

If accepted, this new mechanism could potentially lead to consolidation of the
code currently used by users of OF_DECLARE, since they could be converted to
actual platform drivers.

[1] https://lkml.org/lkml/2018/4/26/657
[2] https://lkml.org/lkml/2018/4/30/547
[3] https://lkml.org/lkml/2018/4/26/1094

Bartosz Golaszewski (12):
  platform/early: add a new field to struct device
  platform/early: don't WARN() on non-empty devres list for early
    devices
  platform/early: export platform_match() locally
  platform: provide a separate function for initializing platform
    devices
  platform: export platform_device_release() locally
  of: add a new flag for OF device nodes
  of/platform: provide a separate routine for setting up device
    resources
  of/platform: provide a separate routine for device initialization
  platform/early: add an init section for early driver data
  platform/early: implement support for early platform drivers
  misc: implement a dummy early platform driver
  of/platform: make the OF code aware of early platform drivers

 drivers/base/Kconfig              |   3 +
 drivers/base/Makefile             |   1 +
 drivers/base/base.h               |   4 +
 drivers/base/dd.c                 |   2 +-
 drivers/base/early.c              | 332 ++++++++++++++++++++++++++++++
 drivers/base/platform.c           |  28 ++-
 drivers/misc/Kconfig              |   8 +
 drivers/misc/Makefile             |   2 +
 drivers/misc/dummy-early.c        |  82 ++++++++
 drivers/of/platform.c             |  85 +++++---
 include/asm-generic/vmlinux.lds.h |  11 +
 include/linux/device.h            |   1 +
 include/linux/early_platform.h    |  75 +++++++
 include/linux/of.h                |   1 +
 include/linux/of_platform.h       |   2 +
 include/linux/platform_device.h   |   2 +
 16 files changed, 604 insertions(+), 35 deletions(-)
 create mode 100644 drivers/base/early.c
 create mode 100644 drivers/misc/dummy-early.c
 create mode 100644 include/linux/early_platform.h

-- 
2.17.0

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

* [PATCH 01/12] platform/early: add a new field to struct device
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:24   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices Bartosz Golaszewski
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Add a new single-bit field to struct device which will be used to
indicate that a device was probed early in the boot sequence.

This does not affect the size of struct device on any architecture
I built on (ARM, ARM64, x86_64).

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/linux/device.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 477956990f5e..bcff8b598b20 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -992,6 +992,7 @@ struct device {
 	bool			offline_disabled:1;
 	bool			offline:1;
 	bool			of_node_reused:1;
+	bool			early:1;
 };
 
 static inline struct device *kobj_to_dev(struct kobject *kobj)
-- 
2.17.0

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

* [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
  2018-05-11 16:20 ` [PATCH 01/12] platform/early: add a new field to struct device Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:24   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 03/12] platform/early: export platform_match() locally Bartosz Golaszewski
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Early platform devices can have devres objects allocated in
early_probe(). This is not a bug so don't dump stack in this case.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/base/dd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c9f54089429b..0b94d9426757 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -410,7 +410,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 	atomic_inc(&probe_count);
 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 		 drv->bus->name, __func__, drv->name, dev_name(dev));
-	WARN_ON(!list_empty(&dev->devres_head));
+	WARN_ON(!dev->early && !list_empty(&dev->devres_head));
 
 re_probe:
 	dev->driver = drv;
-- 
2.17.0

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

* [PATCH 03/12] platform/early: export platform_match() locally
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
  2018-05-11 16:20 ` [PATCH 01/12] platform/early: add a new field to struct device Bartosz Golaszewski
  2018-05-11 16:20 ` [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:25   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 04/12] platform: provide a separate function for initializing platform devices Bartosz Golaszewski
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We will use this function to match devices in the early platform core
code. Export it locally in drivers/base.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/base/base.h     | 3 +++
 drivers/base/platform.c | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/base/base.h b/drivers/base/base.h
index d800de650fa5..7a72ae72a98e 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -161,3 +161,6 @@ extern void device_links_driver_cleanup(struct device *dev);
 extern void device_links_no_driver(struct device *dev);
 extern bool device_links_busy(struct device *dev);
 extern void device_links_unbind_consumers(struct device *dev);
+
+/* Platform device helpers. */
+extern int platform_match(struct device *dev, struct device_driver *drv);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 70b156ee267a..0c53e3e3e5aa 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -961,7 +961,7 @@ static const struct platform_device_id *platform_match_id(
  * and compare it against the name of the driver. Return whether they match
  * or not.
  */
-static int platform_match(struct device *dev, struct device_driver *drv)
+int platform_match(struct device *dev, struct device_driver *drv)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct platform_driver *pdrv = to_platform_driver(drv);
-- 
2.17.0

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

* [PATCH 04/12] platform: provide a separate function for initializing platform devices
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 03/12] platform/early: export platform_match() locally Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:25   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 05/12] platform: export platform_device_release() locally Bartosz Golaszewski
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The early platform driver framework will allocate platform devices
using its own internal mechanisms. Provide a function that allows to
initialize a platform device object without allocating it.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/base/platform.c         | 24 ++++++++++++++++++++----
 include/linux/platform_device.h |  2 ++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 0c53e3e3e5aa..0ba4effb9618 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -252,6 +252,25 @@ static void platform_device_release(struct device *dev)
 	kfree(pa);
 }
 
+/**
+ * platform_device_init - initialize a platform device
+ * @pdev: platform device to initialize
+ * @name: base name of the device we're adding, NOTE: it's not copied
+ * @id: instance id
+ *
+ * Initiate an already allocated platform device. This routine does not set
+ * the release device callback.
+ */
+void platform_device_init(struct platform_device *pdev,
+			  const char *name, int id)
+{
+	pdev->name = name;
+	pdev->id = id;
+	device_initialize(&pdev->dev);
+	arch_setup_pdev_archdata(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_init);
+
 /**
  * platform_device_alloc - create a platform device
  * @name: base name of the device we're adding
@@ -267,11 +286,8 @@ struct platform_device *platform_device_alloc(const char *name, int id)
 	pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
 	if (pa) {
 		strcpy(pa->name, name);
-		pa->pdev.name = pa->name;
-		pa->pdev.id = id;
-		device_initialize(&pa->pdev.dev);
+		platform_device_init(&pa->pdev, pa->name, id);
 		pa->pdev.dev.release = platform_device_release;
-		arch_setup_pdev_archdata(&pa->pdev);
 	}
 
 	return pa ? &pa->pdev : NULL;
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 099aaf804b50..46bfd5ff666f 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -165,6 +165,8 @@ static inline struct platform_device *platform_device_register_data(
 			NULL, 0, data, size);
 }
 
+extern void platform_device_init(struct platform_device *pdev,
+				 const char *name, int id);
 extern struct platform_device *platform_device_alloc(const char *name, int id);
 extern int platform_device_add_resources(struct platform_device *pdev,
 					 const struct resource *res,
-- 
2.17.0

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

* [PATCH 05/12] platform: export platform_device_release() locally
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (3 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 04/12] platform: provide a separate function for initializing platform devices Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:25   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 06/12] of: add a new flag for OF device nodes Bartosz Golaszewski
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The early platform driver mechanism will use this function as the
device release callback. Make it available in drivers/base.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/base/base.h     | 1 +
 drivers/base/platform.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/base/base.h b/drivers/base/base.h
index 7a72ae72a98e..514a6d198f14 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -164,3 +164,4 @@ extern void device_links_unbind_consumers(struct device *dev);
 
 /* Platform device helpers. */
 extern int platform_match(struct device *dev, struct device_driver *drv);
+extern void platform_device_release(struct device *dev);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 0ba4effb9618..417ab6071350 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -239,7 +239,7 @@ void platform_device_put(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(platform_device_put);
 
-static void platform_device_release(struct device *dev)
+void platform_device_release(struct device *dev)
 {
 	struct platform_object *pa = container_of(dev, struct platform_object,
 						  pdev.dev);
-- 
2.17.0

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

* [PATCH 06/12] of: add a new flag for OF device nodes
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (4 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 05/12] platform: export platform_device_release() locally Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:25   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 07/12] of/platform: provide a separate routine for setting up device resources Bartosz Golaszewski
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This flag indicates that a device node has been populated early and
that it needs different handling when called from
of_platform_populate().

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/linux/of.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/of.h b/include/linux/of.h
index 4d25e4f952d9..49ba6427c6b2 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -143,6 +143,7 @@ extern raw_spinlock_t devtree_lock;
 #define OF_DETACHED	2 /* node has been detached from the device tree */
 #define OF_POPULATED	3 /* device already created for the node */
 #define OF_POPULATED_BUS	4 /* of_platform_populate recursed to children of this node */
+#define OF_POPULATED_EARLY	5 /* device is already allocated */
 
 #define OF_BAD_ADDR	((u64)-1)
 
-- 
2.17.0

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

* [PATCH 07/12] of/platform: provide a separate routine for setting up device resources
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (5 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 06/12] of: add a new flag for OF device nodes Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:26   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 08/12] of/platform: provide a separate routine for device initialization Bartosz Golaszewski
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The early platform driver framework will need to setup the device
resources before the regular populating of the device tree happens.

Provide a separate function for that.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/of/platform.c       | 54 +++++++++++++++++++++++--------------
 include/linux/of_platform.h |  2 ++
 2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index c00d81dfac0b..24791e558ec5 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -99,24 +99,12 @@ static void of_device_make_bus_id(struct device *dev)
 	}
 }
 
-/**
- * of_device_alloc - Allocate and initialize an of_device
- * @np: device node to assign to device
- * @bus_id: Name to assign to the device.  May be null to use default name.
- * @parent: Parent device.
- */
-struct platform_device *of_device_alloc(struct device_node *np,
-				  const char *bus_id,
-				  struct device *parent)
+int of_device_init_resources(struct platform_device *pdev,
+			     struct device_node *np)
 {
-	struct platform_device *dev;
 	int rc, i, num_reg = 0, num_irq;
 	struct resource *res, temp_res;
 
-	dev = platform_device_alloc("", PLATFORM_DEVID_NONE);
-	if (!dev)
-		return NULL;
-
 	/* count the io and irq resources */
 	while (of_address_to_resource(np, num_reg, &temp_res) == 0)
 		num_reg++;
@@ -125,22 +113,48 @@ struct platform_device *of_device_alloc(struct device_node *np,
 	/* Populate the resource table */
 	if (num_irq || num_reg) {
 		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
-		if (!res) {
-			platform_device_put(dev);
-			return NULL;
-		}
+		if (!res)
+			return -ENOMEM;
+
+		pdev->num_resources = num_reg + num_irq;
+		pdev->resource = res;
 
-		dev->num_resources = num_reg + num_irq;
-		dev->resource = res;
 		for (i = 0; i < num_reg; i++, res++) {
 			rc = of_address_to_resource(np, i, res);
 			WARN_ON(rc);
 		}
+
 		if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
 			pr_debug("not all legacy IRQ resources mapped for %s\n",
 				 np->name);
 	}
 
+	return 0;
+}
+
+/**
+ * of_device_alloc - Allocate and initialize an of_device
+ * @np: device node to assign to device
+ * @bus_id: Name to assign to the device.  May be null to use default name.
+ * @parent: Parent device.
+ */
+struct platform_device *of_device_alloc(struct device_node *np,
+				  const char *bus_id,
+				  struct device *parent)
+{
+	struct platform_device *dev;
+	int rc;
+
+	dev = platform_device_alloc("", PLATFORM_DEVID_NONE);
+	if (!dev)
+		return NULL;
+
+	rc = of_device_init_resources(dev, np);
+	if (rc) {
+		platform_device_put(dev);
+		return NULL;
+	}
+
 	dev->dev.of_node = of_node_get(np);
 	dev->dev.fwnode = &np->fwnode;
 	dev->dev.parent = parent ? : &platform_bus;
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 84a966623e78..387ab4d4a210 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -52,6 +52,8 @@ extern const struct of_device_id of_default_bus_match_table[];
 extern struct platform_device *of_device_alloc(struct device_node *np,
 					 const char *bus_id,
 					 struct device *parent);
+extern int of_device_init_resources(struct platform_device *pdev,
+				    struct device_node *np);
 #ifdef CONFIG_OF
 extern struct platform_device *of_find_device_by_node(struct device_node *np);
 #else
-- 
2.17.0

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

* [PATCH 08/12] of/platform: provide a separate routine for device initialization
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (6 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 07/12] of/platform: provide a separate routine for setting up device resources Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:26   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 09/12] platform/early: add an init section for early driver data Bartosz Golaszewski
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The early platform device framework will need to initialize the
platform device objects without them being allocated in
of_device_alloc(). Provide a routine that allows it.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/of/platform.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 24791e558ec5..0e554fe1f325 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -132,6 +132,19 @@ int of_device_init_resources(struct platform_device *pdev,
 	return 0;
 }
 
+static void of_device_init(struct platform_device *pdev, struct device_node *np,
+			   const char *bus_id, struct device *parent)
+{
+	pdev->dev.of_node = of_node_get(np);
+	pdev->dev.fwnode = &np->fwnode;
+	pdev->dev.parent = parent ? : &platform_bus;
+
+	if (bus_id)
+		dev_set_name(&pdev->dev, "%s", bus_id);
+	else
+		of_device_make_bus_id(&pdev->dev);
+}
+
 /**
  * of_device_alloc - Allocate and initialize an of_device
  * @np: device node to assign to device
@@ -155,14 +168,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
 		return NULL;
 	}
 
-	dev->dev.of_node = of_node_get(np);
-	dev->dev.fwnode = &np->fwnode;
-	dev->dev.parent = parent ? : &platform_bus;
-
-	if (bus_id)
-		dev_set_name(&dev->dev, "%s", bus_id);
-	else
-		of_device_make_bus_id(&dev->dev);
+	of_device_init(dev, np, bus_id, parent);
 
 	return dev;
 }
-- 
2.17.0

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

* [PATCH 09/12] platform/early: add an init section for early driver data
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (7 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 08/12] of/platform: provide a separate routine for device initialization Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:29   ` Geert Uytterhoeven
  2018-05-11 16:20 ` [PATCH 10/12] platform/early: implement support for early platform drivers Bartosz Golaszewski
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Provide a separate section in which pointers to early platform driver
structs will be stored.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/asm-generic/vmlinux.lds.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index af240573e482..6b5205f30ef2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -214,6 +214,16 @@
 #define CPU_METHOD_OF_TABLES()	OF_TABLE(CONFIG_SMP, cpu_method)
 #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
 
+#ifdef CONFIG_EARLY_PLATFORM
+#define EARLY_PLATFORM_DRIVERS_TABLE()					\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__early_platform_drivers_table) = .;		\
+	KEEP(*(__early_platform_drivers_table))				\
+	VMLINUX_SYMBOL(__early_platform_drivers_table_end) = .;
+#else
+#define EARLY_PLATFORM_DRIVERS_TABLE()
+#endif
+
 #ifdef CONFIG_ACPI
 #define ACPI_PROBE_TABLE(name)						\
 	. = ALIGN(8);							\
@@ -593,6 +603,7 @@
 	RESERVEDMEM_OF_TABLES()						\
 	TIMER_OF_TABLES()						\
 	IOMMU_OF_TABLES()						\
+	EARLY_PLATFORM_DRIVERS_TABLE()					\
 	CPU_METHOD_OF_TABLES()						\
 	CPUIDLE_METHOD_OF_TABLES()					\
 	KERNEL_DTB()							\
-- 
2.17.0

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

* [PATCH 10/12] platform/early: implement support for early platform drivers
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (8 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 09/12] platform/early: add an init section for early driver data Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 13:37   ` Rob Herring
  2018-05-11 16:20 ` [PATCH 11/12] misc: implement a dummy early platform driver Bartosz Golaszewski
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This introduces the core part of support for early platform drivers
and devices.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/base/Kconfig           |   3 +
 drivers/base/Makefile          |   1 +
 drivers/base/early.c           | 332 +++++++++++++++++++++++++++++++++
 drivers/misc/Makefile          |   1 +
 include/linux/early_platform.h |  75 ++++++++
 5 files changed, 412 insertions(+)
 create mode 100644 drivers/base/early.c
 create mode 100644 include/linux/early_platform.h

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 29b0eb452b3a..ea648daecec1 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -205,6 +205,9 @@ config DEBUG_TEST_DRIVER_REMOVE
 	  unusable. You should say N here unless you are explicitly looking to
 	  test this functionality.
 
+config EARLY_PLATFORM
+	def_bool n
+
 source "drivers/base/test/Kconfig"
 
 config SYS_HYPERVISOR
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 7845c95ee1b2..3998ad6719f1 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -7,6 +7,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 			   attribute_container.o transport_class.o \
 			   topology.o container.o property.o cacheinfo.o \
 			   devcon.o
+obj-$(CONFIG_EARLY_PLATFORM) += early.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
diff --git a/drivers/base/early.c b/drivers/base/early.c
new file mode 100644
index 000000000000..7d0b7fb85f58
--- /dev/null
+++ b/drivers/base/early.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Texas Instruments, Inc.
+ *
+ * Author:
+ *     Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ */
+
+#include <linux/early_platform.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+#include "base.h"
+
+extern struct early_platform_driver *__early_platform_drivers_table[];
+extern struct early_platform_driver *__early_platform_drivers_table_end[];
+
+static bool early_platform_done;
+
+static LIST_HEAD(early_platform_drivers);
+static LIST_HEAD(early_platform_devices);
+
+static int early_platform_device_set_name(struct early_platform_device *edev)
+{
+	switch (edev->pdev.id) {
+	case PLATFORM_DEVID_AUTO:
+		pr_warn("auto device ID not supported in early platform devices\n");
+		/* fallthrough */
+	case PLATFORM_DEVID_NONE:
+		edev->pdev.dev.init_name = kasprintf(GFP_KERNEL,
+						     "%s", edev->pdev.name);
+		break;
+	default:
+		edev->pdev.dev.init_name = kasprintf(GFP_KERNEL, "%s.%d",
+						     edev->pdev.name,
+						     edev->pdev.id);
+		break;
+	}
+
+	if (!edev->pdev.dev.init_name)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void early_platform_device_add(struct early_platform_device *edev)
+{
+	edev->pdev.dev.early = true;
+	INIT_LIST_HEAD(&edev->list);
+	list_add_tail(&edev->list, &early_platform_devices);
+}
+
+static void early_platform_probe_deferred(void)
+{
+	struct early_platform_device *edev;
+	int rv;
+
+	list_for_each_entry(edev, &early_platform_devices, list) {
+		if (!edev->deferred || !edev->deferred_drv->early_probe)
+			continue;
+
+		rv = edev->deferred_drv->early_probe(&edev->pdev);
+		if (rv && rv != -EPROBE_DEFER) {
+			dev_err(&edev->pdev.dev,
+				"early platform driver probe failed: %d\n",
+				rv);
+		}
+	}
+}
+
+static void early_platform_try_probe(struct early_platform_driver *edrv,
+				     struct early_platform_device *edev)
+{
+	int rv;
+
+	rv = early_platform_device_set_name(edev);
+	if (rv)
+		pr_warn("unable to set the early platform device name\n");
+
+	if (edrv->early_probe) {
+		rv = edrv->early_probe(&edev->pdev);
+		if (rv && rv != -EPROBE_DEFER &&
+		    rv != -ENODEV && rv != -ENXIO) {
+			dev_err(&edev->pdev.dev,
+				"early platform driver probe failed: %d\n",
+				rv);
+			return;
+		} else if (rv == -EPROBE_DEFER) {
+			edev->deferred = true;
+			edev->deferred_drv = edrv;
+		} else {
+			early_platform_probe_deferred();
+		}
+	}
+}
+
+/**
+ * of_early_to_platform_device - return the platform device with which this
+ *                               device node is associated
+ * @np - device node to look up
+ *
+ * If a device node was populated early, the corresponding platform device
+ * already exists. Instead of allocating a new object, we need to retrieve
+ * the previous one. This routine enables it.
+ */
+struct platform_device *of_early_to_platform_device(struct device_node *np)
+{
+	struct early_platform_device *edev;
+
+	list_for_each_entry(edev, &early_platform_devices, list) {
+		if (np == edev->pdev.dev.of_node)
+			return &edev->pdev;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+static int of_early_platform_device_create(struct device_node *node,
+					   struct early_platform_driver *edrv)
+{
+	struct early_platform_device *edev;
+	int rc;
+
+	edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+	if (!edev)
+		return -ENOMEM;
+
+	platform_device_init(&edev->pdev, "", PLATFORM_DEVID_NONE);
+	/*
+	 * We can safely use platform_device_release since the platform_device
+	 * struct is the first member of early_platform_device.
+	 */
+	edev->pdev.dev.release = platform_device_release;
+
+	rc = of_device_init_resources(&edev->pdev, node);
+	if (rc) {
+		kfree(edev);
+		return rc;
+	}
+
+	of_node_set_flag(node, OF_POPULATED_EARLY);
+	edev->pdev.name = edrv->pdrv.driver.name;
+	edev->pdev.dev.of_node = of_node_get(node);
+	edev->pdev.dev.fwnode = &node->fwnode;
+	early_platform_device_add(edev);
+	early_platform_try_probe(edrv, edev);
+
+	return 0;
+}
+
+static int of_early_platform_populate(struct device_node *root)
+{
+	struct early_platform_driver *edrv;
+	const struct of_device_id *match;
+	struct device_node *child;
+	int rv;
+
+	if (!root)
+		return 0;
+
+	list_for_each_entry(edrv, &early_platform_drivers, list) {
+		if (!edrv->pdrv.driver.of_match_table)
+			continue;
+
+		match = of_match_node(edrv->pdrv.driver.of_match_table, root);
+		if (!match)
+			continue;
+
+		rv = of_early_platform_device_create(root, edrv);
+		if (rv)
+			return rv;
+	}
+
+	for_each_child_of_node(root, child) {
+		rv = of_early_platform_populate(child);
+		if (rv) {
+			of_node_put(child);
+			return rv;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * early_platform_start - start handling early devices
+ *
+ * This should be called by the architecture code early in the boot sequence
+ * to register all early platform drivers, populate the early devices from DT
+ * and start matching platform devices specified in machine code.
+ */
+void early_platform_start(void)
+{
+	struct early_platform_driver **edrv;
+	struct device_node *root;
+	int rv;
+
+	WARN_ONCE(!slab_is_available(), "slab is required for early devices\n");
+
+	pr_debug("%s(): registering pending early platform drivers\n",
+		 __func__);
+
+	for (edrv = __early_platform_drivers_table;
+	     edrv < __early_platform_drivers_table_end; edrv++) {
+		rv = early_platform_driver_register(*edrv);
+		if (rv)
+			pr_warn("error registering early platform driver: %d\n",
+				rv);
+	}
+
+	if (of_have_populated_dt()) {
+		pr_debug("%s(): populating early_platform devices from DT\n",
+			 __func__);
+
+		root = of_find_node_by_path("/");
+
+		rv = of_early_platform_populate(root);
+		if (rv)
+			pr_warn("error populating early devices from DT: %d\n",
+				rv);
+
+		of_node_put(root);
+	}
+}
+EXPORT_SYMBOL_GPL(early_platform_start);
+
+/**
+ * early_platform_driver_register - register an early platform driver
+ * @edrv: early platform driver to register
+ *
+ * If we're past postcore initcall, this works exactly as
+ * platform_device_register().
+ */
+int early_platform_driver_register(struct early_platform_driver *edrv)
+{
+	struct early_platform_device *edev;
+
+	if (early_platform_done)
+		return platform_driver_register(&edrv->pdrv);
+
+	INIT_LIST_HEAD(&edrv->list);
+	list_add_tail(&edrv->list, &early_platform_drivers);
+
+	list_for_each_entry(edev, &early_platform_devices, list) {
+		if (platform_match(&edev->pdev.dev, &edrv->pdrv.driver)) {
+			early_platform_try_probe(edrv, edev);
+			break;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(early_platform_driver_register);
+
+/**
+ * early_platform_device_register - register an early platform device
+ * @edev: early platform device to register
+ *
+ * If we're past postcore initcall, this works exactly as
+ * platform_device_register().
+ */
+int early_platform_device_register(struct early_platform_device *edev)
+{
+	struct early_platform_driver *edrv;
+
+	if (early_platform_done)
+		return platform_device_register(&edev->pdev);
+
+	device_initialize(&edev->pdev.dev);
+	early_platform_device_add(edev);
+
+	list_for_each_entry(edrv, &early_platform_drivers, list) {
+		if (platform_match(&edev->pdev.dev, &edrv->pdrv.driver)) {
+			early_platform_try_probe(edrv, edev);
+			break;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(early_platform_device_register);
+
+/*
+ * This is called once the entire device model infrastructure is in place to
+ * seamlessly convert all early platform devices & drivers to regular ones.
+ *
+ * From this point forward all early platform devices work exactly like normal
+ * platform devices.
+ */
+static int early_platform_finalize(void)
+{
+	struct early_platform_driver *edrv;
+	struct early_platform_device *edev;
+	int rv;
+
+	early_platform_done = true;
+
+	pr_debug("%s(): converting early platform drivers to real platform drivers\n",
+		 __func__);
+
+	list_for_each_entry(edrv, &early_platform_drivers, list) {
+		rv = platform_driver_register(&edrv->pdrv);
+		if (rv)
+			pr_warn("%s: error converting early platform driver to real platform driver\n",
+				edrv->pdrv.driver.name);
+	}
+
+	pr_debug("%s(): converting early platform devices to real platform devices\n",
+		 __func__);
+
+	list_for_each_entry(edev, &early_platform_devices, list) {
+		if (edev->pdev.dev.of_node)
+			/* This will be handled by of_platform_populate(). */
+			continue;
+
+		kfree(edev->pdev.dev.init_name);
+
+		/*
+		 * We don't want to reinitialize the associated struct device
+		 * so we must not call platform_device_register().
+		 */
+		rv = platform_device_add(&edev->pdev);
+		if (rv)
+			pr_warn("%s: error converting early platform device to real platform device\n",
+				dev_name(&edev->pdev.dev));
+	}
+
+	return 0;
+}
+postcore_initcall(early_platform_finalize);
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 20be70c3f118..d0a8788d5151 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -57,3 +57,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
 obj-$(CONFIG_PCI_ENDPOINT_TEST)	+= pci_endpoint_test.o
 obj-$(CONFIG_OCXL)		+= ocxl/
 obj-$(CONFIG_MISC_RTSX)		+= cardreader/
+CFLAGS_dummy-early.o := -DDEBUG
diff --git a/include/linux/early_platform.h b/include/linux/early_platform.h
new file mode 100644
index 000000000000..fd3fd4db8322
--- /dev/null
+++ b/include/linux/early_platform.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments, Inc.
+ *
+ * Author:
+ *     Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ */
+
+#ifndef __EARLY_PLATFORM_H__
+#define __EARLY_PLATFORM_H__
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/**
+ * struct early_platform_driver
+ *
+ * @pdrv: real platform driver associated with this early platform driver
+ * @list: list head for the list of early platform drivers
+ * @early_probe: early probe callback
+ */
+struct early_platform_driver {
+	struct platform_driver pdrv;
+	struct list_head list;
+	int (*early_probe)(struct platform_device *);
+};
+
+/**
+ * struct early_platform_device
+ *
+ * @pdev: real platform device associated with this early platform device
+ * @list: list head for the list of early platform devices
+ * @deferred: true if this device's early probe was deferred
+ * @deferred_drv: early platform driver with which this device was matched
+ */
+struct early_platform_device {
+	struct platform_device pdev;
+	struct list_head list;
+	bool deferred;
+	struct early_platform_driver *deferred_drv;
+};
+
+#ifdef CONFIG_EARLY_PLATFORM
+extern void early_platform_start(void);
+extern int early_platform_driver_register(struct early_platform_driver *edrv);
+extern int early_platform_device_register(struct early_platform_device *edev);
+#else /* CONFIG_EARLY_PLATFORM */
+static inline void early_platform_start(void) {}
+static int void
+early_platform_driver_register(struct early_platform_driver *edrv) {}
+static int void
+early_platform_device_register(struct early_platform_device *edev) {}
+#endif /* CONFIG_EARLY_PLATFORM */
+
+#if defined(CONFIG_EARLY_PLATFORM) && defined(CONFIG_OF)
+extern struct platform_device *
+of_early_to_platform_device(struct device_node *np);
+#else
+static inline struct platform_device *
+of_early_to_platform_device(struct device_node *np)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif /* defined(CONFIG_EARLY_PLATFORM) && defined(CONFIG_OF) */
+
+#ifdef CONFIG_EARLY_PLATFORM
+#define module_early_platform_driver(_edrv)				\
+	static const struct early_platform_driver *__##_edrv##_entry	\
+		__used __section(__early_platform_drivers_table)	\
+		= &(_edrv)
+#else /* CONFIG_EARLY_PLATFORM */
+#define module_early_platform_driver(_edrv)
+#endif /* CONFIG_EARLY_PLATFORM */
+
+#endif /* __EARLY_PLATFORM_H__ */
-- 
2.17.0

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

* [PATCH 11/12] misc: implement a dummy early platform driver
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (9 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 10/12] platform/early: implement support for early platform drivers Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-11 16:20 ` [PATCH 12/12] of/platform: make the OF code aware of early platform drivers Bartosz Golaszewski
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Implement a very simple early platform driver. Its purpose is to show
how such drivers can be registered and to emit a message when probed.

It can be then added to the device tree or machine code to verify that
the early platform devices work as expected.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/misc/Kconfig       |  8 ++++
 drivers/misc/Makefile      |  1 +
 drivers/misc/dummy-early.c | 82 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+)
 create mode 100644 drivers/misc/dummy-early.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5d713008749b..60fef04eb236 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -91,6 +91,14 @@ config DUMMY_IRQ
 	  The sole purpose of this module is to help with debugging of systems on
 	  which spurious IRQs would happen on disabled IRQ vector.
 
+config DUMMY_EARLY
+	bool "Dummy early platform driver"
+	select EARLY_PLATFORM
+	default n
+	help
+	  This module's only function is to register itself with the early
+	  platform device framework and be probed early in the boot process.
+
 config IBM_ASM
 	tristate "Device driver for IBM RSA service processor"
 	depends on X86 && PCI && INPUT
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d0a8788d5151..6170855853a1 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
+obj-$(CONFIG_DUMMY_EARLY)	+= dummy-early.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
 obj-$(CONFIG_LKDTM)		+= lkdtm/
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
diff --git a/drivers/misc/dummy-early.c b/drivers/misc/dummy-early.c
new file mode 100644
index 000000000000..eb8f826aea64
--- /dev/null
+++ b/drivers/misc/dummy-early.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Texas Instruments
+ *
+ * Author:
+ *   Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ *
+ * Dummy testing driver whose only purpose is to be registered and probed
+ * using the early platform device mechanism.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/early_platform.h>
+
+struct dummy_early_data {
+	int a;
+	int b;
+};
+
+static int dummy_early_probe_early(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct dummy_early_data *data;
+	struct resource *res;
+
+	dev_notice(dev, "dummy-early driver probed early!\n");
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->a = 123;
+	data->b = 321;
+
+	dev_dbg(dev, "setting driver data early: a = %d, b = %d\n",
+		data->a, data->b);
+	dev_set_drvdata(dev, data);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		dev_dbg(dev, "got early resource: start = 0x%08x, end = 0x%08x\n",
+			res->start, res->end);
+
+	return 0;
+}
+
+static int dummy_early_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct dummy_early_data *data;
+
+	dev_notice(dev, "dummy-early driver probed late!\n");
+	data = dev_get_drvdata(dev);
+	dev_dbg(dev, "retrieving driver data late: a = %d, b = %d\n",
+		data->a, data->b);
+
+	return 0;
+}
+
+static const struct of_device_id dummy_early_of_match[] = {
+	{ .compatible = "dummy-early", },
+	{ },
+};
+
+static struct early_platform_driver dummy_early_driver = {
+	.early_probe = dummy_early_probe_early,
+	.pdrv = {
+		.probe = dummy_early_probe,
+		.driver = {
+			.name = "dummy-early",
+			.of_match_table = dummy_early_of_match,
+		},
+	}
+};
+module_early_platform_driver(dummy_early_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_DESCRIPTION("Dummy early platform device driver");
+MODULE_LICENSE("GPL v2");
-- 
2.17.0

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

* [PATCH 12/12] of/platform: make the OF code aware of early platform drivers
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (10 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 11/12] misc: implement a dummy early platform driver Bartosz Golaszewski
@ 2018-05-11 16:20 ` Bartosz Golaszewski
  2018-05-14 21:32   ` Geert Uytterhoeven
  2018-05-11 20:13 ` [PATCH 00/12] introduce support for " Rob Herring
  2018-10-19 12:08 ` Bartosz Golaszewski
  13 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-11 16:20 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-arch,
	Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Check the relevant flag in the device node and skip the allocation
part for devices that were populated early.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/of/platform.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 0e554fe1f325..91760e2d3dc7 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -21,6 +21,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/early_platform.h>
 
 const struct of_device_id of_default_bus_match_table[] = {
 	{ .compatible = "simple-bus", },
@@ -196,9 +197,17 @@ static struct platform_device *of_platform_device_create_pdata(
 	    of_node_test_and_set_flag(np, OF_POPULATED))
 		return NULL;
 
-	dev = of_device_alloc(np, bus_id, parent);
-	if (!dev)
-		goto err_clear_flag;
+	if (of_node_check_flag(np, OF_POPULATED_EARLY)) {
+		dev = of_early_to_platform_device(np);
+		if (IS_ERR(dev))
+			goto err_clear_flag;
+
+		of_device_init(dev, np, bus_id, parent);
+	} else {
+		dev = of_device_alloc(np, bus_id, parent);
+		if (!dev)
+			goto err_clear_flag;
+	}
 
 	dev->dev.bus = &platform_bus_type;
 	dev->dev.platform_data = platform_data;
-- 
2.17.0

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (11 preceding siblings ...)
  2018-05-11 16:20 ` [PATCH 12/12] of/platform: make the OF code aware of early platform drivers Bartosz Golaszewski
@ 2018-05-11 20:13 ` Rob Herring
  2018-05-14 11:38   ` Bartosz Golaszewski
  2018-10-19 12:08 ` Bartosz Golaszewski
  13 siblings, 1 reply; 35+ messages in thread
From: Rob Herring @ 2018-05-11 20:13 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> This series is a follow-up to the RFC[1] posted a couple days ago.
>
> NOTE: this series applies on top of my recent patches[2] that move the previous
> implementation of early platform devices to arch/sh.
>
> Problem:
>
> Certain class of devices, such as timers, certain clock drivers and irq chip
> drivers need to be probed early in the boot sequence. The currently preferred
> approach is using one of the OF_DECLARE() macros. This however does not create
> a platform device which has many drawbacks - such as not being able to use
> devres routines, dev_ log functions or no way of deferring the init OF function
> if some other resources are missing.

I skimmed though this and it doesn't look horrible (how's that for
positive feedback? ;) ). But before going into the details, I think
first there needs to be agreement this is the right direction.

The question does remain though as to whether this class of devices
should be platform drivers. They can't be modules. They can't be
hotplugged. Can they be runtime-pm enabled? So the advantage is ...

I assume that the clock maintainers had some reason to move clocks to
be platform drivers. It's just not clear to me what that was.

> For drivers that use both platform drivers and OF_DECLARE the situation is even
> more complicated as the code needs to take into account that there can possibly
> be no struct device present. For a specific use case that we're having problems
> with, please refer to the recent DaVinci common-clock conversion patches and
> the nasty workaround that this problem implies[3].

So devm_kzalloc will work with this solution? Why did we need
devm_kzalloc in the first place? The clocks can never be removed and
cleaning up on error paths is kind of pointless. The system would be
hosed, right?

> We also used to have an early platform drivers implementation but they were not
> integrated with the linux device model at all - they merely used the same data
> structures. The users could not use devres, defer probe and the early devices
> never became actual platform devices later on.
>
> Proposed solution:
>
> This series aims at solving this problem by (re-)introducing the concept of
> early platform drivers and devices - this time however in a way that seamlessly
> integrates with the existing platform drivers and also offers device-tree
> support.
>
> The idea is to provide a way for users to probe devices early, while already
> being able to use devres, devices resources and properties and also deferred
> probing.
>
> New structures are introduced: the early platform driver contains the
> early_probe callback which has the same signature as regular platform_device
> probe. This callback is called early on. The user can have both the early and
> regular probe speficied or only one of them and they both receive the same
> platform device object as argument. Any device data allocated early will be
> carried over to the normal probe.
>
> The architecture code is responsible for calling early_platform_start() in
> which the early drivers will be registered and devices populated from DT.

Can we really do this in one spot for different devices (clk, timers,
irq). The sequence is all very carefully crafted. Platform specific
hooks is another thing to consider.

> Once the device and kobject mechanisms are ready, all early drivers and devices
> will be converted into real platform drivers and devices. Also: if any of the
> early platform registration functions will be called once early initialization
> is done, these functions will work like regular platform_device/driver ones.

This could leave devices in a weird state. They've successfully probed
early, but then are on the deferred list for normal probe for example.

Rob

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-11 20:13 ` [PATCH 00/12] introduce support for " Rob Herring
@ 2018-05-14 11:38   ` Bartosz Golaszewski
  2018-05-14 13:20     ` Rob Herring
  0 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-14 11:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

2018-05-11 22:13 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> This series is a follow-up to the RFC[1] posted a couple days ago.
>>
>> NOTE: this series applies on top of my recent patches[2] that move the previous
>> implementation of early platform devices to arch/sh.
>>
>> Problem:
>>
>> Certain class of devices, such as timers, certain clock drivers and irq chip
>> drivers need to be probed early in the boot sequence. The currently preferred
>> approach is using one of the OF_DECLARE() macros. This however does not create
>> a platform device which has many drawbacks - such as not being able to use
>> devres routines, dev_ log functions or no way of deferring the init OF function
>> if some other resources are missing.
>
> I skimmed though this and it doesn't look horrible (how's that for
> positive feedback? ;) ). But before going into the details, I think
> first there needs to be agreement this is the right direction.
>
> The question does remain though as to whether this class of devices
> should be platform drivers. They can't be modules. They can't be
> hotplugged. Can they be runtime-pm enabled? So the advantage is ...
>

The main (but not the only) advantage for drivers that can both be
platform drivers and OF_DECLARE drivers is that we get a single entry
point and can reuse code without resorting to checking if (!dev). It
results in more consistent code base. Another big advantage is
consolidation of device tree and machine code for SoC drivers used in
different boards of which some are still using board files and others
are defined in DT (see: DaVinci).

> I assume that the clock maintainers had some reason to move clocks to
> be platform drivers. It's just not clear to me what that was.
>
>> For drivers that use both platform drivers and OF_DECLARE the situation is even
>> more complicated as the code needs to take into account that there can possibly
>> be no struct device present. For a specific use case that we're having problems
>> with, please refer to the recent DaVinci common-clock conversion patches and
>> the nasty workaround that this problem implies[3].
>
> So devm_kzalloc will work with this solution? Why did we need
> devm_kzalloc in the first place? The clocks can never be removed and
> cleaning up on error paths is kind of pointless. The system would be
> hosed, right?
>

It depends - not all clocks are necessary for system to boot.

>> We also used to have an early platform drivers implementation but they were not
>> integrated with the linux device model at all - they merely used the same data
>> structures. The users could not use devres, defer probe and the early devices
>> never became actual platform devices later on.
>>
>> Proposed solution:
>>
>> This series aims at solving this problem by (re-)introducing the concept of
>> early platform drivers and devices - this time however in a way that seamlessly
>> integrates with the existing platform drivers and also offers device-tree
>> support.
>>
>> The idea is to provide a way for users to probe devices early, while already
>> being able to use devres, devices resources and properties and also deferred
>> probing.
>>
>> New structures are introduced: the early platform driver contains the
>> early_probe callback which has the same signature as regular platform_device
>> probe. This callback is called early on. The user can have both the early and
>> regular probe speficied or only one of them and they both receive the same
>> platform device object as argument. Any device data allocated early will be
>> carried over to the normal probe.
>>
>> The architecture code is responsible for calling early_platform_start() in
>> which the early drivers will be registered and devices populated from DT.
>
> Can we really do this in one spot for different devices (clk, timers,
> irq). The sequence is all very carefully crafted. Platform specific
> hooks is another thing to consider.
>

This is why I added support for early probe deferral - so that we can
stop caring for the order as long as the drivers are aware of other
resources they need and we call early_platform_start() the moment the
earliest of the early devices is needed.

>> Once the device and kobject mechanisms are ready, all early drivers and devices
>> will be converted into real platform drivers and devices. Also: if any of the
>> early platform registration functions will be called once early initialization
>> is done, these functions will work like regular platform_device/driver ones.
>
> This could leave devices in a weird state. They've successfully probed
> early, but then are on the deferred list for normal probe for example.
>

It's not really a weird state - once we're past the 'early' stage, the
drivers' "earlyness" no longer plays any role. An early deferred
device wouldn't be any different from other deferred devices. It's
possible that we enabled some crucial resources in the early stage and
then failed to fully probe the device later. I don't see a problem
with that.

Best regards,
Bartosz Golaszewski

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-14 11:38   ` Bartosz Golaszewski
@ 2018-05-14 13:20     ` Rob Herring
  2018-05-30 19:40       ` Michael Turquette
  0 siblings, 1 reply; 35+ messages in thread
From: Rob Herring @ 2018-05-14 13:20 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

On Mon, May 14, 2018 at 6:38 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> 2018-05-11 22:13 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
>> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>> This series is a follow-up to the RFC[1] posted a couple days ago.
>>>
>>> NOTE: this series applies on top of my recent patches[2] that move the previous
>>> implementation of early platform devices to arch/sh.
>>>
>>> Problem:
>>>
>>> Certain class of devices, such as timers, certain clock drivers and irq chip
>>> drivers need to be probed early in the boot sequence. The currently preferred
>>> approach is using one of the OF_DECLARE() macros. This however does not create
>>> a platform device which has many drawbacks - such as not being able to use
>>> devres routines, dev_ log functions or no way of deferring the init OF function
>>> if some other resources are missing.
>>
>> I skimmed though this and it doesn't look horrible (how's that for
>> positive feedback? ;) ). But before going into the details, I think
>> first there needs to be agreement this is the right direction.
>>
>> The question does remain though as to whether this class of devices
>> should be platform drivers. They can't be modules. They can't be
>> hotplugged. Can they be runtime-pm enabled? So the advantage is ...
>>
>
> The main (but not the only) advantage for drivers that can both be
> platform drivers and OF_DECLARE drivers is that we get a single entry
> point and can reuse code without resorting to checking if (!dev). It
> results in more consistent code base. Another big advantage is
> consolidation of device tree and machine code for SoC drivers used in
> different boards of which some are still using board files and others
> are defined in DT (see: DaVinci).
>
>> I assume that the clock maintainers had some reason to move clocks to
>> be platform drivers. It's just not clear to me what that was.
>>
>>> For drivers that use both platform drivers and OF_DECLARE the situation is even
>>> more complicated as the code needs to take into account that there can possibly
>>> be no struct device present. For a specific use case that we're having problems
>>> with, please refer to the recent DaVinci common-clock conversion patches and
>>> the nasty workaround that this problem implies[3].
>>
>> So devm_kzalloc will work with this solution? Why did we need
>> devm_kzalloc in the first place? The clocks can never be removed and
>> cleaning up on error paths is kind of pointless. The system would be
>> hosed, right?
>>
>
> It depends - not all clocks are necessary for system to boot.

That doesn't matter. You have a single driver for all/most of the
clocks, so the driver can't be removed.

>>> We also used to have an early platform drivers implementation but they were not
>>> integrated with the linux device model at all - they merely used the same data
>>> structures. The users could not use devres, defer probe and the early devices
>>> never became actual platform devices later on.
>>>
>>> Proposed solution:
>>>
>>> This series aims at solving this problem by (re-)introducing the concept of
>>> early platform drivers and devices - this time however in a way that seamlessly
>>> integrates with the existing platform drivers and also offers device-tree
>>> support.
>>>
>>> The idea is to provide a way for users to probe devices early, while already
>>> being able to use devres, devices resources and properties and also deferred
>>> probing.
>>>
>>> New structures are introduced: the early platform driver contains the
>>> early_probe callback which has the same signature as regular platform_device
>>> probe. This callback is called early on. The user can have both the early and
>>> regular probe speficied or only one of them and they both receive the same
>>> platform device object as argument. Any device data allocated early will be
>>> carried over to the normal probe.
>>>
>>> The architecture code is responsible for calling early_platform_start() in
>>> which the early drivers will be registered and devices populated from DT.
>>
>> Can we really do this in one spot for different devices (clk, timers,
>> irq). The sequence is all very carefully crafted. Platform specific
>> hooks is another thing to consider.
>>
>
> This is why I added support for early probe deferral - so that we can
> stop caring for the order as long as the drivers are aware of other
> resources they need and we call early_platform_start() the moment the
> earliest of the early devices is needed.

Deferred probe helps for inter-device dependencies, but I am more
concerned about timing of trying to register clocksources, irqchips,
etc. What happens if we probe drivers before the infrastructure is
initialized?

Rob

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

* Re: [PATCH 10/12] platform/early: implement support for early platform drivers
  2018-05-11 16:20 ` [PATCH 10/12] platform/early: implement support for early platform drivers Bartosz Golaszewski
@ 2018-05-14 13:37   ` Rob Herring
  2018-05-15 14:06     ` Bartosz Golaszewski
  0 siblings, 1 reply; 35+ messages in thread
From: Rob Herring @ 2018-05-14 13:37 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES, Bartosz Golaszewski

On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> This introduces the core part of support for early platform drivers
> and devices.
>

It looks like most of your prep patches are to separate the alloc and
init of platform devices because you are essentially making early
devices/drivers a sub-class. Maybe you could avoid doing that and
simplify things a bit. Comments below based on doing that...

> +/**
> + * struct early_platform_driver
> + *
> + * @pdrv: real platform driver associated with this early platform driver
> + * @list: list head for the list of early platform drivers
> + * @early_probe: early probe callback
> + */
> +struct early_platform_driver {
> +       struct platform_driver pdrv;
> +       struct list_head list;

Couldn't you use an existing list in driver_private until you move
over to the normal bus infra.

> +       int (*early_probe)(struct platform_device *);

Just add this to platform_driver.

> +};
> +
> +/**
> + * struct early_platform_device
> + *
> + * @pdev: real platform device associated with this early platform device
> + * @list: list head for the list of early platform devices
> + * @deferred: true if this device's early probe was deferred
> + * @deferred_drv: early platform driver with which this device was matched
> + */
> +struct early_platform_device {
> +       struct platform_device pdev;
> +       struct list_head list;

Use a list in device_private?

> +       bool deferred;
> +       struct early_platform_driver *deferred_drv;

Can't you use the existing deferred probe list?

Rob

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

* Re: [PATCH 01/12] platform/early: add a new field to struct device
  2018-05-11 16:20 ` [PATCH 01/12] platform/early: add a new field to struct device Bartosz Golaszewski
@ 2018-05-14 21:24   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:24 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Add a new single-bit field to struct device which will be used to
> indicate that a device was probed early in the boot sequence.
>
> This does not affect the size of struct device on any architecture
> I built on (ARM, ARM64, x86_64).
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices
  2018-05-11 16:20 ` [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices Bartosz Golaszewski
@ 2018-05-14 21:24   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:24 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Early platform devices can have devres objects allocated in
> early_probe(). This is not a bug so don't dump stack in this case.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 03/12] platform/early: export platform_match() locally
  2018-05-11 16:20 ` [PATCH 03/12] platform/early: export platform_match() locally Bartosz Golaszewski
@ 2018-05-14 21:25   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:25 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> We will use this function to match devices in the early platform core
> code. Export it locally in drivers/base.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 04/12] platform: provide a separate function for initializing platform devices
  2018-05-11 16:20 ` [PATCH 04/12] platform: provide a separate function for initializing platform devices Bartosz Golaszewski
@ 2018-05-14 21:25   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:25 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> The early platform driver framework will allocate platform devices
> using its own internal mechanisms. Provide a function that allows to
> initialize a platform device object without allocating it.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 05/12] platform: export platform_device_release() locally
  2018-05-11 16:20 ` [PATCH 05/12] platform: export platform_device_release() locally Bartosz Golaszewski
@ 2018-05-14 21:25   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:25 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> The early platform driver mechanism will use this function as the
> device release callback. Make it available in drivers/base.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 06/12] of: add a new flag for OF device nodes
  2018-05-11 16:20 ` [PATCH 06/12] of: add a new flag for OF device nodes Bartosz Golaszewski
@ 2018-05-14 21:25   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:25 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> This flag indicates that a device node has been populated early and
> that it needs different handling when called from
> of_platform_populate().
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 07/12] of/platform: provide a separate routine for setting up device resources
  2018-05-11 16:20 ` [PATCH 07/12] of/platform: provide a separate routine for setting up device resources Bartosz Golaszewski
@ 2018-05-14 21:26   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:26 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> The early platform driver framework will need to setup the device
> resources before the regular populating of the device tree happens.
>
> Provide a separate function for that.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 08/12] of/platform: provide a separate routine for device initialization
  2018-05-11 16:20 ` [PATCH 08/12] of/platform: provide a separate routine for device initialization Bartosz Golaszewski
@ 2018-05-14 21:26   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:26 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> The early platform device framework will need to initialize the
> platform device objects without them being allocated in
> of_device_alloc(). Provide a routine that allows it.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 09/12] platform/early: add an init section for early driver data
  2018-05-11 16:20 ` [PATCH 09/12] platform/early: add an init section for early driver data Bartosz Golaszewski
@ 2018-05-14 21:29   ` Geert Uytterhoeven
  2018-05-15  8:41     ` Bartosz Golaszewski
  0 siblings, 1 reply; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:29 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

Hi Bartosz,

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Provide a separate section in which pointers to early platform driver
> structs will be stored.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Thanks for your patch!

> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -214,6 +214,16 @@
>  #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
>  #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
>
> +#ifdef CONFIG_EARLY_PLATFORM
> +#define EARLY_PLATFORM_DRIVERS_TABLE()                                 \
> +       . = ALIGN(8);                                                   \

Should this use STRUCT_ALIGN() instead?

> +       VMLINUX_SYMBOL(__early_platform_drivers_table) = .;             \
> +       KEEP(*(__early_platform_drivers_table))                         \
> +       VMLINUX_SYMBOL(__early_platform_drivers_table_end) = .;
> +#else
> +#define EARLY_PLATFORM_DRIVERS_TABLE()
> +#endif

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 12/12] of/platform: make the OF code aware of early platform drivers
  2018-05-11 16:20 ` [PATCH 12/12] of/platform: make the OF code aware of early platform drivers Bartosz Golaszewski
@ 2018-05-14 21:32   ` Geert Uytterhoeven
  0 siblings, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-14 21:32 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

Hi Bartosz,

On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Check the relevant flag in the device node and skip the allocation
> part for devices that were populated early.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Thanks for your patch!

> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c

> @@ -196,9 +197,17 @@ static struct platform_device *of_platform_device_create_pdata(
>             of_node_test_and_set_flag(np, OF_POPULATED))
>                 return NULL;
>
> -       dev = of_device_alloc(np, bus_id, parent);
> -       if (!dev)
> -               goto err_clear_flag;
> +       if (of_node_check_flag(np, OF_POPULATED_EARLY)) {
> +               dev = of_early_to_platform_device(np);
> +               if (IS_ERR(dev))
> +                       goto err_clear_flag;
> +
> +               of_device_init(dev, np, bus_id, parent);
> +       } else {
> +               dev = of_device_alloc(np, bus_id, parent);
> +               if (!dev)
> +                       goto err_clear_flag;
> +       }

The above may become cleaner if:
  1. of_early_to_platform_device() would return NULL instead -ENOENT,
  2. of_device_alloc() would be split in alloc and init phases, too.

Then you can do:

        dev = of_node_check_flag(np, OF_POPULATED_EARLY)
                ? of_early_to_platform_device(np)
                 : __of_device_alloc(np, bus_id, parent);
        if (!dev)
                goto err_clear_flag;

        of_device_init(dev, np, bus_id, parent);

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 09/12] platform/early: add an init section for early driver data
  2018-05-14 21:29   ` Geert Uytterhoeven
@ 2018-05-15  8:41     ` Bartosz Golaszewski
  0 siblings, 0 replies; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-15  8:41 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Magnus Damm, Johan Hovold, Rob Herring,
	Frank Rowand, Linux ARM, Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Arch, Bartosz Golaszewski

2018-05-14 23:29 GMT+02:00 Geert Uytterhoeven <geert@linux-m68k.org>:
> Hi Bartosz,
>
> On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>
>> Provide a separate section in which pointers to early platform driver
>> structs will be stored.
>>
>> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Thanks for your patch!
>
>> --- a/include/asm-generic/vmlinux.lds.h
>> +++ b/include/asm-generic/vmlinux.lds.h
>> @@ -214,6 +214,16 @@
>>  #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
>>  #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
>>
>> +#ifdef CONFIG_EARLY_PLATFORM
>> +#define EARLY_PLATFORM_DRIVERS_TABLE()                                 \
>> +       . = ALIGN(8);                                                   \
>
> Should this use STRUCT_ALIGN() instead?
>

No, we're only using it to store pointers to structs, not the actual
struct early_platform_driver objects.

>> +       VMLINUX_SYMBOL(__early_platform_drivers_table) = .;             \
>> +       KEEP(*(__early_platform_drivers_table))                         \
>> +       VMLINUX_SYMBOL(__early_platform_drivers_table_end) = .;
>> +#else
>> +#define EARLY_PLATFORM_DRIVERS_TABLE()
>> +#endif
>
> Gr{oetje,eeting}s,
>
>                         Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds

Thanks,
Bartosz

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

* Re: [PATCH 10/12] platform/early: implement support for early platform drivers
  2018-05-14 13:37   ` Rob Herring
@ 2018-05-15 14:06     ` Bartosz Golaszewski
  2018-05-16  1:06       ` Rob Herring
  0 siblings, 1 reply; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-05-15 14:06 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES, Bartosz Golaszewski

2018-05-14 15:37 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>
>> This introduces the core part of support for early platform drivers
>> and devices.
>>
>
> It looks like most of your prep patches are to separate the alloc and
> init of platform devices because you are essentially making early
> devices/drivers a sub-class. Maybe you could avoid doing that and
> simplify things a bit. Comments below based on doing that...
>

My aim was to change as little as possible for everybody else while
fixing our problem. These changes are already controversial enough
without risky reusing of existing fields in common structures. I was
just afraid that there are too many intricacies for it to be safe.

>> +/**
>> + * struct early_platform_driver
>> + *
>> + * @pdrv: real platform driver associated with this early platform driver
>> + * @list: list head for the list of early platform drivers
>> + * @early_probe: early probe callback
>> + */
>> +struct early_platform_driver {
>> +       struct platform_driver pdrv;
>> +       struct list_head list;
>
> Couldn't you use an existing list in driver_private until you move
> over to the normal bus infra.
>

This is something that the previous implementation did. It was quite
unreadable, so I decided to go with a separate list.

>> +       int (*early_probe)(struct platform_device *);
>
> Just add this to platform_driver.
>

This would extend the structure for everybody else while there'll be
very few such devices and not all systems would even require it.

>> +};
>> +
>> +/**
>> + * struct early_platform_device
>> + *
>> + * @pdev: real platform device associated with this early platform device
>> + * @list: list head for the list of early platform devices
>> + * @deferred: true if this device's early probe was deferred
>> + * @deferred_drv: early platform driver with which this device was matched
>> + */
>> +struct early_platform_device {
>> +       struct platform_device pdev;
>> +       struct list_head list;
>
> Use a list in device_private?
>
>> +       bool deferred;
>> +       struct early_platform_driver *deferred_drv;
>
> Can't you use the existing deferred probe list?
>

I thought about it, but I was afraid there could be some timing issues
with that and decided against it. The early deferral also doesn't work
in a workque, but is synchronous instead.

Best regards,
Bartosz Golaszewski

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

* Re: [PATCH 10/12] platform/early: implement support for early platform drivers
  2018-05-15 14:06     ` Bartosz Golaszewski
@ 2018-05-16  1:06       ` Rob Herring
  0 siblings, 0 replies; 35+ messages in thread
From: Rob Herring @ 2018-05-16  1:06 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES, Bartosz Golaszewski

On Tue, May 15, 2018 at 9:06 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> 2018-05-14 15:37 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
>> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>>
>>> This introduces the core part of support for early platform drivers
>>> and devices.
>>>
>>
>> It looks like most of your prep patches are to separate the alloc and
>> init of platform devices because you are essentially making early
>> devices/drivers a sub-class. Maybe you could avoid doing that and
>> simplify things a bit. Comments below based on doing that...
>>
>
> My aim was to change as little as possible for everybody else while
> fixing our problem. These changes are already controversial enough
> without risky reusing of existing fields in common structures. I was
> just afraid that there are too many intricacies for it to be safe.

I don't think those intricacies would go away just by having separate
fields. Perhaps it would make things fail more explicitly. After all,
I think it needs to be a very atomic operation when a device is
switched.

>>> +/**
>>> + * struct early_platform_driver
>>> + *
>>> + * @pdrv: real platform driver associated with this early platform driver
>>> + * @list: list head for the list of early platform drivers
>>> + * @early_probe: early probe callback
>>> + */
>>> +struct early_platform_driver {
>>> +       struct platform_driver pdrv;
>>> +       struct list_head list;
>>
>> Couldn't you use an existing list in driver_private until you move
>> over to the normal bus infra.
>>
>
> This is something that the previous implementation did. It was quite
> unreadable, so I decided to go with a separate list.
>
>>> +       int (*early_probe)(struct platform_device *);
>>
>> Just add this to platform_driver.
>>
>
> This would extend the structure for everybody else while there'll be
> very few such devices and not all systems would even require it.
>
>>> +};
>>> +
>>> +/**
>>> + * struct early_platform_device
>>> + *
>>> + * @pdev: real platform device associated with this early platform device
>>> + * @list: list head for the list of early platform devices
>>> + * @deferred: true if this device's early probe was deferred
>>> + * @deferred_drv: early platform driver with which this device was matched
>>> + */
>>> +struct early_platform_device {
>>> +       struct platform_device pdev;
>>> +       struct list_head list;
>>
>> Use a list in device_private?
>>
>>> +       bool deferred;
>>> +       struct early_platform_driver *deferred_drv;
>>
>> Can't you use the existing deferred probe list?
>>
>
> I thought about it, but I was afraid there could be some timing issues
> with that and decided against it. The early deferral also doesn't work
> in a workque, but is synchronous instead.

I didn't mean use the wq, but just the list fields. You'd still have
the early list and normal list with different list heads. If you ever
had a device wanting to be on both lists at the same time, then you've
got major problems.

Rob

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-14 13:20     ` Rob Herring
@ 2018-05-30 19:40       ` Michael Turquette
  2018-05-30 22:36         ` Rob Herring
  0 siblings, 1 reply; 35+ messages in thread
From: Michael Turquette @ 2018-05-30 19:40 UTC (permalink / raw)
  To: Bartosz Golaszewski, Rob Herring
  Cc: Sekhar Nori, Kevin Hilman, David Lechner, Stephen Boyd,
	Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland, Yoshinori Sato,
	Rich Felker, Andy Shevchenko, Marc Zyngier, Rafael J . Wysocki,
	Peter Rosin, Jiri Slaby, Thomas Gleixner, Daniel Lezcano,
	Geert Uytterhoeven, Magnus Damm, Johan Hovold, Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

Hi Rob,

Quoting Rob Herring (2018-05-14 06:20:57)
> On Mon, May 14, 2018 at 6:38 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > 2018-05-11 22:13 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
> >> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> >>> This series is a follow-up to the RFC[1] posted a couple days ago.
> >>>
> >>> NOTE: this series applies on top of my recent patches[2] that move the previous
> >>> implementation of early platform devices to arch/sh.
> >>>
> >>> Problem:
> >>>
> >>> Certain class of devices, such as timers, certain clock drivers and irq chip
> >>> drivers need to be probed early in the boot sequence. The currently preferred
> >>> approach is using one of the OF_DECLARE() macros. This however does not create
> >>> a platform device which has many drawbacks - such as not being able to use
> >>> devres routines, dev_ log functions or no way of deferring the init OF function
> >>> if some other resources are missing.
> >>
> >> I skimmed though this and it doesn't look horrible (how's that for
> >> positive feedback? ;) ). But before going into the details, I think
> >> first there needs to be agreement this is the right direction.
> >>
> >> The question does remain though as to whether this class of devices
> >> should be platform drivers. They can't be modules. They can't be
> >> hotplugged. Can they be runtime-pm enabled? So the advantage is ...
> >>
> >
> > The main (but not the only) advantage for drivers that can both be
> > platform drivers and OF_DECLARE drivers is that we get a single entry
> > point and can reuse code without resorting to checking if (!dev). It
> > results in more consistent code base. Another big advantage is
> > consolidation of device tree and machine code for SoC drivers used in
> > different boards of which some are still using board files and others
> > are defined in DT (see: DaVinci).
> >
> >> I assume that the clock maintainers had some reason to move clocks to
> >> be platform drivers. It's just not clear to me what that was.
> >>
> >>> For drivers that use both platform drivers and OF_DECLARE the situation is even
> >>> more complicated as the code needs to take into account that there can possibly
> >>> be no struct device present. For a specific use case that we're having problems
> >>> with, please refer to the recent DaVinci common-clock conversion patches and
> >>> the nasty workaround that this problem implies[3].
> >>
> >> So devm_kzalloc will work with this solution? Why did we need
> >> devm_kzalloc in the first place? The clocks can never be removed and
> >> cleaning up on error paths is kind of pointless. The system would be
> >> hosed, right?
> >>
> >
> > It depends - not all clocks are necessary for system to boot.
> 
> That doesn't matter. You have a single driver for all/most of the
> clocks, so the driver can't be removed.

-ECANOFWORMS

A couple of quick rebuttals, but I imagine we're going to disagree on
the platform_driver thing as a matter of taste no matter what...

1) There should be multiple clk drivers in a properly modeled system.
Some folks still incorrectly put all clocks in a system into a single
driver because That's How We Used To Do It, and some systems (simpler
ones) really only have a single clock generator IP block.

Excepting those two reasons above, we really should have separate
drivers for clocks controlled by the PMIC, for the (one or more) clock
generator blocks inside of the AP/SoC, and then even more for the
drivers that map to IP blocks that have their own clock gens.

Good examples of the latter are display controllers that generate their
own PLL and pixel clock. Or MMC controllers that have a
runtime-programmable clock divider. Examples of these are merged into
mainline.

2) Stephen and I wanted clock drivers to actually be represented in the
driver model. There were these gigantic clock drivers that exclusively
used CLK_OF_DECLARE and they just sort of floated out there in the
ether... no representation in sysfs, no struct device to map onto a
clock controller struct, etc.

I'd be happy to hear why you think that platform_driver is a bad fit for
a device driver that generally manages memory-mapped system resources
that are part of the system glue and not really tied to a specific bus.
Sounds like a good fit to me.

If platform_driver doesn't handle the early boot thing well, that tells
me that we have a problem to solve in platform_driver, not in the clk
subsystem or drivers.

3) Lots of clock controllers should be loadable modules. E.g. i2c clock
expanders, potentially external PMIC-related drivers, external audio
codecs, etc.

Again, repeating my point #1 above, just because many platforms have a
monolithic clock driver does not mean that this is the Right Way to do
it.

Best regards,
Mike

> 
> >>> We also used to have an early platform drivers implementation but they were not
> >>> integrated with the linux device model at all - they merely used the same data
> >>> structures. The users could not use devres, defer probe and the early devices
> >>> never became actual platform devices later on.
> >>>
> >>> Proposed solution:
> >>>
> >>> This series aims at solving this problem by (re-)introducing the concept of
> >>> early platform drivers and devices - this time however in a way that seamlessly
> >>> integrates with the existing platform drivers and also offers device-tree
> >>> support.
> >>>
> >>> The idea is to provide a way for users to probe devices early, while already
> >>> being able to use devres, devices resources and properties and also deferred
> >>> probing.
> >>>
> >>> New structures are introduced: the early platform driver contains the
> >>> early_probe callback which has the same signature as regular platform_device
> >>> probe. This callback is called early on. The user can have both the early and
> >>> regular probe speficied or only one of them and they both receive the same
> >>> platform device object as argument. Any device data allocated early will be
> >>> carried over to the normal probe.
> >>>
> >>> The architecture code is responsible for calling early_platform_start() in
> >>> which the early drivers will be registered and devices populated from DT.
> >>
> >> Can we really do this in one spot for different devices (clk, timers,
> >> irq). The sequence is all very carefully crafted. Platform specific
> >> hooks is another thing to consider.
> >>
> >
> > This is why I added support for early probe deferral - so that we can
> > stop caring for the order as long as the drivers are aware of other
> > resources they need and we call early_platform_start() the moment the
> > earliest of the early devices is needed.
> 
> Deferred probe helps for inter-device dependencies, but I am more
> concerned about timing of trying to register clocksources, irqchips,
> etc. What happens if we probe drivers before the infrastructure is
> initialized?
> 
> Rob

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-30 19:40       ` Michael Turquette
@ 2018-05-30 22:36         ` Rob Herring
  2018-05-31  6:42           ` Geert Uytterhoeven
  0 siblings, 1 reply; 35+ messages in thread
From: Rob Herring @ 2018-05-30 22:36 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Bartosz Golaszewski, Sekhar Nori, Kevin Hilman, David Lechner,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

On Wed, May 30, 2018 at 2:40 PM, Michael Turquette
<mturquette@baylibre.com> wrote:
> Hi Rob,
>
> Quoting Rob Herring (2018-05-14 06:20:57)
>> On Mon, May 14, 2018 at 6:38 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> > 2018-05-11 22:13 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
>> >> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> >>> This series is a follow-up to the RFC[1] posted a couple days ago.
>> >>>
>> >>> NOTE: this series applies on top of my recent patches[2] that move the previous
>> >>> implementation of early platform devices to arch/sh.
>> >>>
>> >>> Problem:
>> >>>
>> >>> Certain class of devices, such as timers, certain clock drivers and irq chip
>> >>> drivers need to be probed early in the boot sequence. The currently preferred
>> >>> approach is using one of the OF_DECLARE() macros. This however does not create
>> >>> a platform device which has many drawbacks - such as not being able to use
>> >>> devres routines, dev_ log functions or no way of deferring the init OF function
>> >>> if some other resources are missing.
>> >>
>> >> I skimmed though this and it doesn't look horrible (how's that for
>> >> positive feedback? ;) ). But before going into the details, I think
>> >> first there needs to be agreement this is the right direction.
>> >>
>> >> The question does remain though as to whether this class of devices
>> >> should be platform drivers. They can't be modules. They can't be
>> >> hotplugged. Can they be runtime-pm enabled? So the advantage is ...
>> >>
>> >
>> > The main (but not the only) advantage for drivers that can both be
>> > platform drivers and OF_DECLARE drivers is that we get a single entry
>> > point and can reuse code without resorting to checking if (!dev). It
>> > results in more consistent code base. Another big advantage is
>> > consolidation of device tree and machine code for SoC drivers used in
>> > different boards of which some are still using board files and others
>> > are defined in DT (see: DaVinci).
>> >
>> >> I assume that the clock maintainers had some reason to move clocks to
>> >> be platform drivers. It's just not clear to me what that was.
>> >>
>> >>> For drivers that use both platform drivers and OF_DECLARE the situation is even
>> >>> more complicated as the code needs to take into account that there can possibly
>> >>> be no struct device present. For a specific use case that we're having problems
>> >>> with, please refer to the recent DaVinci common-clock conversion patches and
>> >>> the nasty workaround that this problem implies[3].
>> >>
>> >> So devm_kzalloc will work with this solution? Why did we need
>> >> devm_kzalloc in the first place? The clocks can never be removed and
>> >> cleaning up on error paths is kind of pointless. The system would be
>> >> hosed, right?
>> >>
>> >
>> > It depends - not all clocks are necessary for system to boot.
>>
>> That doesn't matter. You have a single driver for all/most of the
>> clocks, so the driver can't be removed.
>
> -ECANOFWORMS
>
> A couple of quick rebuttals, but I imagine we're going to disagree on
> the platform_driver thing as a matter of taste no matter what...

It's really more should the clocksource, clockevents and primary
interrupt controller be drivers. Let's get agreement on that first. If
yes, then it probably does make sense that their dependencies are
drivers too. If not, then making only the dependencies drivers doesn't
seem right to me.

> 1) There should be multiple clk drivers in a properly modeled system.
> Some folks still incorrectly put all clocks in a system into a single
> driver because That's How We Used To Do It, and some systems (simpler
> ones) really only have a single clock generator IP block.
>
> Excepting those two reasons above, we really should have separate
> drivers for clocks controlled by the PMIC, for the (one or more) clock
> generator blocks inside of the AP/SoC, and then even more for the
> drivers that map to IP blocks that have their own clock gens.

I agree those should be separate entities at least. But for a given
h/w block, if you already have to use OF_DECLARE, why would you try to
split that into OF_DECLARE and a driver? what advantage does putting
non-boot essential clocks in a driver or transitioning to a driver get
you?

And I've seen PMIC clocks could be inputs to the SoC's clock
controller(s), so the dependencies get more complicated. Then does the
PMIC driver and its dependencies need to be early drivers too?

> Good examples of the latter are display controllers that generate their
> own PLL and pixel clock. Or MMC controllers that have a
> runtime-programmable clock divider. Examples of these are merged into
> mainline.

But those are drivers of types other than a clock controller that
happen to register some clocks as well. I wasn't saying these cases
can't or shouldn't be part of the driver model. Look at irqchips. We
have some that use the driver model (e.g. every GPIO driver) and some
that don't because there's no need (e.g. GIC).

> 2) Stephen and I wanted clock drivers to actually be represented in the
> driver model. There were these gigantic clock drivers that exclusively
> used CLK_OF_DECLARE and they just sort of floated out there in the
> ether... no representation in sysfs, no struct device to map onto a
> clock controller struct, etc.
>
> I'd be happy to hear why you think that platform_driver is a bad fit for
> a device driver that generally manages memory-mapped system resources
> that are part of the system glue and not really tied to a specific bus.
> Sounds like a good fit to me.
>
> If platform_driver doesn't handle the early boot thing well, that tells
> me that we have a problem to solve in platform_driver, not in the clk
> subsystem or drivers.

Doing things earlier is not the only way to solve the problems.
Perhaps we need to figure out how to start things later. Maybe it's
not feasible here, I don't know.

> 3) Lots of clock controllers should be loadable modules. E.g. i2c clock
> expanders, potentially external PMIC-related drivers, external audio
> codecs, etc.
>
> Again, repeating my point #1 above, just because many platforms have a
> monolithic clock driver does not mean that this is the Right Way to do
> it.

And in those cases, I completely agree they should be part of a driver.

Rob

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-30 22:36         ` Rob Herring
@ 2018-05-31  6:42           ` Geert Uytterhoeven
  2018-05-31 14:16             ` Tony Lindgren
  0 siblings, 1 reply; 35+ messages in thread
From: Geert Uytterhoeven @ 2018-05-31  6:42 UTC (permalink / raw)
  To: Rob Herring
  Cc: Michael Turquette, Bartosz Golaszewski, Sekhar Nori,
	Kevin Hilman, David Lechner, Stephen Boyd, Arnd Bergmann,
	Greg Kroah-Hartman, Mark Rutland, Yoshinori Sato, Rich Felker,
	Andy Shevchenko, Marc Zyngier, Rafael J . Wysocki, Peter Rosin,
	Jiri Slaby, Thomas Gleixner, Daniel Lezcano, Magnus Damm,
	Johan Hovold, Frank Rowand,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-kernel, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

Hi Rob,

On Thu, May 31, 2018 at 12:36 AM, Rob Herring <robh+dt@kernel.org> wrote:
> On Wed, May 30, 2018 at 2:40 PM, Michael Turquette
> <mturquette@baylibre.com> wrote:
>> Quoting Rob Herring (2018-05-14 06:20:57)
>>> On Mon, May 14, 2018 at 6:38 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>> > 2018-05-11 22:13 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
>>> >> On Fri, May 11, 2018 at 11:20 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>> >>> This series is a follow-up to the RFC[1] posted a couple days ago.
>>> >>>
>>> >>> NOTE: this series applies on top of my recent patches[2] that move the previous
>>> >>> implementation of early platform devices to arch/sh.
>>> >>>
>>> >>> Problem:
>>> >>>
>>> >>> Certain class of devices, such as timers, certain clock drivers and irq chip
>>> >>> drivers need to be probed early in the boot sequence. The currently preferred
>>> >>> approach is using one of the OF_DECLARE() macros. This however does not create
>>> >>> a platform device which has many drawbacks - such as not being able to use
>>> >>> devres routines, dev_ log functions or no way of deferring the init OF function
>>> >>> if some other resources are missing.
>>> >>
>>> >> I skimmed though this and it doesn't look horrible (how's that for
>>> >> positive feedback? ;) ). But before going into the details, I think
>>> >> first there needs to be agreement this is the right direction.
>>> >>
>>> >> The question does remain though as to whether this class of devices
>>> >> should be platform drivers. They can't be modules. They can't be
>>> >> hotplugged. Can they be runtime-pm enabled? So the advantage is ...
>>> >>
>>> >
>>> > The main (but not the only) advantage for drivers that can both be
>>> > platform drivers and OF_DECLARE drivers is that we get a single entry
>>> > point and can reuse code without resorting to checking if (!dev). It
>>> > results in more consistent code base. Another big advantage is
>>> > consolidation of device tree and machine code for SoC drivers used in
>>> > different boards of which some are still using board files and others
>>> > are defined in DT (see: DaVinci).
>>> >
>>> >> I assume that the clock maintainers had some reason to move clocks to
>>> >> be platform drivers. It's just not clear to me what that was.
>>> >>
>>> >>> For drivers that use both platform drivers and OF_DECLARE the situation is even
>>> >>> more complicated as the code needs to take into account that there can possibly
>>> >>> be no struct device present. For a specific use case that we're having problems
>>> >>> with, please refer to the recent DaVinci common-clock conversion patches and
>>> >>> the nasty workaround that this problem implies[3].
>>> >>
>>> >> So devm_kzalloc will work with this solution? Why did we need
>>> >> devm_kzalloc in the first place? The clocks can never be removed and
>>> >> cleaning up on error paths is kind of pointless. The system would be
>>> >> hosed, right?
>>> >>
>>> >
>>> > It depends - not all clocks are necessary for system to boot.
>>>
>>> That doesn't matter. You have a single driver for all/most of the
>>> clocks, so the driver can't be removed.
>>
>> -ECANOFWORMS
>>
>> A couple of quick rebuttals, but I imagine we're going to disagree on
>> the platform_driver thing as a matter of taste no matter what...
>
> It's really more should the clocksource, clockevents and primary
> interrupt controller be drivers. Let's get agreement on that first. If
> yes, then it probably does make sense that their dependencies are
> drivers too. If not, then making only the dependencies drivers doesn't
> seem right to me.

Yes, they should all be drivers.

Assuming clocksources, clockevents, or primary interrupt controllers are
special, and thus forcing everyone to use OF_DECLARE for the whole
subsystem, doesn't fly everywhere.

Clockevents and interrupt controllers can have a module clock.
All three can be part of a PM Domain, which requires a struct device to
be handled properly.

>> 1) There should be multiple clk drivers in a properly modeled system.
>> Some folks still incorrectly put all clocks in a system into a single
>> driver because That's How We Used To Do It, and some systems (simpler
>> ones) really only have a single clock generator IP block.
>>
>> Excepting those two reasons above, we really should have separate
>> drivers for clocks controlled by the PMIC, for the (one or more) clock
>> generator blocks inside of the AP/SoC, and then even more for the
>> drivers that map to IP blocks that have their own clock gens.
>
> I agree those should be separate entities at least. But for a given
> h/w block, if you already have to use OF_DECLARE, why would you try to
> split that into OF_DECLARE and a driver? what advantage does putting
> non-boot essential clocks in a driver or transitioning to a driver get
> you?

You may want to split it because of dependencies. OF_DECLARE
doesn't handle EPROBE_DEFER, while some critical parts may be
needed early.

> And I've seen PMIC clocks could be inputs to the SoC's clock
> controller(s), so the dependencies get more complicated. Then does the
> PMIC driver and its dependencies need to be early drivers too?

Especially if there are clock loops, but that's something different.
Cfr. cs2000 in arch/arm64/boot/dts/renesas/salvator-common.dtsi, which
provides a clock from the main SoC, but also consumes a clock from the main
SoC. The latter is modeled in DT as a fixed-clock as a workaround.

>> Good examples of the latter are display controllers that generate their
>> own PLL and pixel clock. Or MMC controllers that have a
>> runtime-programmable clock divider. Examples of these are merged into
>> mainline.
>
> But those are drivers of types other than a clock controller that
> happen to register some clocks as well. I wasn't saying these cases
> can't or shouldn't be part of the driver model. Look at irqchips. We
> have some that use the driver model (e.g. every GPIO driver) and some
> that don't because there's no need (e.g. GIC).

There is a need for using the driver model for the GIC. On some platforms,
the GIC can be part of a clock and/or power domain.

For secondary GICs, that got fixed in commit 9c8edddfc9924cb4
("irqchip/gic: Add platform driver for non-root GICs that require RPM").
For primary GICs, it's still not fixed, so we have to live with
CLK_IS_CRITICAL, and rely on other critical devices in the same power
domain to avoid the power domain being powered off.

>> 2) Stephen and I wanted clock drivers to actually be represented in the
>> driver model. There were these gigantic clock drivers that exclusively
>> used CLK_OF_DECLARE and they just sort of floated out there in the
>> ether... no representation in sysfs, no struct device to map onto a
>> clock controller struct, etc.
>>
>> I'd be happy to hear why you think that platform_driver is a bad fit for
>> a device driver that generally manages memory-mapped system resources
>> that are part of the system glue and not really tied to a specific bus.
>> Sounds like a good fit to me.
>>
>> If platform_driver doesn't handle the early boot thing well, that tells
>> me that we have a problem to solve in platform_driver, not in the clk
>> subsystem or drivers.
>
> Doing things earlier is not the only way to solve the problems.
> Perhaps we need to figure out how to start things later. Maybe it's
> not feasible here, I don't know.

The fixed probe order imposed by OF_DECLARE() limits this: if your
OF_DECLARE() driver depends on something else, the latter must become an
early device.
If all subsystems would use real devices, EPROBE_DEFER would handle most of
it automatically.

Then, next step would be to avoid triggering EPROBE_DEFER, e.g. by
analyzing dependencies in DT...

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-31  6:42           ` Geert Uytterhoeven
@ 2018-05-31 14:16             ` Tony Lindgren
  0 siblings, 0 replies; 35+ messages in thread
From: Tony Lindgren @ 2018-05-31 14:16 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Rob Herring, Mark Rutland, Rich Felker, Michael Turquette,
	Sekhar Nori, Frank Rowand,
	open list:GENERIC INCLUDE/ASM HEADER FILES, Yoshinori Sato,
	Kevin Hilman, Bartosz Golaszewski, Rafael J . Wysocki,
	Magnus Damm, Andy Shevchenko, Jiri Slaby, devicetree,
	David Lechner, Arnd Bergmann, Marc Zyngier, Johan Hovold,
	Thomas Gleixner,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	Daniel Lezcano, Stephen Boyd, Greg Kroah-Hartman, linux-kernel,
	Peter Rosin

* Geert Uytterhoeven <geert@linux-m68k.org> [180531 06:45]:
> Yes, they should all be drivers.
> 
> Assuming clocksources, clockevents, or primary interrupt controllers are
> special, and thus forcing everyone to use OF_DECLARE for the whole
> subsystem, doesn't fly everywhere.
> 
> Clockevents and interrupt controllers can have a module clock.
> All three can be part of a PM Domain, which requires a struct device to
> be handled properly.

I agree it sure would be nice to have all these as drivers. I believe
SoC specific clockevent using SoC specific clocks is the reason why some
clocks cannot currently be drivers.

Regards,

Tony

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

* Re: [PATCH 00/12] introduce support for early platform drivers
  2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
                   ` (12 preceding siblings ...)
  2018-05-11 20:13 ` [PATCH 00/12] introduce support for " Rob Herring
@ 2018-10-19 12:08 ` Bartosz Golaszewski
  13 siblings, 0 replies; 35+ messages in thread
From: Bartosz Golaszewski @ 2018-10-19 12:08 UTC (permalink / raw)
  To: Sekhar Nori, Kevin Hilman, David Lechner, Michael Turquette,
	Stephen Boyd, Arnd Bergmann, Greg Kroah-Hartman, Mark Rutland,
	Yoshinori Sato, Rich Felker, Andy Shevchenko, Marc Zyngier,
	Rafael J . Wysocki, Peter Rosin, Jiri Slaby, Thomas Gleixner,
	Daniel Lezcano, Geert Uytterhoeven, Magnus Damm, Johan Hovold,
	Rob Herring, Frank Rowand
  Cc: Linux ARM, Linux Kernel Mailing List, devicetree,
	open list:GENERIC INCLUDE/ASM HEADER FILES

pt., 11 maj 2018 o 18:21 Bartosz Golaszewski <brgl@bgdev.pl> napisał(a):
>
> This series is a follow-up to the RFC[1] posted a couple days ago.
>
> NOTE: this series applies on top of my recent patches[2] that move the previous
> implementation of early platform devices to arch/sh.
>
> Problem:
>
> Certain class of devices, such as timers, certain clock drivers and irq chip
> drivers need to be probed early in the boot sequence. The currently preferred
> approach is using one of the OF_DECLARE() macros. This however does not create
> a platform device which has many drawbacks - such as not being able to use
> devres routines, dev_ log functions or no way of deferring the init OF function
> if some other resources are missing.
>
> For drivers that use both platform drivers and OF_DECLARE the situation is even
> more complicated as the code needs to take into account that there can possibly
> be no struct device present. For a specific use case that we're having problems
> with, please refer to the recent DaVinci common-clock conversion patches and
> the nasty workaround that this problem implies[3].
>
> We also used to have an early platform drivers implementation but they were not
> integrated with the linux device model at all - they merely used the same data
> structures. The users could not use devres, defer probe and the early devices
> never became actual platform devices later on.
>
> Proposed solution:
>
> This series aims at solving this problem by (re-)introducing the concept of
> early platform drivers and devices - this time however in a way that seamlessly
> integrates with the existing platform drivers and also offers device-tree
> support.
>
> The idea is to provide a way for users to probe devices early, while already
> being able to use devres, devices resources and properties and also deferred
> probing.
>
> New structures are introduced: the early platform driver contains the
> early_probe callback which has the same signature as regular platform_device
> probe. This callback is called early on. The user can have both the early and
> regular probe speficied or only one of them and they both receive the same
> platform device object as argument. Any device data allocated early will be
> carried over to the normal probe.
>
> The architecture code is responsible for calling early_platform_start() in
> which the early drivers will be registered and devices populated from DT.
>
> Once the device and kobject mechanisms are ready, all early drivers and devices
> will be converted into real platform drivers and devices. Also: if any of the
> early platform registration functions will be called once early initialization
> is done, these functions will work like regular platform_device/driver ones.
>
> Patches 1-9/12 introduce changes to existing code that are necessary before
> adding support for early drivers. Patch 10/12 contains the new framwork in an
> isolated file which can be compiled only if needed by the architecture.
>
> Patch 11/12 contains a dummy early platform driver that serves as a code
> example and can be used for simple testing.
>
> The last patch finally makes the of/platform code aware of early platform
> drivers.
>
> If accepted, this new mechanism could potentially lead to consolidation of the
> code currently used by users of OF_DECLARE, since they could be converted to
> actual platform drivers.
>
> [1] https://lkml.org/lkml/2018/4/26/657
> [2] https://lkml.org/lkml/2018/4/30/547
> [3] https://lkml.org/lkml/2018/4/26/1094
>
> Bartosz Golaszewski (12):
>   platform/early: add a new field to struct device
>   platform/early: don't WARN() on non-empty devres list for early
>     devices
>   platform/early: export platform_match() locally
>   platform: provide a separate function for initializing platform
>     devices
>   platform: export platform_device_release() locally
>   of: add a new flag for OF device nodes
>   of/platform: provide a separate routine for setting up device
>     resources
>   of/platform: provide a separate routine for device initialization
>   platform/early: add an init section for early driver data
>   platform/early: implement support for early platform drivers
>   misc: implement a dummy early platform driver
>   of/platform: make the OF code aware of early platform drivers
>
>  drivers/base/Kconfig              |   3 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/base.h               |   4 +
>  drivers/base/dd.c                 |   2 +-
>  drivers/base/early.c              | 332 ++++++++++++++++++++++++++++++
>  drivers/base/platform.c           |  28 ++-
>  drivers/misc/Kconfig              |   8 +
>  drivers/misc/Makefile             |   2 +
>  drivers/misc/dummy-early.c        |  82 ++++++++
>  drivers/of/platform.c             |  85 +++++---
>  include/asm-generic/vmlinux.lds.h |  11 +
>  include/linux/device.h            |   1 +
>  include/linux/early_platform.h    |  75 +++++++
>  include/linux/of.h                |   1 +
>  include/linux/of_platform.h       |   2 +
>  include/linux/platform_device.h   |   2 +
>  16 files changed, 604 insertions(+), 35 deletions(-)
>  create mode 100644 drivers/base/early.c
>  create mode 100644 drivers/misc/dummy-early.c
>  create mode 100644 include/linux/early_platform.h
>
> --
> 2.17.0
>

Hi

For anyone interested: I'll be doing a BoF about early platform
drivers next week on Monday at 6:00pm during the ELCE 2018 in
Edinburgh. It would be great to discuss this topic personally.

Best regards and hope to see you there
Bartosz Golaszewski

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

end of thread, other threads:[~2018-10-19 12:09 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-11 16:20 [PATCH 00/12] introduce support for early platform drivers Bartosz Golaszewski
2018-05-11 16:20 ` [PATCH 01/12] platform/early: add a new field to struct device Bartosz Golaszewski
2018-05-14 21:24   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 02/12] platform/early: don't WARN() on non-empty devres list for early devices Bartosz Golaszewski
2018-05-14 21:24   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 03/12] platform/early: export platform_match() locally Bartosz Golaszewski
2018-05-14 21:25   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 04/12] platform: provide a separate function for initializing platform devices Bartosz Golaszewski
2018-05-14 21:25   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 05/12] platform: export platform_device_release() locally Bartosz Golaszewski
2018-05-14 21:25   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 06/12] of: add a new flag for OF device nodes Bartosz Golaszewski
2018-05-14 21:25   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 07/12] of/platform: provide a separate routine for setting up device resources Bartosz Golaszewski
2018-05-14 21:26   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 08/12] of/platform: provide a separate routine for device initialization Bartosz Golaszewski
2018-05-14 21:26   ` Geert Uytterhoeven
2018-05-11 16:20 ` [PATCH 09/12] platform/early: add an init section for early driver data Bartosz Golaszewski
2018-05-14 21:29   ` Geert Uytterhoeven
2018-05-15  8:41     ` Bartosz Golaszewski
2018-05-11 16:20 ` [PATCH 10/12] platform/early: implement support for early platform drivers Bartosz Golaszewski
2018-05-14 13:37   ` Rob Herring
2018-05-15 14:06     ` Bartosz Golaszewski
2018-05-16  1:06       ` Rob Herring
2018-05-11 16:20 ` [PATCH 11/12] misc: implement a dummy early platform driver Bartosz Golaszewski
2018-05-11 16:20 ` [PATCH 12/12] of/platform: make the OF code aware of early platform drivers Bartosz Golaszewski
2018-05-14 21:32   ` Geert Uytterhoeven
2018-05-11 20:13 ` [PATCH 00/12] introduce support for " Rob Herring
2018-05-14 11:38   ` Bartosz Golaszewski
2018-05-14 13:20     ` Rob Herring
2018-05-30 19:40       ` Michael Turquette
2018-05-30 22:36         ` Rob Herring
2018-05-31  6:42           ` Geert Uytterhoeven
2018-05-31 14:16             ` Tony Lindgren
2018-10-19 12:08 ` Bartosz Golaszewski

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).