[PATCH v2 00/37] dm: Implement OF_PLATDATA_INST in driver model (part E)

This series builds on the recent dtoc implementation of build-time device instantiation.
It adds the required driver model support, which is basically a few more data structures.
With this, sandbox_spl and chromebook_coral both use the new feature.
For coral TPL there is a 1.5KB code-size reduction and a 1.75KB data-size increase:
text data bss dec hex 18836 3080 12 21928 55a8 original 17229 4896 12 22137 5679 with OF_PLATDATA_INST 17277 4896 12 22185 56a9 with OF_PLATDATA_RT
The extra data size is due to the build-time devices which are now included in the image instead of being built at runtime. Also the private data for each device is allocated in the data region at present, even through much of it is just zeroes.
The reduction in code size is due to not needing to bind devices at runtime, as a well as a simplified probe() function. Coral requires that data be copied out to RAM before being updated, so that adds a small amount to size (shown in the third line).
Quite a lot of future work is possible, including reducing the size of data structures. See [1] for more ideas. But this series implements the basic feature.
To try this out on your board, define CONFIG_SPL_OF_PLATDATA_INST and see what you get.
Note: SPL tests do not yet pass with this series. The driver_rt struct is not set up so device_get_by_driver_info_idx() does not work. This means that looking up phandles will fail. This will be addressed in a v2 series, along with documentation updates and a little more information on code-size impact.
This series is available at u-boot-dm/tin-working
[1] https://lists.denx.de/pipermail/u-boot/2020-July/418433.html
Changes in v2: - Update to deal with test refactoring series - Use separate OF_PLATDATA_DRIVER_RT Kconfigs for driver run-time data - Update the condition for dm_test_of_plat_dev() - Leave the flags_ memeber in the same struct position
Simon Glass (37): sandbox: Drop debug message in os_spl_to_uboot() linker_lists: Allow use in data structures dm: core: Add macros to access the new linker lists dm: core: Allow dropping run-time binding of devices dm: core: Adjust uclass setup with of-platdata dm: core: Set up driver model for OF_PLATDATA_INST dm: core: Skip adding uclasses with OF_PLATDATA_INST dm: Add the new dtoc-generated files to the build dm: core: Include dt-decl.h automatically dm: test: Avoid destroying uclasses with of-platdata-inst clk: sandbox: Move priv/plat data to a header file clk: fixed-rate: Export driver parts for OF_PLATDATA_INST clk: sandbox: Create a special fixed-rate driver dm: core: Drop device_get_by_driver_info() dm: core: Drop uclass_find_device_by_phandle() with of-platdata sandbox: i2c: Move platdata structs to header files dm: Rename device_get_by_driver_info_idx() sandbox_spl: Increase SPL malloc() size sandbox: i2c: Support i2c emulation with of-platdata Revert "sandbox: Disable I2C emulators in SPL" sandbox: Create a new sandbox_noinst build test: Run sandbox_spl tests on sandbox_noinst azure/gitlab: Add tests for sandbox_noinst dm: core: Add an option to support SPL in read-only memory dm: core: Create a struct for device runtime info dm: core: Move flags to device-runtime info dm: core: Allow storing priv/plat data separately sandbox: Define a region for device priv/plat data dm: core: Use separate priv/plat data region x86: Define a region for device priv/plat data x86: apl: Fix the header order in pmc x86: apl: Tell of-platdata about a required header file x86: itss: Tidy up bind() for of-platdata-inst x86: Support a fake PCI device with of-platdata-inst x86: Don't include reset driver in SPL x86: coral: Drop ACPI properties from of-platdata x86: apl: Use read-only SPL and new of-platdata
.azure-pipelines.yml | 3 + .gitlab-ci.yml | 10 +- arch/sandbox/cpu/os.c | 1 - arch/sandbox/cpu/u-boot-spl.lds | 8 + arch/sandbox/dts/sandbox.dtsi | 12 +- arch/sandbox/include/asm/clk.h | 24 +++ arch/sandbox/include/asm/i2c.h | 15 ++ arch/sandbox/include/asm/rtc.h | 24 +++ arch/x86/cpu/apollolake/Kconfig | 2 + arch/x86/cpu/apollolake/pmc.c | 2 +- arch/x86/cpu/apollolake/punit.c | 1 + arch/x86/cpu/intel_common/itss.c | 5 +- arch/x86/cpu/u-boot-spl.lds | 8 + arch/x86/dts/reset.dtsi | 2 +- arch/x86/lib/tpl.c | 1 + board/sandbox/MAINTAINERS | 7 + common/spl/Kconfig | 24 +++ configs/chromebook_coral_defconfig | 1 + configs/sandbox_noinst_defconfig | 229 +++++++++++++++++++++++++++++ configs/sandbox_spl_defconfig | 3 + drivers/clk/clk-uclass.c | 2 +- drivers/clk/clk_fixed_rate.c | 14 +- drivers/clk/clk_sandbox.c | 40 ++++- drivers/clk/clk_sandbox_test.c | 6 - drivers/core/device.c | 107 +++++++++----- drivers/core/root.c | 85 +++++++++-- drivers/core/uclass.c | 7 +- drivers/i2c/Makefile | 2 - drivers/i2c/i2c-emul-uclass.c | 26 ++-- drivers/misc/irq-uclass.c | 2 +- drivers/mmc/fsl_esdhc_imx.c | 3 +- drivers/rtc/i2c_rtc_emul.c | 19 --- drivers/rtc/sandbox_rtc.c | 13 ++ dts/Kconfig | 58 ++++++++ include/asm-generic/global_data.h | 26 +++- include/asm-generic/sections.h | 3 + include/dm/device-internal.h | 26 ++++ include/dm/device.h | 63 +++++--- include/dm/root.h | 3 + include/dm/uclass-internal.h | 23 +++ include/dm/uclass.h | 20 +++ include/dm/util.h | 9 ++ include/dt-structs.h | 2 + include/i2c.h | 15 ++ include/linker_lists.h | 28 ++++ include/linux/clk-provider.h | 5 + scripts/Makefile.spl | 3 +- test/dm/of_platdata.c | 32 ++-- test/run | 4 + test/test-main.c | 30 ++-- 50 files changed, 885 insertions(+), 173 deletions(-) create mode 100644 configs/sandbox_noinst_defconfig

This is not needed in normal operation. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/cpu/os.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 39db636d777..4bb4caed8f9 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -797,7 +797,6 @@ int os_spl_to_uboot(const char *fname) { struct sandbox_state *state = state_get_current();
- printf("%s\n", __func__); /* U-Boot will delete ram buffer after read: "--rm_memory"*/ state->ram_buf_rm = true; return os_jump_to_file(fname);

On 03.02.21 17:43, Simon Glass wrote:
This is not needed in normal operation. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
(no changes since v1)
arch/sandbox/cpu/os.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 39db636d777..4bb4caed8f9 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -797,7 +797,6 @@ int os_spl_to_uboot(const char *fname) { struct sandbox_state *state = state_get_current();
- printf("%s\n", __func__); /* U-Boot will delete ram buffer after read: "--rm_memory"*/ state->ram_buf_rm = true; return os_jump_to_file(fname);

At present linker lists are designed for use in code. They make use of statements within expressions ({...}), for example.
It is possible to generate a reference to a linker_list entry that can be used in data structures, where such features are not permitted. It requires that the reference first be declared as extern. In other words the existing macro needs to be split into two parts.
Add new macros to support this.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
include/linker_lists.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/include/linker_lists.h b/include/linker_lists.h index fd98ecd297c..55631f0240c 100644 --- a/include/linker_lists.h +++ b/include/linker_lists.h @@ -211,6 +211,34 @@ _ll_result; \ })
+/** + * ll_entry_decl() - Declare a linker-generated array entry reference as extern + * + * This declares a reference to a list entry so that it can be used later, + * without needing the code in ll_entry_get(). + * + * To use this, put ll_entry_decl() somewhere in your file, then use + * ll_entry_ref() later on, to reference the entry. + * + * @_type: Data type of the entry + * @_name: Name of the entry + * @_list: Name of the list in which this entry is placed + */ +#define ll_entry_decl(_type, _name, _list) \ + extern _type _u_boot_list_2_##_list##_2_##_name + +/** + * ll_entry_ref() - Get a reference to a linker-generated array entry + * + * Once ll_entry_decl() has been used to declare the reference, this macro + * allows the entry to be accessed. + * + * This is like ll_entry_get(), but without the extra code, so it is suitable + * for putting into data structures. + */ +#define ll_entry_ref(_type, _name, _list) \ + ((_type *)&_u_boot_list_2_##_list##_2_##_name) + /** * ll_start() - Point to first entry of first linker-generated array * @_type: Data type of the entry

