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