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