1/*	$NetBSD: machdep.c,v 1.5 2011/08/16 06:59:19 matt Exp $	*/
2/*-
3 * Copyright (c) 2011 CradlePoint Technology, Inc.
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
30__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.5 2011/08/16 06:59:19 matt Exp $");
31
32#include <sys/param.h>
33#include <sys/boot_flag.h>
34#include <sys/buf.h>
35#include <sys/device.h>
36#include <sys/mount.h>
37#include <sys/kcore.h>
38#include <sys/reboot.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/termios.h>
42
43#include <uvm/uvm_extern.h>
44
45#include <dev/cons.h>
46
47#include <mips/cache.h>
48#include <mips/locore.h>
49#include <mips/cpuregs.h>
50
51#include <mips/ralink/ralink_reg.h>
52#include <mips/ralink/ralink_var.h>
53
54/* structures we define/alloc for other files in the kernel */
55struct vm_map *mb_map = NULL;
56struct vm_map *phys_map = NULL;
57struct cpu_info cpu_info_store;
58int physmem;		/* # pages of physical memory */
59int mem_cluster_cnt = 0;
60phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
61
62/* structures others define for us */
63extern struct user *proc0paddr;
64
65void mach_init(void);
66
67static inline uint32_t
68sysctl_read(u_int offset)
69{
70	return *RA_IOREG_VADDR(RA_SYSCTL_BASE, offset);
71}
72
73static inline void
74sysctl_write(u_int offset, uint32_t val)
75{
76	*RA_IOREG_VADDR(RA_SYSCTL_BASE, offset) = val;
77}
78
79static void
80cal_timer(void)
81{
82	uint32_t cntfreq;
83
84	cntfreq = curcpu()->ci_cpu_freq = RA_CLOCK_RATE;
85
86	/* MIPS 4Kc CP0 counts every other clock */
87	if (mips_options.mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT)
88		cntfreq /= 2;
89
90	curcpu()->ci_cycles_per_hz = (cntfreq + hz / 2) / hz;
91
92	/* Compute number of cycles per 1us (1/MHz). 0.5MHz is for roundup. */
93	curcpu()->ci_divisor_delay = ((cntfreq + 500000) / 1000000);
94}
95
96void
97mach_init(void)
98{
99	vaddr_t kernend;
100	psize_t memsize;
101
102	extern char kernel_text[];
103	extern char edata[], end[];	/* From Linker */
104
105	/* clear the BSS segment */
106	kernend = mips_round_page(end);
107
108	memset(edata, 0, kernend - (vaddr_t)edata);
109
110#ifdef RALINK_CONSOLE_EARLY
111	/*
112	 * set up early console
113	 *  cannot printf until sometime (?) in mips_vector_init
114	 *  meanwhile can use the ra_console_putc primitive if necessary
115	 */
116	ralink_console_early();
117#endif
118
119	/* set CPU model info for sysctl_hw */
120	uint32_t tmp;
121	tmp = sysctl_read(RA_SYSCTL_ID0);
122	memcpy(&cpu_model[0], &tmp, 4);
123	tmp = sysctl_read(RA_SYSCTL_ID1);
124	memcpy(&cpu_model[4], &tmp, 4);
125	cpu_model[9] = 0;
126
127	/*
128	 * Set up the exception vectors and CPU-specific function
129	 * vectors early on.  We need the wbflush() vector set up
130	 * before comcnattach() is called (or at least before the
131	 * first printf() after that is called).
132	 * Sets up mips_cpu_flags that may be queried by other
133	 * functions called during startup.
134	 * Also clears the I+D caches.
135	 */
136	mips_vector_init(NULL, false);
137
138	/*
139	 * Calibrate timers.
140	 */
141	cal_timer();
142
143	/*
144	 * Set the VM page size.
145	 */
146	uvm_setpagesize();
147
148	/*
149	 * Look at arguments passed to us and compute boothowto.
150	 */
151	boothowto = RB_AUTOBOOT;
152#ifdef KADB
153	boothowto |= RB_KDB;
154#endif
155
156	/*
157	 * Determine the memory size.
158	 */
159	memsize = *(volatile uint32_t *)
160	    MIPS_PHYS_TO_KSEG1(RA_SYSCTL_BASE + RA_SYSCTL_CFG0);
161	memsize = __SHIFTOUT(memsize, SYSCTL_CFG0_DRAM_SIZE);
162	if (__predict_false(memsize == 0)) {
163		memsize = 2 << 20;
164	} else {
165		memsize = 4 << (20 + memsize);
166	}
167
168	physmem = btoc(memsize);
169
170	mem_clusters[mem_cluster_cnt].start = 0;
171	mem_clusters[mem_cluster_cnt].size = memsize;
172	mem_cluster_cnt++;
173
174	/*
175	 * Load the memory into the VM system
176	 */
177	mips_page_physload((vaddr_t)kernel_text, kernend,
178	    mem_clusters, mem_cluster_cnt,
179	    NULL, 0);
180
181	/*
182	 * Initialize message buffer (at end of core).
183	 */
184	mips_init_msgbuf();
185
186	/*
187	 * Initialize the virtual memory system.
188	 */
189	pmap_bootstrap();
190
191	/*
192	 * Init mapping for u page(s) for proc0.
193	 */
194	mips_init_lwp0_uarea();
195
196	/*
197	 * Initialize busses.
198	 */
199	ra_bus_init();
200
201#ifdef DDB
202	if (boothowto & RB_KDB)
203		Debugger();
204#endif
205}
206
207void
208cpu_startup(void)
209{
210#ifdef DEBUG
211	extern int pmapdebug;
212	const int opmapdebug = pmapdebug;
213	pmapdebug = 0;		/* Shut up pmap debug during bootstrap */
214#endif
215
216	cpu_startup_common();
217
218#ifdef DEBUG
219	pmapdebug = opmapdebug;
220#endif
221}
222
223void
224cpu_reboot(int howto, char *bootstr)
225{
226	static int waittime = -1;
227
228	/* Take a snapshot before clobbering any registers. */
229	savectx(lwp_getpcb(curlwp));
230
231	/* If "always halt" was specified as a boot flag, obey. */
232	if (boothowto & RB_HALT)
233		howto |= RB_HALT;
234
235	boothowto = howto;
236
237	/* If system is cold, just halt. */
238	if (cold) {
239		boothowto |= RB_HALT;
240		goto haltsys;
241	}
242
243	if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
244		waittime = 0;
245
246		/*
247		 * Synchronize the disks....
248		 */
249		vfs_shutdown();
250
251		/*
252		 * If we've been adjusting the clock, the todr
253		 * will be out of synch; adjust it now.
254		 */
255		resettodr();
256	}
257
258	/* Disable interrupts. */
259	splhigh();
260
261	if (boothowto & RB_DUMP)
262		dumpsys();
263
264 haltsys:
265	/* Run any shutdown hooks. */
266	doshutdownhooks();
267
268	pmf_system_shutdown(boothowto);
269
270	/*
271	 * Firmware may autoboot (depending on settings), and we cannot pass
272	 * flags to it (at least I haven't figured out how to yet), so
273	 * we "pseudo-halt" now.
274	 */
275	if (boothowto & RB_HALT) {
276		printf("\n");
277		printf("The operating system has halted.\n");
278		printf("Please press any key to reboot.\n\n");
279		cnpollc(1);	/* For proper keyboard command handling */
280		cngetc();
281		cnpollc(0);
282	}
283
284	printf("reseting board...\n\n");
285	mips_icache_sync_all();
286	mips_dcache_wbinv_all();
287
288	sysctl_write(RA_SYSCTL_RST, 1);  /* SoC Reset */
289	sysctl_write(RA_SYSCTL_RST, 0);
290
291#if 0
292	__asm volatile("jr	%0" :: "r"(MIPS_RESET_EXC_VEC));
293#endif
294	printf("Oops, back from reset\n\nSpinning...");
295	for (;;)
296		/* spin forever */ ;	/* XXX */
297	/*NOTREACHED*/
298}
299
300#define NO_SECURITY_MAGIC	0x27051958
301#define SERIAL_MAGIC		0x100000
302int
303ra_check_memo_reg(int key)
304{
305	uint32_t magic;
306
307	/*
308	 * These registers may be overwritten.  Keep the value around in case
309	 * it is used later.  Bitmask 1 == security, 2 = serial
310	 */
311	static int keyvalue;
312
313	switch (key) {
314	case NO_SECURITY:
315		magic = sysctl_read(RA_SYSCTL_MEMO0);
316		if ((NO_SECURITY_MAGIC == magic) || ((keyvalue & 1) != 0)) {
317			keyvalue |= 1;
318			return 1;
319		}
320		return 0;
321		break;
322
323	case SERIAL_CONSOLE:
324		magic = sysctl_read(RA_SYSCTL_MEMO1);
325		if (((SERIAL_MAGIC & magic) != 0) || ((keyvalue & 2) != 0)) {
326			keyvalue |= 2;
327			return 1;
328		}
329		return 0;
330		break;
331
332	default:
333		return 0;
334	}
335
336}
337