1/* 2 * U-Boot compatibility wrapper for the TP-Link TL-WDR4900 v1 board 3 * 4 * Copyright (c) 2013 Gabor Juhos <juhosg@openwrt.org> 5 * 6 * Based on: 7 * cuboot-85xx.c 8 * Author: Scott Wood <scottwood@freescale.com> 9 * Copyright (c) 2007 Freescale Semiconductor, Inc. 10 * 11 * simpleboot.c 12 * Authors: Scott Wood <scottwood@freescale.com> 13 * Grant Likely <grant.likely@secretlab.ca> 14 * Copyright (c) 2007 Freescale Semiconductor, Inc. 15 * Copyright (c) 2008 Secret Lab Technologies Ltd. 16 * 17 * This program is free software; you can redistribute it and/or modify it 18 * under the terms of the GNU General Public License version 2 as published 19 * by the Free Software Foundation. 20 */ 21 22#include "ops.h" 23#include "types.h" 24#include "io.h" 25#include "stdio.h" 26#include <libfdt.h> 27 28BSS_STACK(4*1024); 29 30static unsigned long bus_freq; 31static unsigned long int_freq; 32static u64 mem_size; 33static unsigned char enetaddr[6]; 34 35static void process_boot_dtb(void *boot_dtb) 36{ 37 const u32 *na, *ns, *reg, *val32; 38 const char *path; 39 u64 memsize64; 40 int node, size, i; 41 42 /* Make sure FDT blob is sane */ 43 if (fdt_check_header(boot_dtb) != 0) 44 fatal("Invalid device tree blob\n"); 45 46 /* Find the #address-cells and #size-cells properties */ 47 node = fdt_path_offset(boot_dtb, "/"); 48 if (node < 0) 49 fatal("Cannot find root node\n"); 50 na = fdt_getprop(boot_dtb, node, "#address-cells", &size); 51 if (!na || (size != 4)) 52 fatal("Cannot find #address-cells property"); 53 54 ns = fdt_getprop(boot_dtb, node, "#size-cells", &size); 55 if (!ns || (size != 4)) 56 fatal("Cannot find #size-cells property"); 57 58 /* Find the memory range */ 59 node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type", 60 "memory", sizeof("memory")); 61 if (node < 0) 62 fatal("Cannot find memory node\n"); 63 reg = fdt_getprop(boot_dtb, node, "reg", &size); 64 if (size < (*na+*ns) * sizeof(u32)) 65 fatal("cannot get memory range\n"); 66 67 /* Only interested in memory based at 0 */ 68 for (i = 0; i < *na; i++) 69 if (*reg++ != 0) 70 fatal("Memory range is not based at address 0\n"); 71 72 /* get the memsize and trucate it to under 4G on 32 bit machines */ 73 memsize64 = 0; 74 for (i = 0; i < *ns; i++) 75 memsize64 = (memsize64 << 32) | *reg++; 76 if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL) 77 memsize64 = 0xffffffff; 78 79 mem_size = memsize64; 80 81 /* get clock frequencies */ 82 node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type", 83 "cpu", sizeof("cpu")); 84 if (!node) 85 fatal("Cannot find cpu node\n"); 86 87 val32 = fdt_getprop(boot_dtb, node, "clock-frequency", &size); 88 if (!val32 || (size != 4)) 89 fatal("Cannot get clock frequency"); 90 91 int_freq = *val32; 92 93 val32 = fdt_getprop(boot_dtb, node, "bus-frequency", &size); 94 if (!val32 || (size != 4)) 95 fatal("Cannot get bus frequency"); 96 97 bus_freq = *val32; 98 99 path = fdt_get_alias(boot_dtb, "ethernet0"); 100 if (path) { 101 const void *p; 102 103 node = fdt_path_offset(boot_dtb, path); 104 if (node < 0) 105 fatal("Cannot find ethernet0 node"); 106 107 p = fdt_getprop(boot_dtb, node, "mac-address", &size); 108 if (!p || (size < 6)) { 109 printf("no mac-address property, finding local\n\r"); 110 p = fdt_getprop(boot_dtb, node, "local-mac-address", &size); 111 } 112 113 if (!p || (size < 6)) 114 fatal("cannot get MAC addres"); 115 116 memcpy(enetaddr, p, sizeof(enetaddr)); 117 } 118} 119 120static void platform_fixups(void) 121{ 122 void *soc, *mpic; 123 124 dt_fixup_memory(0, mem_size); 125 126 dt_fixup_mac_address_by_alias("ethernet0", enetaddr); 127 dt_fixup_cpu_clocks(int_freq, bus_freq / 8, bus_freq); 128 129 /* Unfortunately, the specific model number is encoded in the 130 * soc node name in existing dts files -- once that is fixed, 131 * this can do a simple path lookup. 132 */ 133 soc = find_node_by_devtype(NULL, "soc"); 134 if (soc) { 135 void *serial = NULL; 136 137 setprop(soc, "bus-frequency", &bus_freq, sizeof(bus_freq)); 138 139 while ((serial = find_node_by_devtype(serial, "serial"))) { 140 if (get_parent(serial) != soc) 141 continue; 142 143 setprop(serial, "clock-frequency", &bus_freq, 144 sizeof(bus_freq)); 145 } 146 } 147 148 mpic = find_node_by_compatible(NULL, "fsl,mpic"); 149 if (mpic) 150 setprop(mpic, "clock-frequency", &bus_freq, sizeof(bus_freq)); 151} 152 153void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 154 unsigned long r6, unsigned long r7) 155{ 156 mem_size = 64 * 1024 * 1024; 157 158 simple_alloc_init(_end, mem_size - (u32)_end - 1024*1024, 32, 64); 159 160 fdt_init(_dtb_start); 161 serial_console_init(); 162 163 printf("\n\r-- TL-WDR4900 v1 boot wrapper --\n\r"); 164 165 process_boot_dtb((void *) r3); 166 167 platform_ops.fixups = platform_fixups; 168} 169