mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
dm: Support parent devices with of-platdata
At present of-platdata does not provide parent information. But this is useful for I2C devices, for example, since it allows them to determine which bus they are on. Add support for setting the parent correctly, by storing the parent driver_info index in dtoc and reading this in lists_bind_drivers(). This needs multiple passes since we must process children after their parents already have been bound. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
67507e4aab
commit
e41651fffd
5 changed files with 116 additions and 3 deletions
|
@ -51,21 +51,48 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
|
||||
static int bind_drivers_pass(struct udevice *parent, bool pre_reloc_only)
|
||||
{
|
||||
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 missing_parent = false;
|
||||
int result = 0;
|
||||
uint idx;
|
||||
|
||||
/*
|
||||
* Do one iteration through the driver_info records. For of-platdata,
|
||||
* bind only devices whose parent is already bound. If we find any
|
||||
* device we can't bind, set missing_parent to true, which will cause
|
||||
* this function to be called again.
|
||||
*/
|
||||
for (idx = 0; idx < n_ents; idx++) {
|
||||
struct udevice *par = parent;
|
||||
const struct driver_info *entry = info + idx;
|
||||
struct driver_rt *drt = gd_dm_driver_rt() + idx;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev);
|
||||
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||
int parent_idx = driver_info_parent_id(entry);
|
||||
|
||||
if (drt->dev)
|
||||
continue;
|
||||
|
||||
if (CONFIG_IS_ENABLED(OF_PLATDATA_PARENT) &&
|
||||
parent_idx != -1) {
|
||||
struct driver_rt *parent_drt;
|
||||
|
||||
parent_drt = gd_dm_driver_rt() + parent_idx;
|
||||
if (!parent_drt->dev) {
|
||||
missing_parent = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
par = parent_drt->dev;
|
||||
}
|
||||
}
|
||||
ret = device_bind_by_name(par, pre_reloc_only, entry, &dev);
|
||||
if (!ret) {
|
||||
if (CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||
drt->dev = dev;
|
||||
|
@ -76,6 +103,29 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
|
|||
}
|
||||
}
|
||||
|
||||
return result ? result : missing_parent ? -EAGAIN : 0;
|
||||
}
|
||||
|
||||
int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
|
||||
{
|
||||
int result = 0;
|
||||
int pass;
|
||||
|
||||
/*
|
||||
* 10 passes is 10 levels deep in the devicetree, which is plenty. If
|
||||
* OF_PLATDATA_PARENT is not enabled, then bind_drivers_pass() will
|
||||
* always succeed on the first pass.
|
||||
*/
|
||||
for (pass = 0; pass < 10; pass++) {
|
||||
int ret;
|
||||
|
||||
ret = bind_drivers_pass(parent, pre_reloc_only);
|
||||
if (!ret)
|
||||
break;
|
||||
if (ret != -EAGAIN && !result)
|
||||
result = ret;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
18
dts/Kconfig
18
dts/Kconfig
|
@ -355,6 +355,15 @@ config SPL_OF_PLATDATA
|
|||
compatible string, then adding platform data and U_BOOT_DEVICE
|
||||
declarations for each node. See of-plat.txt for more information.
|
||||
|
||||
config SPL_OF_PLATDATA_PARENT
|
||||
bool "Support parent information in devices"
|
||||
depends on SPL_OF_PLATDATA
|
||||
default y
|
||||
help
|
||||
Generally it is useful to be able to access the parent of a device
|
||||
with of-platdata. To save space this can be disabled, but in that
|
||||
case dev_get_parent() will always return NULL;
|
||||
|
||||
config TPL_OF_PLATDATA
|
||||
bool "Generate platform data for use in TPL"
|
||||
depends on TPL_OF_CONTROL
|
||||
|
@ -376,4 +385,13 @@ config TPL_OF_PLATDATA
|
|||
compatible string, then adding platform data and U_BOOT_DEVICE
|
||||
declarations for each node. See of-plat.txt for more information.
|
||||
|
||||
config TPL_OF_PLATDATA_PARENT
|
||||
bool "Support parent information in devices"
|
||||
depends on TPL_OF_PLATDATA
|
||||
default y
|
||||
help
|
||||
Generally it is useful to be able to access the parent of a device
|
||||
with of-platdata. To save space this can be disabled, but in that
|
||||
case dev_get_parent() will always return NULL;
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -22,15 +22,23 @@
|
|||
* @name: Driver name
|
||||
* @platdata: Driver-specific platform data
|
||||
* @platdata_size: Size of platform data structure
|
||||
* @parent_idx: Index of the parent driver_info structure
|
||||
*/
|
||||
struct driver_info {
|
||||
const char *name;
|
||||
const void *platdata;
|
||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||
uint platdata_size;
|
||||
unsigned short platdata_size;
|
||||
short parent_idx;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||
#define driver_info_parent_id(driver_info) driver_info->parent_idx
|
||||
#else
|
||||
#define driver_info_parent_id(driver_info) (-1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* driver_rt - runtime information set up by U-Boot
|
||||
*
|
||||
|
|
|
@ -662,6 +662,10 @@ class DtbPlatdata(object):
|
|||
self.buf('\t.name\t\t= "%s",\n' % struct_name)
|
||||
self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
|
||||
self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
|
||||
idx = -1
|
||||
if node.parent and node.parent in self._valid_nodes:
|
||||
idx = node.parent.idx
|
||||
self.buf('\t.parent_idx\t= %d,\n' % idx)
|
||||
self.buf('};\n')
|
||||
self.buf('\n')
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ U_BOOT_DEVICE(i2c_at_0) = {
|
|||
\t.name\t\t= "sandbox_i2c_test",
|
||||
\t.platdata\t= &dtv_i2c_at_0,
|
||||
\t.platdata_size\t= sizeof(dtv_i2c_at_0),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /i2c@0/pmic@9 index 1 */
|
||||
|
@ -227,6 +228,7 @@ U_BOOT_DEVICE(pmic_at_9) = {
|
|||
\t.name\t\t= "sandbox_pmic_test",
|
||||
\t.platdata\t= &dtv_pmic_at_9,
|
||||
\t.platdata_size\t= sizeof(dtv_pmic_at_9),
|
||||
\t.parent_idx\t= 0,
|
||||
};
|
||||
|
||||
/* Node /spl-test index 2 */
|
||||
|
@ -246,6 +248,7 @@ U_BOOT_DEVICE(spl_test) = {
|
|||
\t.name\t\t= "sandbox_spl_test",
|
||||
\t.platdata\t= &dtv_spl_test,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /spl-test2 index 3 */
|
||||
|
@ -264,6 +267,7 @@ U_BOOT_DEVICE(spl_test2) = {
|
|||
\t.name\t\t= "sandbox_spl_test",
|
||||
\t.platdata\t= &dtv_spl_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /spl-test3 index 4 */
|
||||
|
@ -276,6 +280,7 @@ U_BOOT_DEVICE(spl_test3) = {
|
|||
\t.name\t\t= "sandbox_spl_test",
|
||||
\t.platdata\t= &dtv_spl_test3,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test3),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /spl-test4 index 5 */
|
||||
|
@ -285,6 +290,7 @@ U_BOOT_DEVICE(spl_test4) = {
|
|||
\t.name\t\t= "sandbox_spl_test_2",
|
||||
\t.platdata\t= &dtv_spl_test4,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test4),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
@ -318,6 +324,7 @@ U_BOOT_DEVICE(gpios_at_0) = {
|
|||
\t.name\t\t= "sandbox_gpio",
|
||||
\t.platdata\t= &dtv_gpios_at_0,
|
||||
\t.platdata_size\t= sizeof(dtv_gpios_at_0),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
void dm_populate_phandle_data(void) {
|
||||
|
@ -349,6 +356,7 @@ U_BOOT_DEVICE(spl_test) = {
|
|||
\t.name\t\t= "invalid",
|
||||
\t.platdata\t= &dtv_spl_test,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
void dm_populate_phandle_data(void) {
|
||||
|
@ -383,6 +391,7 @@ U_BOOT_DEVICE(phandle2_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle2_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle3-target index 1 */
|
||||
|
@ -393,6 +402,7 @@ U_BOOT_DEVICE(phandle3_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle3_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-target index 4 */
|
||||
|
@ -403,6 +413,7 @@ U_BOOT_DEVICE(phandle_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-source index 2 */
|
||||
|
@ -417,6 +428,7 @@ U_BOOT_DEVICE(phandle_source) = {
|
|||
\t.name\t\t= "source",
|
||||
\t.platdata\t= &dtv_phandle_source,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-source2 index 3 */
|
||||
|
@ -428,6 +440,7 @@ U_BOOT_DEVICE(phandle_source2) = {
|
|||
\t.name\t\t= "source",
|
||||
\t.platdata\t= &dtv_phandle_source2,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
void dm_populate_phandle_data(void) {
|
||||
|
@ -470,6 +483,7 @@ U_BOOT_DEVICE(phandle_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-source2 index 0 */
|
||||
|
@ -481,6 +495,7 @@ U_BOOT_DEVICE(phandle_source2) = {
|
|||
\t.name\t\t= "source",
|
||||
\t.platdata\t= &dtv_phandle_source2,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
void dm_populate_phandle_data(void) {
|
||||
|
@ -504,6 +519,7 @@ U_BOOT_DEVICE(phandle2_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle2_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle3-target index 1 */
|
||||
|
@ -514,6 +530,7 @@ U_BOOT_DEVICE(phandle3_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle3_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-target index 4 */
|
||||
|
@ -524,6 +541,7 @@ U_BOOT_DEVICE(phandle_target) = {
|
|||
\t.name\t\t= "target",
|
||||
\t.platdata\t= &dtv_phandle_target,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-source index 2 */
|
||||
|
@ -538,6 +556,7 @@ U_BOOT_DEVICE(phandle_source) = {
|
|||
\t.name\t\t= "source",
|
||||
\t.platdata\t= &dtv_phandle_source,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /phandle-source2 index 3 */
|
||||
|
@ -549,6 +568,7 @@ U_BOOT_DEVICE(phandle_source2) = {
|
|||
\t.name\t\t= "source",
|
||||
\t.platdata\t= &dtv_phandle_source2,
|
||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
void dm_populate_phandle_data(void) {
|
||||
|
@ -611,6 +631,7 @@ U_BOOT_DEVICE(test1) = {
|
|||
\t.name\t\t= "test1",
|
||||
\t.platdata\t= &dtv_test1,
|
||||
\t.platdata_size\t= sizeof(dtv_test1),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test2 index 1 */
|
||||
|
@ -621,6 +642,7 @@ U_BOOT_DEVICE(test2) = {
|
|||
\t.name\t\t= "test2",
|
||||
\t.platdata\t= &dtv_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test3 index 2 */
|
||||
|
@ -631,6 +653,7 @@ U_BOOT_DEVICE(test3) = {
|
|||
\t.name\t\t= "test3",
|
||||
\t.platdata\t= &dtv_test3,
|
||||
\t.platdata_size\t= sizeof(dtv_test3),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
@ -663,6 +686,7 @@ U_BOOT_DEVICE(test1) = {
|
|||
\t.name\t\t= "test1",
|
||||
\t.platdata\t= &dtv_test1,
|
||||
\t.platdata_size\t= sizeof(dtv_test1),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test2 index 1 */
|
||||
|
@ -673,6 +697,7 @@ U_BOOT_DEVICE(test2) = {
|
|||
\t.name\t\t= "test2",
|
||||
\t.platdata\t= &dtv_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
@ -708,6 +733,7 @@ U_BOOT_DEVICE(test1) = {
|
|||
\t.name\t\t= "test1",
|
||||
\t.platdata\t= &dtv_test1,
|
||||
\t.platdata_size\t= sizeof(dtv_test1),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test2 index 1 */
|
||||
|
@ -718,6 +744,7 @@ U_BOOT_DEVICE(test2) = {
|
|||
\t.name\t\t= "test2",
|
||||
\t.platdata\t= &dtv_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test3 index 2 */
|
||||
|
@ -728,6 +755,7 @@ U_BOOT_DEVICE(test3) = {
|
|||
\t.name\t\t= "test3",
|
||||
\t.platdata\t= &dtv_test3,
|
||||
\t.platdata_size\t= sizeof(dtv_test3),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
@ -763,6 +791,7 @@ U_BOOT_DEVICE(test1) = {
|
|||
\t.name\t\t= "test1",
|
||||
\t.platdata\t= &dtv_test1,
|
||||
\t.platdata_size\t= sizeof(dtv_test1),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test2 index 1 */
|
||||
|
@ -773,6 +802,7 @@ U_BOOT_DEVICE(test2) = {
|
|||
\t.name\t\t= "test2",
|
||||
\t.platdata\t= &dtv_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /test3 index 2 */
|
||||
|
@ -783,6 +813,7 @@ U_BOOT_DEVICE(test3) = {
|
|||
\t.name\t\t= "test3",
|
||||
\t.platdata\t= &dtv_test3,
|
||||
\t.platdata_size\t= sizeof(dtv_test3),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
@ -833,6 +864,7 @@ U_BOOT_DEVICE(spl_test) = {
|
|||
\t.name\t\t= "sandbox_spl_test",
|
||||
\t.platdata\t= &dtv_spl_test,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
/* Node /spl-test2 index 1 */
|
||||
|
@ -843,6 +875,7 @@ U_BOOT_DEVICE(spl_test2) = {
|
|||
\t.name\t\t= "sandbox_spl_test",
|
||||
\t.platdata\t= &dtv_spl_test2,
|
||||
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
||||
\t.parent_idx\t= -1,
|
||||
};
|
||||
|
||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||
|
|
Loading…
Reference in a new issue