1
2
3
4
5
6
7
8
9
10
11#include <common.h>
12#include <dm.h>
13#include <fdt_support.h>
14#include <asm/io.h>
15#include <dm/device-internal.h>
16
17DECLARE_GLOBAL_DATA_PTR;
18
19fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index)
20{
21#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
22 fdt_addr_t addr;
23
24 if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
25 const fdt32_t *reg;
26 int len = 0;
27 int na, ns;
28
29 na = fdt_address_cells(gd->fdt_blob,
30 dev_of_offset(dev->parent));
31 if (na < 1) {
32 debug("bad #address-cells\n");
33 return FDT_ADDR_T_NONE;
34 }
35
36 ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
37 if (ns < 0) {
38 debug("bad #size-cells\n");
39 return FDT_ADDR_T_NONE;
40 }
41
42 reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",
43 &len);
44 if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
45 debug("Req index out of range\n");
46 return FDT_ADDR_T_NONE;
47 }
48
49 reg += index * (na + ns);
50
51 if (ns) {
52
53
54
55
56 addr = fdt_translate_address((void *)gd->fdt_blob,
57 dev_of_offset(dev), reg);
58 } else {
59
60 addr = fdt_read_number(reg, na);
61 }
62 } else {
63
64
65
66
67 addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
68 dev_of_offset(dev->parent), dev_of_offset(dev),
69 "reg", index, NULL, false);
70 if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
71 if (device_get_uclass_id(dev->parent) ==
72 UCLASS_SIMPLE_BUS)
73 addr = simple_bus_translate(dev->parent, addr);
74 }
75 }
76
77
78
79
80
81
82
83 addr += dm_get_translation_offset();
84
85 return addr;
86#else
87 return FDT_ADDR_T_NONE;
88#endif
89}
90
91fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index,
92 fdt_size_t *size)
93{
94#if CONFIG_IS_ENABLED(OF_CONTROL)
95
96
97
98
99
100 fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev),
101 "reg", index, size, false);
102
103
104
105
106
107 return devfdt_get_addr_index(dev, index);
108#else
109 return FDT_ADDR_T_NONE;
110#endif
111}
112
113fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name)
114{
115#if CONFIG_IS_ENABLED(OF_CONTROL)
116 int index;
117
118 index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
119 "reg-names", name);
120 if (index < 0)
121 return index;
122
123 return devfdt_get_addr_index(dev, index);
124#else
125 return FDT_ADDR_T_NONE;
126#endif
127}
128
129fdt_addr_t devfdt_get_addr(struct udevice *dev)
130{
131 return devfdt_get_addr_index(dev, 0);
132}
133
134void *devfdt_get_addr_ptr(struct udevice *dev)
135{
136 return (void *)(uintptr_t)devfdt_get_addr_index(dev, 0);
137}
138
139void *devfdt_remap_addr_index(struct udevice *dev, int index)
140{
141 fdt_addr_t addr = devfdt_get_addr(dev);
142
143 if (addr == FDT_ADDR_T_NONE)
144 return NULL;
145
146 return map_physmem(addr, 0, MAP_NOCACHE);
147}
148
149void *devfdt_remap_addr(struct udevice *dev)
150{
151 return devfdt_remap_addr_index(dev, 0);
152}
153
154void *devfdt_map_physmem(struct udevice *dev, unsigned long size)
155{
156 fdt_addr_t addr = devfdt_get_addr(dev);
157
158 if (addr == FDT_ADDR_T_NONE)
159 return NULL;
160
161 return map_physmem(addr, size, MAP_NOCACHE);
162}
163