Blame view
drivers/core/fdtaddr.c
5.1 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
d6ffb00a4
|
2 3 4 5 6 7 8 |
/* * Device addresses * * Copyright (c) 2017 Google, Inc * * (C) Copyright 2012 * Pavel Herrmann <morpheus.ibis@gmail.com> |
d6ffb00a4
|
9 10 11 12 13 14 15 16 17 |
*/ #include <common.h> #include <dm.h> #include <fdt_support.h> #include <asm/io.h> #include <dm/device-internal.h> DECLARE_GLOBAL_DATA_PTR; |
d975ce21c
|
18 |
fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) |
d6ffb00a4
|
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
{ #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) fdt_addr_t addr; if (CONFIG_IS_ENABLED(OF_TRANSLATE)) { const fdt32_t *reg; int len = 0; int na, ns; na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent)); if (na < 1) { debug("bad #address-cells "); return FDT_ADDR_T_NONE; } ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); if (ns < 0) { debug("bad #size-cells "); return FDT_ADDR_T_NONE; } reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg", &len); if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) { debug("Req index out of range "); return FDT_ADDR_T_NONE; } reg += index * (na + ns); |
e8d529182
|
52 53 54 55 56 57 58 59 60 61 62 |
if (ns) { /* * Use the full-fledged translate function for complex * bus setups. */ addr = fdt_translate_address((void *)gd->fdt_blob, dev_of_offset(dev), reg); } else { /* Non translatable if #size-cells == 0 */ addr = fdt_read_number(reg, na); } |
d6ffb00a4
|
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
} else { /* * Use the "simple" translate function for less complex * bus setups. */ addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, dev_of_offset(dev->parent), dev_of_offset(dev), "reg", index, NULL, false); if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) { if (device_get_uclass_id(dev->parent) == UCLASS_SIMPLE_BUS) addr = simple_bus_translate(dev->parent, addr); } } |
f2100f6f7
|
77 |
#if defined(CONFIG_TRANSLATION_OFFSET) |
d6ffb00a4
|
78 79 80 |
/* * Some platforms need a special address translation. Those * platforms (e.g. mvebu in SPL) can configure a translation |
f2100f6f7
|
81 82 83 |
* offset by setting this value in the GD and enaling this * feature via CONFIG_TRANSLATION_OFFSET. This value will * get added to all addresses returned by devfdt_get_addr(). |
d6ffb00a4
|
84 |
*/ |
f2100f6f7
|
85 86 |
addr += gd->translation_offset; #endif |
d6ffb00a4
|
87 88 89 90 91 92 |
return addr; #else return FDT_ADDR_T_NONE; #endif } |
d975ce21c
|
93 94 |
fdt_addr_t devfdt_get_addr_size_index(const struct udevice *dev, int index, fdt_size_t *size) |
d6ffb00a4
|
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
{ #if CONFIG_IS_ENABLED(OF_CONTROL) /* * Only get the size in this first call. We'll get the addr in the * next call to the exisiting dev_get_xxx function which handles * all config options. */ fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev), "reg", index, size, false); /* * Get the base address via the existing function which handles * all Kconfig cases */ |
a821c4af7
|
109 |
return devfdt_get_addr_index(dev, index); |
d6ffb00a4
|
110 111 112 113 |
#else return FDT_ADDR_T_NONE; #endif } |
d975ce21c
|
114 |
fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name) |
d6ffb00a4
|
115 116 117 118 119 120 121 122 |
{ #if CONFIG_IS_ENABLED(OF_CONTROL) int index; index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), "reg-names", name); if (index < 0) return index; |
a821c4af7
|
123 |
return devfdt_get_addr_index(dev, index); |
d6ffb00a4
|
124 125 126 127 |
#else return FDT_ADDR_T_NONE; #endif } |
d975ce21c
|
128 129 |
fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev, const char *name, fdt_size_t *size) |
f5b904796
|
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
{ #if CONFIG_IS_ENABLED(OF_CONTROL) int index; index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), "reg-names", name); if (index < 0) return index; return devfdt_get_addr_size_index(dev, index, size); #else return FDT_ADDR_T_NONE; #endif } |
d975ce21c
|
144 |
fdt_addr_t devfdt_get_addr(const struct udevice *dev) |
d6ffb00a4
|
145 |
{ |
a821c4af7
|
146 |
return devfdt_get_addr_index(dev, 0); |
d6ffb00a4
|
147 |
} |
d975ce21c
|
148 |
void *devfdt_get_addr_ptr(const struct udevice *dev) |
d6ffb00a4
|
149 |
{ |
a821c4af7
|
150 |
return (void *)(uintptr_t)devfdt_get_addr_index(dev, 0); |
d6ffb00a4
|
151 |
} |
d975ce21c
|
152 |
void *devfdt_remap_addr_index(const struct udevice *dev, int index) |
30a90f56c
|
153 |
{ |
427ddd842
|
154 |
fdt_addr_t addr = devfdt_get_addr_index(dev, index); |
30a90f56c
|
155 156 157 158 159 160 |
if (addr == FDT_ADDR_T_NONE) return NULL; return map_physmem(addr, 0, MAP_NOCACHE); } |
d975ce21c
|
161 |
void *devfdt_remap_addr_name(const struct udevice *dev, const char *name) |
795988204
|
162 163 164 165 166 167 168 169 |
{ fdt_addr_t addr = devfdt_get_addr_name(dev, name); if (addr == FDT_ADDR_T_NONE) return NULL; return map_physmem(addr, 0, MAP_NOCACHE); } |
d975ce21c
|
170 |
void *devfdt_remap_addr(const struct udevice *dev) |
30a90f56c
|
171 172 173 |
{ return devfdt_remap_addr_index(dev, 0); } |
d975ce21c
|
174 |
void *devfdt_map_physmem(const struct udevice *dev, unsigned long size) |
d6ffb00a4
|
175 |
{ |
a821c4af7
|
176 |
fdt_addr_t addr = devfdt_get_addr(dev); |
d6ffb00a4
|
177 178 179 180 181 182 |
if (addr == FDT_ADDR_T_NONE) return NULL; return map_physmem(addr, size, MAP_NOCACHE); } |
33c215af4
|
183 |
|
d975ce21c
|
184 |
fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev) |
33c215af4
|
185 186 187 188 189 190 191 192 193 |
{ ulong addr; addr = devfdt_get_addr(dev); if (CONFIG_IS_ENABLED(PCI) && IS_ENABLED(CONFIG_DM_PCI) && addr == FDT_ADDR_T_NONE) { struct fdt_pci_addr pci_addr; u32 bar; int ret; |
594d272cf
|
194 195 |
ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_MEM32, "reg", &pci_addr); |
33c215af4
|
196 197 |
if (ret) { /* try if there is any i/o-mapped register */ |
594d272cf
|
198 199 200 |
ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_IO, "reg", &pci_addr); |
33c215af4
|
201 202 203 204 205 206 207 208 209 210 211 |
if (ret) return FDT_ADDR_T_NONE; } ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); if (ret) return FDT_ADDR_T_NONE; addr = bar; } return addr; } |