2 * Copyright (c) 2013 Google, Inc
5 * Pavel Herrmann <morpheus.ibis@gmail.com>
7 * SPDX-License-Identifier: GPL-2.0+
15 #include <dm/device.h>
16 #include <dm/device-internal.h>
18 #include <dm/platdata.h>
20 #include <dm/uclass.h>
22 #include <linux/list.h>
24 DECLARE_GLOBAL_DATA_PTR
;
27 fdt_addr_t translation_offset
; /* optional translation offset */
30 static const struct driver_info root_info
= {
31 .name
= "root_driver",
34 struct udevice
*dm_root(void)
37 dm_warn("Virtual root driver does not exist!\n");
44 void dm_fixup_for_gd_move(struct global_data
*new_gd
)
46 /* The sentinel node has moved, so update things that point to it */
47 new_gd
->uclass_root
.next
->prev
= &new_gd
->uclass_root
;
48 new_gd
->uclass_root
.prev
->next
= &new_gd
->uclass_root
;
51 fdt_addr_t
dm_get_translation_offset(void)
53 struct udevice
*root
= dm_root();
54 struct root_priv
*priv
= dev_get_priv(root
);
56 return priv
->translation_offset
;
59 void dm_set_translation_offset(fdt_addr_t offs
)
61 struct udevice
*root
= dm_root();
62 struct root_priv
*priv
= dev_get_priv(root
);
64 priv
->translation_offset
= offs
;
67 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
68 void fix_drivers(void)
71 ll_entry_start(struct driver
, driver
);
72 const int n_ents
= ll_entry_count(struct driver
, driver
);
75 for (entry
= drv
; entry
!= drv
+ n_ents
; entry
++) {
77 entry
->of_match
= (const struct udevice_id
*)
78 ((u32
)entry
->of_match
+ gd
->reloc_off
);
80 entry
->bind
+= gd
->reloc_off
;
82 entry
->probe
+= gd
->reloc_off
;
84 entry
->remove
+= gd
->reloc_off
;
86 entry
->unbind
+= gd
->reloc_off
;
87 if (entry
->ofdata_to_platdata
)
88 entry
->ofdata_to_platdata
+= gd
->reloc_off
;
89 if (entry
->child_post_bind
)
90 entry
->child_post_bind
+= gd
->reloc_off
;
91 if (entry
->child_pre_probe
)
92 entry
->child_pre_probe
+= gd
->reloc_off
;
93 if (entry
->child_post_remove
)
94 entry
->child_post_remove
+= gd
->reloc_off
;
95 /* OPS are fixed in every uclass post_probe function */
97 entry
->ops
+= gd
->reloc_off
;
101 void fix_uclass(void)
103 struct uclass_driver
*uclass
=
104 ll_entry_start(struct uclass_driver
, uclass
);
105 const int n_ents
= ll_entry_count(struct uclass_driver
, uclass
);
106 struct uclass_driver
*entry
;
108 for (entry
= uclass
; entry
!= uclass
+ n_ents
; entry
++) {
109 if (entry
->post_bind
)
110 entry
->post_bind
+= gd
->reloc_off
;
111 if (entry
->pre_unbind
)
112 entry
->pre_unbind
+= gd
->reloc_off
;
113 if (entry
->pre_probe
)
114 entry
->pre_probe
+= gd
->reloc_off
;
115 if (entry
->post_probe
)
116 entry
->post_probe
+= gd
->reloc_off
;
117 if (entry
->pre_remove
)
118 entry
->pre_remove
+= gd
->reloc_off
;
119 if (entry
->child_post_bind
)
120 entry
->child_post_bind
+= gd
->reloc_off
;
121 if (entry
->child_pre_probe
)
122 entry
->child_pre_probe
+= gd
->reloc_off
;
124 entry
->init
+= gd
->reloc_off
;
126 entry
->destroy
+= gd
->reloc_off
;
127 /* FIXME maybe also need to fix these ops */
129 entry
->ops
+= gd
->reloc_off
;
133 void fix_devices(void)
135 struct driver_info
*dev
=
136 ll_entry_start(struct driver_info
, driver_info
);
137 const int n_ents
= ll_entry_count(struct driver_info
, driver_info
);
138 struct driver_info
*entry
;
140 for (entry
= dev
; entry
!= dev
+ n_ents
; entry
++) {
142 entry
->platdata
+= gd
->reloc_off
;
153 dm_warn("Virtual root driver already exists!\n");
156 INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST
);
158 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
164 ret
= device_bind_by_name(NULL
, false, &root_info
, &DM_ROOT_NON_CONST
);
167 #if CONFIG_IS_ENABLED(OF_CONTROL)
168 DM_ROOT_NON_CONST
->of_offset
= 0;
170 ret
= device_probe(DM_ROOT_NON_CONST
);
179 device_remove(dm_root());
180 device_unbind(dm_root());
185 int dm_scan_platdata(bool pre_reloc_only
)
189 ret
= lists_bind_drivers(DM_ROOT_NON_CONST
, pre_reloc_only
);
190 if (ret
== -ENOENT
) {
191 dm_warn("Some drivers were not found\n");
198 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
199 int dm_scan_fdt_node(struct udevice
*parent
, const void *blob
, int offset
,
204 for (offset
= fdt_first_subnode(blob
, offset
);
206 offset
= fdt_next_subnode(blob
, offset
)) {
207 if (pre_reloc_only
&&
208 !fdt_getprop(blob
, offset
, "u-boot,dm-pre-reloc", NULL
))
210 if (!fdtdec_get_is_enabled(blob
, offset
)) {
211 dm_dbg(" - ignoring disabled device\n");
214 err
= lists_bind_fdt(parent
, blob
, offset
, NULL
);
217 debug("%s: ret=%d\n", fdt_get_name(blob
, offset
, NULL
),
223 dm_warn("Some drivers failed to bind\n");
228 int dm_scan_fdt_dev(struct udevice
*dev
)
230 if (dev
->of_offset
== -1)
233 return dm_scan_fdt_node(dev
, gd
->fdt_blob
, dev
->of_offset
,
234 gd
->flags
& GD_FLG_RELOC
? false : true);
237 int dm_scan_fdt(const void *blob
, bool pre_reloc_only
)
239 return dm_scan_fdt_node(gd
->dm_root
, blob
, 0, pre_reloc_only
);
243 __weak
int dm_scan_other(bool pre_reloc_only
)
248 int dm_init_and_scan(bool pre_reloc_only
)
254 debug("dm_init() failed: %d\n", ret
);
257 ret
= dm_scan_platdata(pre_reloc_only
);
259 debug("dm_scan_platdata() failed: %d\n", ret
);
263 if (CONFIG_IS_ENABLED(OF_CONTROL
) && !CONFIG_IS_ENABLED(OF_PLATDATA
)) {
264 ret
= dm_scan_fdt(gd
->fdt_blob
, pre_reloc_only
);
266 debug("dm_scan_fdt() failed: %d\n", ret
);
271 ret
= dm_scan_other(pre_reloc_only
);
278 /* This is the root driver - all drivers are children of this */
279 U_BOOT_DRIVER(root_driver
) = {
280 .name
= "root_driver",
282 .priv_auto_alloc_size
= sizeof(struct root_priv
),
285 /* This is the root uclass */
286 UCLASS_DRIVER(root
) = {