On 03.02.21 17:43, Simon Glass wrote:
At present linker lists are designed for use in code. They make use of statements within expressions ({...}), for example.
It is possible to generate a reference to a linker_list entry that can be used in data structures, where such features are not permitted. It requires that the reference first be declared as extern. In other words the existing macro needs to be split into two parts.
Add new macros to support this.
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v1)
include/linker_lists.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/include/linker_lists.h b/include/linker_lists.h index fd98ecd297c..55631f0240c 100644 --- a/include/linker_lists.h +++ b/include/linker_lists.h @@ -211,6 +211,34 @@ _ll_result; \ })
+/**
- ll_entry_decl() - Declare a linker-generated array entry reference as extern
- This declares a reference to a list entry so that it can be used later,
- without needing the code in ll_entry_get().
- To use this, put ll_entry_decl() somewhere in your file, then use
- ll_entry_ref() later on, to reference the entry.
- @_type: Data type of the entry
- @_name: Name of the entry
- @_list: Name of the list in which this entry is placed
- */
+#define ll_entry_decl(_type, _name, _list) \
- extern _type _u_boot_list_2_##_list##_2_##_name
Can't you simply add the extern keyword to ll_entry_declare()?
Why do we need entries with and entries without extern?
Best regards
Heinrich
+/**
- ll_entry_ref() - Get a reference to a linker-generated array entry
- Once ll_entry_decl() has been used to declare the reference, this macro
- allows the entry to be accessed.
- This is like ll_entry_get(), but without the extra code, so it is suitable
- for putting into data structures.
- */
+#define ll_entry_ref(_type, _name, _list) \
- ((_type *)&_u_boot_list_2_##_list##_2_##_name)
/**
- ll_start() - Point to first entry of first linker-generated array
- @_type: Data type of the entry

Hi Heinrich,
On Thu, 4 Feb 2021 at 06:54, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 03.02.21 17:43, Simon Glass wrote:
At present linker lists are designed for use in code. They make use of statements within expressions ({...}), for example.
It is possible to generate a reference to a linker_list entry that can be used in data structures, where such features are not permitted. It requires that the reference first be declared as extern. In other words the existing macro needs to be split into two parts.
Add new macros to support this.
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v1)
include/linker_lists.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/include/linker_lists.h b/include/linker_lists.h index fd98ecd297c..55631f0240c 100644 --- a/include/linker_lists.h +++ b/include/linker_lists.h @@ -211,6 +211,34 @@ _ll_result; \ })
+/**
- ll_entry_decl() - Declare a linker-generated array entry reference as extern
- This declares a reference to a list entry so that it can be used later,
- without needing the code in ll_entry_get().
- To use this, put ll_entry_decl() somewhere in your file, then use
- ll_entry_ref() later on, to reference the entry.
- @_type: Data type of the entry
- @_name: Name of the entry
- @_list: Name of the list in which this entry is placed
- */
+#define ll_entry_decl(_type, _name, _list) \
extern _type _u_boot_list_2_##_list##_2_##_name
Can't you simply add the extern keyword to ll_entry_declare()?
Why do we need entries with and entries without extern?
My original reason was because I wanted to prevent the non-extern versions from being used in code not generated by dtoc, since this of course breaks the whole thing.
But so far I have not enforced this, so I am OK with doing what you suggest. It is easy enough to change later if it causes problems.
Regards, Simon

Add macros which work with instantiated devices and uclasses, as created at build time by dtoc. Include variants that can be used in data structures.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
include/dm/device-internal.h | 26 ++++++++++++++++++++++++++ include/dm/device.h | 11 +++++++++++ include/dm/uclass-internal.h | 23 +++++++++++++++++++++++ include/dm/uclass.h | 20 ++++++++++++++++++++ 4 files changed, 80 insertions(+)
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 639bbd293d9..9d7256130cd 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -10,11 +10,37 @@ #ifndef _DM_DEVICE_INTERNAL_H #define _DM_DEVICE_INTERNAL_H
+#include <linker_lists.h> #include <dm/ofnode.h>
struct device_node; struct udevice;
+/* + * These are only allowed these in code generated by dtoc, because the ordering + * is important and if other instances creep in then they may mess up the + * ordering expected by dtoc. + */ + +/* Declare a bound device ready for run-time use */ +#define DM_DEVICE_INST(__name) \ + ll_entry_declare(struct udevice, __name, udevice) + +/* Declare a bound device as an extern, so it can be referenced at build time */ +#define DM_DEVICE_DECL(__name) \ + ll_entry_decl(struct udevice, __name, udevice) + +/* + * Get a pointer to a given device, for use in data structures. This requires + * that the symbol be declared with DM_DRIVER_DECL() first + */ +#define DM_DEVICE_REF(__name) \ + ll_entry_ref(struct udevice, __name, udevice) + +/* Get a pointer to a given device */ +#define DM_DEVICE_GET(__name) \ + ll_entry_get(struct udevice, __name, udevice) + /** * device_bind() - Create a device and bind it to a driver * diff --git a/include/dm/device.h b/include/dm/device.h index 1c52c9d3120..38ef47baa01 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -338,6 +338,17 @@ struct driver { #define DM_DRIVER_GET(__name) \ ll_entry_get(struct driver, __name, driver)
+/* Declare a driver as an extern, so it can be referenced at build time */ +#define DM_DRIVER_DECL(__name) \ + ll_entry_decl(struct driver, __name, driver) + +/* + * Get a pointer to a given driver, for use in data structures. This requires + * that the symbol be declared with DM_DRIVER_DECL() first + */ +#define DM_DRIVER_REF(__name) \ + ll_entry_ref(struct driver, __name, driver) + /** * Declare a macro to state a alias for a driver name. This macro will * produce no code but its information will be parsed by tools like diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index c5a464be7c4..fc4d8dc2b53 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -11,6 +11,29 @@
#include <dm/ofnode.h>
+/* + * These are only allowed these in code generated by dtoc, because the ordering + * is important and if other instances creep in then they may mess up the + * ordering expected by dtoc. + */ + +/* + * Declare a uclass ready for run-time use. This adds an actual struct uclass + * to a list which is found by driver model on start-up. + */ +#define DM_UCLASS_INST(__name) \ + ll_entry_declare(struct uclass, __name, uclass) + +#define DM_UCLASS_DECL(__name) \ + ll_entry_decl(struct uclass, __name, uclass) + +/* + * Declare a uclass as an extern, so it can be referenced at build time. This + * is an extern for DM_UCLASS_INST(). + */ +#define DM_UCLASS_REF(__name) \ + ll_entry_ref(struct uclass, __name, uclass) + /** * uclass_set_priv() - Set the private data for a uclass * diff --git a/include/dm/uclass.h b/include/dm/uclass.h index d95683740cb..152f49e97dc 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -114,6 +114,26 @@ struct uclass_driver { #define UCLASS_DRIVER(__name) \ ll_entry_declare(struct uclass_driver, __name, uclass_driver)
+/* + * These two macros are related to of-platdata, and normally only used in + * code generated by dtoc + */ + +/* + * Declare a uclass driver as an extern, so it can be referenced at build time + * This is the extern equivalent of UCLASS_DRIVER(). You need to place this at + * the top level before you use DM_UCLASS_DRIVER_REF() in a file. + */ +#define DM_UCLASS_DRIVER_DECL(__name) \ + ll_entry_decl(struct uclass_driver, __name, uclass_driver) + +/* + * Get a pointer to a given uclass driver, for use in data structures. This + * requires that the symbol be declared with DM_UCLASS_DRIVER_DECL() first + */ +#define DM_UCLASS_DRIVER_REF(__name) \ + ll_entry_ref(struct uclass_driver, __name, uclass_driver) + /** * uclass_get_priv() - Get the private data for a uclass *

On 03.02.21 17:43, Simon Glass wrote:
Add macros which work with instantiated devices and uclasses, as created at build time by dtoc. Include variants that can be used in data structures.
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v1)
include/dm/device-internal.h | 26 ++++++++++++++++++++++++++ include/dm/device.h | 11 +++++++++++ include/dm/uclass-internal.h | 23 +++++++++++++++++++++++ include/dm/uclass.h | 20 ++++++++++++++++++++ 4 files changed, 80 insertions(+)
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 639bbd293d9..9d7256130cd 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -10,11 +10,37 @@ #ifndef _DM_DEVICE_INTERNAL_H #define _DM_DEVICE_INTERNAL_H
+#include <linker_lists.h> #include <dm/ofnode.h>
struct device_node; struct udevice;
+/*
- These are only allowed these in code generated by dtoc, because the ordering
- is important and if other instances creep in then they may mess up the
- ordering expected by dtoc.
- */
+/* Declare a bound device ready for run-time use */ +#define DM_DEVICE_INST(__name) \
- ll_entry_declare(struct udevice, __name, udevice)
+/* Declare a bound device as an extern, so it can be referenced at build time */ +#define DM_DEVICE_DECL(__name) \
- ll_entry_decl(struct udevice, __name, udevice)
+/*
- Get a pointer to a given device, for use in data structures. This requires
- that the symbol be declared with DM_DRIVER_DECL() first
- */
+#define DM_DEVICE_REF(__name) \
- ll_entry_ref(struct udevice, __name, udevice)
+/* Get a pointer to a given device */ +#define DM_DEVICE_GET(__name) \
- ll_entry_get(struct udevice, __name, udevice)
/**
- device_bind() - Create a device and bind it to a driver
diff --git a/include/dm/device.h b/include/dm/device.h index 1c52c9d3120..38ef47baa01 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -338,6 +338,17 @@ struct driver { #define DM_DRIVER_GET(__name) \ ll_entry_get(struct driver, __name, driver)
+/* Declare a driver as an extern, so it can be referenced at build time */ +#define DM_DRIVER_DECL(__name) \
- ll_entry_decl(struct driver, __name, driver)
+/*
- Get a pointer to a given driver, for use in data structures. This requires
- that the symbol be declared with DM_DRIVER_DECL() first
- */
+#define DM_DRIVER_REF(__name) \
- ll_entry_ref(struct driver, __name, driver)
/**
- Declare a macro to state a alias for a driver name. This macro will
- produce no code but its information will be parsed by tools like
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index c5a464be7c4..fc4d8dc2b53 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -11,6 +11,29 @@
#include <dm/ofnode.h>
+/*
- These are only allowed these in code generated by dtoc, because the ordering
%s/These/The next three macros/
- is important and if other instances creep in then they may mess up the
- ordering expected by dtoc.
- */
+/*
- Declare a uclass ready for run-time use. This adds an actual struct uclass
- to a list which is found by driver model on start-up.
- */
It is unclear which type __name might have.
Please, describe in Sphinx style for each macro what the macro is used for, how it is used, what the parameters are used for, which type they take.
Best regards
Heinrich
+#define DM_UCLASS_INST(__name) \
- ll_entry_declare(struct uclass, __name, uclass)
+#define DM_UCLASS_DECL(__name) \
- ll_entry_decl(struct uclass, __name, uclass)
+/*
- Declare a uclass as an extern, so it can be referenced at build time. This
- is an extern for DM_UCLASS_INST().
- */
+#define DM_UCLASS_REF(__name) \
- ll_entry_ref(struct uclass, __name, uclass)
/**
- uclass_set_priv() - Set the private data for a uclass
diff --git a/include/dm/uclass.h b/include/dm/uclass.h index d95683740cb..152f49e97dc 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -114,6 +114,26 @@ struct uclass_driver { #define UCLASS_DRIVER(__name) \ ll_entry_declare(struct uclass_driver, __name, uclass_driver)
+/*
- These two macros are related to of-platdata, and normally only used in
- code generated by dtoc
- */
+/*
- Declare a uclass driver as an extern, so it can be referenced at build time
- This is the extern equivalent of UCLASS_DRIVER(). You need to place this at
- the top level before you use DM_UCLASS_DRIVER_REF() in a file.
- */
+#define DM_UCLASS_DRIVER_DECL(__name) \
- ll_entry_decl(struct uclass_driver, __name, uclass_driver)
+/*
- Get a pointer to a given uclass driver, for use in data structures. This
- requires that the symbol be declared with DM_UCLASS_DRIVER_DECL() first
- */
+#define DM_UCLASS_DRIVER_REF(__name) \
- ll_entry_ref(struct uclass_driver, __name, uclass_driver)
/**
- uclass_get_priv() - Get the private data for a uclass

With OF_PLATDATA_INST devices are bound at build time. we should not allow binding of devices at runtime. Add an option to control this.
Update the driver model core so that it does not bind devices. Update device_bind() to return an error if called.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/device.c | 38 +++++++++++++++++++++----------------- dts/Kconfig | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c index 8629df8defb..02e28f014b5 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -44,6 +44,9 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv, bool auto_seq = true; void *ptr;
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) + return -ENOSYS; + if (devp) *devp = NULL; if (!name) @@ -382,26 +385,27 @@ int device_of_to_plat(struct udevice *dev) if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID) return 0;
- /* Ensure all parents have ofdata */ - if (dev->parent) { - ret = device_of_to_plat(dev->parent); + if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) { + /* Ensure all parents have ofdata */ + if (dev->parent) { + ret = device_of_to_plat(dev->parent); + if (ret) + goto fail; + + /* + * The device might have already been probed during + * the call to device_probe() on its parent device + * (e.g. PCI bridge devices). Test the flags again + * so that we don't mess up the device. + */ + if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID) + return 0; + } + + ret = device_alloc_priv(dev); if (ret) goto fail; - - /* - * The device might have already been probed during - * the call to device_probe() on its parent device - * (e.g. PCI bridge devices). Test the flags again - * so that we don't mess up the device. - */ - if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID) - return 0; } - - ret = device_alloc_priv(dev); - if (ret) - goto fail; - drv = dev->driver; assert(drv);
diff --git a/dts/Kconfig b/dts/Kconfig index e861ea48d01..645a2d2b84d 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -371,6 +371,14 @@ config SPL_OF_PLATDATA_INST Declare devices as udevice instances so that they do not need to be bound when U-Boot starts. This can save time and code space.
+config SPL_OF_PLATDATA_NO_BIND + bool "Don't allow run-time binding of devices" + depends on SPL_OF_PLATDATA_INST + default y + help + This removes the ability to bind devices at run time, thus saving + some code space in U-Boot. + endif
config TPL_OF_PLATDATA @@ -411,6 +419,14 @@ config TPL_OF_PLATDATA_INST Declare devices as udevice instances so that they do not need to be bound when U-Boot starts. This can save time and code space.
+config TPL_OF_PLATDATA_NO_BIND + bool "Don't allow run-time binding of devices" + depends on TPL_OF_PLATDATA_INST + default y + help + This removes the ability to bind devices at run time, thus saving + some code space in U-Boot. + endif
endmenu

