diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 39406c3f35..71e5c75028 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -10,11 +10,86 @@ #ifndef _DM_DEVICE_INTERNAL_H #define _DM_DEVICE_INTERNAL_H +#include #include struct device_node; struct udevice; +/* + * These two macros DM_DEVICE_INST and DM_DEVICE_REF are only allowed 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. + * + * It is OK to use them with 'extern' though, since that does not actually + * add a new record to the linker_list. + */ + +/** + * DM_DEVICE_INST() - Declare a bound device ready for run-time use + * + * This adds an actual struct udevice to a list which is found by driver model + * on start-up. + * + * For example: + * + * extern U_BOOT_DRIVER(sandbox_fixed_clock); + * extern DM_UCLASS_INST(clk); + * + * DM_DEVICE_INST(clk_fixed) = { + * .driver = DM_DRIVER_REF(sandbox_fixed_clock), + * .name = "sandbox_fixed_clock", + * .plat_ = &_sandbox_fixed_clock_plat_clk_fixed, + * .uclass = DM_UCLASS_REF(clk), + * ... + * .seq_ = 0, + * }; + * + * @_name: Name of the udevice. This must be a valid C identifier, used by the + * linker_list. + */ +#define DM_DEVICE_INST(_name) \ + ll_entry_declare(struct udevice, _name, udevice) + +/** + * DM_DEVICE_REF() - Get a reference to a device + * + * This is useful in data structures and code for referencing a udevice at + * build time. Before this is used, an extern DM_DEVICE_INST() must have been + * declared. + * + * For example: + * + * extern DM_DEVICE_INST(clk_fixed); + * + * struct udevice *devs[] = { + * DM_DEVICE_REF(clk_fixed), + * }; + * + * @_name: Name of the udevice. This must be a valid C identifier, used by the + * linker_list + * @returns struct udevice * for the device + */ +#define DM_DEVICE_REF(_name) \ + ll_entry_ref(struct udevice, _name, udevice) + +/** + * DM_DEVICE_GET() - Get a pointer to a given device + * + * This is similar to DM_DEVICE_REF() except that it does not need the extern + * declaration before it. However it cannot be used in a data structures, only + * in code within a function. + * + * For example: + * + * void some_function() { + * struct udevice *dev = DM_DEVICE_GET(clk_fixed); + * ... + * } + */ +#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 45010b4df9..5b8f27d455 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -362,6 +362,28 @@ struct driver { #define DM_DRIVER_GET(__name) \ ll_entry_get(struct driver, __name, driver) +/** + * DM_DRIVER_REF() - Get a reference to a driver + * + * This is useful in data structures and code for referencing a driver at + * build time. Before this is used, an extern U_BOOT_DRIVER() must have been + * declared. + * + * For example: + * + * extern U_BOOT_DRIVER(sandbox_fixed_clock); + * + * struct driver *drvs[] = { + * DM_DRIVER_REF(sandbox_fixed_clock), + * }; + * + * @_name: Name of the driver. This must be a valid C identifier, used by the + * linker_list + * @returns struct driver * for the driver + */ +#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 c5a464be7c..f2a780682b 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -11,6 +11,55 @@ #include +/* + * These next two macros DM_UCLASS_INST() and DM_UCLASS_REF() are only allowed + * 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. + * + * It is OK to use them with 'extern' though, since that does not actually + * add a new record to the linker_list. + */ + +/** + * DM_UCLASS_INST() - 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. + * + * For example: + * + * DM_UCLASS_INST(clk) = { + * .uc_drv = DM_UCLASS_DRIVER_REF(clk), + * ... + * }; + * + * @_name: Name of the uclass. This must be a valid C identifier, used by the + * linker_list. + */ +#define DM_UCLASS_INST(_name) \ + ll_entry_declare(struct uclass, _name, uclass) + +/** + * DM_UCLASS_REF() - Get a reference to a uclass + * + * This is useful for referencing a uclass at build time. Before this is used, + * an extern DM_UCLASS_INST() must have been declared. + * + * For example: + * + * extern DM_UCLASS_INST(clk); + * + * struct uclass *ucs[] = { + * DM_UCLASS_REF(clk), + * } + * + * @_name: Name of the uclass. This must be a valid C identifier, used by the + * linker_list + * @returns struct uclass * for the device + */ +#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 d95683740c..6752d8ee0b 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -114,6 +114,37 @@ struct uclass_driver { #define UCLASS_DRIVER(__name) \ ll_entry_declare(struct uclass_driver, __name, uclass_driver) +/* + * These two macros DM_UCLASS_DRIVER_REF and DM_UCLASS_DRIVER_REF are only + * allowed 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. + * + * It is OK to use them with 'extern' though, since that does not actually + * add a new record to the linker_list. + */ + +/** + * DM_UCLASS_DRIVER_REF() - Get a reference to a uclass driver + * + * This is useful in data structures and code for referencing a uclass_driver at + * build time. Before this is used, an extern UCLASS_DRIVER() must have been + * declared. + * + * For example: + * + * extern UCLASS_DRIVER(clk); + * + * struct uclass_driver *drvs[] = { + * DM_UCLASS_DRIVER_REF(clk), + * }; + * + * @_name: Name of the uclass_driver. This must be a valid C identifier, used by + * the linker_list. + * @returns struct uclass_driver * for the uclass driver + */ +#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 * diff --git a/include/linker_lists.h b/include/linker_lists.h index 0ca30da417..81a280a884 100644 --- a/include/linker_lists.h +++ b/include/linker_lists.h @@ -214,8 +214,8 @@ /** * 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. + * Once an extern ll_entry_declare() 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.