Grant Likely | d2477b5 | 2008-03-19 04:07:43 +1100 | [diff] [blame^] | 1 | /* |
| 2 | * The simple platform -- for booting when firmware doesn't supply a device |
| 3 | * tree or any platform configuration information. |
| 4 | * All data is extracted from an embedded device tree |
| 5 | * blob. |
| 6 | * |
| 7 | * Authors: Scott Wood <scottwood@freescale.com> |
| 8 | * Grant Likely <grant.likely@secretlab.ca> |
| 9 | * |
| 10 | * Copyright (c) 2007 Freescale Semiconductor, Inc. |
| 11 | * Copyright (c) 2008 Secret Lab Technologies Ltd. |
| 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify it |
| 14 | * under the terms of the GNU General Public License version 2 as published |
| 15 | * by the Free Software Foundation. |
| 16 | */ |
| 17 | |
| 18 | #include "ops.h" |
| 19 | #include "types.h" |
| 20 | #include "io.h" |
| 21 | #include "stdio.h" |
| 22 | #include "libfdt/libfdt.h" |
| 23 | |
| 24 | BSS_STACK(4*1024); |
| 25 | |
| 26 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
| 27 | unsigned long r6, unsigned long r7) |
| 28 | { |
| 29 | const u32 *na, *ns, *reg, *timebase; |
| 30 | u64 memsize64; |
| 31 | int node, size, i; |
| 32 | |
| 33 | /* Make sure FDT blob is sane */ |
| 34 | if (fdt_check_header(_dtb_start) != 0) |
| 35 | fatal("Invalid device tree blob\n"); |
| 36 | |
| 37 | /* Find the #address-cells and #size-cells properties */ |
| 38 | node = fdt_path_offset(_dtb_start, "/"); |
| 39 | if (node < 0) |
| 40 | fatal("Cannot find root node\n"); |
| 41 | na = fdt_getprop(_dtb_start, node, "#address-cells", &size); |
| 42 | if (!na || (size != 4)) |
| 43 | fatal("Cannot find #address-cells property"); |
| 44 | ns = fdt_getprop(_dtb_start, node, "#size-cells", &size); |
| 45 | if (!ns || (size != 4)) |
| 46 | fatal("Cannot find #size-cells property"); |
| 47 | |
| 48 | /* Find the memory range */ |
| 49 | node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type", |
| 50 | "memory", sizeof("memory")); |
| 51 | if (node < 0) |
| 52 | fatal("Cannot find memory node\n"); |
| 53 | reg = fdt_getprop(_dtb_start, node, "reg", &size); |
| 54 | if (size < (*na+*ns) * sizeof(u32)) |
| 55 | fatal("cannot get memory range\n"); |
| 56 | |
| 57 | /* Only interested in memory based at 0 */ |
| 58 | for (i = 0; i < *na; i++) |
| 59 | if (*reg++ != 0) |
| 60 | fatal("Memory range is not based at address 0\n"); |
| 61 | |
| 62 | /* get the memsize and trucate it to under 4G on 32 bit machines */ |
| 63 | memsize64 = 0; |
| 64 | for (i = 0; i < *ns; i++) |
| 65 | memsize64 = (memsize64 << 32) | *reg++; |
| 66 | if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL) |
| 67 | memsize64 = 0xffffffff; |
| 68 | |
| 69 | /* finally, setup the timebase */ |
| 70 | node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type", |
| 71 | "cpu", sizeof("cpu")); |
| 72 | if (!node) |
| 73 | fatal("Cannot find cpu node\n"); |
| 74 | timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size); |
| 75 | if (timebase && (size == 4)) |
| 76 | timebase_period_ns = 1000000000 / *timebase; |
| 77 | |
| 78 | /* Now we have the memory size; initialize the heap */ |
| 79 | simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64); |
| 80 | |
| 81 | /* prepare the device tree and find the console */ |
| 82 | fdt_init(_dtb_start); |
| 83 | serial_console_init(); |
| 84 | } |