On 03.02.21 17:43, Simon Glass wrote:
With OF_PLATDATA_INST devices are bound at build time. we should not allow binding of devices at runtime. Add an option to control this.
Update the driver model core so that it does not bind devices. Update device_bind() to return an error if called.
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v1)
drivers/core/device.c | 38 +++++++++++++++++++++----------------- dts/Kconfig | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c index 8629df8defb..02e28f014b5 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -44,6 +44,9 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv, bool auto_seq = true; void *ptr;
- if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND))
return -ENOSYS;
- if (devp) *devp = NULL; if (!name)
@@ -382,26 +385,27 @@ int device_of_to_plat(struct udevice *dev) if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID) return 0;
- /* Ensure all parents have ofdata */
- if (dev->parent) {
ret = device_of_to_plat(dev->parent);
- if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) {
In the commit message you write this depends on OF_PLATDATA_INST. Why should we use another symbol here?
/* Ensure all parents have ofdata */
if (dev->parent) {
ret = device_of_to_plat(dev->parent);
if (ret)
goto fail;
/*
* The device might have already been probed during
* the call to device_probe() on its parent device
* (e.g. PCI bridge devices). Test the flags again
* so that we don't mess up the device.
*/
if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
return 0;
}
if (ret) goto fail;ret = device_alloc_priv(dev);
/*
* The device might have already been probed during
* the call to device_probe() on its parent device
* (e.g. PCI bridge devices). Test the flags again
* so that we don't mess up the device.
*/
if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
}return 0;
- ret = device_alloc_priv(dev);
- if (ret)
goto fail;
- drv = dev->driver; assert(drv);
diff --git a/dts/Kconfig b/dts/Kconfig index e861ea48d01..645a2d2b84d 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -371,6 +371,14 @@ config SPL_OF_PLATDATA_INST Declare devices as udevice instances so that they do not need to be bound when U-Boot starts. This can save time and code space.
+config SPL_OF_PLATDATA_NO_BIND
- bool "Don't allow run-time binding of devices"
- depends on SPL_OF_PLATDATA_INST
- default y
- help
This removes the ability to bind devices at run time, thus saving
some code space in U-Boot.
endif
config TPL_OF_PLATDATA @@ -411,6 +419,14 @@ config TPL_OF_PLATDATA_INST Declare devices as udevice instances so that they do not need to be bound when U-Boot starts. This can save time and code space.
+config TPL_OF_PLATDATA_NO_BIND
- bool "Don't allow run-time binding of devices"
- depends on TPL_OF_PLATDATA_INST
- default y
In which case would I want to set this to no? This needs a better description if the symbol is needed at all.
Best regards
Heinrich
- help
This removes the ability to bind devices at run time, thus saving
some code space in U-Boot.
endif
endmenu

When OF_PLATDATA_INST is enabled we don't need to create the uclass list. Instead we just need to point to the existing list. Update the code accordingly.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/root.c | 8 ++++++-- include/dm/root.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/core/root.c b/drivers/core/root.c index 2bfa75b4725..6dadca18ee1 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -139,8 +139,12 @@ int dm_init(bool of_live) dm_warn("Virtual root driver already exists!\n"); return -EINVAL; } - gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST; - INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST); + if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { + gd->uclass_root = &uclass_head; + } else { + gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST; + INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST); + }
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) { fix_drivers(); diff --git a/include/dm/root.h b/include/dm/root.h index 89afbee6196..42510b106ab 100644 --- a/include/dm/root.h +++ b/include/dm/root.h @@ -11,6 +11,9 @@
struct udevice;
+/* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */ +extern struct list_head uclass_head; + /** * dm_root() - Return pointer to the top of the driver tree *

With this we don't need to scan and bind drivers, not even the root device. We just need to locate the root device that was set up at build time, then set our root in global_data to point to it.
Update the code to handle this case.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/root.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/core/root.c b/drivers/core/root.c index 6dadca18ee1..75513c2ab25 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -128,6 +128,13 @@ void fix_devices(void) } }
+static int dm_setup_inst(void) +{ + DM_ROOT_NON_CONST = DM_DEVICE_GET(root); + + return 0; +} + int dm_init(bool of_live) { int ret; @@ -152,14 +159,23 @@ int dm_init(bool of_live) fix_devices(); }
- ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); - if (ret) - return ret; - if (CONFIG_IS_ENABLED(OF_CONTROL)) - dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root()); - ret = device_probe(DM_ROOT_NON_CONST); - if (ret) - return ret; + if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { + ret = dm_setup_inst(); + if (ret) { + log_debug("dm_setup_inst() failed: %d\n", ret); + return ret; + } + } else { + ret = device_bind_by_name(NULL, false, &root_info, + &DM_ROOT_NON_CONST); + if (ret) + return ret; + if (CONFIG_IS_ENABLED(OF_CONTROL)) + dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root()); + ret = device_probe(DM_ROOT_NON_CONST); + if (ret) + return ret; + }
return 0; } @@ -348,10 +364,12 @@ int dm_init_and_scan(bool pre_reloc_only) debug("dm_init() failed: %d\n", ret); return ret; } - ret = dm_scan(pre_reloc_only); - if (ret) { - log_debug("dm_scan() failed: %d\n", ret); - return ret; + if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { + ret = dm_scan(pre_reloc_only); + if (ret) { + log_debug("dm_scan() failed: %d\n", ret); + return ret; + } }
return 0;

There is no need to ever add new uclasses since these are set up at build time. Update the code to return an error if this is attempted.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/uclass.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index f38122d54b5..2a7b0881b18 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -147,8 +147,11 @@ int uclass_get(enum uclass_id id, struct uclass **ucp)
*ucp = NULL; uc = uclass_find(id); - if (!uc) + if (!uc) { + if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) + return -ENOENT; return uclass_add(id, ucp); + } *ucp = uc;
return 0;

Now that dtoc generates some new C files, add these to the build so that the instantiated devices and uclasses can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
scripts/Makefile.spl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 52609112ecd..fe9b616dcc4 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -120,7 +120,8 @@ endif u-boot-spl-init := $(head-y) u-boot-spl-main := $(libs-y) ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA -u-boot-spl-platdata := $(obj)/dts/dt-plat.o +u-boot-spl-platdata := $(obj)/dts/dt-plat.o $(obj)/dts/dt-uclass.o \ + $(obj)/dts/dt-device.o u-boot-spl-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-platdata)) endif

When dt-structs.h is used, include the dt-decl.h header as well, so that these declarations are available.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
include/dt-structs.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/dt-structs.h b/include/dt-structs.h index f0e1c9cb901..f9ccaf56a46 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -24,7 +24,9 @@ struct phandle_2_arg { uint idx; int arg[2]; }; + #include <generated/dt-structs-gen.h> +#include <generated/dt-decl.h> #endif
#endif

It is not possible to destroy the uclasses when they are created at build time. Skip this step so that SPL test can complete successfully.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update to deal with test refactoring series
test/test-main.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/test/test-main.c b/test/test-main.c index e1b49e091ab..46a0c2ee2f6 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -62,17 +62,25 @@ static int dm_test_post_run(struct unit_test_state *uts) { int id;
- for (id = 0; id < UCLASS_COUNT; id++) { - struct uclass *uc; - - /* - * If the uclass doesn't exist we don't want to create it. So - * check that here before we call uclass_find_device(). - */ - uc = uclass_find(id); - if (!uc) - continue; - ut_assertok(uclass_destroy(uc)); + /* + * With of-platdata-inst the uclasses are created at build time. If we + * destroy them we cannot get them back since uclass_add() is not + * supported. So skip this. + */ + if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { + for (id = 0; id < UCLASS_COUNT; id++) { + struct uclass *uc; + + /* + * If the uclass doesn't exist we don't want to create + * it. So check that here before we call + * uclass_find_device(). + */ + uc = uclass_find(id); + if (!uc) + continue; + ut_assertok(uclass_destroy(uc)); + } }
return 0;

At present the structs used by this driver are not accessible outside it, so cannot be used with OF_PLATDATA_INST. Move them to a header file to fix this.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/include/asm/clk.h | 16 ++++++++++++++++ drivers/clk/clk_sandbox.c | 7 ------- drivers/clk/clk_sandbox_test.c | 6 ------ 3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h index 0294baee278..a566874d606 100644 --- a/arch/sandbox/include/asm/clk.h +++ b/arch/sandbox/include/asm/clk.h @@ -7,6 +7,9 @@ #define __SANDBOX_CLK_H
#include <common.h> +#include <clk.h> +#include <dt-structs.h> +#include <linux/clk-provider.h>
struct udevice;
@@ -45,6 +48,19 @@ enum sandbox_clk_test_id {
#define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
+struct sandbox_clk_priv { + bool probed; + ulong rate[SANDBOX_CLK_ID_COUNT]; + bool enabled[SANDBOX_CLK_ID_COUNT]; + bool requested[SANDBOX_CLK_ID_COUNT]; +}; + +struct sandbox_clk_test { + struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT]; + struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT]; + struct clk_bulk bulk; +}; + /** * sandbox_clk_query_rate - Query the current rate of a sandbox clock. * diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index b28b67b4486..e1313f6d880 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -10,13 +10,6 @@ #include <malloc.h> #include <asm/clk.h>
-struct sandbox_clk_priv { - bool probed; - ulong rate[SANDBOX_CLK_ID_COUNT]; - bool enabled[SANDBOX_CLK_ID_COUNT]; - bool requested[SANDBOX_CLK_ID_COUNT]; -}; - static ulong sandbox_clk_get_rate(struct clk *clk) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c index c4e44815084..f665fd3cc45 100644 --- a/drivers/clk/clk_sandbox_test.c +++ b/drivers/clk/clk_sandbox_test.c @@ -11,12 +11,6 @@ #include <dm/device_compat.h> #include <linux/err.h>
-struct sandbox_clk_test { - struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT]; - struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT]; - struct clk_bulk bulk; -}; - static const char * const sandbox_clk_test_names[] = { [SANDBOX_CLK_TEST_ID_FIXED] = "fixed", [SANDBOX_CLK_TEST_ID_SPI] = "spi",

We need to allow SoCs to create their own drivers for this so that they can use their own of-platdata structs. To minimise code duplication, export the driver operations and the ofdata_to_plat() setup function.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/clk/clk_fixed_rate.c | 14 ++++++++++---- include/linux/clk-provider.h | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index 3c5a83c523c..09f9ef26a42 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -25,18 +25,24 @@ const struct clk_ops clk_fixed_rate_ops = { .enable = dummy_enable, };
-static int clk_fixed_rate_of_to_plat(struct udevice *dev) +void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev, + struct clk_fixed_rate *plat) { - struct clk *clk = &to_clk_fixed_rate(dev)->clk; + struct clk *clk = &plat->clk; #if !CONFIG_IS_ENABLED(OF_PLATDATA) - to_clk_fixed_rate(dev)->fixed_rate = - dev_read_u32_default(dev, "clock-frequency", 0); + plat->fixed_rate = dev_read_u32_default(dev, "clock-frequency", 0); #endif /* Make fixed rate clock accessible from higher level struct clk */ /* FIXME: This is not allowed */ dev_set_uclass_priv(dev, clk); + clk->dev = dev; clk->enable_count = 0; +} + +static int clk_fixed_rate_of_to_plat(struct udevice *dev) +{ + clk_fixed_rate_ofdata_to_plat_(dev, to_clk_fixed_rate(dev));
return 0; } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c871ea646d3..f9ca8e433ec 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -193,6 +193,8 @@ struct clk_fixed_factor { unsigned int div; };
+extern const struct clk_ops clk_fixed_rate_ops; + #define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\ clk)
@@ -203,6 +205,9 @@ struct clk_fixed_rate {
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_plat(dev))
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev, + struct clk_fixed_rate *plat); + struct clk_composite { struct clk clk; struct clk_ops ops;

Create a version of this driver for sandbox so that it can use the of-platdata struct.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/dts/sandbox.dtsi | 2 +- arch/sandbox/include/asm/clk.h | 8 ++++++++ drivers/clk/clk_sandbox.c | 33 +++++++++++++++++++++++++++++++++ test/dm/of_platdata.c | 2 +- 4 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 7455c99a739..5bf84451c99 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -31,7 +31,7 @@
clk_fixed: clk-fixed { u-boot,dm-pre-reloc; - compatible = "fixed-clock"; + compatible = "sandbox,fixed-clock"; #clock-cells = <0>; clock-frequency = <1234>; }; diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h index a566874d606..92f59a8e841 100644 --- a/arch/sandbox/include/asm/clk.h +++ b/arch/sandbox/include/asm/clk.h @@ -61,6 +61,14 @@ struct sandbox_clk_test { struct clk_bulk bulk; };
+/* Platform data for the sandbox fixed-rate clock driver */ +struct sandbox_clk_fixed_rate_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_sandbox_fixed_clock dtplat; +#endif + struct clk_fixed_rate fixed; +}; + /** * sandbox_clk_query_rate - Query the current rate of a sandbox clock. * diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index e1313f6d880..57acf7d8553 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -9,6 +9,7 @@ #include <errno.h> #include <malloc.h> #include <asm/clk.h> +#include <linux/clk-provider.h>
static ulong sandbox_clk_get_rate(struct clk *clk) { @@ -171,3 +172,35 @@ int sandbox_clk_query_requested(struct udevice *dev, int id) return -EINVAL; return priv->requested[id]; } + +int clk_fixed_rate_of_to_plat(struct udevice *dev) +{ + struct clk_fixed_rate *cplat; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev); + + cplat = &plat->fixed; + cplat->fixed_rate = plat->dtplat.clock_frequency; +#else + cplat = to_clk_fixed_rate(dev); +#endif + clk_fixed_rate_ofdata_to_plat_(dev, cplat); + + return 0; +} + +static const struct udevice_id sandbox_clk_fixed_rate_match[] = { + { .compatible = "sandbox,fixed-clock" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sandbox_fixed_clock) = { + .name = "sandbox_fixed_clock", + .id = UCLASS_CLK, + .of_match = sandbox_clk_fixed_rate_match, + .of_to_plat = clk_fixed_rate_of_to_plat, + .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat), + .ops = &clk_fixed_rate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index 26c50922c56..f93a75b4481 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -184,7 +184,7 @@ static int dm_test_of_plat_phandle(struct unit_test_state *uts) plat = dev_get_plat(dev);
ut_assertok(device_get_by_driver_info_idx(plat->clocks[0].idx, &clk)); - ut_asserteq_str("fixed_clock", clk->name); + ut_asserteq_str("sandbox_fixed_clock", clk->name);
ut_assertok(device_get_by_driver_info_idx(plat->clocks[1].idx, &clk)); ut_asserteq_str("sandbox_clk", clk->name);

This function is now only used in a test. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/device.c | 15 --------------- include/dm/device.h | 15 --------------- test/dm/of_platdata.c | 7 ++----- 3 files changed, 2 insertions(+), 35 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c index 02e28f014b5..51516391d16 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -753,21 +753,6 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp) }
#if CONFIG_IS_ENABLED(OF_PLATDATA) -int device_get_by_driver_info(const struct driver_info *info, - struct udevice **devp) -{ - struct driver_info *info_base = - ll_entry_start(struct driver_info, driver_info); - int idx = info - info_base; - struct driver_rt *drt = gd_dm_driver_rt() + idx; - struct udevice *dev; - - dev = drt->dev; - *devp = NULL; - - return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp); -} - int device_get_by_driver_info_idx(uint idx, struct udevice **devp) { struct driver_rt *drt = gd_dm_driver_rt() + idx; diff --git a/include/dm/device.h b/include/dm/device.h index 38ef47baa01..c9afa4dce50 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -631,21 +631,6 @@ int device_find_global_by_ofnode(ofnode node, struct udevice **devp); */ int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
-/** - * device_get_by_driver_info() - Get a device based on driver_info - * - * Locates a device by its struct driver_info, by using its reference which - * is updated during the bind process. - * - * The device is probed to activate it ready for use. - * - * @info: Struct driver_info - * @devp: Returns pointer to device if found, otherwise this is set to NULL - * @return 0 if OK, -ve on error - */ -int device_get_by_driver_info(const struct driver_info *info, - struct udevice **devp); - /** * device_get_by_driver_info_idx() - Get a device based on driver_info index * diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index f93a75b4481..0de4ab5dafa 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -141,8 +141,6 @@ static int find_driver_info(struct unit_test_state *uts, struct udevice *parent, /* Check that every device is recorded in its driver_info struct */ static int dm_test_of_plat_dev(struct unit_test_state *uts) { - const struct driver_info *info = - ll_entry_start(struct driver_info, driver_info); const int n_ents = ll_entry_count(struct driver_info, driver_info); bool found[n_ents]; uint i; @@ -154,18 +152,17 @@ static int dm_test_of_plat_dev(struct unit_test_state *uts) /* Make sure that the driver entries without devices have no ->dev */ for (i = 0; i < n_ents; i++) { const struct driver_rt *drt = gd_dm_driver_rt() + i; - const struct driver_info *entry = info + i; struct udevice *dev;
if (found[i]) { /* Make sure we can find it */ ut_assertnonnull(drt->dev); - ut_assertok(device_get_by_driver_info(entry, &dev)); + ut_assertok(device_get_by_driver_info_idx(i, &dev)); ut_asserteq_ptr(dev, drt->dev); } else { ut_assertnull(drt->dev); ut_asserteq(-ENOENT, - device_get_by_driver_info(entry, &dev)); + device_get_by_driver_info_idx(i, &dev)); } }

