Deleted Added
sdiff udiff text old ( 202786 ) new ( 202831 )
full compact
1/*-
2 * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202831 2010-01-22 20:40:07Z imp $
27 */
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202831 2010-01-22 20:40:07Z imp $");
30
31#include <sys/param.h>
32#include <sys/conf.h>
33#include <sys/kernel.h>
34#include <sys/systm.h>
35#include <sys/imgact.h>
36#include <sys/bio.h>
37#include <sys/buf.h>
38#include <sys/bus.h>
39#include <sys/cpu.h>
40#include <sys/cons.h>
41#include <sys/exec.h>
42#include <sys/ucontext.h>
43#include <sys/proc.h>
44#include <sys/kdb.h>
45#include <sys/ptrace.h>
46#include <sys/reboot.h>
47#include <sys/signalvar.h>
48#include <sys/sysent.h>
49#include <sys/sysproto.h>
50#include <sys/user.h>
51
52#include <vm/vm.h>
53#include <vm/vm_object.h>
54#include <vm/vm_page.h>
55#include <vm/vm_pager.h>
56
57#include <machine/atomic.h>
58#include <machine/cache.h>
59#include <machine/clock.h>
60#include <machine/cpu.h>
61#include <machine/cpuregs.h>
62#include <machine/cpufunc.h>
63#include <mips/cavium/octeon_pcmap_regs.h>
64#include <mips/cavium/octeonreg.h>
65#include <machine/hwfunc.h>
66#include <machine/intr_machdep.h>
67#include <machine/locore.h>
68#include <machine/md_var.h>
69#include <machine/pcpu.h>
70#include <machine/pte.h>
71#include <machine/trap.h>
72#include <machine/vmparam.h>
73
74#if defined(__mips_n64)
75#define MAX_APP_DESC_ADDR 0xffffffffafffffff
76#else
77#define MAX_APP_DESC_ADDR 0xafffffff
78#endif
79
80static struct pcpu pcpu0;
81extern int *edata;
82extern int *end;
83
84uint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip);
85void ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip);
86
87static void octeon_boot_params_init(register_t ptr);
88static uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx);
89static uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx);
90
91static __inline void
92mips_wr_ebase(u_int32_t a0)
93{
94 __asm __volatile("mtc0 %[a0], $15, 1 ;"
95 :
96 : [a0] "r"(a0));
97
98 mips_barrier();
99}
100
101void
102platform_cpu_init()
103{
104 /* Nothing special yet */
105}
106
107/*
108 * Perform a board-level soft-reset.
109 */
110void
111platform_reset(void)
112{
113 ((void(*)(void))(long)0x9fc00000)(); /* Jump to MIPS reset vector */
114}
115
116
117static inline uint32_t
118octeon_disable_interrupts(void)
119{
120 uint32_t status_bits;
121
122 status_bits = mips_rd_status();
123 mips_wr_status(status_bits & ~MIPS_SR_INT_IE);
124 return (status_bits);
125}
126
127
128static inline void
129octeon_set_interrupts(uint32_t status_bits)
130{
131 mips_wr_status(status_bits);
132}
133
134
135void
136octeon_led_write_char(int char_position, char val)
137{
138 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
139
140 if (!octeon_board_real())
141 return;
142
143 char_position &= 0x7; /* only 8 chars */
144 ptr += char_position;
145 oct_write8_x8(ptr, val);
146}
147
148void
149octeon_led_write_char0(char val)
150{
151 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
152
153 if (!octeon_board_real())
154 return;
155 oct_write8_x8(ptr, val);
156}
157
158void
159octeon_led_write_hexchar(int char_position, char hexval)
160{
161 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
162 char char1, char2;
163
164 if (!octeon_board_real())
165 return;
166
167 char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7';
168 char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7';
169 char_position &= 0x7; /* only 8 chars */
170 if (char_position > 6)
171 char_position = 6;
172 ptr += char_position;
173 oct_write8_x8(ptr, char1);
174 ptr++;
175 oct_write8_x8(ptr, char2);
176}
177
178void
179octeon_led_write_string(const char *str)
180{
181 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
182 int i;
183
184 if (!octeon_board_real())
185 return;
186
187 for (i=0; i<8; i++, ptr++) {
188 if (str && *str)
189 oct_write8_x8(ptr, *str++);
190 else
191 oct_write8_x8(ptr, ' ');
192 oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
193 }
194}
195
196static char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'};
197
198void
199octeon_led_run_wheel(int *prog_count, int led_position)
200{
201 if (!octeon_board_real())
202 return;
203 octeon_led_write_char(led_position, progress[*prog_count]);
204 *prog_count += 1;
205 *prog_count &= 0x7;
206}
207
208#define LSR_DATAREADY 0x01 /* Data ready */
209#define LSR_THRE 0x20 /* Transmit holding register empty */
210#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */
211#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */
212
213/*
214 * octeon_uart_write_byte
215 *
216 * Put out a single byte off of uart port.
217 */
218
219void
220octeon_uart_write_byte(int uart_index, uint8_t ch)
221{
222 uint64_t val, val2;
223 if (uart_index < 0 || uart_index > 1)
224 return;
225
226 while (1) {
227 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
228 val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400));
229 if ((((uint8_t) val) & LSR_THRE) ||
230 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
231 break;
232 }
233 }
234
235 /* Write the byte */
236 oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch);
237
238 /* Force Flush the IOBus */
239 oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
240}
241
242
243void
244octeon_uart_write_byte0(uint8_t ch)
245{
246 uint64_t val, val2;
247
248 while (1) {
249 val = oct_read64(OCTEON_MIO_UART0_LSR);
250 val2 = oct_read64(OCTEON_MIO_UART0_USR);
251 if ((((uint8_t) val) & LSR_THRE) ||
252 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
253 break;
254 }
255 }
256
257 /* Write the byte */
258 oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch);
259
260 /* Force Flush the IOBus */
261 oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
262}
263
264/*
265 * octeon_uart_write_string
266 *
267 */
268void
269octeon_uart_write_string(int uart_index, const char *str)
270{
271 /* Just loop writing one byte at a time */
272
273 while (*str) {
274 octeon_uart_write_byte(uart_index, *str);
275 if (*str == '\n') {
276 octeon_uart_write_byte(uart_index, '\r');
277 }
278 str++;
279 }
280}
281
282static char wstr[30];
283
284void
285octeon_led_write_hex(uint32_t wl)
286{
287 char nbuf[80];
288
289 sprintf(nbuf, "%X", wl);
290 octeon_led_write_string(nbuf);
291}
292
293
294void octeon_uart_write_hex2(uint32_t wl, uint32_t wh)
295{
296 sprintf(wstr, "0x%X-0x%X ", wh, wl);
297 octeon_uart_write_string(0, wstr);
298}
299
300void
301octeon_uart_write_hex(uint32_t wl)
302{
303 sprintf(wstr, " 0x%X ", wl);
304 octeon_uart_write_string(0, wstr);
305}
306
307/*
308 * octeon_wait_uart_flush
309 */
310void
311octeon_wait_uart_flush(int uart_index, uint8_t ch)
312{
313 uint64_t val;
314 int64_t val3;
315 uint32_t cpu_status_bits;
316
317 if (uart_index < 0 || uart_index > 1)
318 return;
319
320 cpu_status_bits = octeon_disable_interrupts();
321 /* Force Flush the IOBus */
322 oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
323 for (val3 = 0xfffffffff; val3 > 0; val3--) {
324 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
325 if (((uint8_t) val) & LSR_TEMT)
326 break;
327 }
328 octeon_set_interrupts(cpu_status_bits);
329}
330
331
332/*
333 * octeon_debug_symbol
334 *
335 * Does nothing.
336 * Used to mark the point for simulator to begin tracing
337 */
338void
339octeon_debug_symbol(void)
340{
341}
342
343void
344octeon_ciu_stop_gtimer(int timer)
345{
346 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll);
347}
348
349void
350octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles)
351{
352 octeon_ciu_gentimer gentimer;
353
354 gentimer.word64 = 0;
355 gentimer.bits.one_shot = one_shot;
356 gentimer.bits.len = time_cycles - 1;
357 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64);
358}
359
360/*
361 * octeon_ciu_reset
362 *
363 * Shutdown all CIU to IP2, IP3 mappings
364 */
365void
366octeon_ciu_reset(void)
367{
368
369 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0);
370 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1);
371 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2);
372 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3);
373
374 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0);
375 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1);
376 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0);
377 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1);
378
379 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll);
380 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll);
381 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll);
382}
383
384/*
385 * mips_disable_interrupt_controllers
386 *
387 * Disable interrupts in the CPU controller
388 */
389void
390mips_disable_interrupt_controls(void)
391{
392 /*
393 * Disable interrupts in CIU.
394 */
395 octeon_ciu_reset();
396}
397
398/*
399 * ciu_get_intr_sum_reg_addr
400 */
401static uint64_t
402ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx)
403{
404 uint64_t ciu_intr_sum_reg_addr;
405
406 if (enx == CIU_EN_0)
407 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR +
408 (core_num * 0x10) + (intx * 0x8);
409 else
410 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR;
411
412 return (ciu_intr_sum_reg_addr);
413}
414
415
416/*
417 * ciu_get_intr_en_reg_addr
418 */
419static uint64_t
420ciu_get_intr_en_reg_addr(int core_num, int intx, int enx)
421{
422 uint64_t ciu_intr_reg_addr;
423
424 ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR +
425 ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20);
426 return (ciu_intr_reg_addr);
427}
428
429
430
431
432/*
433 * ciu_get_intr_reg_addr
434 *
435 * 200 ---int0,en0 ip2
436 * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog
437 *
438 * 210 ---int0,en0 ip3 --
439 * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right?
440 *
441 * 220 ---int1,en0 ip2
442 * 228 ---int1,en1 ip2
443 * 230 ---int1,en0 ip3 --
444 * 238 ---int1,en1 ip3
445 *
446 */
447uint64_t
448ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip)
449{
450 uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR;
451
452 /* XXX kasserts? */
453 if (enx < CIU_EN_0 || enx > CIU_EN_1) {
454 printf("%s: invalid enx value %d, should be %d or %d\n",
455 __FUNCTION__, enx, CIU_EN_0, CIU_EN_1);
456 return 0;
457 }
458 if (intx < CIU_INT_0 || intx > CIU_INT_1) {
459 printf("%s: invalid intx value %d, should be %d or %d\n",
460 __FUNCTION__, enx, CIU_INT_0, CIU_INT_1);
461 return 0;
462 }
463 if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) {
464 printf("%s: invalid ciu_ip value %d, should be %d or %d\n",
465 __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3);
466 return 0;
467 }
468
469 ciu_intr_reg_addr += (enx * 0x8);
470 ciu_intr_reg_addr += (ciu_ip * 0x10);
471 ciu_intr_reg_addr += (intx * 0x20);
472 return (ciu_intr_reg_addr);
473}
474
475/*
476 * ciu_get_int_summary
477 */
478uint64_t
479ciu_get_int_summary(int core_num, int intx, int enx)
480{
481 uint64_t ciu_intr_sum_reg_addr;
482
483 if (core_num == CIU_THIS_CORE)
484 core_num = octeon_get_core_num();
485 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
486 return (oct_read64(ciu_intr_sum_reg_addr));
487}
488
489//#define DEBUG_CIU 1
490
491#ifdef DEBUG_CIU
492#define DEBUG_CIU_SUM 1
493#define DEBUG_CIU_EN 1
494#endif
495
496
497/*
498 * ciu_clear_int_summary
499 */
500void
501ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits)
502{
503 uint32_t cpu_status_bits;
504 uint64_t ciu_intr_sum_reg_addr;
505
506//#define DEBUG_CIU_SUM 1
507
508#ifdef DEBUG_CIU_SUM
509 uint64_t ciu_intr_sum_bits;
510#endif
511
512
513 if (core_num == CIU_THIS_CORE) {
514 core_num = octeon_get_core_num();
515 }
516
517#ifdef DEBUG_CIU_SUM
518 printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n",
519 core_num, intx, enx, write_bits);
520#endif
521
522 cpu_status_bits = octeon_disable_interrupts();
523
524 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
525
526#ifdef DEBUG_CIU_SUM
527 ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */
528 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX",
529 cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits,
530 ciu_intr_sum_bits | write_bits);
531#endif
532
533 oct_write64(ciu_intr_sum_reg_addr, write_bits);
534 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
535
536#ifdef DEBUG_CIU_SUM
537 printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr));
538#endif
539
540 octeon_set_interrupts(cpu_status_bits);
541}
542
543/*
544 * ciu_disable_intr
545 */
546void
547ciu_disable_intr(int core_num, int intx, int enx)
548{
549 uint32_t cpu_status_bits;
550 uint64_t ciu_intr_reg_addr;
551
552 if (core_num == CIU_THIS_CORE)
553 core_num = octeon_get_core_num();
554
555 cpu_status_bits = octeon_disable_interrupts();
556
557 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
558
559 oct_read64(ciu_intr_reg_addr); /* Dummy read */
560
561 oct_write64(ciu_intr_reg_addr, 0LL);
562 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
563
564 octeon_set_interrupts(cpu_status_bits);
565}
566
567void
568ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip)
569{
570
571 uint64_t ciu_intr_reg_addr;
572 uint64_t ciu_intr_bits;
573
574 if (core_num == CIU_THIS_CORE) {
575 core_num = octeon_get_core_num();
576 }
577
578#ifndef OCTEON_SMP_1
579 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
580#else
581 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
582#endif
583
584 if (!ciu_intr_reg_addr) {
585 printf("Bad call to %s\n", __FUNCTION__);
586 while(1);
587 return;
588 }
589
590 ciu_intr_bits = oct_read64(ciu_intr_reg_addr);
591 printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n",
592 core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr,
593 (unsigned long long)ciu_intr_bits, mips_rd_status());
594}
595
596
597/*
598 * ciu_enable_interrupts
599 */
600void ciu_enable_interrupts(int core_num, int intx, int enx,
601 uint64_t set_these_interrupt_bits, int ciu_ip)
602{
603 uint32_t cpu_status_bits;
604 uint64_t ciu_intr_reg_addr;
605 uint64_t ciu_intr_bits;
606
607 if (core_num == CIU_THIS_CORE)
608 core_num = octeon_get_core_num();
609
610//#define DEBUG_CIU_EN 1
611
612#ifdef DEBUG_CIU_EN
613 printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n",
614 core_num, intx, enx, ciu_ip, set_these_interrupt_bits);
615#endif
616
617 cpu_status_bits = octeon_disable_interrupts();
618
619#ifndef OCTEON_SMP_1
620 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
621#else
622 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
623#endif
624
625 if (!ciu_intr_reg_addr) {
626 printf("Bad call to %s\n", __FUNCTION__);
627 while(1);
628 return; /* XXX */
629 }
630
631 ciu_intr_bits = oct_read64(ciu_intr_reg_addr);
632
633#ifdef DEBUG_CIU_EN
634 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX",
635 cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits);
636#endif
637 ciu_intr_bits |= set_these_interrupt_bits;
638 oct_write64(ciu_intr_reg_addr, ciu_intr_bits);
639#ifdef OCTEON_SMP
640 mips_wbflush();
641#endif
642 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
643
644#ifdef DEBUG_CIU_EN
645 printf(" Readback: 0x%llX\n\n ",
646 (uint64_t)oct_read64(ciu_intr_reg_addr));
647#endif
648
649 octeon_set_interrupts(cpu_status_bits);
650}
651
652unsigned long
653octeon_get_clock_rate(void)
654{
655 return octeon_cpu_clock;
656}
657
658static void
659octeon_memory_init(void)
660{
661 uint32_t realmem_bytes;
662
663 if (octeon_board_real()) {
664 printf("octeon_dram == %llx\n", octeon_dram);
665 printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20);
666
667 realmem_bytes = (octeon_dram - PAGE_SIZE);
668 realmem_bytes &= ~(PAGE_SIZE - 1);
669 printf("Real memory bytes is %x\n", realmem_bytes);
670 } else {
671 /* Simulator we limit to 96 meg */
672 realmem_bytes = (96 << 20);
673 }
674 /* phys_avail regions are in bytes */
675 phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1);
676 if (octeon_board_real()) {
677 if (realmem_bytes > OCTEON_DRAM_FIRST_256_END)
678 phys_avail[1] = OCTEON_DRAM_FIRST_256_END;
679 else
680 phys_avail[1] = realmem_bytes;
681 realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
682 realmem_bytes &= ~(PAGE_SIZE - 1);
683 printf("phys_avail[0] = %x phys_avail[1] = %x\n",
684 phys_avail[0], phys_avail[1]);
685 } else {
686 /* Simulator gets 96Meg period. */
687 phys_avail[1] = (96 << 20);
688 }
689 /*-
690 * Octeon Memory looks as follows:
691 * PA
692 * 0000 0000 to 0x0 0000 0000 0000
693 * 0FFF FFFF First 256 MB memory Maps to 0x0 0000 0FFF FFFF
694 *
695 * 1000 0000 to 0x1 0000 1000 0000
696 * 1FFF FFFF Uncached Bu I/O space.converted to 0x1 0000 1FFF FFFF
697 *
698 * 2FFF FFFF to Cached 0x0 0000 2000 0000
699 * FFFF FFFF all dram mem above the first 512M 0x3 FFFF FFFF FFFF
700 *
701 */
702 physmem = btoc(phys_avail[1] - phys_avail[0]);
703 if ((octeon_board_real()) &&
704 (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) {
705 /* take out the upper non-cached 1/2 */
706 realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
707 realmem_bytes &= ~(PAGE_SIZE - 1);
708 /* Now map the rest of the memory */
709 phys_avail[2] = 0x20000000;
710 printf("realmem_bytes is now at %x\n", realmem_bytes);
711 phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes);
712 printf("Next block of memory goes from %x to %x\n",
713 phys_avail[2], phys_avail[3]);
714 physmem += btoc(phys_avail[3] - phys_avail[2]);
715 } else {
716 printf("realmem_bytes is %d\n", realmem_bytes);
717 }
718 realmem = physmem;
719
720 printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram);
721 printf("\nBank 0 = 0x%8X -> 0x%8X", phys_avail[0], phys_avail[1]);
722 printf("\nBank 1 = 0x%8X -> 0x%8X\n", phys_avail[2], phys_avail[3]);
723 printf("\nphysmem: 0x%lx", physmem);
724
725 Maxmem = physmem;
726
727}
728
729void
730platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
731 __register_t a3)
732{
733 uint64_t platform_counter_freq;
734
735 /* Initialize pcpu stuff */
736 mips_pcpu0_init();
737 mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
738 cninit();
739
740 octeon_ciu_reset();
741 octeon_boot_params_init(a3);
742 bootverbose = 1;
743 cpuid_to_pcpu[0] = &pcpu0;
744
745 /*
746 * For some reason on the cn38xx simulator ebase register is set to
747 * 0x80001000 at bootup time. Move it back to the default, but
748 * when we move to having support for multiple executives, we need
749 * to rethink this.
750 */
751 mips_wr_ebase(0x80000000);
752
753 octeon_memory_init();
754 init_param1();
755 init_param2(physmem);
756 mips_cpu_init();
757 pmap_bootstrap();
758 mips_proc0_init();
759 mutex_init();
760#ifdef DDB
761 kdb_init();
762#endif
763 platform_counter_freq = octeon_get_clock_rate();
764 mips_timer_init_params(platform_counter_freq, 1);
765}
766
767/* impSTART: This stuff should move back into the Cavium SDK */
768/*
769 ****************************************************************************************
770 *
771 * APP/BOOT DESCRIPTOR STUFF
772 *
773 ****************************************************************************************
774 */
775
776/* Define the struct that is initialized by the bootloader used by the
777 * startup code.
778 *
779 * Copyright (c) 2004, 2005, 2006 Cavium Networks.
780 *
781 * The authors hereby grant permission to use, copy, modify, distribute,
782 * and license this software and its documentation for any purpose, provided
783 * that existing copyright notices are retained in all copies and that this
784 * notice is included verbatim in any distributions. No written agreement,
785 * license, or royalty fee is required for any of the authorized uses.
786 * Modifications to this software may be copyrighted by their authors
787 * and need not follow the licensing terms described here, provided that
788 * the new terms are clearly indicated on the first page of each file where
789 * they apply.
790 */
791
792#define OCTEON_CURRENT_DESC_VERSION 6
793#define OCTEON_ARGV_MAX_ARGS (64)
794#define OCTOEN_SERIAL_LEN 20
795
796
797typedef struct {
798 /* Start of block referenced by assembly code - do not change! */
799 uint32_t desc_version;
800 uint32_t desc_size;
801
802 uint64_t stack_top;
803 uint64_t heap_base;
804 uint64_t heap_end;
805 uint64_t entry_point; /* Only used by bootloader */
806 uint64_t desc_vaddr;
807 /* End of This block referenced by assembly code - do not change! */
808
809 uint32_t exception_base_addr;
810 uint32_t stack_size;
811 uint32_t heap_size;
812 uint32_t argc; /* Argc count for application */
813 uint32_t argv[OCTEON_ARGV_MAX_ARGS];
814 uint32_t flags;
815 uint32_t core_mask;
816 uint32_t dram_size; /**< DRAM size in megabyes */
817 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/
818 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */
819 uint32_t eclock_hz; /**< CPU clock speed, in hz */
820 uint32_t dclock_hz; /**< DRAM clock speed, in hz */
821 uint32_t spi_clock_hz; /**< SPI4 clock in hz */
822 uint16_t board_type;
823 uint8_t board_rev_major;
824 uint8_t board_rev_minor;
825 uint16_t chip_type;
826 uint8_t chip_rev_major;
827 uint8_t chip_rev_minor;
828 char board_serial_number[OCTOEN_SERIAL_LEN];
829 uint8_t mac_addr_base[6];
830 uint8_t mac_addr_count;
831 uint64_t cvmx_desc_vaddr;
832} octeon_boot_descriptor_t;
833
834
835typedef struct {
836 uint32_t major_version;
837 uint32_t minor_version;
838
839 uint64_t stack_top;
840 uint64_t heap_base;
841 uint64_t heap_end;
842 uint64_t desc_vaddr;
843
844 uint32_t exception_base_addr;
845 uint32_t stack_size;
846 uint32_t flags;
847 uint32_t core_mask;
848 uint32_t dram_size; /**< DRAM size in megabyes */
849 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/
850 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */
851 uint32_t eclock_hz; /**< CPU clock speed, in hz */
852 uint32_t dclock_hz; /**< DRAM clock speed, in hz */
853 uint32_t spi_clock_hz; /**< SPI4 clock in hz */
854 uint16_t board_type;
855 uint8_t board_rev_major;
856 uint8_t board_rev_minor;
857 uint16_t chip_type;
858 uint8_t chip_rev_major;
859 uint8_t chip_rev_minor;
860 char board_serial_number[OCTOEN_SERIAL_LEN];
861 uint8_t mac_addr_base[6];
862 uint8_t mac_addr_count;
863} cvmx_bootinfo_t;
864
865uint32_t octeon_cpu_clock;
866uint64_t octeon_dram;
867uint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type;
868uint8_t octeon_mac_addr[6] = { 0 };
869int octeon_core_mask, octeon_mac_addr_count;
870int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0;
871
872static octeon_boot_descriptor_t *app_desc_ptr;
873static cvmx_bootinfo_t *cvmx_desc_ptr;
874
875#define OCTEON_BOARD_TYPE_NONE 0
876#define OCTEON_BOARD_TYPE_SIM 1
877
878#define OCTEON_CLOCK_MIN (100 * 1000 * 1000)
879#define OCTEON_CLOCK_MAX (800 * 1000 * 1000)
880#define OCTEON_DRAM_DEFAULT (256 * 1024 * 1024)
881#define OCTEON_DRAM_MIN 30
882#define OCTEON_DRAM_MAX 3000
883
884
885int
886octeon_board_real(void)
887{
888 if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) ||
889 (octeon_board_type == OCTEON_BOARD_TYPE_SIM) ||
890 !octeon_board_rev_major)
891 return 0;
892 return 1;
893}
894
895static void
896octeon_process_app_desc_ver_unknown(void)
897{
898 printf(" Unknown Boot-Descriptor: Using Defaults\n");
899
900 octeon_cpu_clock = OCTEON_CLOCK_DEFAULT;
901 octeon_dram = OCTEON_DRAM_DEFAULT;
902 octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0;
903 octeon_core_mask = 1;
904 octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0;
905 octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f;
906 octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10;
907 octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06;
908 octeon_mac_addr_count = 1;
909}
910
911static int
912octeon_process_app_desc_ver_6(void)
913{
914 /* XXX Why is 0x00000000ffffffffULL a bad value? */
915 if (app_desc_ptr->cvmx_desc_vaddr == 0 ||
916 app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) {
917 printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr);
918 return 1;
919 }
920 cvmx_desc_ptr =
921 (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr;
922 cvmx_desc_ptr =
923 (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START);
924 octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) +
925 cvmx_desc_ptr->minor_version;
926 if (cvmx_desc_ptr->major_version != 1) {
927 panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n",
928 (int) cvmx_desc_ptr->major_version,
929 (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr);
930 }
931
932 octeon_core_mask = cvmx_desc_ptr->core_mask;
933 octeon_cpu_clock = cvmx_desc_ptr->eclock_hz;
934 octeon_board_type = cvmx_desc_ptr->board_type;
935 octeon_board_rev_major = cvmx_desc_ptr->board_rev_major;
936 octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor;
937 octeon_chip_type = cvmx_desc_ptr->chip_type;
938 octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major;
939 octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor;
940 octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0];
941 octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1];
942 octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2];
943 octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3];
944 octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4];
945 octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5];
946 octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count;
947
948 if (app_desc_ptr->dram_size > 16*1024*1024)
949 octeon_dram = (uint64_t)app_desc_ptr->dram_size;
950 else
951 octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20;
952 return 0;
953}
954
955static void
956octeon_boot_params_init(register_t ptr)
957{
958 int bad_desc = 1;
959
960 if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) {
961 app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
962 octeon_bd_ver = app_desc_ptr->desc_version;
963 if (app_desc_ptr->desc_version == 6)
964 bad_desc = octeon_process_app_desc_ver_6();
965 }
966 if (bad_desc)
967 octeon_process_app_desc_ver_unknown();
968
969 printf("Boot Descriptor Ver: %u -> %u/%u",
970 octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100);
971 printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000);
972 printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20));
973 printf(" Board Type: %u Revision: %u/%u\n",
974 octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor);
975 printf(" Octeon Chip: %u Rev %u/%u",
976 octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor);
977
978 printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n",
979 octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2],
980 octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5],
981 octeon_mac_addr_count);
982}
983/* impEND: This stuff should move back into the Cavium SDK */