octeon_machdep.c revision 202997
138494Sobrien/*-
2174294Sobrien * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
338494Sobrien * All rights reserved.
438494Sobrien *
538494Sobrien * Redistribution and use in source and binary forms, with or without
638494Sobrien * modification, are permitted provided that the following conditions
738494Sobrien * are met:
838494Sobrien * 1. Redistributions of source code must retain the above copyright
938494Sobrien *    notice, this list of conditions and the following disclaimer.
1038494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1138494Sobrien *    notice, this list of conditions and the following disclaimer in the
1238494Sobrien *    documentation and/or other materials provided with the distribution.
1338494Sobrien *
1438494Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2042629Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438494Sobrien * SUCH DAMAGE.
2538494Sobrien *
2638494Sobrien * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202997 2010-01-26 02:39:14Z imp $
2738494Sobrien */
2838494Sobrien#include <sys/cdefs.h>
2938494Sobrien__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202997 2010-01-26 02:39:14Z imp $");
3038494Sobrien
3138494Sobrien#include <sys/param.h>
3238494Sobrien#include <sys/conf.h>
3338494Sobrien#include <sys/kernel.h>
3438494Sobrien#include <sys/systm.h>
3538494Sobrien#include <sys/imgact.h>
3638494Sobrien#include <sys/bio.h>
3738494Sobrien#include <sys/buf.h>
3838494Sobrien#include <sys/bus.h>
3938494Sobrien#include <sys/cpu.h>
40174294Sobrien#include <sys/cons.h>
4138494Sobrien#include <sys/exec.h>
4238494Sobrien#include <sys/ucontext.h>
4338494Sobrien#include <sys/proc.h>
4438494Sobrien#include <sys/kdb.h>
4538494Sobrien#include <sys/ptrace.h>
4638494Sobrien#include <sys/reboot.h>
4738494Sobrien#include <sys/signalvar.h>
4838494Sobrien#include <sys/sysent.h>
4938494Sobrien#include <sys/sysproto.h>
5038494Sobrien#include <sys/user.h>
5138494Sobrien
5238494Sobrien#include <vm/vm.h>
5338494Sobrien#include <vm/vm_object.h>
54174294Sobrien#include <vm/vm_page.h>
5538494Sobrien#include <vm/vm_pager.h>
5638494Sobrien
57174294Sobrien#include <machine/atomic.h>
58174294Sobrien#include <machine/cache.h>
59174294Sobrien#include <machine/clock.h>
60174294Sobrien#include <machine/cpu.h>
6138494Sobrien#include <machine/cpuregs.h>
6238494Sobrien#include <machine/cpufunc.h>
6338494Sobrien#include <mips/cavium/octeon_pcmap_regs.h>
6438494Sobrien#include <machine/hwfunc.h>
6538494Sobrien#include <machine/intr_machdep.h>
66174294Sobrien#include <machine/locore.h>
67174294Sobrien#include <machine/md_var.h>
68174294Sobrien#include <machine/pcpu.h>
69174294Sobrien#include <machine/pte.h>
70174294Sobrien#include <machine/trap.h>
71174294Sobrien#include <machine/vmparam.h>
72174294Sobrien
73174294Sobrien#if defined(__mips_n64)
74174294Sobrien#define MAX_APP_DESC_ADDR     0xffffffffafffffff
75174294Sobrien#else
76174294Sobrien#define MAX_APP_DESC_ADDR     0xafffffff
77174294Sobrien#endif
78174294Sobrien
79174294Sobrienextern int	*edata;
8038494Sobrienextern int	*end;
8138494Sobrien
8238494Sobrienuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip);
83174294Sobrienvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip);
8438494Sobrien
8538494Sobrienstatic void octeon_boot_params_init(register_t ptr);
8638494Sobrienstatic uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx);
87174294Sobrienstatic uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx);
8838494Sobrien
89174294Sobrienstatic __inline void
9038494Sobrienmips_wr_ebase(u_int32_t a0)
91174294Sobrien{
9238494Sobrien	__asm __volatile("mtc0 %[a0], $15, 1 ;"
9338494Sobrien	    :
9438494Sobrien	    :     [a0] "r"(a0));
9538494Sobrien
9638494Sobrien	mips_barrier();
9738494Sobrien}
9838494Sobrien
9938494Sobrienvoid
10038494Sobrienplatform_cpu_init()
10138494Sobrien{
10238494Sobrien	/* Nothing special yet */
10338494Sobrien}
10438494Sobrien
10538494Sobrien/*
10638494Sobrien * Perform a board-level soft-reset.
10738494Sobrien */
10838494Sobrienvoid
10938494Sobrienplatform_reset(void)
11038494Sobrien{
11138494Sobrien	oct_write64(OCTEON_CIU_SOFT_RST, 1);
11238494Sobrien}
11338494Sobrien
11438494Sobrien
11538494Sobrienstatic inline uint32_t
11638494Sobrienocteon_disable_interrupts(void)
11738494Sobrien{
11838494Sobrien	uint32_t status_bits;
11938494Sobrien
12038494Sobrien	status_bits = mips_rd_status();
121174294Sobrien	mips_wr_status(status_bits & ~MIPS_SR_INT_IE);
122174294Sobrien	return (status_bits);
12338494Sobrien}
12438494Sobrien
12538494Sobrien
12638494Sobrienstatic inline void
12738494Sobrienocteon_set_interrupts(uint32_t status_bits)
12838494Sobrien{
12938494Sobrien	mips_wr_status(status_bits);
13038494Sobrien}
13138494Sobrien
13238494Sobrien
13338494Sobrienvoid
13438494Sobrienocteon_led_write_char(int char_position, char val)
13538494Sobrien{
13638494Sobrien	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
13738494Sobrien
13838494Sobrien	if (!octeon_board_real())
13938494Sobrien		return;
140174294Sobrien
141174294Sobrien	char_position &= 0x7;  /* only 8 chars */
142174294Sobrien	ptr += char_position;
14338494Sobrien	oct_write8_x8(ptr, val);
14438494Sobrien}
14538494Sobrien
14638494Sobrienvoid
14738494Sobrienocteon_led_write_char0(char val)
14838494Sobrien{
14938494Sobrien	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
15038494Sobrien
15138494Sobrien	if (!octeon_board_real())
15238494Sobrien		return;
15338494Sobrien	oct_write8_x8(ptr, val);
15438494Sobrien}
15538494Sobrien
15638494Sobrienvoid
15738494Sobrienocteon_led_write_hexchar(int char_position, char hexval)
15838494Sobrien{
15938494Sobrien	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
16038494Sobrien	char char1, char2;
16138494Sobrien
16238494Sobrien	if (!octeon_board_real())
16338494Sobrien		return;
16438494Sobrien
16538494Sobrien	char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7';
16638494Sobrien	char2 = (hexval  & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7';
16738494Sobrien	char_position &= 0x7;  /* only 8 chars */
16838494Sobrien	if (char_position > 6)
16982794Sobrien		char_position = 6;
17082794Sobrien	ptr += char_position;
17182794Sobrien	oct_write8_x8(ptr, char1);
17238494Sobrien	ptr++;
17338494Sobrien	oct_write8_x8(ptr, char2);
17438494Sobrien}
17538494Sobrien
176174294Sobrienvoid
177174294Sobrienocteon_led_write_string(const char *str)
178174294Sobrien{
179174294Sobrien	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
180174294Sobrien	int i;
181174294Sobrien
182174294Sobrien	if (!octeon_board_real())
18338494Sobrien		return;
18438494Sobrien
18538494Sobrien	for (i=0; i<8; i++, ptr++) {
18638494Sobrien		if (str && *str)
18738494Sobrien			oct_write8_x8(ptr, *str++);
18838494Sobrien		else
189174294Sobrien			oct_write8_x8(ptr, ' ');
19038494Sobrien		oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
19138494Sobrien	}
19238494Sobrien}
19338494Sobrien
19438494Sobrienstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'};
19538494Sobrien
19638494Sobrienvoid
19738494Sobrienocteon_led_run_wheel(int *prog_count, int led_position)
19838494Sobrien{
19938494Sobrien	if (!octeon_board_real())
20038494Sobrien		return;
20138494Sobrien	octeon_led_write_char(led_position, progress[*prog_count]);
20238494Sobrien	*prog_count += 1;
20338494Sobrien	*prog_count &= 0x7;
20438494Sobrien}
20538494Sobrien
206174294Sobrien#define LSR_DATAREADY        0x01    /* Data ready */
207174294Sobrien#define LSR_THRE             0x20    /* Transmit holding register empty */
208174294Sobrien#define LSR_TEMT	     0x40    /* Transmitter Empty. THR, TSR & FIFO */
209174294Sobrien#define USR_TXFIFO_NOTFULL   0x02    /* Uart TX FIFO Not full */
210174294Sobrien
211174294Sobrien/*
212174294Sobrien * octeon_uart_write_byte
213174294Sobrien *
214174294Sobrien * Put out a single byte off of uart port.
215174294Sobrien */
216174294Sobrien
217174294Sobrienvoid
218174294Sobrienocteon_uart_write_byte(int uart_index, uint8_t ch)
219174294Sobrien{
220174294Sobrien	uint64_t val, val2;
221174294Sobrien	if (uart_index < 0 || uart_index > 1)
222174294Sobrien		return;
223174294Sobrien
224174294Sobrien	while (1) {
225174294Sobrien		val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
226174294Sobrien		val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400));
22738494Sobrien		if ((((uint8_t) val) & LSR_THRE) ||
22838494Sobrien		    (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
22938494Sobrien			break;
230174294Sobrien		}
231174294Sobrien	}
232174294Sobrien
233174294Sobrien	/* Write the byte */
234174294Sobrien	oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch);
23538494Sobrien
23638494Sobrien	/* Force Flush the IOBus */
23738494Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
23838494Sobrien}
23938494Sobrien
24038494Sobrien
24138494Sobrienvoid
24238494Sobrienocteon_uart_write_byte0(uint8_t ch)
24338494Sobrien{
24438494Sobrien	uint64_t val, val2;
24538494Sobrien
24638494Sobrien	while (1) {
24738494Sobrien		val = oct_read64(OCTEON_MIO_UART0_LSR);
24838494Sobrien		val2 = oct_read64(OCTEON_MIO_UART0_USR);
24938494Sobrien		if ((((uint8_t) val) & LSR_THRE) ||
25038494Sobrien		    (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
251174294Sobrien			break;
25238494Sobrien		}
25338494Sobrien	}
254174294Sobrien
255174294Sobrien	/* Write the byte */
256174294Sobrien	oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch);
257174294Sobrien
258174294Sobrien	/* Force Flush the IOBus */
259174294Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
26038494Sobrien}
261174294Sobrien
262174294Sobrien/*
263174294Sobrien * octeon_uart_write_string
264174294Sobrien *
265174294Sobrien */
26638494Sobrienvoid
26738494Sobrienocteon_uart_write_string(int uart_index, const char *str)
26838494Sobrien{
269174294Sobrien	/* Just loop writing one byte at a time */
27038494Sobrien
27138494Sobrien	while (*str) {
27238494Sobrien		octeon_uart_write_byte(uart_index, *str);
273174294Sobrien		if (*str == '\n') {
274174294Sobrien			octeon_uart_write_byte(uart_index, '\r');
27538494Sobrien		}
276174294Sobrien		str++;
277174294Sobrien	}
278174294Sobrien}
279174294Sobrien
280174294Sobrienstatic char wstr[30];
281119679Smbr
282119679Smbrvoid
283119679Smbrocteon_led_write_hex(uint32_t wl)
284174294Sobrien{
285174294Sobrien	char nbuf[80];
286174294Sobrien
287174294Sobrien	sprintf(nbuf, "%X", wl);
288174294Sobrien	octeon_led_write_string(nbuf);
289174294Sobrien}
290174294Sobrien
291174294Sobrien
292174294Sobrienvoid octeon_uart_write_hex2(uint32_t wl, uint32_t wh)
293119679Smbr{
294174294Sobrien	sprintf(wstr, "0x%X-0x%X  ", wh, wl);
295174294Sobrien	octeon_uart_write_string(0, wstr);
296174294Sobrien}
297174294Sobrien
298174294Sobrienvoid
299174294Sobrienocteon_uart_write_hex(uint32_t wl)
300174294Sobrien{
30138494Sobrien	sprintf(wstr, " 0x%X  ", wl);
302174294Sobrien	octeon_uart_write_string(0, wstr);
30338494Sobrien}
304174294Sobrien
305174294Sobrien/*
30638494Sobrien * octeon_wait_uart_flush
30738494Sobrien */
30838494Sobrienvoid
30938494Sobrienocteon_wait_uart_flush(int uart_index, uint8_t ch)
31038494Sobrien{
31138494Sobrien	uint64_t val;
31238494Sobrien	int64_t val3;
313174294Sobrien	uint32_t cpu_status_bits;
31438494Sobrien
31538494Sobrien	if (uart_index < 0 || uart_index > 1)
316174294Sobrien		return;
31738494Sobrien
318174294Sobrien	cpu_status_bits = octeon_disable_interrupts();
31938494Sobrien	/* Force Flush the IOBus */
32038494Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
32138494Sobrien	for (val3 = 0xfffffffff; val3 > 0; val3--) {
322174294Sobrien		val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
32338494Sobrien		if (((uint8_t) val) & LSR_TEMT)
32438494Sobrien			break;
325174294Sobrien	}
32638494Sobrien	octeon_set_interrupts(cpu_status_bits);
32738494Sobrien}
328174294Sobrien
329174294Sobrien
330174294Sobrien/*
331174294Sobrien * octeon_debug_symbol
332174294Sobrien *
333174294Sobrien * Does nothing.
334174294Sobrien * Used to mark the point for simulator to begin tracing
335174294Sobrien */
336174294Sobrienvoid
33738494Sobrienocteon_debug_symbol(void)
33838494Sobrien{
339174294Sobrien}
340174294Sobrien
341174294Sobrienvoid
342174294Sobrienocteon_ciu_stop_gtimer(int timer)
343174294Sobrien{
344174294Sobrien	oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll);
34538494Sobrien}
34638494Sobrien
34738494Sobrienvoid
34838494Sobrienocteon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles)
34938494Sobrien{
35038494Sobrien    	octeon_ciu_gentimer gentimer;
35138494Sobrien
35238494Sobrien        gentimer.word64 = 0;
353174294Sobrien        gentimer.bits.one_shot = one_shot;
354174294Sobrien        gentimer.bits.len = time_cycles - 1;
355174294Sobrien        oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64);
356174294Sobrien}
357174294Sobrien
358174294Sobrien/*
359174294Sobrien * octeon_ciu_reset
360174294Sobrien *
361174294Sobrien * Shutdown all CIU to IP2, IP3 mappings
362174294Sobrien */
363174294Sobrienvoid
364174294Sobrienocteon_ciu_reset(void)
365174294Sobrien{
366174294Sobrien
367174294Sobrien	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0);
368174294Sobrien	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1);
369174294Sobrien	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2);
370174294Sobrien	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3);
371174294Sobrien
372174294Sobrien	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0);
373174294Sobrien	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1);
374174294Sobrien	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0);
375174294Sobrien	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1);
376174294Sobrien
377174294Sobrien	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll);
378174294Sobrien	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll);
379174294Sobrien	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll);
380174294Sobrien}
381174294Sobrien
382174294Sobrien/*
383174294Sobrien * mips_disable_interrupt_controllers
384174294Sobrien *
385174294Sobrien * Disable interrupts in the CPU controller
386174294Sobrien */
387174294Sobrienvoid
388174294Sobrienmips_disable_interrupt_controls(void)
389174294Sobrien{
390174294Sobrien	/*
391174294Sobrien	 * Disable interrupts in CIU.
392174294Sobrien	 */
393174294Sobrien	octeon_ciu_reset();
394174294Sobrien}
395174294Sobrien
396174294Sobrien/*
397174294Sobrien * ciu_get_intr_sum_reg_addr
398174294Sobrien */
399174294Sobrienstatic uint64_t
400174294Sobrienciu_get_intr_sum_reg_addr(int core_num, int intx, int enx)
401174294Sobrien{
402174294Sobrien	uint64_t ciu_intr_sum_reg_addr;
403174294Sobrien
404174294Sobrien    	if (enx == CIU_EN_0)
405174294Sobrien            	ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR +
406174294Sobrien		    (core_num * 0x10) + (intx * 0x8);
407174294Sobrien	else
408174294Sobrien            	ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR;
409174294Sobrien
410174294Sobrien        return (ciu_intr_sum_reg_addr);
411174294Sobrien}
412174294Sobrien
413174294Sobrien
414174294Sobrien/*
415174294Sobrien * ciu_get_intr_en_reg_addr
416174294Sobrien */
417174294Sobrienstatic uint64_t
418174294Sobrienciu_get_intr_en_reg_addr(int core_num, int intx, int enx)
419174294Sobrien{
420174294Sobrien	uint64_t ciu_intr_reg_addr;
421174294Sobrien
422174294Sobrien    	ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR +
423174294Sobrien	    ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) +  (core_num * 0x20);
424174294Sobrien        return (ciu_intr_reg_addr);
425174294Sobrien}
426174294Sobrien
427174294Sobrien
428174294Sobrien
429174294Sobrien
430174294Sobrien/*
431174294Sobrien * ciu_get_intr_reg_addr
432174294Sobrien *
433174294Sobrien * 200 ---int0,en0 ip2
434174294Sobrien * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog
435174294Sobrien *
436174294Sobrien * 210 ---int0,en0 ip3 --
437174294Sobrien * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right?
438174294Sobrien *
439174294Sobrien * 220 ---int1,en0 ip2
440174294Sobrien * 228 ---int1,en1 ip2
441174294Sobrien * 230 ---int1,en0 ip3 --
442174294Sobrien * 238 ---int1,en1 ip3
443174294Sobrien *
444174294Sobrien */
445174294Sobrienuint64_t
44638494Sobrienciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip)
447174294Sobrien{
44838494Sobrien	uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR;
449174294Sobrien
450174294Sobrien	/* XXX kasserts? */
451174294Sobrien	if (enx < CIU_EN_0 || enx > CIU_EN_1) {
452174294Sobrien		printf("%s: invalid enx value %d, should be %d or %d\n",
453174294Sobrien		    __FUNCTION__, enx, CIU_EN_0, CIU_EN_1);
454174294Sobrien		return 0;
455174294Sobrien	}
45638494Sobrien	if (intx < CIU_INT_0 || intx > CIU_INT_1) {
457174294Sobrien		printf("%s: invalid intx value %d, should be %d or %d\n",
458174294Sobrien		    __FUNCTION__, enx, CIU_INT_0, CIU_INT_1);
459174294Sobrien		return 0;
460174294Sobrien	}
46138494Sobrien	if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) {
462174294Sobrien		printf("%s: invalid ciu_ip value %d, should be %d or %d\n",
463174294Sobrien		    __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3);
464174294Sobrien		return 0;
465174294Sobrien	}
466174294Sobrien
467174294Sobrien	ciu_intr_reg_addr += (enx    * 0x8);
468174294Sobrien	ciu_intr_reg_addr += (ciu_ip * 0x10);
469174294Sobrien	ciu_intr_reg_addr += (intx   * 0x20);
470174294Sobrien	return (ciu_intr_reg_addr);
471174294Sobrien}
472174294Sobrien
473174294Sobrien/*
474174294Sobrien * ciu_get_int_summary
475174294Sobrien */
476174294Sobrienuint64_t
477174294Sobrienciu_get_int_summary(int core_num, int intx, int enx)
478174294Sobrien{
479174294Sobrien	uint64_t ciu_intr_sum_reg_addr;
480174294Sobrien
481174294Sobrien	if (core_num == CIU_THIS_CORE)
48238494Sobrien        	core_num = octeon_get_core_num();
48338494Sobrien	ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
484174294Sobrien	return (oct_read64(ciu_intr_sum_reg_addr));
485174294Sobrien}
486174294Sobrien
487174294Sobrien//#define DEBUG_CIU 1
488174294Sobrien
489174294Sobrien#ifdef DEBUG_CIU
490174294Sobrien#define DEBUG_CIU_SUM 1
491174294Sobrien#define DEBUG_CIU_EN 1
492174294Sobrien#endif
493174294Sobrien
494174294Sobrien
495174294Sobrien/*
496174294Sobrien * ciu_clear_int_summary
497174294Sobrien */
498174294Sobrienvoid
499174294Sobrienciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits)
500174294Sobrien{
501174294Sobrien	uint32_t cpu_status_bits;
502174294Sobrien	uint64_t ciu_intr_sum_reg_addr;
503174294Sobrien
504174294Sobrien//#define DEBUG_CIU_SUM 1
505174294Sobrien
506174294Sobrien#ifdef DEBUG_CIU_SUM
507174294Sobrien	uint64_t ciu_intr_sum_bits;
508174294Sobrien#endif
509174294Sobrien
510174294Sobrien
511174294Sobrien	if (core_num == CIU_THIS_CORE) {
512174294Sobrien        	core_num = octeon_get_core_num();
513174294Sobrien	}
514174294Sobrien
515174294Sobrien#ifdef DEBUG_CIU_SUM
516174294Sobrien        printf(" CIU: core %u clear sum IntX %u  Enx %u  Bits: 0x%llX\n",
517174294Sobrien	    core_num, intx, enx, write_bits);
518174294Sobrien#endif
519174294Sobrien
520174294Sobrien	cpu_status_bits = octeon_disable_interrupts();
521174294Sobrien
522174294Sobrien	ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
523174294Sobrien
524174294Sobrien#ifdef DEBUG_CIU_SUM
525174294Sobrien    	ciu_intr_sum_bits =  oct_read64(ciu_intr_sum_reg_addr);	/* unneeded dummy read */
526174294Sobrien        printf(" CIU: status: 0x%X  reg_addr: 0x%llX   Val: 0x%llX   ->  0x%llX",
527174294Sobrien	    cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits,
528174294Sobrien	    ciu_intr_sum_bits | write_bits);
529174294Sobrien#endif
530174294Sobrien
531174294Sobrien	oct_write64(ciu_intr_sum_reg_addr, write_bits);
532174294Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
533174294Sobrien
534174294Sobrien#ifdef DEBUG_CIU_SUM
535174294Sobrien        printf(" Readback: 0x%llX\n\n   ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr));
536174294Sobrien#endif
537174294Sobrien
538174294Sobrien	octeon_set_interrupts(cpu_status_bits);
539174294Sobrien}
540174294Sobrien
541174294Sobrien/*
542174294Sobrien * ciu_disable_intr
543174294Sobrien */
544174294Sobrienvoid
545174294Sobrienciu_disable_intr(int core_num, int intx, int enx)
546174294Sobrien{
547174294Sobrien	uint32_t cpu_status_bits;
548174294Sobrien	uint64_t ciu_intr_reg_addr;
549174294Sobrien
550174294Sobrien	if (core_num == CIU_THIS_CORE)
551174294Sobrien        	core_num = octeon_get_core_num();
552174294Sobrien
553174294Sobrien	cpu_status_bits = octeon_disable_interrupts();
554174294Sobrien
555174294Sobrien	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
556174294Sobrien
557174294Sobrien	oct_read64(ciu_intr_reg_addr);	/* Dummy read */
558174294Sobrien
559174294Sobrien	oct_write64(ciu_intr_reg_addr, 0LL);
560174294Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
561174294Sobrien
562174294Sobrien	octeon_set_interrupts(cpu_status_bits);
563174294Sobrien}
564174294Sobrien
565174294Sobrienvoid
566174294Sobrienciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip)
567174294Sobrien{
568174294Sobrien
569174294Sobrien	uint64_t ciu_intr_reg_addr;
570174294Sobrien	uint64_t ciu_intr_bits;
571174294Sobrien
572174294Sobrien        if (core_num == CIU_THIS_CORE) {
573174294Sobrien            	core_num = octeon_get_core_num();
574174294Sobrien        }
575174294Sobrien
576174294Sobrien#ifndef OCTEON_SMP_1
577174294Sobrien	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
578174294Sobrien#else
579174294Sobrien	ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
580174294Sobrien#endif
581174294Sobrien
582174294Sobrien        if (!ciu_intr_reg_addr) {
583174294Sobrien            printf("Bad call to %s\n", __FUNCTION__);
584174294Sobrien            while(1);
585174294Sobrien            return;
586174294Sobrien        }
587174294Sobrien
588174294Sobrien	ciu_intr_bits =  oct_read64(ciu_intr_reg_addr);
589174294Sobrien        printf(" CIU core %d  int: %d  en: %d  ip: %d  Add: %#llx  enabled: %#llx  SR: %x\n",
590174294Sobrien	    core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr,
591174294Sobrien	    (unsigned long long)ciu_intr_bits, mips_rd_status());
592174294Sobrien}
593174294Sobrien
594174294Sobrien
595174294Sobrien/*
596174294Sobrien * ciu_enable_interrupts
597174294Sobrien */
598174294Sobrienvoid ciu_enable_interrupts(int core_num, int intx, int enx,
599174294Sobrien    uint64_t set_these_interrupt_bits, int ciu_ip)
600174294Sobrien{
601174294Sobrien	uint32_t cpu_status_bits;
602174294Sobrien	uint64_t ciu_intr_reg_addr;
603174294Sobrien	uint64_t ciu_intr_bits;
604174294Sobrien
605174294Sobrien        if (core_num == CIU_THIS_CORE)
606174294Sobrien            	core_num = octeon_get_core_num();
607174294Sobrien
608174294Sobrien//#define DEBUG_CIU_EN 1
609174294Sobrien
610174294Sobrien#ifdef DEBUG_CIU_EN
611174294Sobrien        printf(" CIU: core %u enabling Intx %u  Enx %u IP %d  Bits: 0x%llX\n",
612174294Sobrien	    core_num, intx, enx, ciu_ip, set_these_interrupt_bits);
613174294Sobrien#endif
614174294Sobrien
615174294Sobrien	cpu_status_bits = octeon_disable_interrupts();
616174294Sobrien
617174294Sobrien#ifndef OCTEON_SMP_1
618174294Sobrien	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
619174294Sobrien#else
620174294Sobrien	ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
621174294Sobrien#endif
622174294Sobrien
623174294Sobrien        if (!ciu_intr_reg_addr) {
624174294Sobrien		printf("Bad call to %s\n", __FUNCTION__);
625174294Sobrien		while(1);
626174294Sobrien		return;	/* XXX */
627174294Sobrien        }
628174294Sobrien
629174294Sobrien	ciu_intr_bits =  oct_read64(ciu_intr_reg_addr);
630174294Sobrien
631174294Sobrien#ifdef DEBUG_CIU_EN
632174294Sobrien        printf(" CIU: status: 0x%X  reg_addr: 0x%llX   Val: 0x%llX   ->  0x%llX",
633174294Sobrien	    cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits);
634174294Sobrien#endif
635174294Sobrien	ciu_intr_bits |=  set_these_interrupt_bits;
636174294Sobrien	oct_write64(ciu_intr_reg_addr, ciu_intr_bits);
637174294Sobrien#ifdef OCTEON_SMP
638174294Sobrien	mips_wbflush();
639174294Sobrien#endif
640174294Sobrien	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
641174294Sobrien
642174294Sobrien#ifdef DEBUG_CIU_EN
643174294Sobrien        printf(" Readback: 0x%llX\n\n   ",
644174294Sobrien	    (uint64_t)oct_read64(ciu_intr_reg_addr));
645174294Sobrien#endif
646174294Sobrien
647174294Sobrien	octeon_set_interrupts(cpu_status_bits);
648174294Sobrien}
649174294Sobrien
650174294Sobrienunsigned long
651174294Sobrienocteon_get_clock_rate(void)
65238494Sobrien{
65338494Sobrien	return octeon_cpu_clock;
65438494Sobrien}
65538494Sobrien
65638494Sobrienstatic void
65738494Sobrienocteon_memory_init(void)
65838494Sobrien{
65938494Sobrien	uint32_t realmem_bytes;
66038494Sobrien
66138494Sobrien	if (octeon_board_real()) {
66238494Sobrien		printf("octeon_dram == %llx\n", octeon_dram);
66338494Sobrien		printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20);
66438494Sobrien
66538494Sobrien		realmem_bytes = (octeon_dram - PAGE_SIZE);
66638494Sobrien		realmem_bytes &= ~(PAGE_SIZE - 1);
66738494Sobrien		printf("Real memory bytes is %x\n", realmem_bytes);
668174294Sobrien	} else {
66938494Sobrien		/* Simulator we limit to 96 meg */
67038494Sobrien		realmem_bytes = (96 << 20);
671174294Sobrien	}
672174294Sobrien	/* phys_avail regions are in bytes */
673174294Sobrien	phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1);
674174294Sobrien	if (octeon_board_real()) {
675174294Sobrien		if (realmem_bytes > OCTEON_DRAM_FIRST_256_END)
676174294Sobrien			phys_avail[1] = OCTEON_DRAM_FIRST_256_END;
677174294Sobrien		else
678174294Sobrien			phys_avail[1] = realmem_bytes;
679174294Sobrien		realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
680174294Sobrien		realmem_bytes &= ~(PAGE_SIZE - 1);
681174294Sobrien		printf("phys_avail[0] = %x phys_avail[1] = %x\n",
682174294Sobrien		    phys_avail[0], phys_avail[1]);
683174294Sobrien	} else {
684174294Sobrien		/* Simulator gets 96Meg period. */
685174294Sobrien		phys_avail[1] = (96 << 20);
686174294Sobrien	}
687174294Sobrien	/*-
688174294Sobrien	 * Octeon Memory looks as follows:
689174294Sobrien         *   PA
690174294Sobrien	 * 0000 0000 to                                       0x0 0000 0000 0000
691174294Sobrien	 * 0FFF FFFF      First 256 MB memory   Maps to       0x0 0000 0FFF FFFF
692174294Sobrien	 *
693174294Sobrien	 * 1000 0000 to                                       0x1 0000 1000 0000
694174294Sobrien	 * 1FFF FFFF      Uncached Bu I/O space.converted to  0x1 0000 1FFF FFFF
695174294Sobrien	 *
696174294Sobrien	 * 2FFF FFFF to            Cached                     0x0 0000 2000 0000
697174294Sobrien	 * FFFF FFFF      all dram mem above the first 512M   0x3 FFFF FFFF FFFF
698174294Sobrien	 *
699174294Sobrien	 */
700174294Sobrien	physmem = btoc(phys_avail[1] - phys_avail[0]);
701174294Sobrien	if ((octeon_board_real()) &&
702174294Sobrien	    (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) {
703174294Sobrien		/* take out the upper non-cached 1/2 */
704174294Sobrien		realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
705174294Sobrien		realmem_bytes &= ~(PAGE_SIZE - 1);
706174294Sobrien		/* Now map the rest of the memory */
707174294Sobrien		phys_avail[2] = 0x20000000;
70838494Sobrien		printf("realmem_bytes is now at %x\n", realmem_bytes);
70938494Sobrien		phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes);
71038494Sobrien		printf("Next block of memory goes from %x to %x\n",
711174294Sobrien		    phys_avail[2], phys_avail[3]);
71238494Sobrien		physmem += btoc(phys_avail[3] - phys_avail[2]);
713174294Sobrien	} else {
714174294Sobrien		printf("realmem_bytes is %d\n", realmem_bytes);
715174294Sobrien	}
716174294Sobrien	realmem = physmem;
717174294Sobrien
718174294Sobrien	printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram);
719174294Sobrien	printf("\nBank 0 = 0x%8X   ->  0x%8X", phys_avail[0], phys_avail[1]);
720174294Sobrien	printf("\nBank 1 = 0x%8X   ->  0x%8X\n", phys_avail[2], phys_avail[3]);
721174294Sobrien	printf("\nphysmem: 0x%lx", physmem);
722174294Sobrien
723174294Sobrien	Maxmem = physmem;
724174294Sobrien
725174294Sobrien}
726174294Sobrien
727174294Sobrienvoid
728174294Sobrienplatform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
729174294Sobrien    __register_t a3)
730174294Sobrien{
731174294Sobrien	uint64_t platform_counter_freq;
732174294Sobrien
733174294Sobrien	/* Initialize pcpu stuff */
734174294Sobrien	mips_pcpu0_init();
735174294Sobrien	mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
736174294Sobrien	cninit();
737174294Sobrien
738174294Sobrien	octeon_ciu_reset();
739174294Sobrien	octeon_boot_params_init(a3);
740174294Sobrien	bootverbose = 1;
74138494Sobrien
74238494Sobrien	/*
74338494Sobrien	 * For some reason on the cn38xx simulator ebase register is set to
74438494Sobrien	 * 0x80001000 at bootup time.  Move it back to the default, but
74538494Sobrien	 * when we move to having support for multiple executives, we need
74638494Sobrien	 * to rethink this.
74738494Sobrien	 */
74838494Sobrien	mips_wr_ebase(0x80000000);
74938494Sobrien
75038494Sobrien	octeon_memory_init();
75138494Sobrien	init_param1();
75238494Sobrien	init_param2(physmem);
75338494Sobrien	mips_cpu_init();
75438494Sobrien	pmap_bootstrap();
75538494Sobrien	mips_proc0_init();
75638494Sobrien	mutex_init();
75738494Sobrien	kdb_init();
75838494Sobrien#ifdef KDB
75938494Sobrien	if (boothowto & RB_KDB)
76038494Sobrien		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
76138494Sobrien#endif
76242629Sobrien	platform_counter_freq = octeon_get_clock_rate();
76338494Sobrien	mips_timer_init_params(platform_counter_freq, 1);
76438494Sobrien}
765174294Sobrien
76638494Sobrien/* impSTART: This stuff should move back into the Cavium SDK */
76738494Sobrien/*
76838494Sobrien ****************************************************************************************
76938494Sobrien *
77038494Sobrien * APP/BOOT  DESCRIPTOR  STUFF
77138494Sobrien *
77238494Sobrien ****************************************************************************************
77338494Sobrien */
77438494Sobrien
77538494Sobrien/* Define the struct that is initialized by the bootloader used by the
77638494Sobrien * startup code.
77738494Sobrien *
77838494Sobrien * Copyright (c) 2004, 2005, 2006 Cavium Networks.
77938494Sobrien *
780174294Sobrien * The authors hereby grant permission to use, copy, modify, distribute,
781174294Sobrien * and license this software and its documentation for any purpose, provided
78238494Sobrien * that existing copyright notices are retained in all copies and that this
78338494Sobrien * notice is included verbatim in any distributions. No written agreement,
784 * license, or royalty fee is required for any of the authorized uses.
785 * Modifications to this software may be copyrighted by their authors
786 * and need not follow the licensing terms described here, provided that
787 * the new terms are clearly indicated on the first page of each file where
788 * they apply.
789 */
790
791#define OCTEON_CURRENT_DESC_VERSION     6
792#define OCTEON_ARGV_MAX_ARGS            (64)
793#define OCTOEN_SERIAL_LEN 20
794
795
796typedef struct {
797	/* Start of block referenced by assembly code - do not change! */
798	uint32_t desc_version;
799	uint32_t desc_size;
800
801	uint64_t stack_top;
802	uint64_t heap_base;
803	uint64_t heap_end;
804	uint64_t entry_point;   /* Only used by bootloader */
805	uint64_t desc_vaddr;
806	/* End of This block referenced by assembly code - do not change! */
807
808	uint32_t exception_base_addr;
809	uint32_t stack_size;
810	uint32_t heap_size;
811	uint32_t argc;  /* Argc count for application */
812	uint32_t argv[OCTEON_ARGV_MAX_ARGS];
813	uint32_t flags;
814	uint32_t core_mask;
815	uint32_t dram_size;  /**< DRAM size in megabyes */
816	uint32_t phy_mem_desc_addr;  /**< physical address of free memory descriptor block*/
817	uint32_t debugger_flags_base_addr;  /**< used to pass flags from app to debugger */
818	uint32_t eclock_hz;  /**< CPU clock speed, in hz */
819	uint32_t dclock_hz;  /**< DRAM clock speed, in hz */
820	uint32_t spi_clock_hz;  /**< SPI4 clock in hz */
821	uint16_t board_type;
822	uint8_t board_rev_major;
823	uint8_t board_rev_minor;
824	uint16_t chip_type;
825	uint8_t chip_rev_major;
826	uint8_t chip_rev_minor;
827	char board_serial_number[OCTOEN_SERIAL_LEN];
828	uint8_t mac_addr_base[6];
829	uint8_t mac_addr_count;
830	uint64_t cvmx_desc_vaddr;
831} octeon_boot_descriptor_t;
832
833
834typedef struct {
835	uint32_t major_version;
836	uint32_t minor_version;
837
838	uint64_t stack_top;
839	uint64_t heap_base;
840	uint64_t heap_end;
841	uint64_t desc_vaddr;
842
843	uint32_t exception_base_addr;
844	uint32_t stack_size;
845	uint32_t flags;
846	uint32_t core_mask;
847	uint32_t dram_size;  /**< DRAM size in megabyes */
848	uint32_t phy_mem_desc_addr;  /**< physical address of free memory descriptor block*/
849	uint32_t debugger_flags_base_addr;  /**< used to pass flags from app to debugger */
850	uint32_t eclock_hz;  /**< CPU clock speed, in hz */
851	uint32_t dclock_hz;  /**< DRAM clock speed, in hz */
852	uint32_t spi_clock_hz;  /**< SPI4 clock in hz */
853	uint16_t board_type;
854	uint8_t board_rev_major;
855	uint8_t board_rev_minor;
856	uint16_t chip_type;
857	uint8_t chip_rev_major;
858	uint8_t chip_rev_minor;
859	char board_serial_number[OCTOEN_SERIAL_LEN];
860	uint8_t mac_addr_base[6];
861	uint8_t mac_addr_count;
862} cvmx_bootinfo_t;
863
864uint32_t octeon_cpu_clock;
865uint64_t octeon_dram;
866uint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type;
867uint8_t octeon_mac_addr[6] = { 0 };
868int octeon_core_mask, octeon_mac_addr_count;
869int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0;
870
871static octeon_boot_descriptor_t *app_desc_ptr;
872static cvmx_bootinfo_t *cvmx_desc_ptr;
873
874#define OCTEON_BOARD_TYPE_NONE 0
875#define OCTEON_BOARD_TYPE_SIM  1
876
877#define OCTEON_CLOCK_MIN     (100 * 1000 * 1000)
878#define OCTEON_CLOCK_MAX     (800 * 1000 * 1000)
879#define OCTEON_DRAM_DEFAULT  (256 * 1024 * 1024)
880#define OCTEON_DRAM_MIN	     30
881#define OCTEON_DRAM_MAX	     3000
882
883
884int
885octeon_board_real(void)
886{
887	if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) ||
888	    (octeon_board_type == OCTEON_BOARD_TYPE_SIM) ||
889	    !octeon_board_rev_major)
890		return 0;
891	return 1;
892}
893
894static void
895octeon_process_app_desc_ver_unknown(void)
896{
897    	printf(" Unknown Boot-Descriptor: Using Defaults\n");
898
899    	octeon_cpu_clock = OCTEON_CLOCK_DEFAULT;
900        octeon_dram = OCTEON_DRAM_DEFAULT;
901        octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0;
902        octeon_core_mask = 1;
903        octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0;
904        octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f;
905        octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10;
906        octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06;
907        octeon_mac_addr_count = 1;
908}
909
910static int
911octeon_process_app_desc_ver_6(void)
912{
913	/* XXX Why is 0x00000000ffffffffULL a bad value?  */
914	if (app_desc_ptr->cvmx_desc_vaddr == 0 ||
915	    app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) {
916            	printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr);
917                return 1;
918	}
919    	cvmx_desc_ptr =
920	    (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr;
921        cvmx_desc_ptr =
922	    (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START);
923        octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) +
924	    cvmx_desc_ptr->minor_version;
925        if (cvmx_desc_ptr->major_version != 1) {
926            	panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n",
927                       (int) cvmx_desc_ptr->major_version,
928                       (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr);
929        }
930
931        octeon_core_mask = cvmx_desc_ptr->core_mask;
932        octeon_cpu_clock  = cvmx_desc_ptr->eclock_hz;
933        octeon_board_type = cvmx_desc_ptr->board_type;
934        octeon_board_rev_major = cvmx_desc_ptr->board_rev_major;
935        octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor;
936        octeon_chip_type = cvmx_desc_ptr->chip_type;
937        octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major;
938        octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor;
939        octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0];
940        octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1];
941        octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2];
942        octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3];
943        octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4];
944        octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5];
945        octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count;
946
947        if (app_desc_ptr->dram_size > 16*1024*1024)
948            	octeon_dram = (uint64_t)app_desc_ptr->dram_size;
949	else
950            	octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20;
951        return 0;
952}
953
954static void
955octeon_boot_params_init(register_t ptr)
956{
957	int bad_desc = 1;
958
959    	if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) {
960	        app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
961		octeon_bd_ver = app_desc_ptr->desc_version;
962		if (app_desc_ptr->desc_version < 6)
963			panic("Your boot code is too old to be supported.\n");
964		if (app_desc_ptr->desc_version >= 6)
965			bad_desc = octeon_process_app_desc_ver_6();
966        }
967        if (bad_desc)
968        	octeon_process_app_desc_ver_unknown();
969
970        printf("Boot Descriptor Ver: %u -> %u/%u",
971               octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100);
972        printf("  CPU clock: %uMHz\n", octeon_cpu_clock/1000000);
973        printf("  Dram: %u MB", (uint32_t)(octeon_dram >> 20));
974        printf("  Board Type: %u  Revision: %u/%u\n",
975               octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor);
976        printf("  Octeon Chip: %u  Rev %u/%u",
977               octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor);
978
979        printf("  Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n",
980	    octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2],
981	    octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5],
982	    octeon_mac_addr_count);
983}
984/* impEND: This stuff should move back into the Cavium SDK */
985