At present this function is included in the build but with of-platdata it only services to produce a confusing link error complaining about a call to dev_read_u32_default().
Drop it so that any call to uclass_find_device_by_phandle() is flagged as an error, making it easier to see what is going on.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 2a7b0881b18..774d279cd94 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -393,7 +393,7 @@ done: return ret; }
-#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent, const char *name, struct udevice **devp) {

At present the structs used by these drivers are declared in the C files and so are not accessible to dtoc. Move them to header files, as required.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/include/asm/i2c.h | 15 +++++++++++++++ arch/sandbox/include/asm/rtc.h | 24 ++++++++++++++++++++++++ drivers/i2c/i2c-emul-uclass.c | 13 +------------ drivers/rtc/i2c_rtc_emul.c | 19 ------------------- 4 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/arch/sandbox/include/asm/i2c.h b/arch/sandbox/include/asm/i2c.h index b482be485ca..4fc190be4bd 100644 --- a/arch/sandbox/include/asm/i2c.h +++ b/arch/sandbox/include/asm/i2c.h @@ -11,4 +11,19 @@ struct sandbox_i2c_priv { bool test_mode; };
+/** + * struct i2c_emul_uc_plat - information about the emulator for this device + * + * This is used by devices in UCLASS_I2C_EMUL to record information about the + * device being emulated. It is accessible with dev_get_uclass_plat() + * + * @dev: Device being emulated + * @idx: of-platdata index, set up by the device's bind() method if of-platdata + * is in use + */ +struct i2c_emul_uc_plat { + struct udevice *dev; + int idx; +}; + #endif /* __asn_i2c_h */ diff --git a/arch/sandbox/include/asm/rtc.h b/arch/sandbox/include/asm/rtc.h index 5bb032f59f2..025cd6c67cf 100644 --- a/arch/sandbox/include/asm/rtc.h +++ b/arch/sandbox/include/asm/rtc.h @@ -9,6 +9,8 @@ #ifndef __asm_rtc_h #define __asm_rtc_h
+#include <dt-structs.h> + /* Register numbers in the sandbox RTC */ enum { REG_SEC = 5, @@ -29,4 +31,26 @@ enum { REG_COUNT = 0x80, };
+/** + * struct sandbox_i2c_rtc_plat_data - platform data for the RTC + * + * @base_time: Base system time when RTC device was bound + * @offset: RTC offset from current system time + * @use_system_time: true to use system time, false to use @base_time + * @reg: Register values + */ +struct sandbox_i2c_rtc_plat_data { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_sandbox_i2c_rtc_emul dtplat; +#endif + long base_time; + long offset; + bool use_system_time; + u8 reg[REG_COUNT]; +}; + +struct sandbox_i2c_rtc { + unsigned int offset_secs; +}; + #endif diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 75d79883380..9ef4651fa43 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -7,6 +7,7 @@ #include <dm.h> #include <i2c.h> #include <log.h> +#include <asm/i2c.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h>
@@ -23,18 +24,6 @@ * uclass so avoid having strange devices on the I2C bus. */
-/** - * struct i2c_emul_uc_plat - information about the emulator for this device - * - * This is used by devices in UCLASS_I2C_EMUL to record information about the - * device being emulated. It is accessible with dev_get_uclass_plat() - * - * @dev: Device being emulated - */ -struct i2c_emul_uc_plat { - struct udevice *dev; -}; - struct udevice *i2c_emul_get_device(struct udevice *emul) { struct i2c_emul_uc_plat *uc_plat = dev_get_uclass_plat(emul); diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c index fdc885c518b..ba418c25daf 100644 --- a/drivers/rtc/i2c_rtc_emul.c +++ b/drivers/rtc/i2c_rtc_emul.c @@ -28,25 +28,6 @@ #define debug_buffer(x, ...) #endif
-/** - * struct sandbox_i2c_rtc_plat_data - platform data for the RTC - * - * @base_time: Base system time when RTC device was bound - * @offset: RTC offset from current system time - * @use_system_time: true to use system time, false to use @base_time - * @reg: Register values - */ -struct sandbox_i2c_rtc_plat_data { - long base_time; - long offset; - bool use_system_time; - u8 reg[REG_COUNT]; -}; - -struct sandbox_i2c_rtc { - unsigned int offset_secs; -}; - long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time, int offset) {

This function finds a device by its driver_info index. With of-platdata-inst we do not use driver_info, but instead instantiate udevice records at build-time.
However the semantics of using the function are the same in each case: the caller provides an index and gets back a device.
So rename the function to device_get_by_ofplat_idx(), so that it can be used for both situations. The caller does not really need to worry about the details.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/clk/clk-uclass.c | 2 +- drivers/core/device.c | 13 ++++++++++--- drivers/misc/irq-uclass.c | 2 +- drivers/mmc/fsl_esdhc_imx.c | 3 +-- include/dm/device.h | 16 +++++++++++----- test/dm/of_platdata.c | 15 +++++++-------- 6 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index d5c4e3cbe51..0e62c49d7a8 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -38,7 +38,7 @@ int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells, { int ret;
- ret = device_get_by_driver_info_idx(cells->idx, &clk->dev); + ret = device_get_by_ofplat_idx(cells->idx, &clk->dev); if (ret) return ret; clk->id = cells->arg[0]; diff --git a/drivers/core/device.c b/drivers/core/device.c index 51516391d16..657ddcc12b6 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -753,12 +753,19 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp) }
#if CONFIG_IS_ENABLED(OF_PLATDATA) -int device_get_by_driver_info_idx(uint idx, struct udevice **devp) +int device_get_by_ofplat_idx(uint idx, struct udevice **devp) { - struct driver_rt *drt = gd_dm_driver_rt() + idx; struct udevice *dev;
- dev = drt->dev; + if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { + struct udevice *base = ll_entry_start(struct udevice, udevice); + + dev = base + idx; + } else { + struct driver_rt *drt = gd_dm_driver_rt() + idx; + + dev = drt->dev; + } *devp = NULL;
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp); diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c index 24b27962a7d..3aa26f61d9e 100644 --- a/drivers/misc/irq-uclass.c +++ b/drivers/misc/irq-uclass.c @@ -69,7 +69,7 @@ int irq_get_by_driver_info(struct udevice *dev, { int ret;
- ret = device_get_by_driver_info_idx(cells->idx, &irq->dev); + ret = device_get_by_ofplat_idx(cells->idx, &irq->dev); if (ret) return ret; irq->id = cells->arg[0]; diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 8ac859797f0..fbdf21acb8c 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -1523,8 +1523,7 @@ static int fsl_esdhc_probe(struct udevice *dev) if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) { struct udevice *gpiodev;
- ret = device_get_by_driver_info_idx(dtplat->cd_gpios->idx, - &gpiodev); + ret = device_get_by_ofplat_idx(dtplat->cd_gpios->idx, &gpiodev); if (ret) return ret;
diff --git a/include/dm/device.h b/include/dm/device.h index c9afa4dce50..891a5f84243 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -632,18 +632,24 @@ int device_find_global_by_ofnode(ofnode node, struct udevice **devp); int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
/** - * device_get_by_driver_info_idx() - Get a device based on driver_info index + * device_get_by_ofplat_idx() - Get a device based on of-platdata index * - * Locates a device by its struct driver_info, by using its index number which - * is written into the idx field of struct phandle_1_arg, etc. + * Locates a device by either its struct driver_info index, or its + * struct udevice index. The latter is used with OF_PLATDATA_INST, since we have + * a list of build-time instantiated struct udevice records, The former is used + * with !OF_PLATDATA_INST since in that case we have a list of + * struct driver_info records. + * + * The index number is written into the idx field of struct phandle_1_arg, etc. + * It is the position of this driver_info/udevice in its linker list. * * The device is probed to activate it ready for use. * - * @idx: Index number of the driver_info structure (0=first) + * @idx: Index number of the driver_info/udevice structure (0=first) * @devp: Returns pointer to device if found, otherwise this is set to NULL * @return 0 if OK, -ve on error */ -int device_get_by_driver_info_idx(uint idx, struct udevice **devp); +int device_get_by_ofplat_idx(uint idx, struct udevice **devp);
/** * device_find_first_child() - Find the first child of a device diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index 0de4ab5dafa..1b46bdf555a 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -157,12 +157,11 @@ static int dm_test_of_plat_dev(struct unit_test_state *uts) if (found[i]) { /* Make sure we can find it */ ut_assertnonnull(drt->dev); - ut_assertok(device_get_by_driver_info_idx(i, &dev)); + ut_assertok(device_get_by_ofplat_idx(i, &dev)); ut_asserteq_ptr(dev, drt->dev); } else { ut_assertnull(drt->dev); - ut_asserteq(-ENOENT, - device_get_by_driver_info_idx(i, &dev)); + ut_asserteq(-ENOENT, device_get_by_ofplat_idx(i, &dev)); } }
@@ -180,22 +179,22 @@ static int dm_test_of_plat_phandle(struct unit_test_state *uts) ut_asserteq_str("sandbox_clk_test", dev->name); plat = dev_get_plat(dev);
- ut_assertok(device_get_by_driver_info_idx(plat->clocks[0].idx, &clk)); + ut_assertok(device_get_by_ofplat_idx(plat->clocks[0].idx, &clk)); ut_asserteq_str("sandbox_fixed_clock", clk->name);
- ut_assertok(device_get_by_driver_info_idx(plat->clocks[1].idx, &clk)); + ut_assertok(device_get_by_ofplat_idx(plat->clocks[1].idx, &clk)); ut_asserteq_str("sandbox_clk", clk->name); ut_asserteq(1, plat->clocks[1].arg[0]);
- ut_assertok(device_get_by_driver_info_idx(plat->clocks[2].idx, &clk)); + ut_assertok(device_get_by_ofplat_idx(plat->clocks[2].idx, &clk)); ut_asserteq_str("sandbox_clk", clk->name); ut_asserteq(0, plat->clocks[2].arg[0]);
- ut_assertok(device_get_by_driver_info_idx(plat->clocks[3].idx, &clk)); + ut_assertok(device_get_by_ofplat_idx(plat->clocks[3].idx, &clk)); ut_asserteq_str("sandbox_clk", clk->name); ut_asserteq(3, plat->clocks[3].arg[0]);
- ut_assertok(device_get_by_driver_info_idx(plat->clocks[4].idx, &clk)); + ut_assertok(device_get_by_ofplat_idx(plat->clocks[4].idx, &clk)); ut_asserteq_str("sandbox_clk", clk->name); ut_asserteq(2, plat->clocks[4].arg[0]);

