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; | 	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 dm_init(void) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -47,6 +106,11 @@ int dm_init(void) | ||||||
| 	} | 	} | ||||||
| 	INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); | 	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); | 	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
|  |  | ||||||
|  | @ -258,6 +258,22 @@ static int serial_post_probe(struct udevice *dev) | ||||||
| #endif | #endif | ||||||
| 	int ret; | 	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 */ | 	/* Set the baud rate */ | ||||||
| 	if (ops->setbrg) { | 	if (ops->setbrg) { | ||||||
| 		ret = ops->setbrg(dev, gd->baudrate); | 		ret = ops->setbrg(dev, gd->baudrate); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue