octeon_machdep.c revision 216069
1209878Snwhitehorn/*-
2209878Snwhitehorn * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
3209878Snwhitehorn * All rights reserved.
4209878Snwhitehorn *
5209878Snwhitehorn * Redistribution and use in source and binary forms, with or without
6209878Snwhitehorn * modification, are permitted provided that the following conditions
7209878Snwhitehorn * are met:
8209878Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9209878Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10209878Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11209878Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12209878Snwhitehorn *    documentation and/or other materials provided with the distribution.
13209878Snwhitehorn *
14209878Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15209878Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16209878Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17209878Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18209878Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19209878Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20209878Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21209878Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22209878Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23209878Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24209878Snwhitehorn * SUCH DAMAGE.
25209878Snwhitehorn *
26209878Snwhitehorn * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 216069 2010-11-30 01:27:54Z jmallett $
27209878Snwhitehorn */
28209878Snwhitehorn#include <sys/cdefs.h>
29209878Snwhitehorn__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 216069 2010-11-30 01:27:54Z jmallett $");
30209878Snwhitehorn
31209878Snwhitehorn#include <sys/param.h>
32209878Snwhitehorn#include <sys/conf.h>
33209878Snwhitehorn#include <sys/kernel.h>
34209878Snwhitehorn#include <sys/systm.h>
35209878Snwhitehorn#include <sys/imgact.h>
36209878Snwhitehorn#include <sys/bio.h>
37209878Snwhitehorn#include <sys/buf.h>
38209878Snwhitehorn#include <sys/bus.h>
39209878Snwhitehorn#include <sys/cpu.h>
40209878Snwhitehorn#include <sys/cons.h>
41209878Snwhitehorn#include <sys/exec.h>
42209878Snwhitehorn#include <sys/ucontext.h>
43209878Snwhitehorn#include <sys/proc.h>
44209878Snwhitehorn#include <sys/kdb.h>
45209878Snwhitehorn#include <sys/ptrace.h>
46209878Snwhitehorn#include <sys/reboot.h>
47209878Snwhitehorn#include <sys/signalvar.h>
48209878Snwhitehorn#include <sys/sysent.h>
49209878Snwhitehorn#include <sys/sysproto.h>
50209878Snwhitehorn#include <sys/time.h>
51209878Snwhitehorn#include <sys/timetc.h>
52209878Snwhitehorn#include <sys/user.h>
53209878Snwhitehorn
54209878Snwhitehorn#include <vm/vm.h>
55209878Snwhitehorn#include <vm/vm_object.h>
56209878Snwhitehorn#include <vm/vm_page.h>
57209878Snwhitehorn#include <vm/vm_pager.h>
58209878Snwhitehorn
59209878Snwhitehorn#include <machine/atomic.h>
60209878Snwhitehorn#include <machine/cache.h>
61209878Snwhitehorn#include <machine/clock.h>
62209878Snwhitehorn#include <machine/cpu.h>
63209878Snwhitehorn#include <machine/cpuregs.h>
64209878Snwhitehorn#include <machine/cpufunc.h>
65209878Snwhitehorn#include <mips/cavium/octeon_pcmap_regs.h>
66209878Snwhitehorn#include <machine/hwfunc.h>
67209878Snwhitehorn#include <machine/intr_machdep.h>
68209878Snwhitehorn#include <machine/locore.h>
69209878Snwhitehorn#include <machine/md_var.h>
70209878Snwhitehorn#include <machine/pcpu.h>
71209878Snwhitehorn#include <machine/pte.h>
72209878Snwhitehorn#include <machine/trap.h>
73209878Snwhitehorn#include <machine/vmparam.h>
74209878Snwhitehorn
75209878Snwhitehorn#include <contrib/octeon-sdk/cvmx.h>
76209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-bootmem.h>
77209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-interrupt.h>
78209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-version.h>
79209878Snwhitehorn
80209878Snwhitehorn#if defined(__mips_n64)
81209878Snwhitehorn#define MAX_APP_DESC_ADDR     0xffffffffafffffff
82209878Snwhitehorn#else
83209878Snwhitehorn#define MAX_APP_DESC_ADDR     0xafffffff
84209878Snwhitehorn#endif
85209878Snwhitehorn
86209878Snwhitehorn#define OCTEON_CLOCK_DEFAULT (500 * 1000 * 1000)
87209878Snwhitehorn
88209878Snwhitehornstruct octeon_feature_description {
89209878Snwhitehorn	octeon_feature_t ofd_feature;
90209878Snwhitehorn	const char *ofd_string;
91209878Snwhitehorn};
92209878Snwhitehorn
93209878Snwhitehornextern int	*edata;
94209878Snwhitehornextern int	*end;
95209878Snwhitehorn
96209878Snwhitehornstatic const struct octeon_feature_description octeon_feature_descriptions[] = {
97209878Snwhitehorn	{ OCTEON_FEATURE_SAAD,			"SAAD" },
98209878Snwhitehorn	{ OCTEON_FEATURE_ZIP,			"ZIP" },
99209878Snwhitehorn	{ OCTEON_FEATURE_CRYPTO,		"CRYPTO" },
100209878Snwhitehorn	{ OCTEON_FEATURE_DORM_CRYPTO,		"DORM_CRYPTO" },
101209878Snwhitehorn	{ OCTEON_FEATURE_PCIE,			"PCIE" },
102209878Snwhitehorn	{ OCTEON_FEATURE_SRIO,			"SRIO" },
103209878Snwhitehorn	{ OCTEON_FEATURE_KEY_MEMORY,		"KEY_MEMORY" },
104209878Snwhitehorn	{ OCTEON_FEATURE_LED_CONTROLLER,	"LED_CONTROLLER" },
105209878Snwhitehorn	{ OCTEON_FEATURE_TRA,			"TRA" },
106209878Snwhitehorn	{ OCTEON_FEATURE_MGMT_PORT,		"MGMT_PORT" },
107209878Snwhitehorn	{ OCTEON_FEATURE_RAID,			"RAID" },
108209878Snwhitehorn	{ OCTEON_FEATURE_USB,			"USB" },
109209878Snwhitehorn	{ OCTEON_FEATURE_NO_WPTR,		"NO_WPTR" },
110209878Snwhitehorn	{ OCTEON_FEATURE_DFA,			"DFA" },
111209878Snwhitehorn	{ OCTEON_FEATURE_MDIO_CLAUSE_45,	"MDIO_CLAUSE_45" },
112209878Snwhitehorn	{ OCTEON_FEATURE_NPEI,			"NPEI" },
113209878Snwhitehorn	{ 0,					NULL }
114209878Snwhitehorn};
115209878Snwhitehorn
116209878Snwhitehornuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip);
117209878Snwhitehornvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip);
118209878Snwhitehorn
119209878Snwhitehornstatic uint64_t octeon_get_ticks(void);
120209878Snwhitehornstatic unsigned octeon_get_timecount(struct timecounter *tc);
121209878Snwhitehorn
122209878Snwhitehornstatic void octeon_boot_params_init(register_t ptr);
123209878Snwhitehorn
124209878Snwhitehornstatic struct timecounter octeon_timecounter = {
125209878Snwhitehorn	octeon_get_timecount,	/* get_timecount */
126209878Snwhitehorn	0,			/* no poll_pps */
127209878Snwhitehorn	0xffffffffu,		/* octeon_mask */
128209878Snwhitehorn	0,			/* frequency */
129209878Snwhitehorn	"Octeon",		/* name */
130209878Snwhitehorn	900,			/* quality (adjusted in code) */
131209878Snwhitehorn};
132209878Snwhitehorn
133209878Snwhitehornvoid
134209878Snwhitehornplatform_cpu_init()
135209878Snwhitehorn{
136209878Snwhitehorn	/* Nothing special yet */
137209878Snwhitehorn}
138209878Snwhitehorn
139209878Snwhitehorn/*
140209878Snwhitehorn * Perform a board-level soft-reset.
141209878Snwhitehorn */
142209878Snwhitehornvoid
143209878Snwhitehornplatform_reset(void)
144209878Snwhitehorn{
145209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_SOFT_RST, 1);
146209878Snwhitehorn}
147209878Snwhitehorn
148209878Snwhitehornvoid
149209878Snwhitehornocteon_led_write_char(int char_position, char val)
150209878Snwhitehorn{
151209878Snwhitehorn	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
152209878Snwhitehorn
153209878Snwhitehorn	if (octeon_is_simulation())
154209878Snwhitehorn		return;
155209878Snwhitehorn
156209878Snwhitehorn	char_position &= 0x7;  /* only 8 chars */
157209878Snwhitehorn	ptr += char_position;
158209878Snwhitehorn	oct_write8_x8(ptr, val);
159209878Snwhitehorn}
160209878Snwhitehorn
161209878Snwhitehornvoid
162209878Snwhitehornocteon_led_write_char0(char val)
163209878Snwhitehorn{
164209878Snwhitehorn	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
165209878Snwhitehorn
166209878Snwhitehorn	if (octeon_is_simulation())
167209878Snwhitehorn		return;
168209878Snwhitehorn	oct_write8_x8(ptr, val);
169209878Snwhitehorn}
170209878Snwhitehorn
171209878Snwhitehornvoid
172209878Snwhitehornocteon_led_write_hexchar(int char_position, char hexval)
173209878Snwhitehorn{
174209878Snwhitehorn	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
175209878Snwhitehorn	char char1, char2;
176209878Snwhitehorn
177209878Snwhitehorn	if (octeon_is_simulation())
178209878Snwhitehorn		return;
179209878Snwhitehorn
180209878Snwhitehorn	char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7';
181209878Snwhitehorn	char2 = (hexval  & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7';
182209878Snwhitehorn	char_position &= 0x7;  /* only 8 chars */
183209878Snwhitehorn	if (char_position > 6)
184209878Snwhitehorn		char_position = 6;
185209878Snwhitehorn	ptr += char_position;
186209878Snwhitehorn	oct_write8_x8(ptr, char1);
187209878Snwhitehorn	ptr++;
188209878Snwhitehorn	oct_write8_x8(ptr, char2);
189209878Snwhitehorn}
190209878Snwhitehorn
191209878Snwhitehornvoid
192209878Snwhitehornocteon_led_write_string(const char *str)
193209878Snwhitehorn{
194209878Snwhitehorn	uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
195209878Snwhitehorn	int i;
196209878Snwhitehorn
197209878Snwhitehorn	if (octeon_is_simulation())
198209878Snwhitehorn		return;
199209878Snwhitehorn
200209878Snwhitehorn	for (i=0; i<8; i++, ptr++) {
201209878Snwhitehorn		if (str && *str)
202209878Snwhitehorn			oct_write8_x8(ptr, *str++);
203209878Snwhitehorn		else
204209878Snwhitehorn			oct_write8_x8(ptr, ' ');
205209878Snwhitehorn		(void)cvmx_read_csr(CVMX_MIO_BOOT_BIST_STAT);
206209878Snwhitehorn	}
207209878Snwhitehorn}
208209878Snwhitehorn
209209878Snwhitehornstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'};
210209878Snwhitehorn
211209878Snwhitehornvoid
212209878Snwhitehornocteon_led_run_wheel(int *prog_count, int led_position)
213209878Snwhitehorn{
214209878Snwhitehorn	if (octeon_is_simulation())
215209878Snwhitehorn		return;
216209878Snwhitehorn	octeon_led_write_char(led_position, progress[*prog_count]);
217209878Snwhitehorn	*prog_count += 1;
218209878Snwhitehorn	*prog_count &= 0x7;
219209878Snwhitehorn}
220209878Snwhitehorn
221209878Snwhitehornvoid
222209878Snwhitehornocteon_led_write_hex(uint32_t wl)
223209878Snwhitehorn{
224209878Snwhitehorn	char nbuf[80];
225209878Snwhitehorn
226209878Snwhitehorn	sprintf(nbuf, "%X", wl);
227209878Snwhitehorn	octeon_led_write_string(nbuf);
228209878Snwhitehorn}
229209878Snwhitehorn
230209878Snwhitehorn/*
231209878Snwhitehorn * octeon_debug_symbol
232209878Snwhitehorn *
233209878Snwhitehorn * Does nothing.
234209878Snwhitehorn * Used to mark the point for simulator to begin tracing
235209878Snwhitehorn */
236209878Snwhitehornvoid
237209878Snwhitehornocteon_debug_symbol(void)
238209878Snwhitehorn{
239209878Snwhitehorn}
240209878Snwhitehorn
241209878Snwhitehorn/*
242209878Snwhitehorn * octeon_ciu_reset
243209878Snwhitehorn *
244209878Snwhitehorn * Shutdown all CIU to IP2, IP3 mappings
245209878Snwhitehorn */
246209878Snwhitehornvoid
247209878Snwhitehornocteon_ciu_reset(void)
248209878Snwhitehorn{
249209878Snwhitehorn	/* Disable all CIU interrupts by default */
250209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), 0);
251209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1), 0);
252209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), 0);
253209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2+1), 0);
254209878Snwhitehorn
255209878Snwhitehorn#ifdef SMP
256209878Snwhitehorn	/* Enable the MBOX interrupts.  */
257209878Snwhitehorn	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1),
258209878Snwhitehorn		       (1ull << (CVMX_IRQ_MBOX0 - 8)) |
259209878Snwhitehorn		       (1ull << (CVMX_IRQ_MBOX1 - 8)));
260209878Snwhitehorn#endif
261209878Snwhitehorn}
262209878Snwhitehorn
263209878Snwhitehornstatic void
264209878Snwhitehornocteon_memory_init(void)
265209878Snwhitehorn{
266209878Snwhitehorn	vm_paddr_t phys_end;
267209878Snwhitehorn	int64_t addr;
268209878Snwhitehorn	unsigned i;
269209878Snwhitehorn
270209878Snwhitehorn	phys_end = round_page(MIPS_KSEG0_TO_PHYS((vm_offset_t)&end));
271209878Snwhitehorn
272209878Snwhitehorn	if (octeon_is_simulation()) {
273209878Snwhitehorn		/* Simulator we limit to 96 meg */
274209878Snwhitehorn		phys_avail[0] = phys_end;
275209878Snwhitehorn		phys_avail[1] = 96 << 20;
276209878Snwhitehorn
277209878Snwhitehorn		realmem = physmem = btoc(phys_avail[1] - phys_avail[0]);
278209878Snwhitehorn		return;
279209878Snwhitehorn	}
280209878Snwhitehorn
281209878Snwhitehorn	/*
282209878Snwhitehorn	 * Allocate memory from bootmem 1MB at a time and merge
283209878Snwhitehorn	 * adjacent entries.
284209878Snwhitehorn	 */
285209878Snwhitehorn	i = 0;
286209878Snwhitehorn	while (i < PHYS_AVAIL_ENTRIES) {
287209878Snwhitehorn		addr = cvmx_bootmem_phy_alloc(1 << 20, phys_end,
288209878Snwhitehorn					      ~(vm_paddr_t)0, PAGE_SIZE, 0);
289209878Snwhitehorn		if (addr == -1)
290209878Snwhitehorn			break;
291209878Snwhitehorn
292209878Snwhitehorn		/*
293209878Snwhitehorn		 * The SDK needs to be able to easily map any memory that might
294209878Snwhitehorn		 * come to it e.g. in the form of an mbuf.  Because on !n64 we
295209878Snwhitehorn		 * can't direct-map some addresses and we don't want to manage
296209878Snwhitehorn		 * temporary mappings within the SDK, don't feed memory that
297209878Snwhitehorn		 * can't be direct-mapped to the kernel.
298209878Snwhitehorn		 */
299209878Snwhitehorn#if !defined(__mips_n64)
300209878Snwhitehorn		if (!MIPS_DIRECT_MAPPABLE(addr + (1 << 20) - 1))
301209878Snwhitehorn			continue;
302209878Snwhitehorn#endif
303209878Snwhitehorn
304209878Snwhitehorn		physmem += btoc(1 << 20);
305209878Snwhitehorn
306209878Snwhitehorn		if (i > 0 && phys_avail[i - 1] == addr) {
307209878Snwhitehorn			phys_avail[i - 1] += 1 << 20;
308			continue;
309		}
310
311		phys_avail[i + 0] = addr;
312		phys_avail[i + 1] = addr + (1 << 20);
313
314		i += 2;
315	}
316
317	realmem = physmem;
318}
319
320void
321platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
322    __register_t a3)
323{
324	const struct octeon_feature_description *ofd;
325	uint64_t platform_counter_freq;
326
327	/*
328	 * XXX
329	 * octeon_boot_params_init() should be called before anything else,
330	 * certainly before any output; we may find out from the boot
331	 * descriptor's flags that we're supposed to use the PCI or UART1
332	 * consoles rather than UART0.  No point doing that reorganization
333	 * until we actually intercept UART_DEV_CONSOLE for the UART1 case
334	 * and somehow handle the PCI console, which we lack code for
335	 * entirely.
336	 */
337
338	/* Initialize pcpu stuff */
339	mips_pcpu0_init();
340	mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
341	cninit();
342
343	octeon_ciu_reset();
344	octeon_boot_params_init(a3);
345	/*
346	 * XXX
347	 * We can certainly parse command line arguments or U-Boot environment
348	 * to determine whether to bootverbose / single user / ...  I think
349	 * stass has patches to add support for loader things to U-Boot even.
350	 */
351	bootverbose = 1;
352
353	/*
354	 * For some reason on the cn38xx simulator ebase register is set to
355	 * 0x80001000 at bootup time.  Move it back to the default, but
356	 * when we move to having support for multiple executives, we need
357	 * to rethink this.
358	 */
359	mips_wr_ebase(0x80000000);
360
361	octeon_memory_init();
362	init_param1();
363	init_param2(physmem);
364	mips_cpu_init();
365	pmap_bootstrap();
366	mips_proc0_init();
367	mutex_init();
368	kdb_init();
369#ifdef KDB
370	if (boothowto & RB_KDB)
371		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
372#endif
373	platform_counter_freq = cvmx_sysinfo_get()->cpu_clock_hz;
374
375	octeon_timecounter.tc_frequency = cvmx_sysinfo_get()->cpu_clock_hz;
376	platform_timecounter = &octeon_timecounter;
377
378	mips_timer_init_params(platform_counter_freq, 0);
379
380	set_cputicker(octeon_get_ticks, cvmx_sysinfo_get()->cpu_clock_hz, 0);
381
382#ifdef SMP
383	/*
384	 * Clear any pending IPIs.
385	 */
386	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(0), 0xffffffff);
387#endif
388
389	printf("Octeon SDK: %s\n", OCTEON_SDK_VERSION_STRING);
390	printf("Available Octeon features:");
391	for (ofd = octeon_feature_descriptions; ofd->ofd_string != NULL; ofd++)
392		if (octeon_has_feature(ofd->ofd_feature))
393			printf(" %s", ofd->ofd_string);
394	printf("\n");
395}
396
397static uint64_t
398octeon_get_ticks(void)
399{
400	uint64_t cvmcount;
401
402	CVMX_MF_CYCLE(cvmcount);
403	return (cvmcount);
404}
405
406static unsigned
407octeon_get_timecount(struct timecounter *tc)
408{
409	return ((unsigned)octeon_get_ticks());
410}
411
412/**
413 * version of printf that works better in exception context.
414 *
415 * @param format
416 *
417 * XXX If this function weren't in cvmx-interrupt.c, we'd use the SDK version.
418 */
419void cvmx_safe_printf(const char *format, ...)
420{
421    char buffer[256];
422    char *ptr = buffer;
423    int count;
424    va_list args;
425
426    va_start(args, format);
427#ifndef __U_BOOT__
428    count = vsnprintf(buffer, sizeof(buffer), format, args);
429#else
430    count = vsprintf(buffer, format, args);
431#endif
432    va_end(args);
433
434    while (count-- > 0)
435    {
436        cvmx_uart_lsr_t lsrval;
437
438        /* Spin until there is room */
439        do
440        {
441            lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(0));
442#if !defined(CONFIG_OCTEON_SIM_SPEED)
443            if (lsrval.s.temt == 0)
444                cvmx_wait(10000);   /* Just to reduce the load on the system */
445#endif
446        }
447        while (lsrval.s.temt == 0);
448
449        if (*ptr == '\n')
450            cvmx_write_csr(CVMX_MIO_UARTX_THR(0), '\r');
451        cvmx_write_csr(CVMX_MIO_UARTX_THR(0), *ptr++);
452    }
453}
454
455/* impSTART: This stuff should move back into the Cavium SDK */
456/*
457 ****************************************************************************************
458 *
459 * APP/BOOT  DESCRIPTOR  STUFF
460 *
461 ****************************************************************************************
462 */
463
464/* Define the struct that is initialized by the bootloader used by the
465 * startup code.
466 *
467 * Copyright (c) 2004, 2005, 2006 Cavium Networks.
468 *
469 * The authors hereby grant permission to use, copy, modify, distribute,
470 * and license this software and its documentation for any purpose, provided
471 * that existing copyright notices are retained in all copies and that this
472 * notice is included verbatim in any distributions. No written agreement,
473 * license, or royalty fee is required for any of the authorized uses.
474 * Modifications to this software may be copyrighted by their authors
475 * and need not follow the licensing terms described here, provided that
476 * the new terms are clearly indicated on the first page of each file where
477 * they apply.
478 */
479
480#define OCTEON_CURRENT_DESC_VERSION     6
481#define OCTEON_ARGV_MAX_ARGS            (64)
482#define OCTOEN_SERIAL_LEN 20
483
484typedef struct {
485	/* Start of block referenced by assembly code - do not change! */
486	uint32_t desc_version;
487	uint32_t desc_size;
488
489	uint64_t stack_top;
490	uint64_t heap_base;
491	uint64_t heap_end;
492	uint64_t entry_point;   /* Only used by bootloader */
493	uint64_t desc_vaddr;
494	/* End of This block referenced by assembly code - do not change! */
495
496	uint32_t exception_base_addr;
497	uint32_t stack_size;
498	uint32_t heap_size;
499	uint32_t argc;  /* Argc count for application */
500	uint32_t argv[OCTEON_ARGV_MAX_ARGS];
501	uint32_t flags;
502	uint32_t core_mask;
503	uint32_t dram_size;  /**< DRAM size in megabyes */
504	uint32_t phy_mem_desc_addr;  /**< physical address of free memory descriptor block*/
505	uint32_t debugger_flags_base_addr;  /**< used to pass flags from app to debugger */
506	uint32_t eclock_hz;  /**< CPU clock speed, in hz */
507	uint32_t dclock_hz;  /**< DRAM clock speed, in hz */
508	uint32_t spi_clock_hz;  /**< SPI4 clock in hz */
509	uint16_t board_type;
510	uint8_t board_rev_major;
511	uint8_t board_rev_minor;
512	uint16_t chip_type;
513	uint8_t chip_rev_major;
514	uint8_t chip_rev_minor;
515	char board_serial_number[OCTOEN_SERIAL_LEN];
516	uint8_t mac_addr_base[6];
517	uint8_t mac_addr_count;
518	uint64_t cvmx_desc_vaddr;
519} octeon_boot_descriptor_t;
520
521cvmx_bootinfo_t *octeon_bootinfo;
522
523static octeon_boot_descriptor_t *app_desc_ptr;
524
525int
526octeon_is_simulation(void)
527{
528	switch (cvmx_sysinfo_get()->board_type) {
529	case CVMX_BOARD_TYPE_SIM:
530		return 1;
531	default:
532		return 0;
533	}
534}
535
536static void
537octeon_process_app_desc_ver_6(void)
538{
539	/* XXX Why is 0x00000000ffffffffULL a bad value?  */
540	if (app_desc_ptr->cvmx_desc_vaddr == 0 ||
541	    app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful)
542            	panic("Bad octeon_bootinfo %p", octeon_bootinfo);
543
544    	octeon_bootinfo =
545	    (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr;
546        octeon_bootinfo =
547	    (cvmx_bootinfo_t *) ((intptr_t)octeon_bootinfo | MIPS_KSEG0_START);
548        if (octeon_bootinfo->major_version != 1)
549            	panic("Incompatible CVMX descriptor from bootloader: %d.%d %p",
550                       (int) octeon_bootinfo->major_version,
551                       (int) octeon_bootinfo->minor_version, octeon_bootinfo);
552
553	cvmx_sysinfo_minimal_initialize(octeon_bootinfo->phy_mem_desc_addr,
554					octeon_bootinfo->board_type,
555					octeon_bootinfo->board_rev_major,
556					octeon_bootinfo->board_rev_minor,
557					octeon_bootinfo->eclock_hz);
558}
559
560static void
561octeon_boot_params_init(register_t ptr)
562{
563	if (ptr == 0 || ptr >= MAX_APP_DESC_ADDR)
564		panic("app descriptor passed at invalid address %#jx",
565		    (uintmax_t)ptr);
566
567	app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
568	if (app_desc_ptr->desc_version < 6)
569		panic("Your boot code is too old to be supported.");
570	octeon_process_app_desc_ver_6();
571
572	KASSERT(octeon_bootinfo != NULL, ("octeon_bootinfo should be set"));
573
574	if (cvmx_sysinfo_get()->phy_mem_desc_addr == (uint64_t)0)
575		panic("Your boot loader did not supply a memory descriptor.");
576	cvmx_bootmem_init(cvmx_sysinfo_get()->phy_mem_desc_addr);
577
578        printf("Boot Descriptor Ver: %u -> %u/%u",
579               app_desc_ptr->desc_version, octeon_bootinfo->major_version,
580	       octeon_bootinfo->minor_version);
581        printf("  CPU clock: %uMHz  Core Mask: %#x\n",
582	       cvmx_sysinfo_get()->cpu_clock_hz / 1000000,
583	       cvmx_sysinfo_get()->core_mask);
584        printf("  Board Type: %u  Revision: %u/%u\n",
585               cvmx_sysinfo_get()->board_type,
586	       cvmx_sysinfo_get()->board_rev_major,
587	       cvmx_sysinfo_get()->board_rev_minor);
588
589        printf("  Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n",
590	    octeon_bootinfo->mac_addr_base[0],
591	    octeon_bootinfo->mac_addr_base[1],
592	    octeon_bootinfo->mac_addr_base[2],
593	    octeon_bootinfo->mac_addr_base[3],
594	    octeon_bootinfo->mac_addr_base[4],
595	    octeon_bootinfo->mac_addr_base[5],
596	    octeon_bootinfo->mac_addr_count);
597
598#if defined(OCTEON_BOARD_CAPK_0100ND)
599	if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_CN3010_EVB_HS5)
600		printf("Compiled for CAPK-0100ND, but board type is %s\n",
601		    cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type));
602#else
603	printf("Board: %s\n",
604	    cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type));
605#endif
606	printf("Model: %s\n", octeon_model_get_string(cvmx_get_proc_id()));
607}
608/* impEND: This stuff should move back into the Cavium SDK */
609