The test framework reinits driver model tests before running each test. Since malloc_simple does not support free(), this eventually runs out of memory.
Fix it for now by increasing the space to 32KB.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
configs/sandbox_spl_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 041c72ac261..223f956fb78 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -7,6 +7,7 @@ CONFIG_SYS_MEMTEST_END=0x00101000 CONFIG_ENV_SIZE=0x2000 CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y CONFIG_BOOTSTAGE_STASH_ADDR=0x0 CONFIG_DEFAULT_DEVICE_TREE="sandbox"

On 03.02.21 17:43, Simon Glass wrote:
The test framework reinits driver model tests before running each test. Since malloc_simple does not support free(), this eventually runs out of memory.
Fix it for now by increasing the space to 32KB.
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v1)
configs/sandbox_spl_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 041c72ac261..223f956fb78 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -7,6 +7,7 @@ CONFIG_SYS_MEMTEST_END=0x00101000 CONFIG_ENV_SIZE=0x2000 CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y CONFIG_BOOTSTAGE_STASH_ADDR=0x0 CONFIG_DEFAULT_DEVICE_TREE="sandbox"

At present the i2c emulators require access to the devicetree, which is not possible (by design) with of-platdata.
Add a way for drivers to record the of-platdata index of their emulator, so that we can still find the emulator.
This allows i2c emulation to work with of-platdata.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/i2c/i2c-emul-uclass.c | 13 +++++++++++++ drivers/rtc/sandbox_rtc.c | 13 +++++++++++++ include/i2c.h | 15 +++++++++++++++ 3 files changed, 41 insertions(+)
diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 9ef4651fa43..bb6ef59914b 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -31,14 +31,27 @@ struct udevice *i2c_emul_get_device(struct udevice *emul) return uc_plat->dev; }
+void i2c_emul_set_idx(struct udevice *dev, int emul_idx) +{ + struct dm_i2c_chip *plat = dev_get_parent_plat(dev); + + plat->emul_idx = emul_idx; +} + int i2c_emul_find(struct udevice *dev, struct udevice **emulp) { struct i2c_emul_uc_plat *uc_plat; struct udevice *emul; int ret;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA) ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev, "sandbox,emul", &emul); +#else + struct dm_i2c_chip *plat = dev_get_parent_plat(dev); + + ret = device_get_by_ofplat_idx(plat->emul_idx, &emul); +#endif if (ret) { log_err("No emulators for device '%s'\n", dev->name); return ret; diff --git a/drivers/rtc/sandbox_rtc.c b/drivers/rtc/sandbox_rtc.c index d0864b1df97..657e5c7be2c 100644 --- a/drivers/rtc/sandbox_rtc.c +++ b/drivers/rtc/sandbox_rtc.c @@ -79,6 +79,18 @@ struct acpi_ops sandbox_rtc_acpi_ops = { }; #endif
+static int sandbox_rtc_bind(struct udevice *dev) +{ +#if CONFIG_IS_ENABLED(PLATDATA) + struct sandbox_i2c_rtc_plat_data *plat = dev_get_plat(dev); + + /* Set up the emul_idx for i2c_emul_find() */ + i2c_emul_set_idx(dev, plat->dtplat.sandbox_emul->idx); +#endif + + return 0; +} + static const struct rtc_ops sandbox_rtc_ops = { .get = sandbox_rtc_get, .set = sandbox_rtc_set, @@ -97,5 +109,6 @@ U_BOOT_DRIVER(sandbox_rtc) = { .id = UCLASS_RTC, .of_match = sandbox_rtc_ids, .ops = &sandbox_rtc_ops, + .bind = sandbox_rtc_bind, ACPI_OPS_PTR(&sandbox_rtc_acpi_ops) }; diff --git a/include/i2c.h b/include/i2c.h index e45e33f5037..7eb7eea58e8 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -93,6 +93,8 @@ struct udevice; * datasheet explains it's usage of this addressing * mode. * @emul: Emulator for this chip address (only used for emulation) + * @emul_idx: Emulator index, used for of-platdata and set by each i2c chip's + * bind() method. This allows i2c_emul_find() to work with of-platdata. */ struct dm_i2c_chip { uint chip_addr; @@ -102,6 +104,7 @@ struct dm_i2c_chip { #ifdef CONFIG_SANDBOX struct udevice *emul; bool test_mode; + int emul_idx; #endif };
@@ -554,6 +557,18 @@ void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs); */ int i2c_emul_find(struct udevice *dev, struct udevice **emulp);
+/** + * i2c_emul_set_idx() - Set the emulator index for an i2c sandbox device + * + * With of-platdata we cannot find the emulator using the device tree, so rely + * on the bind() method of each i2c driver calling this function to tell us + * the of-platdata idx of the emulator + * + * @dev: i2c device to set the emulator for + * @emul_idx: of-platdata index for that emulator + */ +void i2c_emul_set_idx(struct udevice *dev, int emul_idx); + /** * i2c_emul_get_device() - Find the device being emulated *

With recent changes this can be supported again. Add it back.
This reverts commit d85f2c4f2970d0ec2f5f075de734afd11200d153.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/dts/sandbox.dtsi | 10 +++------- configs/sandbox_spl_defconfig | 1 + drivers/i2c/Makefile | 2 -- test/dm/of_platdata.c | 8 ++++---- 4 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 5bf84451c99..69d7d3019ee 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -264,14 +264,10 @@ stringarray = "pre-proper"; };
- test-bus { - compatible = "simple-bus"; + spl-test7 { u-boot,dm-spl; - spl-test7 { - u-boot,dm-spl; - compatible = "sandbox,spl-test"; - stringarray = "spl"; - }; + compatible = "sandbox,spl-test"; + stringarray = "spl"; };
square { diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 223f956fb78..a17f7074424 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -102,6 +102,7 @@ CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y CONFIG_DEVRES=y CONFIG_DEBUG_DEVRES=y +# CONFIG_SPL_SIMPLE_BUS is not set CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_AXI=y diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 29aab0f9e30..1aac5c481e2 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -39,9 +39,7 @@ obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o -ifndef CONFIG_SPL_BUILD obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o -endif obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index 1b46bdf555a..b05d2850e9f 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -206,11 +206,11 @@ DM_TEST(dm_test_of_plat_phandle, UT_TESTF_SCAN_PDATA); /* Test that device parents are correctly set up */ static int dm_test_of_plat_parent(struct unit_test_state *uts) { - struct udevice *dev, *bus; + struct udevice *rtc, *i2c;
- ut_assertok(uclass_first_device_err(UCLASS_SIMPLE_BUS, &bus)); - ut_assertok(device_first_child_err(bus, &dev)); - ut_asserteq_ptr(bus, dev_get_parent(dev)); + ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc)); + ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c)); + ut_asserteq_ptr(i2c, dev_get_parent(rtc));
return 0; }

