mpc85xx: move newly created files from patch files to files directory
[openwrt.git] / target / linux / mpc85xx / files / arch / powerpc / boot / cuboot-tl-wdr4900-v1.c
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
28 BSS_STACK(4*1024);
29
30 static unsigned long bus_freq;
31 static unsigned long int_freq;
32 static u64 mem_size;
33 static unsigned char enetaddr[6];
34
35 static 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
120 static 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
153 void 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 }