1 /* 2 * Copyright (c) 2013 Google, Inc 3 * 4 * (C) Copyright 2012 5 * Pavel Herrmann <morpheus.ibis@gmail.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <errno.h> 12 #include <fdtdec.h> 13 #include <malloc.h> 14 #include <libfdt.h> 15 #include <dm/device.h> 16 #include <dm/device-internal.h> 17 #include <dm/lists.h> 18 #include <dm/platdata.h> 19 #include <dm/root.h> 20 #include <dm/uclass.h> 21 #include <dm/util.h> 22 #include <linux/list.h> 23 24 DECLARE_GLOBAL_DATA_PTR; 25 26 struct root_priv { 27 fdt_addr_t translation_offset; /* optional translation offset */ 28 }; 29 30 static const struct driver_info root_info = { 31 .name = "root_driver", 32 }; 33 34 struct udevice *dm_root(void) 35 { 36 if (!gd->dm_root) { 37 dm_warn("Virtual root driver does not exist!\n"); 38 return NULL; 39 } 40 41 return gd->dm_root; 42 } 43 44 fdt_addr_t dm_get_translation_offset(void) 45 { 46 struct udevice *root = dm_root(); 47 struct root_priv *priv = dev_get_priv(root); 48 49 return priv->translation_offset; 50 } 51 52 void dm_set_translation_offset(fdt_addr_t offs) 53 { 54 struct udevice *root = dm_root(); 55 struct root_priv *priv = dev_get_priv(root); 56 57 priv->translation_offset = offs; 58 } 59 60 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 61 void fix_drivers(void) 62 { 63 struct driver *drv = 64 ll_entry_start(struct driver, driver); 65 const int n_ents = ll_entry_count(struct driver, driver); 66 struct driver *entry; 67 68 for (entry = drv; entry != drv + n_ents; entry++) { 69 if (entry->of_match) 70 entry->of_match = (const struct udevice_id *) 71 ((u32)entry->of_match + gd->reloc_off); 72 if (entry->bind) 73 entry->bind += gd->reloc_off; 74 if (entry->probe) 75 entry->probe += gd->reloc_off; 76 if (entry->remove) 77 entry->remove += gd->reloc_off; 78 if (entry->unbind) 79 entry->unbind += gd->reloc_off; 80 if (entry->ofdata_to_platdata) 81 entry->ofdata_to_platdata += gd->reloc_off; 82 if (entry->child_post_bind) 83 entry->child_post_bind += gd->reloc_off; 84 if (entry->child_pre_probe) 85 entry->child_pre_probe += gd->reloc_off; 86 if (entry->child_post_remove) 87 entry->child_post_remove += gd->reloc_off; 88 /* OPS are fixed in every uclass post_probe function */ 89 if (entry->ops) 90 entry->ops += gd->reloc_off; 91 } 92 } 93 94 void fix_uclass(void) 95 { 96 struct uclass_driver *uclass = 97 ll_entry_start(struct uclass_driver, uclass); 98 const int n_ents = ll_entry_count(struct uclass_driver, uclass); 99 struct uclass_driver *entry; 100 101 for (entry = uclass; entry != uclass + n_ents; entry++) { 102 if (entry->post_bind) 103 entry->post_bind += gd->reloc_off; 104 if (entry->pre_unbind) 105 entry->pre_unbind += gd->reloc_off; 106 if (entry->pre_probe) 107 entry->pre_probe += gd->reloc_off; 108 if (entry->post_probe) 109 entry->post_probe += gd->reloc_off; 110 if (entry->pre_remove) 111 entry->pre_remove += gd->reloc_off; 112 if (entry->child_post_bind) 113 entry->child_post_bind += gd->reloc_off; 114 if (entry->child_pre_probe) 115 entry->child_pre_probe += gd->reloc_off; 116 if (entry->init) 117 entry->init += gd->reloc_off; 118 if (entry->destroy) 119 entry->destroy += gd->reloc_off; 120 /* FIXME maybe also need to fix these ops */ 121 if (entry->ops) 122 entry->ops += gd->reloc_off; 123 } 124 } 125 126 void fix_devices(void) 127 { 128 struct driver_info *dev = 129 ll_entry_start(struct driver_info, driver_info); 130 const int n_ents = ll_entry_count(struct driver_info, driver_info); 131 struct driver_info *entry; 132 133 for (entry = dev; entry != dev + n_ents; entry++) { 134 if (entry->platdata) 135 entry->platdata += gd->reloc_off; 136 } 137 } 138 139 #endif 140 141 int dm_init(void) 142 { 143 int ret; 144 145 if (gd->dm_root) { 146 dm_warn("Virtual root driver already exists!\n"); 147 return -EINVAL; 148 } 149 INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); 150 151 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 152 fix_drivers(); 153 fix_uclass(); 154 fix_devices(); 155 #endif 156 157 ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); 158 if (ret) 159 return ret; 160 #if CONFIG_IS_ENABLED(OF_CONTROL) 161 DM_ROOT_NON_CONST->of_offset = 0; 162 #endif 163 ret = device_probe(DM_ROOT_NON_CONST); 164 if (ret) 165 return ret; 166 167 return 0; 168 } 169 170 int dm_uninit(void) 171 { 172 device_remove(dm_root()); 173 device_unbind(dm_root()); 174 175 return 0; 176 } 177 178 int dm_scan_platdata(bool pre_reloc_only) 179 { 180 int ret; 181 182 ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only); 183 if (ret == -ENOENT) { 184 dm_warn("Some drivers were not found\n"); 185 ret = 0; 186 } 187 188 return ret; 189 } 190 191 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 192 int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset, 193 bool pre_reloc_only) 194 { 195 int ret = 0, err; 196 197 for (offset = fdt_first_subnode(blob, offset); 198 offset > 0; 199 offset = fdt_next_subnode(blob, offset)) { 200 if (pre_reloc_only && 201 !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL)) 202 continue; 203 if (!fdtdec_get_is_enabled(blob, offset)) { 204 dm_dbg(" - ignoring disabled device\n"); 205 continue; 206 } 207 err = lists_bind_fdt(parent, blob, offset, NULL); 208 if (err && !ret) { 209 ret = err; 210 debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL), 211 ret); 212 } 213 } 214 215 if (ret) 216 dm_warn("Some drivers failed to bind\n"); 217 218 return ret; 219 } 220 221 int dm_scan_fdt_dev(struct udevice *dev) 222 { 223 if (dev->of_offset == -1) 224 return 0; 225 226 return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, 227 gd->flags & GD_FLG_RELOC ? false : true); 228 } 229 230 int dm_scan_fdt(const void *blob, bool pre_reloc_only) 231 { 232 return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only); 233 } 234 #endif 235 236 __weak int dm_scan_other(bool pre_reloc_only) 237 { 238 return 0; 239 } 240 241 int dm_init_and_scan(bool pre_reloc_only) 242 { 243 int ret; 244 245 ret = dm_init(); 246 if (ret) { 247 debug("dm_init() failed: %d\n", ret); 248 return ret; 249 } 250 ret = dm_scan_platdata(pre_reloc_only); 251 if (ret) { 252 debug("dm_scan_platdata() failed: %d\n", ret); 253 return ret; 254 } 255 256 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { 257 ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only); 258 if (ret) { 259 debug("dm_scan_fdt() failed: %d\n", ret); 260 return ret; 261 } 262 } 263 264 ret = dm_scan_other(pre_reloc_only); 265 if (ret) 266 return ret; 267 268 return 0; 269 } 270 271 /* This is the root driver - all drivers are children of this */ 272 U_BOOT_DRIVER(root_driver) = { 273 .name = "root_driver", 274 .id = UCLASS_ROOT, 275 .priv_auto_alloc_size = sizeof(struct root_priv), 276 }; 277 278 /* This is the root uclass */ 279 UCLASS_DRIVER(root) = { 280 .name = "root", 281 .id = UCLASS_ROOT, 282 }; 283