• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/mips/mti-sead3/
1/*
2 * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
3 *	All rights reserved.
4 *	Authors: Carsten Langgaard <carstenl@mips.com>
5 *		 Maciej W. Rozycki <macro@mips.com>
6 *
7 *  This program is free software; you can distribute it and/or modify it
8 *  under the terms of the GNU General Public License (Version 2) as
9 *  published by the Free Software Foundation.
10 *
11 *  This program is distributed in the hope it will be useful, but WITHOUT
12 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 *  for more details.
15 *
16 *  You should have received a copy of the GNU General Public License along
17 *  with this program; if not, write to the Free Software Foundation, Inc.,
18 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * PROM library initialisation code.
21 */
22#include <linux/init.h>
23#include <linux/string.h>
24#include <linux/kernel.h>
25
26#include <asm/bootinfo.h>
27#include <asm/io.h>
28#include <asm/system.h>
29#include <asm/cacheflush.h>
30#include <asm/traps.h>
31
32#include <asm/mips-boards/prom.h>
33#include <asm/mips-boards/generic.h>
34
35int prom_argc;
36int *_prom_argv, *_prom_envp;
37
38/*
39 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
40 * This macro take care of sign extension, if running in 64-bit mode.
41 */
42#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
43
44int init_debug;  /* global var => auto initialized to 0 */
45
46int mips_revision_corid;
47int mips_revision_sconid;
48
49char *prom_getenv(char *envname)
50{
51	/*
52	 * Return a pointer to the given environment variable.
53	 * In 64-bit mode: we're using 64-bit pointers, but all pointers
54	 * in the PROM structures are only 32-bit, so we need some
55	 * workarounds, if we are running in 64-bit mode.
56	 */
57	int i, index = 0;
58
59	i = strlen(envname);
60
61	while (prom_envp(index)) {
62		if (strncmp(envname, prom_envp(index), i) == 0)
63			return prom_envp(index+1);
64		index += 2;
65	}
66
67	return NULL;
68}
69
70static inline unsigned char str2hexnum(unsigned char c)
71{
72	if (c >= '0' && c <= '9')
73		return c - '0';
74	if (c >= 'a' && c <= 'f')
75		return c - 'a' + 10;
76	return 0; /* foo */
77}
78
79static inline void str2eaddr(unsigned char *ea, unsigned char *str)
80{
81	int i;
82
83	for (i = 0; i < 6; i++) {
84		unsigned char num;
85
86		if ((*str == '.') || (*str == ':'))
87			str++;
88		num = str2hexnum(*str++) << 4;
89		num |= (str2hexnum(*str++));
90		ea[i] = num;
91	}
92}
93
94int get_ethernet_addr(char *ethernet_addr)
95{
96	char *ethaddr_str;
97
98	ethaddr_str = prom_getenv("ethaddr");
99	if (!ethaddr_str) {
100		printk("ethaddr not set in boot prom\n");
101		return -1;
102	}
103	str2eaddr(ethernet_addr, ethaddr_str);
104
105	if (init_debug > 1) {
106		int i;
107		printk("get_ethernet_addr: ");
108		for (i = 0; i < 5; i++)
109			printk("%02x:", (unsigned char)*(ethernet_addr+i));
110		printk("%02x\n", *(ethernet_addr+i));
111	}
112
113	return 0;
114}
115
116#ifdef CONFIG_SERIAL_8250_CONSOLE
117static void __init console_config(void)
118{
119	char console_string[40];
120	int baud = 0;
121	char parity = '\0', bits = '\0', flow = '\0';
122	char *s;
123
124	if ((strstr(prom_getcmdline(), "console=")) == NULL) {
125		s = prom_getenv("modetty0");
126		if (s) {
127			while (*s >= '0' && *s <= '9')
128				baud = baud*10 + *s++ - '0';
129			if (*s == ',')
130				s++;
131			if (*s)
132				parity = *s++;
133			if (*s == ',')
134				s++;
135			if (*s)
136				bits = *s++;
137			if (*s == ',')
138				s++;
139			if (*s == 'h')
140				flow = 'r';
141		}
142		if (baud == 0)
143			baud = 38400;
144		if (parity != 'n' && parity != 'o' && parity != 'e')
145			parity = 'n';
146		if (bits != '7' && bits != '8')
147			bits = '8';
148		if (flow == '\0')
149			flow = 'r';
150		sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
151		strcat(prom_getcmdline(), console_string);
152		pr_info("Config serial console:%s\n", console_string);
153	}
154}
155#endif
156
157static void __init mips_nmi_setup(void)
158{
159	void *base;
160	extern char except_vec_nmi;
161
162	base = cpu_has_veic ?
163		(void *)(CAC_BASE + 0xa80) :
164		(void *)(CAC_BASE + 0x380);
165#ifdef CONFIG_CPU_MICROMIPS
166	/*
167	 * Decrement the exception vector address by one for MicroMIPS.
168	 */
169	memcpy(base, (&except_vec_nmi - 1), 0x80);
170
171	/*
172	 * This is a hack. We do not know if the boot loader was built with
173	 * MicroMIPS instructions or not. If it was not, the NMI exception
174	 * code at 0x80000a80 will be taken in MIPS32 mode. The hand coded
175	 * assembly below forces us into MicroMIPS mode if we are a pure
176	 * MicroMIPS kernel. The assembly instructions are:
177	 *
178	 *  3C1A8000   lui       k0,0x8000
179	 *  375A0381   ori       k0,k0,0x381
180	 *  03400008   jr        k0
181	 *  00000000   nop
182	 *
183	 * The mode switch occurs by jumping to the unaligned exception
184	 * vector address at 0x80000381 which would have been 0x80000380
185	 * in MIPS32 mode. The jump to the unaligned address transitions
186	 * us into MicroMIPS mode.
187	 */
188	if (!cpu_has_veic) {
189		void *base2 = (void *)(CAC_BASE + 0xa80);
190		*((unsigned int *)base2) = 0x3c1a8000;
191		*((unsigned int *)base2 + 1) = 0x375a0381;
192		*((unsigned int *)base2 + 2) = 0x03400008;
193		*((unsigned int *)base2 + 3) = 0x00000000;
194		flush_icache_range((unsigned long)base2, (unsigned long)base2 + 0x10);
195	}
196#else
197	memcpy(base, &except_vec_nmi, 0x80);
198#endif
199	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
200}
201
202static void __init mips_ejtag_setup(void)
203{
204	void *base;
205	extern char except_vec_ejtag_debug;
206
207	base = cpu_has_veic ?
208		(void *)(CAC_BASE + 0xa00) :
209		(void *)(CAC_BASE + 0x300);
210#ifdef CONFIG_CPU_MICROMIPS
211	/* Deja vu... */
212	memcpy(base, (&except_vec_ejtag_debug - 1), 0x80);
213	if (!cpu_has_veic) {
214		void *base2 = (void *)(CAC_BASE + 0xa00);
215		*((unsigned int *)base2) = 0x3c1a8000;
216		*((unsigned int *)base2 + 1) = 0x375a0301;
217		*((unsigned int *)base2 + 2) = 0x03400008;
218		*((unsigned int *)base2 + 3) = 0x00000000;
219		flush_icache_range((unsigned long)base2, (unsigned long)base2 + 0x10);
220	}
221#else
222	memcpy(base, &except_vec_ejtag_debug, 0x80);
223#endif
224	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
225}
226
227extern struct plat_smp_ops msmtc_smp_ops;
228
229void __init prom_init(void)
230{
231	prom_argc = fw_arg0;
232	_prom_argv = (int *) fw_arg1;
233	_prom_envp = (int *) fw_arg2;
234
235	mips_display_message("LINUX");
236
237	mips_revision_corid = MIPS_REVISION_CORID;
238	mips_revision_sconid = MIPS_REVISION_SCONID;
239	if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
240		switch (mips_revision_corid) {
241		case MIPS_REVISION_CORID_QED_RM5261:
242		case MIPS_REVISION_CORID_CORE_LV:
243		case MIPS_REVISION_CORID_CORE_FPGA:
244		case MIPS_REVISION_CORID_CORE_FPGAR2:
245			mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
246			break;
247		case MIPS_REVISION_CORID_CORE_EMUL_BON:
248		case MIPS_REVISION_CORID_BONITO64:
249		case MIPS_REVISION_CORID_CORE_20K:
250			mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
251			break;
252		case MIPS_REVISION_CORID_CORE_MSC:
253		case MIPS_REVISION_CORID_CORE_FPGA2:
254		case MIPS_REVISION_CORID_CORE_24K:
255			/*
256			 * SOCit/ROCit support is essentially identical
257			 * but make an attempt to distinguish them
258			 */
259			mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
260			break;
261		case MIPS_REVISION_CORID_CORE_FPGA3:
262		case MIPS_REVISION_CORID_CORE_FPGA4:
263		case MIPS_REVISION_CORID_CORE_FPGA5:
264		case MIPS_REVISION_CORID_CORE_EMUL_MSC:
265		default:
266			/* See above */
267			mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
268			break;
269		}
270	}
271
272	board_nmi_handler_setup = mips_nmi_setup;
273	board_ejtag_handler_setup = mips_ejtag_setup;
274
275	pr_info("\nLINUX started...\n");
276	prom_init_cmdline();
277	prom_meminit();
278#ifdef CONFIG_SERIAL_8250_CONSOLE
279	console_config();
280#endif
281#ifdef CONFIG_MIPS_CMP
282	register_smp_ops(&cmp_smp_ops);
283#endif
284#ifdef CONFIG_MIPS_MT_SMP
285	register_smp_ops(&vsmp_smp_ops);
286#endif
287#ifdef CONFIG_MIPS_MT_SMTC
288	register_smp_ops(&msmtc_smp_ops);
289#endif
290}
291