]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - drivers/core/fdtaddr.c
1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (c) 2017 Google, Inc
8 * Pavel Herrmann <morpheus.ibis@gmail.com>
13 #include <fdt_support.h>
16 #include <asm/global_data.h>
18 #include <dm/device-internal.h>
20 DECLARE_GLOBAL_DATA_PTR
;
22 fdt_addr_t
devfdt_get_addr_index(const struct udevice
*dev
, int index
)
24 #if CONFIG_IS_ENABLED(OF_REAL)
25 int offset
= dev_of_offset(dev
);
26 int parent
= fdt_parent_offset(gd
->fdt_blob
, offset
);
29 if (CONFIG_IS_ENABLED(OF_TRANSLATE
)) {
34 na
= fdt_address_cells(gd
->fdt_blob
, parent
);
36 debug("bad #address-cells\n");
37 return FDT_ADDR_T_NONE
;
40 ns
= fdt_size_cells(gd
->fdt_blob
, parent
);
42 debug("bad #size-cells\n");
43 return FDT_ADDR_T_NONE
;
46 reg
= fdt_getprop(gd
->fdt_blob
, offset
, "reg", &len
);
47 if (!reg
|| (len
<= (index
* sizeof(fdt32_t
) * (na
+ ns
)))) {
48 debug("Req index out of range\n");
49 return FDT_ADDR_T_NONE
;
52 reg
+= index
* (na
+ ns
);
56 * Use the full-fledged translate function for complex
59 addr
= fdt_translate_address((void *)gd
->fdt_blob
,
62 /* Non translatable if #size-cells == 0 */
63 addr
= fdt_read_number(reg
, na
);
67 * Use the "simple" translate function for less complex
70 addr
= fdtdec_get_addr_size_auto_parent(gd
->fdt_blob
, parent
,
73 if (CONFIG_IS_ENABLED(SIMPLE_BUS
) && addr
!= FDT_ADDR_T_NONE
) {
74 if (device_get_uclass_id(dev
->parent
) ==
76 addr
= simple_bus_translate(dev
->parent
, addr
);
80 #if defined(CONFIG_TRANSLATION_OFFSET)
82 * Some platforms need a special address translation. Those
83 * platforms (e.g. mvebu in SPL) can configure a translation
84 * offset by setting this value in the GD and enaling this
85 * feature via CONFIG_TRANSLATION_OFFSET. This value will
86 * get added to all addresses returned by devfdt_get_addr().
88 addr
+= gd
->translation_offset
;
93 return FDT_ADDR_T_NONE
;
97 void *devfdt_get_addr_index_ptr(const struct udevice
*dev
, int index
)
99 fdt_addr_t addr
= devfdt_get_addr_index(dev
, index
);
101 if (addr
== FDT_ADDR_T_NONE
)
104 return map_sysmem(addr
, 0);
107 fdt_addr_t
devfdt_get_addr_size_index(const struct udevice
*dev
, int index
,
110 #if CONFIG_IS_ENABLED(OF_CONTROL)
112 * Only get the size in this first call. We'll get the addr in the
113 * next call to the exisiting dev_get_xxx function which handles
114 * all config options.
116 fdtdec_get_addr_size_auto_noparent(gd
->fdt_blob
, dev_of_offset(dev
),
117 "reg", index
, size
, false);
120 * Get the base address via the existing function which handles
123 return devfdt_get_addr_index(dev
, index
);
125 return FDT_ADDR_T_NONE
;
129 void *devfdt_get_addr_size_index_ptr(const struct udevice
*dev
, int index
,
132 fdt_addr_t addr
= devfdt_get_addr_size_index(dev
, index
, size
);
134 if (addr
== FDT_ADDR_T_NONE
)
137 return map_sysmem(addr
, 0);
140 fdt_addr_t
devfdt_get_addr_name(const struct udevice
*dev
, const char *name
)
142 #if CONFIG_IS_ENABLED(OF_CONTROL)
145 index
= fdt_stringlist_search(gd
->fdt_blob
, dev_of_offset(dev
),
148 return FDT_ADDR_T_NONE
;
150 return devfdt_get_addr_index(dev
, index
);
152 return FDT_ADDR_T_NONE
;
156 void *devfdt_get_addr_name_ptr(const struct udevice
*dev
, const char *name
)
158 fdt_addr_t addr
= devfdt_get_addr_name(dev
, name
);
160 if (addr
== FDT_ADDR_T_NONE
)
163 return map_sysmem(addr
, 0);
166 fdt_addr_t
devfdt_get_addr_size_name(const struct udevice
*dev
,
167 const char *name
, fdt_size_t
*size
)
169 #if CONFIG_IS_ENABLED(OF_CONTROL)
172 index
= fdt_stringlist_search(gd
->fdt_blob
, dev_of_offset(dev
),
175 return FDT_ADDR_T_NONE
;
177 return devfdt_get_addr_size_index(dev
, index
, size
);
179 return FDT_ADDR_T_NONE
;
183 void *devfdt_get_addr_size_name_ptr(const struct udevice
*dev
,
184 const char *name
, fdt_size_t
*size
)
186 fdt_addr_t addr
= devfdt_get_addr_size_name(dev
, name
, size
);
188 if (addr
== FDT_ADDR_T_NONE
)
191 return map_sysmem(addr
, 0);
194 fdt_addr_t
devfdt_get_addr(const struct udevice
*dev
)
196 return devfdt_get_addr_index(dev
, 0);
199 void *devfdt_get_addr_ptr(const struct udevice
*dev
)
201 return devfdt_get_addr_index_ptr(dev
, 0);
204 void *devfdt_remap_addr_index(const struct udevice
*dev
, int index
)
206 fdt_addr_t addr
= devfdt_get_addr_index(dev
, index
);
208 if (addr
== FDT_ADDR_T_NONE
)
211 return map_physmem(addr
, 0, MAP_NOCACHE
);
214 void *devfdt_remap_addr_name(const struct udevice
*dev
, const char *name
)
216 fdt_addr_t addr
= devfdt_get_addr_name(dev
, name
);
218 if (addr
== FDT_ADDR_T_NONE
)
221 return map_physmem(addr
, 0, MAP_NOCACHE
);
224 void *devfdt_remap_addr(const struct udevice
*dev
)
226 return devfdt_remap_addr_index(dev
, 0);
229 void *devfdt_map_physmem(const struct udevice
*dev
, unsigned long size
)
231 fdt_addr_t addr
= devfdt_get_addr(dev
);
233 if (addr
== FDT_ADDR_T_NONE
)
236 return map_physmem(addr
, size
, MAP_NOCACHE
);
239 fdt_addr_t
devfdt_get_addr_pci(const struct udevice
*dev
, fdt_size_t
*sizep
)
243 addr
= devfdt_get_addr(dev
);
244 if (CONFIG_IS_ENABLED(PCI
) && addr
== FDT_ADDR_T_NONE
) {
245 struct fdt_pci_addr pci_addr
;
249 ret
= ofnode_read_pci_addr(dev_ofnode(dev
), FDT_PCI_SPACE_MEM32
,
250 "reg", &pci_addr
, sizep
);
252 /* try if there is any i/o-mapped register */
253 ret
= ofnode_read_pci_addr(dev_ofnode(dev
),
254 FDT_PCI_SPACE_IO
, "reg",
257 return FDT_ADDR_T_NONE
;
259 ret
= fdtdec_get_pci_bar32(dev
, &pci_addr
, &bar
);
261 return FDT_ADDR_T_NONE
;