| 248 | } |
| 249 | |
| 250 | static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_prop *prop) |
| 251 | { |
| 252 | int id; |
| 253 | const fdt32_t *cell; |
| 254 | struct bus_ranges *ranges = RT_NULL; |
| 255 | int child_address_cells, child_size_cells, parent_address_cells, groups; |
| 256 | rt_uint64_t *child_addr, *parent_addr, *child_size; |
| 257 | |
| 258 | /* |
| 259 | * Address Translation Example: |
| 260 | * |
| 261 | * / { |
| 262 | * #address-cells = <1>; |
| 263 | * #size-cells = <1>; |
| 264 | * |
| 265 | * soc { |
| 266 | * compatible = "simple-bus"; |
| 267 | * #address-cells = <1>; |
| 268 | * #size-cells = <1>; |
| 269 | * ranges = <0x0 0xe0000000 0x00100000>; |
| 270 | * |
| 271 | * serial@4600 { |
| 272 | * device_type = "serial"; |
| 273 | * reg = <0x4600 0x100>; |
| 274 | * clock-frequency = <0>; |
| 275 | * }; |
| 276 | * }; |
| 277 | * } |
| 278 | * |
| 279 | * The soc node specifies a ranges property of <0x0 0xe0000000 0x00100000>; |
| 280 | * This property value specifies that for a 1024 KB range of address space, a |
| 281 | * child node addressed at physical 0x0 maps to a parent address of physical |
| 282 | * 0xe0000000. With this mapping, the serial device node can be addressed by a |
| 283 | * load or store at address 0xe0004600, an offset of 0x4600 (specified in reg) |
| 284 | * plus the 0xe0000000 mapping specified in ranges: |
| 285 | * |
| 286 | * bus-address = parent-bus-address + (reg-address - child-bus-address) |
| 287 | */ |
| 288 | |
| 289 | do { |
| 290 | child_address_cells = rt_ofw_bus_addr_cells(np); |
| 291 | child_size_cells = rt_ofw_bus_size_cells(np); |
| 292 | parent_address_cells = rt_ofw_io_addr_cells(np); |
| 293 | |
| 294 | if (child_address_cells < 0 || child_size_cells < 0 || parent_address_cells < 0) |
| 295 | { |
| 296 | LOG_D("%s read address/size cells fail: child[%d, %d] parent[%d]", |
| 297 | np->full_name, child_address_cells, child_size_cells, parent_address_cells); |
| 298 | |
| 299 | break; |
| 300 | } |
| 301 | |
| 302 | groups = prop->length / sizeof(*cell); |
| 303 | groups /= child_address_cells + child_size_cells + parent_address_cells; |
| 304 | |
| 305 | ranges = rt_malloc(sizeof(*ranges) + sizeof(rt_uint64_t) * 3 * groups); |
| 306 | |
| 307 | if (!ranges) |
no test coverage detected