Move sandbox_spl over to use OF_PLATDATA_INST. Create a new board to test the case when this is not enabled, since we will be keeping that code around for several months and want to avoid regressions.
Skip the dm_test_of_plat_dev() test since driver info is not available for OF_PLATDATA_INST.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
board/sandbox/MAINTAINERS | 7 + configs/sandbox_noinst_defconfig | 229 +++++++++++++++++++++++++++++++ configs/sandbox_spl_defconfig | 1 + test/dm/of_platdata.c | 4 + 4 files changed, 241 insertions(+) create mode 100644 configs/sandbox_noinst_defconfig
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS index 433be48a6f1..d32561cd1d0 100644 --- a/board/sandbox/MAINTAINERS +++ b/board/sandbox/MAINTAINERS @@ -20,6 +20,13 @@ F: board/sandbox/ F: include/configs/sandbox_spl.h F: configs/sandbox_spl_defconfig
+SANDBOX NOINST BOARD +M: Simon Glass sjg@chromium.org +S: Maintained +F: board/sandbox/ +F: include/configs/sandbox_spl.h +F: configs/sandbox_noinst_defconfig + SANDBOX FLAT TREE BOARD M: Simon Glass sjg@chromium.org S: Maintained diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig new file mode 100644 index 00000000000..223f956fb78 --- /dev/null +++ b/configs/sandbox_noinst_defconfig @@ -0,0 +1,229 @@ +CONFIG_SYS_TEXT_BASE=0x200000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_SYS_MEMTEST_START=0x00100000 +CONFIG_SYS_MEMTEST_END=0x00101000 +CONFIG_ENV_SIZE=0x2000 +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y +CONFIG_BOOTSTAGE_STASH_ADDR=0x0 +CONFIG_DEFAULT_DEVICE_TREE="sandbox" +CONFIG_SANDBOX_SPL=y +CONFIG_DEBUG_UART=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_FIT_SIGNATURE=y +CONFIG_FIT_VERBOSE=y +CONFIG_SPL_LOAD_FIT=y +# CONFIG_USE_SPL_FIT_GENERATOR is not set +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_BOOTSTAGE_FDT=y +CONFIG_BOOTSTAGE_STASH=y +CONFIG_BOOTSTAGE_STASH_SIZE=0x4096 +CONFIG_CONSOLE_RECORD=y +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_HANDOFF=y +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_RTC_SUPPORT=y +CONFIG_CMD_CPU=y +CONFIG_CMD_LICENSE=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_BOOTEFI_HELLO=y +# CONFIG_CMD_ELF is not set +CONFIG_CMD_ASKENV=y +CONFIG_CMD_GREPENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_CALLBACK=y +CONFIG_CMD_ENV_FLAGS=y +CONFIG_CMD_NVEDIT_INFO=y +CONFIG_CMD_NVEDIT_LOAD=y +CONFIG_CMD_NVEDIT_SELECT=y +CONFIG_LOOPW=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MX_CYCLIC=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_DEMO=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_IDE=y +CONFIG_CMD_I2C=y +CONFIG_CMD_OSD=y +CONFIG_CMD_PCI=y +CONFIG_CMD_REMOTEPROC=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_BOOTP_DNS2=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_TFTPSRV=y +CONFIG_CMD_RARP=y +CONFIG_CMD_CDP=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_DNS=y +CONFIG_CMD_LINK_LOCAL=y +CONFIG_CMD_BMP=y +CONFIG_CMD_EFIDEBUG=y +CONFIG_CMD_TIME=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_SOUND=y +CONFIG_CMD_QFW=y +CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y +CONFIG_CMD_CBFS=y +CONFIG_CMD_CRAMFS=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_MAC_PARTITION=y +CONFIG_AMIGA_PARTITION=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_HOSTFILE=y +CONFIG_SPL_OF_PLATDATA=y +CONFIG_ENV_IS_NOWHERE=y +CONFIG_ENV_IS_IN_EXT4=y +CONFIG_ENV_EXT4_INTERFACE="host" +CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" +CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_NETCONSOLE=y +CONFIG_IP_DEFRAG=y +CONFIG_SPL_DM=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_DEVRES=y +CONFIG_DEBUG_DEVRES=y +CONFIG_ADC=y +CONFIG_ADC_SANDBOX=y +CONFIG_AXI=y +CONFIG_AXI_SANDBOX=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CPU=y +CONFIG_DM_DEMO=y +CONFIG_DM_DEMO_SIMPLE=y +CONFIG_DM_DEMO_SHAPE=y +CONFIG_SPL_FIRMWARE=y +CONFIG_GPIO_HOG=y +CONFIG_PM8916_GPIO=y +CONFIG_SANDBOX_GPIO=y +CONFIG_I2C_CROS_EC_TUNNEL=y +CONFIG_I2C_CROS_EC_LDO=y +CONFIG_DM_I2C_GPIO=y +CONFIG_SYS_I2C_SANDBOX=y +CONFIG_I2C_MUX=y +CONFIG_I2C_ARB_GPIO_CHALLENGE=y +CONFIG_CROS_EC_KEYB=y +CONFIG_I8042_KEYB=y +CONFIG_LED=y +CONFIG_LED_BLINK=y +CONFIG_LED_GPIO=y +CONFIG_DM_MAILBOX=y +CONFIG_SANDBOX_MBOX=y +CONFIG_MISC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_I2C=y +CONFIG_CROS_EC_LPC=y +CONFIG_CROS_EC_SANDBOX=y +CONFIG_CROS_EC_SPI=y +CONFIG_IRQ=y +CONFIG_P2SB=y +CONFIG_PWRSEQ=y +CONFIG_SPL_PWRSEQ=y +CONFIG_MMC_SANDBOX=y +CONFIG_SPI_FLASH_SANDBOX=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_NVME=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_PCI_SANDBOX=y +CONFIG_PHY=y +CONFIG_PHY_SANDBOX=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_SANDBOX=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_ACT8846=y +CONFIG_DM_PMIC_PFUZE100=y +CONFIG_DM_PMIC_MAX77686=y +CONFIG_DM_PMIC_MC34708=y +CONFIG_PMIC_PM8916=y +CONFIG_PMIC_RK8XX=y +CONFIG_PMIC_S2MPS11=y +CONFIG_DM_PMIC_SANDBOX=y +CONFIG_PMIC_S5M8767=y +CONFIG_PMIC_TPS65090=y +CONFIG_DM_REGULATOR=y +CONFIG_REGULATOR_ACT8846=y +CONFIG_DM_REGULATOR_PFUZE100=y +CONFIG_DM_REGULATOR_MAX77686=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_REGULATOR_S5M8767=y +CONFIG_DM_REGULATOR_SANDBOX=y +CONFIG_REGULATOR_TPS65090=y +CONFIG_DM_PWM=y +CONFIG_PWM_SANDBOX=y +CONFIG_RAM=y +CONFIG_REMOTEPROC_SANDBOX=y +CONFIG_DM_RESET=y +CONFIG_SANDBOX_RESET=y +CONFIG_DM_RTC=y +CONFIG_SPL_DM_RTC=y +CONFIG_SANDBOX_SERIAL=y +CONFIG_SOUND=y +CONFIG_SOUND_SANDBOX=y +CONFIG_SOC_DEVICE=y +CONFIG_SANDBOX_SPI=y +CONFIG_SPMI=y +CONFIG_SPMI_SANDBOX=y +CONFIG_SYSINFO=y +CONFIG_SYSINFO_SANDBOX=y +CONFIG_SYSRESET=y +CONFIG_SPL_SYSRESET=y +CONFIG_TIMER=y +CONFIG_TIMER_EARLY=y +CONFIG_SANDBOX_TIMER=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EMUL=y +CONFIG_USB_KEYBOARD=y +CONFIG_DM_VIDEO=y +CONFIG_CONSOLE_ROTATION=y +CONFIG_CONSOLE_TRUETYPE=y +CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y +CONFIG_VIDEO_SANDBOX_SDL=y +CONFIG_OSD=y +CONFIG_SANDBOX_OSD=y +CONFIG_SPLASH_SCREEN_ALIGN=y +CONFIG_VIDEO_BMP_RLE8=y +CONFIG_FS_CBFS=y +CONFIG_FS_CRAMFS=y +# CONFIG_SPL_USE_TINY_PRINTF is not set +CONFIG_CMD_DHRYSTONE=y +CONFIG_RSA_VERIFY_WITH_PKEY=y +CONFIG_TPM=y +CONFIG_LZ4=y +CONFIG_ERRNO_STR=y +CONFIG_UNIT_TEST=y +CONFIG_SPL_UNIT_TEST=y +CONFIG_UT_TIME=y +CONFIG_UT_DM=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index a17f7074424..cdf5bb2d2b8 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -88,6 +88,7 @@ CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_OF_HOSTFILE=y CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_OF_PLATDATA_INST=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index b05d2850e9f..81c8e3d5b60 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -145,6 +145,10 @@ static int dm_test_of_plat_dev(struct unit_test_state *uts) bool found[n_ents]; uint i;
+ /* Skip this test if there is no platform data */ + if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) + return 0; + /* Record the indexes that are found */ memset(found, '\0', sizeof(found)); ut_assertok(find_driver_info(uts, gd->dm_root, found));

Run the tests on this build too, to prevent regressions.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
test/run | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/test/run b/test/run index 735628e7e37..869406cd8d2 100755 --- a/test/run +++ b/test/run @@ -30,6 +30,10 @@ fi run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \ -k 'test_ofplatdata or test_handoff or test_spl'
+# Run the sane tests with sandbox_noinst (i.e. without OF_PLATDATA_INST) +run_test "sandbox_spl" ./test/py/test.py --bd sandbox_noinst --build \ + -k 'test_ofplatdata or test_handoff or test_spl' + if [ -z "$tools_only" ]; then # Run tests for the flat-device-tree version of sandbox. This is a special # build which does not enable CONFIG_OF_LIVE for the live device tree, so we can

Add this new board to the test plans. Travis-CI is left out, since it is being removed soon due to lack of capacity.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
.azure-pipelines.yml | 3 +++ .gitlab-ci.yml | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index a6279427e13..118f314d594 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -187,6 +187,9 @@ jobs: sandbox_spl: TEST_PY_BD: "sandbox_spl" TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + sandbox_noinst: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" sandbox_flattree: TEST_PY_BD: "sandbox_flattree" evb_ast2500: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2cdcd864c86..2767cd57eb6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -168,7 +168,8 @@ Run binman, buildman, dtoc, Kconfig and patman testsuites: export UBOOT_TRAVIS_BUILD_DIR=/tmp/sandbox_spl; export PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt"; export PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}"; - ./tools/buildman/buildman -o ${UBOOT_TRAVIS_BUILD_DIR} -w sandbox_spl; + ./tools/buildman/buildman -o ${UBOOT_TRAVIS_BUILD_DIR} -w + --board sandbox_spl; ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test; ./tools/buildman/buildman -t; ./tools/dtoc/dtoc -t; @@ -204,6 +205,13 @@ sandbox_spl test.py: TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" <<: *buildman_and_testpy_dfn
+sandbox_noinst_test.py: + tags: [ 'all' ] + variables: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + <<: *buildman_and_testpy_dfn + evb-ast2500 test.py: tags: [ 'all' ] variables:

Some systems (e.g. x86 APL) run SPL from read-only memory. The device instances created by dtoc are therefore not writeable. To make things work we would need to copy the devices to read/write memory.
To avoid this, add an option to use a separate runtime struct for devices, just as is done for drivers. This can be used to hold information that changes at runtime, avoiding the need for a copy.
Also add a Kconfig option for read-only SPL, which selects this feature.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
common/spl/Kconfig | 24 ++++++++++++++++++++++++ dts/Kconfig | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 774541c02bc..584f8483e2e 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -276,6 +276,19 @@ config SPL_SEPARATE_BSS location is used. Normally we put the device tree at the end of BSS but with this option enabled, it goes at _image_binary_end.
+config SPL_READ_ONLY + bool + depends on SPL_OF_PLATDATA + # Bind cannot be supported because the udevice structs are in read-only + # memory so we cannot update the linked lists. + select SPL_OF_PLATDATA_NO_BIND + select SPL_OF_PLATDATA_RT + help + Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only + section of memory. This means that of-platdata must make a copy (in + writeable memory) of anything it wants to modify, such as + device-private data. + config SPL_BANNER_PRINT bool "Enable output of the SPL banner 'U-Boot SPL ...'" default y @@ -1440,6 +1453,17 @@ config TPL_STACK The address of the initial stack-pointer for the TPL stage. Usually this will be the (aligned) top-of-stack.
+config TPL_READ_ONLY + bool + depends on TPL_OF_PLATDATA + select TPL_OF_PLATDATA_NO_BIND + select TPL_OF_PLATDATA_RT + help + Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only + section of memory. This means that of-platdata must make a copy (in + writeable memory) of anything it wants to modify, such as + device-private data. + config TPL_BOOTROM_SUPPORT bool "Support returning to the BOOTROM (from TPL)" help diff --git a/dts/Kconfig b/dts/Kconfig index 645a2d2b84d..a6bfa706637 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -379,6 +379,17 @@ config SPL_OF_PLATDATA_NO_BIND This removes the ability to bind devices at run time, thus saving some code space in U-Boot.
+config SPL_OF_PLATDATA_RT + bool "Use a separate struct for device runtime data" + depends on SPL_OF_PLATDATA_INST + default y + help + For systems running SPL from read-only memory it is convenient to + separate out the runtime information, so that the devices don't need + to be copied before being used. This moves the read-write parts of + struct udevice (at present just the flags) into a separate struct, + which is allocated at runtime. + endif
config TPL_OF_PLATDATA @@ -427,6 +438,17 @@ config TPL_OF_PLATDATA_NO_BIND This removes the ability to bind devices at run time, thus saving some code space in U-Boot.
+config TPL_OF_PLATDATA_RT + bool "Use a separate struct for device runtime data" + depends on TPL_OF_PLATDATA_INST + default y + help + For systems running TPL from read-only memory it is convenient to + separate out the runtime information, so that the devices don't need + to be copied before being used. This moves the read-write parts of + struct udevice (at present just the flags) into a separate struct, + which is allocated at runtime. + endif
endmenu

