1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/init.h>
20#include <linux/sched.h>
21#include <linux/ioport.h>
22#include <linux/pci.h>
23#include <linux/screen_info.h>
24#include <linux/notifier.h>
25#include <linux/etherdevice.h>
26#include <linux/if_ether.h>
27#include <linux/ctype.h>
28#include <linux/cpu.h>
29#include <linux/time.h>
30
31#include <asm/bootinfo.h>
32#include <asm/irq.h>
33#include <asm/mips-boards/generic.h>
34#include <asm/dma.h>
35#include <asm/asm.h>
36#include <asm/traps.h>
37#include <asm/asm-offsets.h>
38#include "reset.h"
39
40#define VAL(n) STR(n)
41
42
43
44
45
46
47
48
49#define LONG_L_ VAL(LONG_L) " "
50#define LONG_S_ VAL(LONG_S) " "
51#define PTR_LA_ VAL(PTR_LA) " "
52
53#ifdef CONFIG_64BIT
54#warning TODO: 64-bit code needs to be verified
55#define REG_SIZE "8"
56#endif
57
58#ifdef CONFIG_32BIT
59#define REG_SIZE "4"
60#endif
61
62static void register_panic_notifier(void);
63static int panic_handler(struct notifier_block *notifier_block,
64 unsigned long event, void *cause_string);
65
66const char *get_system_type(void)
67{
68 return "PowerTV";
69}
70
71void __init plat_mem_setup(void)
72{
73 panic_on_oops = 1;
74 register_panic_notifier();
75
76#if 0
77 mips_pcibios_init();
78#endif
79 mips_reboot_setup();
80}
81
82
83
84
85static void register_panic_notifier()
86{
87 static struct notifier_block panic_notifier = {
88 .notifier_call = panic_handler,
89 .next = NULL,
90 .priority = INT_MAX
91 };
92 atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
93}
94
95static int panic_handler(struct notifier_block *notifier_block,
96 unsigned long event, void *cause_string)
97{
98 struct pt_regs my_regs;
99
100
101 {
102 unsigned long at, v0, v1;
103
104
105
106
107
108
109 __asm__ __volatile__ (
110 ".set noat\n"
111 LONG_S_ "$at, %[at]\n"
112 LONG_S_ "$2, %[v0]\n"
113 LONG_S_ "$3, %[v1]\n"
114 :
115 [at] "=m" (at),
116 [v0] "=m" (v0),
117 [v1] "=m" (v1)
118 :
119 : "at"
120 );
121
122 __asm__ __volatile__ (
123 ".set noat\n"
124 "move $at, %[pt_regs]\n"
125
126
127 LONG_S_ "$4, " VAL(PT_R4) "($at)\n"
128 LONG_S_ "$5, " VAL(PT_R5) "($at)\n"
129 LONG_S_ "$6, " VAL(PT_R6) "($at)\n"
130 LONG_S_ "$7, " VAL(PT_R7) "($at)\n"
131
132
133 LONG_S_ "$8, " VAL(PT_R8) "($at)\n"
134 LONG_S_ "$9, " VAL(PT_R9) "($at)\n"
135 LONG_S_ "$10, " VAL(PT_R10) "($at)\n"
136 LONG_S_ "$11, " VAL(PT_R11) "($at)\n"
137 LONG_S_ "$12, " VAL(PT_R12) "($at)\n"
138 LONG_S_ "$13, " VAL(PT_R13) "($at)\n"
139 LONG_S_ "$14, " VAL(PT_R14) "($at)\n"
140 LONG_S_ "$15, " VAL(PT_R15) "($at)\n"
141
142
143 LONG_S_ "$16, " VAL(PT_R16) "($at)\n"
144 LONG_S_ "$17, " VAL(PT_R17) "($at)\n"
145 LONG_S_ "$18, " VAL(PT_R18) "($at)\n"
146 LONG_S_ "$19, " VAL(PT_R19) "($at)\n"
147 LONG_S_ "$20, " VAL(PT_R20) "($at)\n"
148 LONG_S_ "$21, " VAL(PT_R21) "($at)\n"
149 LONG_S_ "$22, " VAL(PT_R22) "($at)\n"
150 LONG_S_ "$23, " VAL(PT_R23) "($at)\n"
151
152
153 LONG_S_ "$24, " VAL(PT_R24) "($at)\n"
154 LONG_S_ "$25, " VAL(PT_R25) "($at)\n"
155
156
157 LONG_S_ "$26, " VAL(PT_R26) "($at)\n"
158 LONG_S_ "$27, " VAL(PT_R27) "($at)\n"
159
160
161
162 LONG_S_ "$gp, " VAL(PT_R28) "($at)\n"
163 LONG_S_ "$sp, " VAL(PT_R29) "($at)\n"
164 LONG_S_ "$fp, " VAL(PT_R30) "($at)\n"
165 LONG_S_ "$ra, " VAL(PT_R31) "($at)\n"
166
167
168
169 LONG_L_ "$8, %[at]\n"
170 LONG_S_ "$8, " VAL(PT_R1) "($at)\n"
171 LONG_L_ "$8, %[v0]\n"
172 LONG_S_ "$8, " VAL(PT_R2) "($at)\n"
173 LONG_L_ "$8, %[v1]\n"
174 LONG_S_ "$8, " VAL(PT_R3) "($at)\n"
175 :
176 :
177 [at] "m" (at),
178 [v0] "m" (v0),
179 [v1] "m" (v1),
180 [pt_regs] "r" (&my_regs)
181 : "at", "t0"
182 );
183
184
185
186 __asm__ __volatile__ (
187 ".set noat\n"
188 "1:\n"
189 PTR_LA_ "$at, 1b\n"
190 LONG_S_ "$at, %[cp0_epc]\n"
191 :
192 [cp0_epc] "=m" (my_regs.cp0_epc)
193 :
194 : "at"
195 );
196
197 my_regs.cp0_cause = read_c0_cause();
198 my_regs.cp0_status = read_c0_status();
199 }
200
201 pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
202 "zzzz... \n");
203
204 return NOTIFY_DONE;
205}
206
207
208
209static bool have_rfmac;
210static u8 rfmac[ETH_ALEN];
211
212static int rfmac_param(char *p)
213{
214 u8 *q;
215 bool is_high_nibble;
216 int c;
217
218
219 if (*p == '0' && *(p+1) == 'x')
220 p += 2;
221
222 q = rfmac;
223 is_high_nibble = true;
224
225 for (c = (unsigned char) *p++;
226 isxdigit(c) && q - rfmac < ETH_ALEN;
227 c = (unsigned char) *p++) {
228 int nibble;
229
230 nibble = (isdigit(c) ? (c - '0') :
231 (isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
232
233 if (is_high_nibble)
234 *q = nibble << 4;
235 else
236 *q++ |= nibble;
237
238 is_high_nibble = !is_high_nibble;
239 }
240
241
242
243 have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
244
245 return 0;
246}
247
248early_param("rfmac", rfmac_param);
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292void platform_random_ether_addr(u8 addr[ETH_ALEN])
293{
294 const int num_random_bytes = 2;
295 const unsigned char non_sciatl_oui_bits = 0xc0u;
296 const unsigned char mac_addr_locally_managed = (1 << 1);
297
298 if (!have_rfmac) {
299 pr_warning("rfmac not available on command line; "
300 "generating random MAC address\n");
301 eth_random_addr(addr);
302 }
303
304 else {
305 int i;
306
307
308
309
310 addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
311
312
313 get_random_bytes(&addr[1], num_random_bytes);
314
315
316 for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
317 addr[i] = rfmac[i];
318 }
319}
320