dm: Add support for all targets which requires MANUAL_RELOC
Targets with CONFIG_NEEDS_MANUAL_RELOC do not use REL/RELA relocation (mostly only GOT) where functions aray are not updated. This patch is fixing function pointers for DM core and serial-uclass to ensure that relocated functions are called. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Acked-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
99c0ae16d8
commit
484fdf5ba0
@ -37,6 +37,65 @@ struct udevice *dm_root(void)
|
||||
return gd->dm_root;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
void fix_drivers(void)
|
||||
{
|
||||
struct driver *drv =
|
||||
ll_entry_start(struct driver, driver);
|
||||
const int n_ents = ll_entry_count(struct driver, driver);
|
||||
struct driver *entry;
|
||||
|
||||
for (entry = drv; entry != drv + n_ents; entry++) {
|
||||
if (entry->of_match)
|
||||
entry->of_match = (const struct udevice_id *)
|
||||
((u32)entry->of_match + gd->reloc_off);
|
||||
if (entry->bind)
|
||||
entry->bind += gd->reloc_off;
|
||||
if (entry->probe)
|
||||
entry->probe += gd->reloc_off;
|
||||
if (entry->remove)
|
||||
entry->remove += gd->reloc_off;
|
||||
if (entry->unbind)
|
||||
entry->unbind += gd->reloc_off;
|
||||
if (entry->ofdata_to_platdata)
|
||||
entry->ofdata_to_platdata += gd->reloc_off;
|
||||
if (entry->child_pre_probe)
|
||||
entry->child_pre_probe += gd->reloc_off;
|
||||
if (entry->child_post_remove)
|
||||
entry->child_post_remove += gd->reloc_off;
|
||||
/* OPS are fixed in every uclass post_probe function */
|
||||
if (entry->ops)
|
||||
entry->ops += gd->reloc_off;
|
||||
}
|
||||
}
|
||||
|
||||
void fix_uclass(void)
|
||||
{
|
||||
struct uclass_driver *uclass =
|
||||
ll_entry_start(struct uclass_driver, uclass);
|
||||
const int n_ents = ll_entry_count(struct uclass_driver, uclass);
|
||||
struct uclass_driver *entry;
|
||||
|
||||
for (entry = uclass; entry != uclass + n_ents; entry++) {
|
||||
if (entry->post_bind)
|
||||
entry->post_bind += gd->reloc_off;
|
||||
if (entry->pre_unbind)
|
||||
entry->pre_unbind += gd->reloc_off;
|
||||
if (entry->post_probe)
|
||||
entry->post_probe += gd->reloc_off;
|
||||
if (entry->pre_remove)
|
||||
entry->pre_remove += gd->reloc_off;
|
||||
if (entry->init)
|
||||
entry->init += gd->reloc_off;
|
||||
if (entry->destroy)
|
||||
entry->destroy += gd->reloc_off;
|
||||
/* FIXME maybe also need to fix these ops */
|
||||
if (entry->ops)
|
||||
entry->ops += gd->reloc_off;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int dm_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -47,6 +106,11 @@ int dm_init(void)
|
||||
}
|
||||
INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
fix_drivers();
|
||||
fix_uclass();
|
||||
#endif
|
||||
|
||||
ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -258,6 +258,22 @@ static int serial_post_probe(struct udevice *dev)
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
if (ops->setbrg)
|
||||
ops->setbrg += gd->reloc_off;
|
||||
if (ops->getc)
|
||||
ops->getc += gd->reloc_off;
|
||||
if (ops->putc)
|
||||
ops->putc += gd->reloc_off;
|
||||
if (ops->pending)
|
||||
ops->pending += gd->reloc_off;
|
||||
if (ops->clear)
|
||||
ops->clear += gd->reloc_off;
|
||||
#if CONFIG_POST & CONFIG_SYS_POST_UART
|
||||
if (ops->loop)
|
||||
ops->loop += gd->reloc_off
|
||||
#endif
|
||||
#endif
|
||||
/* Set the baud rate */
|
||||
if (ops->setbrg) {
|
||||
ret = ops->setbrg(dev, gd->baudrate);
|
||||
|
Loading…
Reference in New Issue
Block a user