At present when driver model needs to change a device it simply updates the struct udevice structure. But with of-platdata-inst most of the fields are not modified at runtime. In fact, typically only the flags need to change.
For systems running SPL from read-only memory it is convenient to separate out the runtime information, so that the devices don't need to be copied before being used.
Create a new udevice_rt table, similar to the existing driver_rt. For now it just holds the flags, although they are not used in this patch.
Add a new Kconfig for the driver_rt data, since this is not needed when of-platdata-inst is used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Use separate OF_PLATDATA_DRIVER_RT Kconfigs for driver run-time data - Update the condition for dm_test_of_plat_dev()
drivers/core/root.c | 14 +++++++++++++- dts/Kconfig | 20 ++++++++++++++++++++ include/asm-generic/global_data.h | 16 ++++++++++++++-- include/dm/device.h | 15 +++++++++++++++ test/dm/of_platdata.c | 2 +- 5 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/drivers/core/root.c b/drivers/core/root.c index 75513c2ab25..2591eb62347 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -132,6 +132,18 @@ static int dm_setup_inst(void) { DM_ROOT_NON_CONST = DM_DEVICE_GET(root);
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_RT)) { + struct udevice_rt *urt; + int n_ents; + + /* Allocate the udevice_rt table */ + n_ents = ll_entry_count(struct udevice, udevice); + urt = calloc(n_ents, sizeof(struct udevice_rt)); + if (!urt) + return log_msg_ret("urt", -ENOMEM); + gd_set_dm_udevice_rt(urt); + } + return 0; }
@@ -202,7 +214,7 @@ int dm_scan_plat(bool pre_reloc_only) { int ret;
- if (CONFIG_IS_ENABLED(OF_PLATDATA)) { + if (CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) { struct driver_rt *dyn; int n_ents;
diff --git a/dts/Kconfig b/dts/Kconfig index a6bfa706637..40a6d7151d5 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -338,6 +338,7 @@ config SPL_OF_PLATDATA bool "Generate platform data for use in SPL" depends on SPL_OF_CONTROL select DTOC + select SPL_OF_PLATDATA_DRIVER_RT if !SPL_OF_PLATDATA_INST help For very constrained SPL environments the overhead of decoding device tree nodes and converting their contents into platform data @@ -390,12 +391,22 @@ config SPL_OF_PLATDATA_RT struct udevice (at present just the flags) into a separate struct, which is allocated at runtime.
+config SPL_OF_PLATDATA_DRIVER_RT + bool + help + Use a separate struct for driver runtime data. + + This enables the driver_rt information, used with of-platdata when + of-platdata-inst is not used. It allows finding devices by their + driver data. + endif
config TPL_OF_PLATDATA bool "Generate platform data for use in TPL" depends on TPL_OF_CONTROL select DTOC + select TPL_OF_PLATDATA_DRIVER_RT if !TPL_OF_PLATDATA_INST help For very constrained SPL environments the overhead of decoding device tree nodes and converting their contents into platform data @@ -449,6 +460,15 @@ config TPL_OF_PLATDATA_RT struct udevice (at present just the flags) into a separate struct, which is allocated at runtime.
+config TPL_OF_PLATDATA_DRIVER_RT + bool + help + Use a separate struct for driver runtime data. + + This enables the driver_rt information, used with of-platdata when + of-platdata-inst is not used. It allows finding devices by their + driver data. + endif
endmenu diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index b6f707e97e5..4fbfad8f70e 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -215,10 +215,14 @@ struct global_data { * @uclass_root_s. */ struct list_head *uclass_root; -# if CONFIG_IS_ENABLED(OF_PLATDATA) +# if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT) /** @dm_driver_rt: Dynamic info about the driver */ struct driver_rt *dm_driver_rt; # endif +#if CONFIG_IS_ENABLED(OF_PLATDATA_RT) + /** @dm_udevice_rt: Dynamic info about the udevice */ + struct udevice_rt *dm_udevice_rt; +# endif #endif #ifdef CONFIG_TIMER /** @@ -471,7 +475,7 @@ struct global_data { #define gd_set_of_root(_root) #endif
-#if CONFIG_IS_ENABLED(OF_PLATDATA) +#if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT) #define gd_set_dm_driver_rt(dyn) gd->dm_driver_rt = dyn #define gd_dm_driver_rt() gd->dm_driver_rt #else @@ -479,6 +483,14 @@ struct global_data { #define gd_dm_driver_rt() NULL #endif
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT) +#define gd_set_dm_udevice_rt(dyn) gd->dm_udevice_rt = dyn +#define gd_dm_udevice_rt() gd->dm_udevice_rt +#else +#define gd_set_dm_udevice_rt(dyn) +#define gd_dm_udevice_rt() NULL +#endif + #ifdef CONFIG_GENERATE_ACPI_TABLE #define gd_acpi_ctx() gd->acpi_ctx #else diff --git a/include/dm/device.h b/include/dm/device.h index 891a5f84243..cb165c2e922 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -174,6 +174,21 @@ struct udevice { #endif };
+/** + * udevice_rt - runtime information set up by U-Boot + * + * This is only used with OF_PLATDATA_RT + * + * There is one of these for every udevice in the linker list, indexed by + * the udevice_info idx value. + * + * @flags_: Flags for this device DM_FLAG_... (do not access outside driver + * model) + */ +struct udevice_rt { + u32 flags_; +}; + /* Maximum sequence number supported */ #define DM_MAX_SEQ 999
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c index 81c8e3d5b60..15021335e9f 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -146,7 +146,7 @@ static int dm_test_of_plat_dev(struct unit_test_state *uts) uint i;
/* Skip this test if there is no platform data */ - if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) + if (!CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) return 0;
/* Record the indexes that are found */

When of-platdata-inst is active, use the flags in the new udevice_rt table, dropping them from the main struct udevice. This ensures that the latter is not updated at runtime.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Leave the flags_ memeber in the same struct position
drivers/core/device.c | 33 +++++++++++++++++++++++++++++++++ include/dm/device.h | 8 ++++++++ 2 files changed, 41 insertions(+)
diff --git a/drivers/core/device.c b/drivers/core/device.c index 657ddcc12b6..7505363197f 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -1078,3 +1078,36 @@ int dev_enable_by_path(const char *path) return lists_bind_fdt(parent, node, NULL, false); } #endif + +#if CONFIG_IS_ENABLED(OF_PLATDATA_RT) +static struct udevice_rt *dev_get_rt(const struct udevice *dev) +{ + struct udevice *base = ll_entry_start(struct udevice, udevice); + int idx = dev - base; + + struct udevice_rt *urt = gd_dm_udevice_rt() + idx; + + return urt; +} + +u32 dev_get_flags(const struct udevice *dev) +{ + const struct udevice_rt *urt = dev_get_rt(dev); + + return urt->flags_; +} + +void dev_or_flags(const struct udevice *dev, u32 or) +{ + struct udevice_rt *urt = dev_get_rt(dev); + + urt->flags_ |= or; +} + +void dev_bic_flags(const struct udevice *dev, u32 bic) +{ + struct udevice_rt *urt = dev_get_rt(dev); + + urt->flags_ &= ~bic; +} +#endif /* OF_PLATDATA_RT */ diff --git a/include/dm/device.h b/include/dm/device.h index cb165c2e922..475f4657fc7 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -164,7 +164,9 @@ struct udevice { struct list_head uclass_node; struct list_head child_head; struct list_head sibling_node; +#if !CONFIG_IS_ENABLED(OF_PLATDATA_RT) u32 flags_; +#endif int seq_; #if !CONFIG_IS_ENABLED(OF_PLATDATA) ofnode node_; @@ -195,6 +197,11 @@ struct udevice_rt { /* Returns the operations for a device */ #define device_get_ops(dev) (dev->driver->ops)
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT) +u32 dev_get_flags(const struct udevice *dev); +void dev_or_flags(const struct udevice *dev, u32 or); +void dev_bic_flags(const struct udevice *dev, u32 bic); +#else static inline u32 dev_get_flags(const struct udevice *dev) { return dev->flags_; @@ -209,6 +216,7 @@ static inline void dev_bic_flags(struct udevice *dev, u32 bic) { dev->flags_ &= ~bic; } +#endif /* OF_PLATDATA_RT */
/** * dev_ofnode() - get the DT node reference associated with a udevice

At present the device priv/data data allocated by dtoc is stored in the data section along with other variables. On some platforms it is better to allocate space for it separately, e.g. if SPL is running from read-only memory.
Create a new space with the same size as that allocated by dtoc, ready for use.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/root.c | 12 ++++++++++++ include/asm-generic/global_data.h | 10 ++++++++++ include/asm-generic/sections.h | 3 +++ 3 files changed, 25 insertions(+)
diff --git a/drivers/core/root.c b/drivers/core/root.c index 2591eb62347..e92ad52b69c 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -11,6 +11,7 @@ #include <fdtdec.h> #include <log.h> #include <malloc.h> +#include <asm-generic/sections.h> #include <linux/libfdt.h> #include <dm/acpi.h> #include <dm/device.h> @@ -134,7 +135,9 @@ static int dm_setup_inst(void)
if (CONFIG_IS_ENABLED(OF_PLATDATA_RT)) { struct udevice_rt *urt; + void *base; int n_ents; + uint size;
/* Allocate the udevice_rt table */ n_ents = ll_entry_count(struct udevice, udevice); @@ -142,6 +145,15 @@ static int dm_setup_inst(void) if (!urt) return log_msg_ret("urt", -ENOMEM); gd_set_dm_udevice_rt(urt); + + /* Now allocate space for the priv/plat data, and copy it in */ + size = __priv_data_end - __priv_data_start; + + base = calloc(1, size); + if (!base) + return log_msg_ret("priv", -ENOMEM); + memcpy(base, __priv_data_start, size); + gd_set_dm_priv_base(base); }
return 0; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 4fbfad8f70e..5f1f23bb3d1 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -222,6 +222,12 @@ struct global_data { #if CONFIG_IS_ENABLED(OF_PLATDATA_RT) /** @dm_udevice_rt: Dynamic info about the udevice */ struct udevice_rt *dm_udevice_rt; + /** + * @dm_priv_base: Base address of the priv/plat region used when + * udevices and uclasses are in read-only memory. This is NULL if not + * used + */ + void *dm_priv_base; # endif #endif #ifdef CONFIG_TIMER @@ -486,9 +492,13 @@ struct global_data { #if CONFIG_IS_ENABLED(OF_PLATDATA_RT) #define gd_set_dm_udevice_rt(dyn) gd->dm_udevice_rt = dyn #define gd_dm_udevice_rt() gd->dm_udevice_rt +#define gd_set_dm_priv_base(dyn) gd->dm_priv_base = dyn +#define gd_dm_priv_base() gd->dm_priv_base #else #define gd_set_dm_udevice_rt(dyn) #define gd_dm_udevice_rt() NULL +#define gd_set_dm_priv_base(dyn) +#define gd_dm_priv_base() NULL #endif
#ifdef CONFIG_GENERATE_ACPI_TABLE diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 0577238d60b..267f1db73f2 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -28,6 +28,9 @@ extern char __efi_helloworld_end[]; extern char __efi_var_file_begin[]; extern char __efi_var_file_end[];
+/* Private data used by of-platdata devices/uclasses */ +extern char __priv_data_start[], __priv_data_end[]; + /* Start and end of .ctors section - used for constructor calls. */ extern char __ctors_start[], __ctors_end[];

Collect this together in one place, so driver model can access set it up in a new place if needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/sandbox/cpu/u-boot-spl.lds | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds index 649abeb5ee7..18160436a36 100644 --- a/arch/sandbox/cpu/u-boot-spl.lds +++ b/arch/sandbox/cpu/u-boot-spl.lds @@ -13,6 +13,14 @@ SECTIONS KEEP(*(SORT(.u_boot_list*))); }
+ /* Private data for devices with OF_PLATDATA_RT */ + . = ALIGN(4); + .priv_data : { + __priv_data_start = .; + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*))) + __priv_data_end = .; + } + __u_boot_sandbox_option_start = .; _u_boot_sandbox_getopt : { KEEP(*(.u_boot_sandbox_getopt)) } __u_boot_sandbox_option_end = .;

