octeon_machdep.c revision 202850
1194140Simp/*-
2194140Simp * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
3194140Simp * All rights reserved.
4194140Simp *
5194140Simp * Redistribution and use in source and binary forms, with or without
6194140Simp * modification, are permitted provided that the following conditions
7194140Simp * are met:
8194140Simp * 1. Redistributions of source code must retain the above copyright
9194140Simp *    notice, this list of conditions and the following disclaimer.
10194140Simp * 2. Redistributions in binary form must reproduce the above copyright
11194140Simp *    notice, this list of conditions and the following disclaimer in the
12194140Simp *    documentation and/or other materials provided with the distribution.
13194140Simp *
14194140Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15194140Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16194140Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17194140Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18194140Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19194140Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20194140Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21194140Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22194140Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23194140Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24194140Simp * SUCH DAMAGE.
25194140Simp *
26194140Simp * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202850 2010-01-23 00:24:31Z imp $
27194140Simp */
28194140Simp#include <sys/cdefs.h>
29194140Simp__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202850 2010-01-23 00:24:31Z imp $");
30194140Simp
31194140Simp#include <sys/param.h>
32196262Simp#include <sys/conf.h>
33196262Simp#include <sys/kernel.h>
34194140Simp#include <sys/systm.h>
35196262Simp#include <sys/imgact.h>
36196262Simp#include <sys/bio.h>
37196262Simp#include <sys/buf.h>
38196262Simp#include <sys/bus.h>
39196262Simp#include <sys/cpu.h>
40196262Simp#include <sys/cons.h>
41196262Simp#include <sys/exec.h>
42196262Simp#include <sys/ucontext.h>
43196262Simp#include <sys/proc.h>
44196262Simp#include <sys/kdb.h>
45196262Simp#include <sys/ptrace.h>
46196262Simp#include <sys/reboot.h>
47196262Simp#include <sys/signalvar.h>
48196262Simp#include <sys/sysent.h>
49196262Simp#include <sys/sysproto.h>
50196262Simp#include <sys/user.h>
51196262Simp
52196262Simp#include <vm/vm.h>
53196262Simp#include <vm/vm_object.h>
54196262Simp#include <vm/vm_page.h>
55196262Simp#include <vm/vm_pager.h>
56196262Simp
57196262Simp#include <machine/atomic.h>
58196262Simp#include <machine/cache.h>
59196262Simp#include <machine/clock.h>
60196262Simp#include <machine/cpu.h>
61194140Simp#include <machine/cpuregs.h>
62194140Simp#include <machine/cpufunc.h>
63202063Simp#include <mips/cavium/octeon_pcmap_regs.h>
64202063Simp#include <mips/cavium/octeonreg.h>
65196262Simp#include <machine/hwfunc.h>
66196262Simp#include <machine/intr_machdep.h>
67196262Simp#include <machine/locore.h>
68196262Simp#include <machine/md_var.h>
69194140Simp#include <machine/pcpu.h>
70196262Simp#include <machine/pte.h>
71196262Simp#include <machine/trap.h>
72196262Simp#include <machine/vmparam.h>
73194140Simp
74194140Simp#if defined(__mips_n64)
75196262Simp#define MAX_APP_DESC_ADDR     0xffffffffafffffff
76194140Simp#else
77196262Simp#define MAX_APP_DESC_ADDR     0xafffffff
78194140Simp#endif
79194140Simp
80202831Simpstatic struct pcpu pcpu0;
81196262Simpextern int	*edata;
82196262Simpextern int	*end;
83194140Simp
84201530Simpuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip);
85201530Simpvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip);
86201530Simp
87200344Simpstatic void octeon_boot_params_init(register_t ptr);
88201530Simpstatic uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx);
89201530Simpstatic uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx);
90200344Simp
91202831Simpstatic __inline void
92202831Simpmips_wr_ebase(u_int32_t a0)
93202831Simp{
94202831Simp	__asm __volatile("mtc0 %[a0], $15, 1 ;"
95202831Simp	    :
96202831Simp	    :     [a0] "r"(a0));
97202831Simp
98202831Simp	mips_barrier();
99202831Simp}
100202831Simp
101198669Srrsvoid
102198669Srrsplatform_cpu_init()
103198669Srrs{
104198669Srrs	/* Nothing special yet */
105198669Srrs}
106196262Simp
107194140Simp/*
108194140Simp * Perform a board-level soft-reset.
109194140Simp */
110196314Simpvoid
111196314Simpplatform_reset(void)
112194140Simp{
113202850Simp	mips_generic_reset();
114194140Simp}
115194140Simp
116194140Simp
117201530Simpstatic inline uint32_t
118201530Simpocteon_disable_interrupts(void)
119194140Simp{
120201530Simp	uint32_t status_bits;
121194140Simp
122201530Simp	status_bits = mips_rd_status();
123201530Simp	mips_wr_status(status_bits & ~MIPS_SR_INT_IE);
124201530Simp	return (status_bits);
125194140Simp}
126194140Simp
127194140Simp
128201530Simpstatic inline void
129201530Simpocteon_set_interrupts(uint32_t status_bits)
130194140Simp{
131201530Simp	mips_wr_status(status_bits);
132194140Simp}
133194140Simp
134194140Simp
135201530Simpvoid
136201530Simpocteon_led_write_char(int char_position, char val)
137194140Simp{
138201530Simp	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
139194140Simp
140201530Simp	if (!octeon_board_real())
141201530Simp		return;
142194140Simp
143201530Simp	char_position &= 0x7;  /* only 8 chars */
144201530Simp	ptr += char_position;
145201530Simp	oct_write8_x8(ptr, val);
146194140Simp}
147194140Simp
148201530Simpvoid
149201530Simpocteon_led_write_char0(char val)
150194140Simp{
151201530Simp	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
152194140Simp
153201530Simp	if (!octeon_board_real())
154201530Simp		return;
155201530Simp	oct_write8_x8(ptr, val);
156194140Simp}
157194140Simp
158201530Simpvoid
159201530Simpocteon_led_write_hexchar(int char_position, char hexval)
160194140Simp{
161201530Simp	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
162201530Simp	char char1, char2;
163194140Simp
164201530Simp	if (!octeon_board_real())
165201530Simp		return;
166194140Simp
167201530Simp	char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7';
168201530Simp	char2 = (hexval  & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7';
169201530Simp	char_position &= 0x7;  /* only 8 chars */
170201530Simp	if (char_position > 6)
171201530Simp		char_position = 6;
172201530Simp	ptr += char_position;
173201530Simp	oct_write8_x8(ptr, char1);
174201530Simp	ptr++;
175201530Simp	oct_write8_x8(ptr, char2);
176194140Simp}
177194140Simp
178201530Simpvoid
179201530Simpocteon_led_write_string(const char *str)
180194140Simp{
181201530Simp	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
182201530Simp	int i;
183194140Simp
184201530Simp	if (!octeon_board_real())
185201530Simp		return;
186194140Simp
187201530Simp	for (i=0; i<8; i++, ptr++) {
188201530Simp		if (str && *str)
189201530Simp			oct_write8_x8(ptr, *str++);
190201530Simp		else
191201530Simp			oct_write8_x8(ptr, ' ');
192201530Simp		oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
193201530Simp	}
194194140Simp}
195194140Simp
196194140Simpstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'};
197194140Simp
198201530Simpvoid
199201530Simpocteon_led_run_wheel(int *prog_count, int led_position)
200194140Simp{
201201530Simp	if (!octeon_board_real())
202201530Simp		return;
203201530Simp	octeon_led_write_char(led_position, progress[*prog_count]);
204201530Simp	*prog_count += 1;
205201530Simp	*prog_count &= 0x7;
206194140Simp}
207194140Simp
208194140Simp#define LSR_DATAREADY        0x01    /* Data ready */
209194140Simp#define LSR_THRE             0x20    /* Transmit holding register empty */
210194140Simp#define LSR_TEMT	     0x40    /* Transmitter Empty. THR, TSR & FIFO */
211194140Simp#define USR_TXFIFO_NOTFULL   0x02    /* Uart TX FIFO Not full */
212194140Simp
213194140Simp/*
214194140Simp * octeon_uart_write_byte
215194140Simp *
216194140Simp * Put out a single byte off of uart port.
217194140Simp */
218194140Simp
219201530Simpvoid
220201530Simpocteon_uart_write_byte(int uart_index, uint8_t ch)
221194140Simp{
222201530Simp	uint64_t val, val2;
223201530Simp	if (uart_index < 0 || uart_index > 1)
224201530Simp		return;
225194140Simp
226201530Simp	while (1) {
227201530Simp		val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
228201530Simp		val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400));
229201530Simp		if ((((uint8_t) val) & LSR_THRE) ||
230201530Simp		    (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
231201530Simp			break;
232201530Simp		}
233201530Simp	}
234194140Simp
235201530Simp	/* Write the byte */
236201530Simp	oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch);
237194140Simp
238201530Simp	/* Force Flush the IOBus */
239201530Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
240194140Simp}
241194140Simp
242194140Simp
243201530Simpvoid
244201530Simpocteon_uart_write_byte0(uint8_t ch)
245194140Simp{
246201530Simp	uint64_t val, val2;
247194140Simp
248201530Simp	while (1) {
249201530Simp		val = oct_read64(OCTEON_MIO_UART0_LSR);
250201530Simp		val2 = oct_read64(OCTEON_MIO_UART0_USR);
251201530Simp		if ((((uint8_t) val) & LSR_THRE) ||
252201530Simp		    (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) {
253201530Simp			break;
254201530Simp		}
255201530Simp	}
256194140Simp
257201530Simp	/* Write the byte */
258201530Simp	oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch);
259194140Simp
260201530Simp	/* Force Flush the IOBus */
261201530Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
262194140Simp}
263194140Simp
264194140Simp/*
265194140Simp * octeon_uart_write_string
266194140Simp *
267194140Simp */
268201530Simpvoid
269201530Simpocteon_uart_write_string(int uart_index, const char *str)
270194140Simp{
271201530Simp	/* Just loop writing one byte at a time */
272194140Simp
273201530Simp	while (*str) {
274201530Simp		octeon_uart_write_byte(uart_index, *str);
275201530Simp		if (*str == '\n') {
276201530Simp			octeon_uart_write_byte(uart_index, '\r');
277201530Simp		}
278201530Simp		str++;
279201530Simp	}
280201530Simp}
281194140Simp
282194140Simpstatic char wstr[30];
283194140Simp
284201530Simpvoid
285201530Simpocteon_led_write_hex(uint32_t wl)
286194140Simp{
287201530Simp	char nbuf[80];
288194140Simp
289201530Simp	sprintf(nbuf, "%X", wl);
290201530Simp	octeon_led_write_string(nbuf);
291194140Simp}
292194140Simp
293194140Simp
294201530Simpvoid octeon_uart_write_hex2(uint32_t wl, uint32_t wh)
295194140Simp{
296201530Simp	sprintf(wstr, "0x%X-0x%X  ", wh, wl);
297201530Simp	octeon_uart_write_string(0, wstr);
298194140Simp}
299194140Simp
300201530Simpvoid
301201530Simpocteon_uart_write_hex(uint32_t wl)
302194140Simp{
303201530Simp	sprintf(wstr, " 0x%X  ", wl);
304201530Simp	octeon_uart_write_string(0, wstr);
305194140Simp}
306194140Simp
307194140Simp/*
308194140Simp * octeon_wait_uart_flush
309194140Simp */
310201530Simpvoid
311201530Simpocteon_wait_uart_flush(int uart_index, uint8_t ch)
312194140Simp{
313201530Simp	uint64_t val;
314201530Simp	int64_t val3;
315201530Simp	uint32_t cpu_status_bits;
316194140Simp
317201530Simp	if (uart_index < 0 || uart_index > 1)
318201530Simp		return;
319194140Simp
320201530Simp	cpu_status_bits = octeon_disable_interrupts();
321201530Simp	/* Force Flush the IOBus */
322201530Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
323201530Simp	for (val3 = 0xfffffffff; val3 > 0; val3--) {
324201530Simp		val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400));
325201530Simp		if (((uint8_t) val) & LSR_TEMT)
326201530Simp			break;
327201530Simp	}
328201530Simp	octeon_set_interrupts(cpu_status_bits);
329194140Simp}
330194140Simp
331194140Simp
332194140Simp/*
333194140Simp * octeon_debug_symbol
334194140Simp *
335194140Simp * Does nothing.
336194140Simp * Used to mark the point for simulator to begin tracing
337194140Simp */
338201530Simpvoid
339201530Simpocteon_debug_symbol(void)
340194140Simp{
341194140Simp}
342194140Simp
343201530Simpvoid
344201530Simpocteon_ciu_stop_gtimer(int timer)
345194140Simp{
346201530Simp	oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll);
347194140Simp}
348194140Simp
349201530Simpvoid
350201530Simpocteon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles)
351194140Simp{
352194140Simp    	octeon_ciu_gentimer gentimer;
353194140Simp
354194140Simp        gentimer.word64 = 0;
355194140Simp        gentimer.bits.one_shot = one_shot;
356194140Simp        gentimer.bits.len = time_cycles - 1;
357194140Simp        oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64);
358194140Simp}
359194140Simp
360194140Simp/*
361194140Simp * octeon_ciu_reset
362194140Simp *
363194140Simp * Shutdown all CIU to IP2, IP3 mappings
364194140Simp */
365201530Simpvoid
366201530Simpocteon_ciu_reset(void)
367194140Simp{
368194140Simp
369201530Simp	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0);
370201530Simp	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1);
371201530Simp	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2);
372201530Simp	octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3);
373194140Simp
374201530Simp	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0);
375201530Simp	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1);
376201530Simp	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0);
377201530Simp	ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1);
378194140Simp
379201530Simp	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll);
380201530Simp	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll);
381201530Simp	ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll);
382194140Simp}
383194140Simp
384194140Simp/*
385194140Simp * mips_disable_interrupt_controllers
386194140Simp *
387194140Simp * Disable interrupts in the CPU controller
388194140Simp */
389201530Simpvoid
390201530Simpmips_disable_interrupt_controls(void)
391194140Simp{
392201530Simp	/*
393201530Simp	 * Disable interrupts in CIU.
394201530Simp	 */
395201530Simp	octeon_ciu_reset();
396194140Simp}
397194140Simp
398194140Simp/*
399194140Simp * ciu_get_intr_sum_reg_addr
400194140Simp */
401201530Simpstatic uint64_t
402201530Simpciu_get_intr_sum_reg_addr(int core_num, int intx, int enx)
403194140Simp{
404201530Simp	uint64_t ciu_intr_sum_reg_addr;
405194140Simp
406201530Simp    	if (enx == CIU_EN_0)
407201530Simp            	ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR +
408201530Simp		    (core_num * 0x10) + (intx * 0x8);
409201530Simp	else
410194140Simp            	ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR;
411194140Simp
412194140Simp        return (ciu_intr_sum_reg_addr);
413194140Simp}
414194140Simp
415194140Simp
416194140Simp/*
417194140Simp * ciu_get_intr_en_reg_addr
418194140Simp */
419201530Simpstatic uint64_t
420201530Simpciu_get_intr_en_reg_addr(int core_num, int intx, int enx)
421194140Simp{
422201530Simp	uint64_t ciu_intr_reg_addr;
423194140Simp
424201530Simp    	ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR +
425201530Simp	    ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) +  (core_num * 0x20);
426194140Simp        return (ciu_intr_reg_addr);
427194140Simp}
428194140Simp
429194140Simp
430194140Simp
431194140Simp
432194140Simp/*
433194140Simp * ciu_get_intr_reg_addr
434194140Simp *
435194140Simp * 200 ---int0,en0 ip2
436194140Simp * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog
437194140Simp *
438194140Simp * 210 ---int0,en0 ip3 --
439194140Simp * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right?
440194140Simp *
441194140Simp * 220 ---int1,en0 ip2
442194140Simp * 228 ---int1,en1 ip2
443194140Simp * 230 ---int1,en0 ip3 --
444194140Simp * 238 ---int1,en1 ip3
445194140Simp *
446194140Simp */
447201530Simpuint64_t
448201530Simpciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip)
449194140Simp{
450201530Simp	uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR;
451194140Simp
452201530Simp	/* XXX kasserts? */
453201530Simp	if (enx < CIU_EN_0 || enx > CIU_EN_1) {
454201530Simp		printf("%s: invalid enx value %d, should be %d or %d\n",
455201530Simp		    __FUNCTION__, enx, CIU_EN_0, CIU_EN_1);
456201530Simp		return 0;
457201530Simp	}
458201530Simp	if (intx < CIU_INT_0 || intx > CIU_INT_1) {
459201530Simp		printf("%s: invalid intx value %d, should be %d or %d\n",
460201530Simp		    __FUNCTION__, enx, CIU_INT_0, CIU_INT_1);
461201530Simp		return 0;
462201530Simp	}
463201530Simp	if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) {
464201530Simp		printf("%s: invalid ciu_ip value %d, should be %d or %d\n",
465201530Simp		    __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3);
466201530Simp		return 0;
467201530Simp	}
468194140Simp
469201530Simp	ciu_intr_reg_addr += (enx    * 0x8);
470201530Simp	ciu_intr_reg_addr += (ciu_ip * 0x10);
471201530Simp	ciu_intr_reg_addr += (intx   * 0x20);
472201530Simp	return (ciu_intr_reg_addr);
473194140Simp}
474194140Simp
475194140Simp/*
476194140Simp * ciu_get_int_summary
477194140Simp */
478201530Simpuint64_t
479201530Simpciu_get_int_summary(int core_num, int intx, int enx)
480194140Simp{
481201530Simp	uint64_t ciu_intr_sum_reg_addr;
482194140Simp
483201530Simp	if (core_num == CIU_THIS_CORE)
484194140Simp        	core_num = octeon_get_core_num();
485201530Simp	ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
486201530Simp	return (oct_read64(ciu_intr_sum_reg_addr));
487194140Simp}
488194140Simp
489194140Simp//#define DEBUG_CIU 1
490194140Simp
491194140Simp#ifdef DEBUG_CIU
492194140Simp#define DEBUG_CIU_SUM 1
493194140Simp#define DEBUG_CIU_EN 1
494194140Simp#endif
495194140Simp
496194140Simp
497194140Simp/*
498194140Simp * ciu_clear_int_summary
499194140Simp */
500201530Simpvoid
501201530Simpciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits)
502194140Simp{
503201530Simp	uint32_t cpu_status_bits;
504201530Simp	uint64_t ciu_intr_sum_reg_addr;
505194140Simp
506194140Simp//#define DEBUG_CIU_SUM 1
507194140Simp
508194140Simp#ifdef DEBUG_CIU_SUM
509201530Simp	uint64_t ciu_intr_sum_bits;
510194140Simp#endif
511194140Simp
512194140Simp
513201530Simp	if (core_num == CIU_THIS_CORE) {
514194140Simp        	core_num = octeon_get_core_num();
515201530Simp	}
516194140Simp
517194140Simp#ifdef DEBUG_CIU_SUM
518194140Simp        printf(" CIU: core %u clear sum IntX %u  Enx %u  Bits: 0x%llX\n",
519201530Simp	    core_num, intx, enx, write_bits);
520194140Simp#endif
521194140Simp
522201530Simp	cpu_status_bits = octeon_disable_interrupts();
523194140Simp
524201530Simp	ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
525194140Simp
526194140Simp#ifdef DEBUG_CIU_SUM
527194140Simp    	ciu_intr_sum_bits =  oct_read64(ciu_intr_sum_reg_addr);	/* unneeded dummy read */
528194140Simp        printf(" CIU: status: 0x%X  reg_addr: 0x%llX   Val: 0x%llX   ->  0x%llX",
529201530Simp	    cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits,
530201530Simp	    ciu_intr_sum_bits | write_bits);
531194140Simp#endif
532194140Simp
533201530Simp	oct_write64(ciu_intr_sum_reg_addr, write_bits);
534201530Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
535194140Simp
536194140Simp#ifdef DEBUG_CIU_SUM
537194140Simp        printf(" Readback: 0x%llX\n\n   ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr));
538194140Simp#endif
539194140Simp
540201530Simp	octeon_set_interrupts(cpu_status_bits);
541194140Simp}
542194140Simp
543194140Simp/*
544194140Simp * ciu_disable_intr
545194140Simp */
546201530Simpvoid
547201530Simpciu_disable_intr(int core_num, int intx, int enx)
548194140Simp{
549201530Simp	uint32_t cpu_status_bits;
550201530Simp	uint64_t ciu_intr_reg_addr;
551194140Simp
552201530Simp	if (core_num == CIU_THIS_CORE)
553194140Simp        	core_num = octeon_get_core_num();
554194140Simp
555201530Simp	cpu_status_bits = octeon_disable_interrupts();
556194140Simp
557201530Simp	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
558194140Simp
559201530Simp	oct_read64(ciu_intr_reg_addr);	/* Dummy read */
560194140Simp
561201530Simp	oct_write64(ciu_intr_reg_addr, 0LL);
562201530Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
563194140Simp
564201530Simp	octeon_set_interrupts(cpu_status_bits);
565194140Simp}
566194140Simp
567201530Simpvoid
568201530Simpciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip)
569194140Simp{
570194140Simp
571194140Simp	uint64_t ciu_intr_reg_addr;
572194140Simp	uint64_t ciu_intr_bits;
573194140Simp
574194140Simp        if (core_num == CIU_THIS_CORE) {
575194140Simp            	core_num = octeon_get_core_num();
576194140Simp        }
577194140Simp
578194140Simp#ifndef OCTEON_SMP_1
579194140Simp	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
580194140Simp#else
581194140Simp	ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
582194140Simp#endif
583194140Simp
584194140Simp        if (!ciu_intr_reg_addr) {
585194140Simp            printf("Bad call to %s\n", __FUNCTION__);
586194140Simp            while(1);
587194140Simp            return;
588194140Simp        }
589194140Simp
590194140Simp	ciu_intr_bits =  oct_read64(ciu_intr_reg_addr);
591199593Simp        printf(" CIU core %d  int: %d  en: %d  ip: %d  Add: %#llx  enabled: %#llx  SR: %x\n",
592199593Simp	    core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr,
593195414Simp	    (unsigned long long)ciu_intr_bits, mips_rd_status());
594194140Simp}
595194140Simp
596194140Simp
597194140Simp/*
598194140Simp * ciu_enable_interrupts
599194140Simp */
600201530Simpvoid ciu_enable_interrupts(int core_num, int intx, int enx,
601201530Simp    uint64_t set_these_interrupt_bits, int ciu_ip)
602194140Simp{
603194140Simp	uint32_t cpu_status_bits;
604194140Simp	uint64_t ciu_intr_reg_addr;
605194140Simp	uint64_t ciu_intr_bits;
606194140Simp
607201530Simp        if (core_num == CIU_THIS_CORE)
608194140Simp            	core_num = octeon_get_core_num();
609194140Simp
610194140Simp//#define DEBUG_CIU_EN 1
611194140Simp
612194140Simp#ifdef DEBUG_CIU_EN
613194140Simp        printf(" CIU: core %u enabling Intx %u  Enx %u IP %d  Bits: 0x%llX\n",
614201530Simp	    core_num, intx, enx, ciu_ip, set_these_interrupt_bits);
615194140Simp#endif
616194140Simp
617194140Simp	cpu_status_bits = octeon_disable_interrupts();
618194140Simp
619194140Simp#ifndef OCTEON_SMP_1
620194140Simp	ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
621194140Simp#else
622194140Simp	ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
623194140Simp#endif
624194140Simp
625194140Simp        if (!ciu_intr_reg_addr) {
626201530Simp		printf("Bad call to %s\n", __FUNCTION__);
627201530Simp		while(1);
628201530Simp		return;	/* XXX */
629194140Simp        }
630194140Simp
631194140Simp	ciu_intr_bits =  oct_read64(ciu_intr_reg_addr);
632194140Simp
633194140Simp#ifdef DEBUG_CIU_EN
634194140Simp        printf(" CIU: status: 0x%X  reg_addr: 0x%llX   Val: 0x%llX   ->  0x%llX",
635201530Simp	    cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits);
636194140Simp#endif
637194140Simp	ciu_intr_bits |=  set_these_interrupt_bits;
638194140Simp	oct_write64(ciu_intr_reg_addr, ciu_intr_bits);
639194140Simp#ifdef OCTEON_SMP
640194140Simp	mips_wbflush();
641194140Simp#endif
642194140Simp	oct_read64(OCTEON_MIO_BOOT_BIST_STAT);	/* Bus Barrier */
643194140Simp
644194140Simp#ifdef DEBUG_CIU_EN
645201530Simp        printf(" Readback: 0x%llX\n\n   ",
646201530Simp	    (uint64_t)oct_read64(ciu_intr_reg_addr));
647194140Simp#endif
648194140Simp
649194140Simp	octeon_set_interrupts(cpu_status_bits);
650194140Simp}
651194140Simp
652202831Simpunsigned long
653202831Simpocteon_get_clock_rate(void)
654202831Simp{
655202831Simp	return octeon_cpu_clock;
656202831Simp}
657202831Simp
658202831Simpstatic void
659202831Simpocteon_memory_init(void)
660202831Simp{
661202831Simp	uint32_t realmem_bytes;
662202831Simp
663202831Simp	if (octeon_board_real()) {
664202831Simp		printf("octeon_dram == %llx\n", octeon_dram);
665202831Simp		printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20);
666202831Simp
667202831Simp		realmem_bytes = (octeon_dram - PAGE_SIZE);
668202831Simp		realmem_bytes &= ~(PAGE_SIZE - 1);
669202831Simp		printf("Real memory bytes is %x\n", realmem_bytes);
670202831Simp	} else {
671202831Simp		/* Simulator we limit to 96 meg */
672202831Simp		realmem_bytes = (96 << 20);
673202831Simp	}
674202831Simp	/* phys_avail regions are in bytes */
675202831Simp	phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1);
676202831Simp	if (octeon_board_real()) {
677202831Simp		if (realmem_bytes > OCTEON_DRAM_FIRST_256_END)
678202831Simp			phys_avail[1] = OCTEON_DRAM_FIRST_256_END;
679202831Simp		else
680202831Simp			phys_avail[1] = realmem_bytes;
681202831Simp		realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
682202831Simp		realmem_bytes &= ~(PAGE_SIZE - 1);
683202831Simp		printf("phys_avail[0] = %x phys_avail[1] = %x\n",
684202831Simp		    phys_avail[0], phys_avail[1]);
685202831Simp	} else {
686202831Simp		/* Simulator gets 96Meg period. */
687202831Simp		phys_avail[1] = (96 << 20);
688202831Simp	}
689202831Simp	/*-
690202831Simp	 * Octeon Memory looks as follows:
691202831Simp         *   PA
692202831Simp	 * 0000 0000 to                                       0x0 0000 0000 0000
693202831Simp	 * 0FFF FFFF      First 256 MB memory   Maps to       0x0 0000 0FFF FFFF
694202831Simp	 *
695202831Simp	 * 1000 0000 to                                       0x1 0000 1000 0000
696202831Simp	 * 1FFF FFFF      Uncached Bu I/O space.converted to  0x1 0000 1FFF FFFF
697202831Simp	 *
698202831Simp	 * 2FFF FFFF to            Cached                     0x0 0000 2000 0000
699202831Simp	 * FFFF FFFF      all dram mem above the first 512M   0x3 FFFF FFFF FFFF
700202831Simp	 *
701202831Simp	 */
702202831Simp	physmem = btoc(phys_avail[1] - phys_avail[0]);
703202831Simp	if ((octeon_board_real()) &&
704202831Simp	    (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) {
705202831Simp		/* take out the upper non-cached 1/2 */
706202831Simp		realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
707202831Simp		realmem_bytes &= ~(PAGE_SIZE - 1);
708202831Simp		/* Now map the rest of the memory */
709202831Simp		phys_avail[2] = 0x20000000;
710202831Simp		printf("realmem_bytes is now at %x\n", realmem_bytes);
711202831Simp		phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes);
712202831Simp		printf("Next block of memory goes from %x to %x\n",
713202831Simp		    phys_avail[2], phys_avail[3]);
714202831Simp		physmem += btoc(phys_avail[3] - phys_avail[2]);
715202831Simp	} else {
716202831Simp		printf("realmem_bytes is %d\n", realmem_bytes);
717202831Simp	}
718202831Simp	realmem = physmem;
719202831Simp
720202831Simp	printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram);
721202831Simp	printf("\nBank 0 = 0x%8X   ->  0x%8X", phys_avail[0], phys_avail[1]);
722202831Simp	printf("\nBank 1 = 0x%8X   ->  0x%8X\n", phys_avail[2], phys_avail[3]);
723202831Simp	printf("\nphysmem: 0x%lx", physmem);
724202831Simp
725202831Simp	Maxmem = physmem;
726202831Simp
727202831Simp}
728202831Simp
729196262Simpvoid
730201530Simpplatform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
731201530Simp    __register_t a3)
732196262Simp{
733196262Simp	uint64_t platform_counter_freq;
734194140Simp
735201845Simp	/* Initialize pcpu stuff */
736201881Simp	mips_pcpu0_init();
737202831Simp	mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
738202831Simp	cninit();
739201845Simp
740202831Simp	octeon_ciu_reset();
741200344Simp	octeon_boot_params_init(a3);
742196262Simp	bootverbose = 1;
743202831Simp	cpuid_to_pcpu[0] = &pcpu0;
744194140Simp
745202831Simp	/*
746202831Simp	 * For some reason on the cn38xx simulator ebase register is set to
747202831Simp	 * 0x80001000 at bootup time.  Move it back to the default, but
748202831Simp	 * when we move to having support for multiple executives, we need
749202831Simp	 * to rethink this.
750202831Simp	 */
751202831Simp	mips_wr_ebase(0x80000000);
752196262Simp
753202831Simp	octeon_memory_init();
754196262Simp	init_param1();
755196262Simp	init_param2(physmem);
756196262Simp	mips_cpu_init();
757202831Simp	pmap_bootstrap();
758202831Simp	mips_proc0_init();
759196262Simp	mutex_init();
760196262Simp	kdb_init();
761202850Simp#ifdef KDB
762202850Simp	if (boothowto & RB_KDB)
763202850Simp		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
764196262Simp#endif
765202831Simp	platform_counter_freq = octeon_get_clock_rate();
766202831Simp	mips_timer_init_params(platform_counter_freq, 1);
767196262Simp}
768196262Simp
769202831Simp/* impSTART: This stuff should move back into the Cavium SDK */
770194140Simp/*
771194140Simp ****************************************************************************************
772194140Simp *
773194140Simp * APP/BOOT  DESCRIPTOR  STUFF
774194140Simp *
775194140Simp ****************************************************************************************
776194140Simp */
777194140Simp
778194140Simp/* Define the struct that is initialized by the bootloader used by the
779194140Simp * startup code.
780194140Simp *
781194140Simp * Copyright (c) 2004, 2005, 2006 Cavium Networks.
782194140Simp *
783194140Simp * The authors hereby grant permission to use, copy, modify, distribute,
784194140Simp * and license this software and its documentation for any purpose, provided
785194140Simp * that existing copyright notices are retained in all copies and that this
786194140Simp * notice is included verbatim in any distributions. No written agreement,
787194140Simp * license, or royalty fee is required for any of the authorized uses.
788194140Simp * Modifications to this software may be copyrighted by their authors
789194140Simp * and need not follow the licensing terms described here, provided that
790194140Simp * the new terms are clearly indicated on the first page of each file where
791194140Simp * they apply.
792194140Simp */
793194140Simp
794194140Simp#define OCTEON_CURRENT_DESC_VERSION     6
795194140Simp#define OCTEON_ARGV_MAX_ARGS            (64)
796194140Simp#define OCTOEN_SERIAL_LEN 20
797194140Simp
798194140Simp
799194140Simptypedef struct {
800200344Simp	/* Start of block referenced by assembly code - do not change! */
801200344Simp	uint32_t desc_version;
802200344Simp	uint32_t desc_size;
803194140Simp
804200344Simp	uint64_t stack_top;
805200344Simp	uint64_t heap_base;
806200344Simp	uint64_t heap_end;
807200344Simp	uint64_t entry_point;   /* Only used by bootloader */
808200344Simp	uint64_t desc_vaddr;
809200344Simp	/* End of This block referenced by assembly code - do not change! */
810194140Simp
811200344Simp	uint32_t exception_base_addr;
812200344Simp	uint32_t stack_size;
813200344Simp	uint32_t heap_size;
814200344Simp	uint32_t argc;  /* Argc count for application */
815200344Simp	uint32_t argv[OCTEON_ARGV_MAX_ARGS];
816200344Simp	uint32_t flags;
817200344Simp	uint32_t core_mask;
818200344Simp	uint32_t dram_size;  /**< DRAM size in megabyes */
819200344Simp	uint32_t phy_mem_desc_addr;  /**< physical address of free memory descriptor block*/
820200344Simp	uint32_t debugger_flags_base_addr;  /**< used to pass flags from app to debugger */
821200344Simp	uint32_t eclock_hz;  /**< CPU clock speed, in hz */
822200344Simp	uint32_t dclock_hz;  /**< DRAM clock speed, in hz */
823200344Simp	uint32_t spi_clock_hz;  /**< SPI4 clock in hz */
824200344Simp	uint16_t board_type;
825200344Simp	uint8_t board_rev_major;
826200344Simp	uint8_t board_rev_minor;
827200344Simp	uint16_t chip_type;
828200344Simp	uint8_t chip_rev_major;
829200344Simp	uint8_t chip_rev_minor;
830200344Simp	char board_serial_number[OCTOEN_SERIAL_LEN];
831200344Simp	uint8_t mac_addr_base[6];
832200344Simp	uint8_t mac_addr_count;
833200344Simp	uint64_t cvmx_desc_vaddr;
834194140Simp} octeon_boot_descriptor_t;
835194140Simp
836194140Simp
837194140Simptypedef struct {
838200344Simp	uint32_t major_version;
839200344Simp	uint32_t minor_version;
840194140Simp
841200344Simp	uint64_t stack_top;
842200344Simp	uint64_t heap_base;
843200344Simp	uint64_t heap_end;
844200344Simp	uint64_t desc_vaddr;
845194140Simp
846200344Simp	uint32_t exception_base_addr;
847200344Simp	uint32_t stack_size;
848200344Simp	uint32_t flags;
849200344Simp	uint32_t core_mask;
850200344Simp	uint32_t dram_size;  /**< DRAM size in megabyes */
851200344Simp	uint32_t phy_mem_desc_addr;  /**< physical address of free memory descriptor block*/
852200344Simp	uint32_t debugger_flags_base_addr;  /**< used to pass flags from app to debugger */
853200344Simp	uint32_t eclock_hz;  /**< CPU clock speed, in hz */
854200344Simp	uint32_t dclock_hz;  /**< DRAM clock speed, in hz */
855200344Simp	uint32_t spi_clock_hz;  /**< SPI4 clock in hz */
856200344Simp	uint16_t board_type;
857200344Simp	uint8_t board_rev_major;
858200344Simp	uint8_t board_rev_minor;
859200344Simp	uint16_t chip_type;
860200344Simp	uint8_t chip_rev_major;
861200344Simp	uint8_t chip_rev_minor;
862200344Simp	char board_serial_number[OCTOEN_SERIAL_LEN];
863200344Simp	uint8_t mac_addr_base[6];
864200344Simp	uint8_t mac_addr_count;
865194140Simp} cvmx_bootinfo_t;
866194140Simp
867194140Simpuint32_t octeon_cpu_clock;
868194140Simpuint64_t octeon_dram;
869194140Simpuint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type;
870194140Simpuint8_t octeon_mac_addr[6] = { 0 };
871194140Simpint octeon_core_mask, octeon_mac_addr_count;
872194140Simpint octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0;
873194140Simp
874194140Simpstatic octeon_boot_descriptor_t *app_desc_ptr;
875194140Simpstatic cvmx_bootinfo_t *cvmx_desc_ptr;
876194140Simp
877194140Simp#define OCTEON_BOARD_TYPE_NONE 0
878194140Simp#define OCTEON_BOARD_TYPE_SIM  1
879194140Simp
880194140Simp#define OCTEON_CLOCK_MIN     (100 * 1000 * 1000)
881194140Simp#define OCTEON_CLOCK_MAX     (800 * 1000 * 1000)
882194140Simp#define OCTEON_DRAM_DEFAULT  (256 * 1024 * 1024)
883194140Simp#define OCTEON_DRAM_MIN	     30
884194140Simp#define OCTEON_DRAM_MAX	     3000
885194140Simp
886194140Simp
887200344Simpint
888200344Simpocteon_board_real(void)
889194140Simp{
890200344Simp	if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) ||
891200344Simp	    (octeon_board_type == OCTEON_BOARD_TYPE_SIM) ||
892200344Simp	    !octeon_board_rev_major)
893200344Simp		return 0;
894200344Simp	return 1;
895194140Simp}
896194140Simp
897200344Simpstatic void
898200344Simpocteon_process_app_desc_ver_unknown(void)
899194140Simp{
900194140Simp    	printf(" Unknown Boot-Descriptor: Using Defaults\n");
901194140Simp
902194140Simp    	octeon_cpu_clock = OCTEON_CLOCK_DEFAULT;
903194140Simp        octeon_dram = OCTEON_DRAM_DEFAULT;
904194140Simp        octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0;
905194140Simp        octeon_core_mask = 1;
906194140Simp        octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0;
907194140Simp        octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f;
908194140Simp        octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10;
909194140Simp        octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06;
910194140Simp        octeon_mac_addr_count = 1;
911194140Simp}
912194140Simp
913200344Simpstatic int
914200344Simpocteon_process_app_desc_ver_6(void)
915194140Simp{
916200344Simp	/* XXX Why is 0x00000000ffffffffULL a bad value?  */
917200344Simp	if (app_desc_ptr->cvmx_desc_vaddr == 0 ||
918200344Simp	    app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) {
919194174Simp            	printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr);
920194140Simp                return 1;
921200344Simp	}
922200344Simp    	cvmx_desc_ptr =
923200344Simp	    (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr;
924200344Simp        cvmx_desc_ptr =
925200344Simp	    (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START);
926194140Simp        octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) +
927200344Simp	    cvmx_desc_ptr->minor_version;
928194140Simp        if (cvmx_desc_ptr->major_version != 1) {
929202831Simp            	panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n",
930194140Simp                       (int) cvmx_desc_ptr->major_version,
931194140Simp                       (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr);
932194140Simp        }
933194140Simp
934194140Simp        octeon_core_mask = cvmx_desc_ptr->core_mask;
935194140Simp        octeon_cpu_clock  = cvmx_desc_ptr->eclock_hz;
936194140Simp        octeon_board_type = cvmx_desc_ptr->board_type;
937194140Simp        octeon_board_rev_major = cvmx_desc_ptr->board_rev_major;
938194140Simp        octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor;
939194140Simp        octeon_chip_type = cvmx_desc_ptr->chip_type;
940194140Simp        octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major;
941194140Simp        octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor;
942194140Simp        octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0];
943194140Simp        octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1];
944194140Simp        octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2];
945194140Simp        octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3];
946194140Simp        octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4];
947194140Simp        octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5];
948194140Simp        octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count;
949194140Simp
950200344Simp        if (app_desc_ptr->dram_size > 16*1024*1024)
951194140Simp            	octeon_dram = (uint64_t)app_desc_ptr->dram_size;
952200344Simp	else
953200344Simp            	octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20;
954194140Simp        return 0;
955194140Simp}
956194140Simp
957200344Simpstatic void
958200344Simpocteon_boot_params_init(register_t ptr)
959194140Simp{
960200344Simp	int bad_desc = 1;
961202831Simp
962200344Simp    	if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) {
963200344Simp	        app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
964194140Simp		octeon_bd_ver = app_desc_ptr->desc_version;
965202831Simp		if (app_desc_ptr->desc_version == 6)
966200344Simp			bad_desc = octeon_process_app_desc_ver_6();
967194140Simp        }
968200344Simp        if (bad_desc)
969194140Simp        	octeon_process_app_desc_ver_unknown();
970194140Simp
971194140Simp        printf("Boot Descriptor Ver: %u -> %u/%u",
972194140Simp               octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100);
973194140Simp        printf("  CPU clock: %uMHz\n", octeon_cpu_clock/1000000);
974194140Simp        printf("  Dram: %u MB", (uint32_t)(octeon_dram >> 20));
975194140Simp        printf("  Board Type: %u  Revision: %u/%u\n",
976194140Simp               octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor);
977194140Simp        printf("  Octeon Chip: %u  Rev %u/%u",
978194140Simp               octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor);
979194140Simp
980202831Simp        printf("  Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n",
981202831Simp	    octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2],
982202831Simp	    octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5],
983202831Simp	    octeon_mac_addr_count);
984194140Simp}
985202831Simp/* impEND: This stuff should move back into the Cavium SDK */
986