Make use of the new priv/plat data region if enabled. This is implemented as a simple offset from the position set up by dtoc to the new position.
So long as all access goes through dm_priv_to_rw() this is safe.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/core/device.c | 12 ++++++------ drivers/core/root.c | 9 +++++++++ include/dm/util.h | 9 +++++++++ 3 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c index 7505363197f..b44eda68b8a 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -542,7 +542,7 @@ void *dev_get_plat(const struct udevice *dev) return NULL; }
- return dev->plat_; + return dm_priv_to_rw(dev->plat_); }
void *dev_get_parent_plat(const struct udevice *dev) @@ -552,7 +552,7 @@ void *dev_get_parent_plat(const struct udevice *dev) return NULL; }
- return dev->parent_plat_; + return dm_priv_to_rw(dev->parent_plat_); }
void *dev_get_uclass_plat(const struct udevice *dev) @@ -562,7 +562,7 @@ void *dev_get_uclass_plat(const struct udevice *dev) return NULL; }
- return dev->uclass_plat_; + return dm_priv_to_rw(dev->uclass_plat_); }
void *dev_get_priv(const struct udevice *dev) @@ -572,7 +572,7 @@ void *dev_get_priv(const struct udevice *dev) return NULL; }
- return dev->priv_; + return dm_priv_to_rw(dev->priv_); }
void *dev_get_uclass_priv(const struct udevice *dev) @@ -582,7 +582,7 @@ void *dev_get_uclass_priv(const struct udevice *dev) return NULL; }
- return dev->uclass_priv_; + return dm_priv_to_rw(dev->uclass_priv_); }
void *dev_get_parent_priv(const struct udevice *dev) @@ -592,7 +592,7 @@ void *dev_get_parent_priv(const struct udevice *dev) return NULL; }
- return dev->parent_priv_; + return dm_priv_to_rw(dev->parent_priv_); }
static int device_get_device_tail(struct udevice *dev, int ret, diff --git a/drivers/core/root.c b/drivers/core/root.c index e92ad52b69c..0a7ef03e587 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -344,6 +344,15 @@ __weak int dm_scan_other(bool pre_reloc_only) return 0; }
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY) +void *dm_priv_to_rw(void *priv) +{ + long offset = priv - (void *)__priv_data_start; + + return gd_dm_priv_base() + offset; +} +#endif + /** * dm_scan() - Scan tables to bind devices * diff --git a/include/dm/util.h b/include/dm/util.h index 01a044992f2..138893c9354 100644 --- a/include/dm/util.h +++ b/include/dm/util.h @@ -49,3 +49,12 @@ void dm_dump_driver_compat(void); void dm_dump_static_driver_info(void);
#endif + +#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY) +void *dm_priv_to_rw(void *priv); +#else +static inline void *dm_priv_to_rw(void *priv) +{ + return priv; +} +#endif

Collect this together in one place, so driver model can access set it up in a new place if needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/cpu/u-boot-spl.lds | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds index b82e53ab124..4a655bf9b59 100644 --- a/arch/x86/cpu/u-boot-spl.lds +++ b/arch/x86/cpu/u-boot-spl.lds @@ -32,6 +32,14 @@ SECTIONS . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+ . = ALIGN(4); + + .priv_data : { + __priv_data_start = .; + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*))) + __priv_data_end = .; + } + . = ALIGN(4); .data : { *(.data*) }

The dm.h header should come first. In fact it needs to, since otherwise the driver model definitions are not available to dt-structs.h
Fix this, since it causes problems with OF_PLATDATA_INST.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/cpu/apollolake/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/cpu/apollolake/pmc.c b/arch/x86/cpu/apollolake/pmc.c index e23d38ea072..1d21187c96d 100644 --- a/arch/x86/cpu/apollolake/pmc.c +++ b/arch/x86/cpu/apollolake/pmc.c @@ -9,8 +9,8 @@ #define LOG_CATEGORY UCLASS_ACPI_PMC
#include <common.h> -#include <dt-structs.h> #include <dm.h> +#include <dt-structs.h> #include <log.h> #include <spl.h> #include <acpi/acpi_s3.h>

This enum is needed to generate build-time devices. Tell dtoc where to find the header, to avoid compile errors in the generated code.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/cpu/apollolake/punit.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/cpu/apollolake/punit.c b/arch/x86/cpu/apollolake/punit.c index e67c011e22c..5ed7963579e 100644 --- a/arch/x86/cpu/apollolake/punit.c +++ b/arch/x86/cpu/apollolake/punit.c @@ -93,4 +93,5 @@ U_BOOT_DRIVER(intel_apl_punit) = { .id = UCLASS_SYSCON, .of_match = apl_syscon_ids, .probe = apl_punit_probe, + DM_HEADER(<asm/cpu.h>) /* for X86_SYSCON_PUNIT */ };

With the standard of-platdata we must fix up driver_data manually. With of-platadata-inst this is not necessary, since it is added to the device by dtoc.
Update the code to handle this.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/cpu/intel_common/itss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/intel_common/itss.c b/arch/x86/cpu/intel_common/itss.c index ae4de4ca8c6..b258970e2ee 100644 --- a/arch/x86/cpu/intel_common/itss.c +++ b/arch/x86/cpu/intel_common/itss.c @@ -152,8 +152,9 @@ static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
static int itss_bind(struct udevice *dev) { - /* This is not set with of-platdata, so set it manually */ - if (CONFIG_IS_ENABLED(OF_PLATDATA)) + /* This is not set with basic of-platdata, so set it manually */ + if (CONFIG_IS_ENABLED(OF_PLATDATA) && + !CONFIG_IS_ENABLED(OF_PLATDATA_INST)) dev->driver_data = X86_IRQT_ITSS;
return 0;

With TPL we don't need full PCI support and it adds to code size. Instead, a simple_bus driver is good enough to be able to read and write the PCI config and do a little basic setup.
So at present there are two drivers in U-Boot called pci_x86. One is in UCLASS_PCI, used in SPL and U-Boot proper. The other is in UCLASS_SIMPLE_BUS and used only in TPL.
Add a tag to tell dtoc about this, so it knows which one to use when generating the devices and uclasses.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/lib/tpl.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c index c84a0c9bc7d..32e755ac246 100644 --- a/arch/x86/lib/tpl.c +++ b/arch/x86/lib/tpl.c @@ -149,5 +149,6 @@ U_BOOT_DRIVER(pci_x86) = { .name = "pci_x86", .id = UCLASS_SIMPLE_BUS, .of_match = of_match_ptr(tpl_fake_pci_ids), + DM_PHASE(tpl) }; #endif

We don't normally need this driver in TPL/SPL, so drop it for now. It can be enabled by individual boards if needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/dts/reset.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/dts/reset.dtsi b/arch/x86/dts/reset.dtsi index 555d0dd9608..f2ba2fb5e84 100644 --- a/arch/x86/dts/reset.dtsi +++ b/arch/x86/dts/reset.dtsi @@ -1,6 +1,6 @@ / { reset: reset { compatible = "x86,reset"; - u-boot,dm-pre-reloc; + u-boot,dm-pre-proper; }; };

We don't use these in TPL or SPL, so drop them. Also drop 'ranges' since we don't have a full PCI driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
configs/chromebook_coral_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig index ab73a0a88ce..72eded3c214 100644 --- a/configs/chromebook_coral_defconfig +++ b/configs/chromebook_coral_defconfig @@ -72,6 +72,7 @@ CONFIG_MAC_PARTITION=y CONFIG_ISO_PARTITION=y CONFIG_EFI_PARTITION=y # CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent interrupts linux-name acpi,name acpi,path u-boot,acpi-dsdt-order u-boot,acpi-ssdt-order ranges" CONFIG_ENV_OVERWRITE=y CONFIG_REGMAP=y CONFIG_SYSCON=y

With Apollo Lake, SPL is placed in read-only memory. Set this new option so that OF_PLATDATA_INST can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
arch/x86/cpu/apollolake/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig index f5dbd6cbd34..63a05149df8 100644 --- a/arch/x86/cpu/apollolake/Kconfig +++ b/arch/x86/cpu/apollolake/Kconfig @@ -20,6 +20,8 @@ config INTEL_APOLLOLAKE select INTEL_GMA_SWSMISCI select ACPI_GNVS_EXTERNAL select TPL_OF_PLATDATA_PARENT + select TPL_OF_PLATDATA_INST + select TPL_READ_ONLY imply ENABLE_MRC_CACHE imply AHCI_PCI imply SCSI

On 2/3/21 5:43 PM, Simon Glass wrote:
This series builds on the recent dtoc implementation of build-time device instantiation.
It adds the required driver model support, which is basically a few more data structures.
With this, sandbox_spl and chromebook_coral both use the new feature.
For coral TPL there is a 1.5KB code-size reduction and a 1.75KB data-size increase:
text data bss dec hex
18836 3080 12 21928 55a8 original 17229 4896 12 22137 5679 with OF_PLATDATA_INST 17277 4896 12 22185 56a9 with OF_PLATDATA_RT
The extra data size is due to the build-time devices which are now included in the image instead of being built at runtime. Also the private data for each device is allocated in the data region at present, even through much of it is just zeroes.
The reduction in code size is due to not needing to bind devices at runtime, as a well as a simplified probe() function. Coral requires that data be copied out to RAM before being updated, so that adds a small amount to size (shown in the third line).
Quite a lot of future work is possible, including reducing the size of data structures. See [1] for more ideas. But this series implements the basic feature.
To try this out on your board, define CONFIG_SPL_OF_PLATDATA_INST and see what you get.
Note: SPL tests do not yet pass with this series. The driver_rt struct is not set up so device_get_by_driver_info_idx() does not work. This means that looking up phandles will fail. This will be addressed in a v2
This is v2. I see no update to doc/.
Documentation would be very helpful to review the vast change-set.
Best regards
Heinrich
series, along with documentation updates and a little more information on code-size impact.
This series is available at u-boot-dm/tin-working
[1] https://lists.denx.de/pipermail/u-boot/2020-July/418433.html
Changes in v2:
- Update to deal with test refactoring series
- Use separate OF_PLATDATA_DRIVER_RT Kconfigs for driver run-time data
- Update the condition for dm_test_of_plat_dev()
- Leave the flags_ memeber in the same struct position

Hi Heinrich,
On Thu, 4 Feb 2021 at 00:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/3/21 5:43 PM, Simon Glass wrote:
This series builds on the recent dtoc implementation of build-time device instantiation.
It adds the required driver model support, which is basically a few more data structures.
With this, sandbox_spl and chromebook_coral both use the new feature.
For coral TPL there is a 1.5KB code-size reduction and a 1.75KB data-size increase:
text data bss dec hex
18836 3080 12 21928 55a8 original 17229 4896 12 22137 5679 with OF_PLATDATA_INST 17277 4896 12 22185 56a9 with OF_PLATDATA_RT
The extra data size is due to the build-time devices which are now included in the image instead of being built at runtime. Also the private data for each device is allocated in the data region at present, even through much of it is just zeroes.
The reduction in code size is due to not needing to bind devices at runtime, as a well as a simplified probe() function. Coral requires that data be copied out to RAM before being updated, so that adds a small amount to size (shown in the third line).
Quite a lot of future work is possible, including reducing the size of data structures. See [1] for more ideas. But this series implements the basic feature.
To try this out on your board, define CONFIG_SPL_OF_PLATDATA_INST and see what you get.
Note: SPL tests do not yet pass with this series. The driver_rt struct is not set up so device_get_by_driver_info_idx() does not work. This means that looking up phandles will fail. This will be addressed in a v2
This is v2. I see no update to doc/.
Documentation would be very helpful to review the vast change-set.
Eek I completely forgot about that...
I'll send v3.
Regards, Simon
participants (2)
-
Heinrich Schuchardt
-
Simon Glass