patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / mips / momentum / jaguar_atx / prom.c
1 /*
2  * Copyright 2002 Momentum Computer Inc.
3  * Author: Matthew Dharm <mdharm@momenco.com>
4  *
5  * Louis Hamilton, Red Hat, Inc.
6  * hamilton@redhat.com  [MIPS64 modifications]
7  *
8  * Based on Ocelot Linux port, which is
9  * Copyright 2001 MontaVista Software Inc.
10  * Author: jsun@mvista.com or jsun@junsun.net
11  *
12  * This program is free software; you can redistribute  it and/or modify it
13  * under  the terms of  the GNU General  Public License as published by the
14  * Free Software Foundation;  either version 2 of the  License, or (at your
15  * option) any later version.
16  *
17  * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com)
18  */
19 #include <linux/config.h>
20 #include <linux/init.h>
21 #include <linux/mm.h>
22 #include <linux/sched.h>
23 #include <linux/bootmem.h>
24
25 #include <asm/addrspace.h>
26 #include <asm/bootinfo.h>
27 #include <asm/mv64340.h>
28 #include <asm/pmon.h>
29
30 #include "jaguar_atx_fpga.h"
31
32 extern void ja_setup_console(void);
33
34 struct callvectors *debug_vectors;
35
36 extern unsigned long mv64340_base;
37 extern unsigned long cpu_clock;
38
39 const char *get_system_type(void)
40 {
41         return "Momentum Jaguar-ATX";
42 }
43
44 #ifdef CONFIG_MV64340_ETH
45 extern unsigned char prom_mac_addr_base[6];
46
47 static void burn_clocks(void)
48 {
49         int i;
50
51         /* this loop should burn at least 1us -- this should be plenty */
52         for (i = 0; i < 0x10000; i++)
53                 ;
54 }
55
56 static u8 exchange_bit(u8 val, u8 cs)
57 {
58         /* place the data */
59         JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
60         burn_clocks();
61
62         /* turn the clock on */
63         JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
64         burn_clocks();
65
66         /* turn the clock off and read-strobe */
67         JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
68         
69         /* return the data */
70         return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
71 }
72
73 void get_mac(char dest[6])
74 {
75         u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
76         int i,j;
77
78         for (i = 0; i < 12; i++)
79                 exchange_bit(read_opcode[i], 1);
80
81         for (j = 0; j < 6; j++) {
82                 dest[j] = 0;
83                 for (i = 0; i < 8; i++) {
84                         dest[j] <<= 1;
85                         dest[j] |= exchange_bit(0, 1);
86                 }
87         }
88
89         /* turn off CS */
90         exchange_bit(0,0);
91 }
92 #endif
93
94 #ifdef CONFIG_MIPS64
95
96 unsigned long signext(unsigned long addr)
97 {
98         addr &= 0xffffffff;
99         return (unsigned long)((int)addr);
100 }
101
102 void *get_arg(unsigned long args, int arc)
103 {
104         unsigned long ul;
105         unsigned char *puc, uc;
106
107         args += (arc * 4);
108         ul = (unsigned long)signext(args);
109         puc = (unsigned char *)ul;
110         if (puc == 0)
111                 return (void *)0;
112
113 #ifdef CONFIG_CPU_LITTLE_ENDIAN
114         uc = *puc++;
115         l = (unsigned long)uc;
116         uc = *puc++;
117         ul |= (((unsigned long)uc) << 8);
118         uc = *puc++;
119         ul |= (((unsigned long)uc) << 16);
120         uc = *puc++;
121         ul |= (((unsigned long)uc) << 24);
122 #else
123         uc = *puc++;
124         ul = ((unsigned long)uc) << 24;
125         uc = *puc++;
126         ul |= (((unsigned long)uc) << 16);
127         uc = *puc++;
128         ul |= (((unsigned long)uc) << 8);
129         uc = *puc++;
130         ul |= ((unsigned long)uc);
131 #endif
132         ul = signext(ul);
133
134         return (void *)ul;
135 }
136
137 char *arg64(unsigned long addrin, int arg_index)
138 {
139         unsigned long args;
140         char *p;
141
142         args = signext(addrin);
143         p = (char *)get_arg(args, arg_index);
144
145         return p;
146 }
147 #endif  /* CONFIG_MIPS64 */
148
149 /* PMON passes arguments in C main() style */
150 void __init prom_init(void)
151 {
152         int argc = fw_arg0;
153         char **arg = (char **) fw_arg1;
154         char **env = (char **) fw_arg2;
155         struct callvectors *cv = (struct callvectors *) fw_arg3;
156         int i;
157
158 #ifdef CONFIG_SERIAL_8250_CONSOLE
159 //      ja_setup_console();     /* The very first thing.  */
160 #endif
161
162 #ifdef CONFIG_MIPS64
163         char *ptr;
164
165         printk("Mips64 Jaguar-ATX\n");
166         /* save the PROM vectors for debugging use */
167         debug_vectors = (struct callvectors *)signext((unsigned long)cv);
168
169         /* arg[0] is "g", the rest is boot parameters */
170         arcs_cmdline[0] = '\0';
171
172         for (i = 1; i < argc; i++) {
173                 ptr = (char *)arg64((unsigned long)arg, i);
174                 if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
175                     sizeof(arcs_cmdline))
176                         break;
177                 strcat(arcs_cmdline, ptr);
178                 strcat(arcs_cmdline, " ");
179         }
180
181         i = 0;
182         while (1) {
183                 ptr = (char *)arg64((unsigned long)env, i);
184                 if (! ptr)
185                         break;
186
187                 if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
188                         mv64340_base = simple_strtol(ptr + strlen("gtbase="),
189                                                         NULL, 16);
190
191                         if ((mv64340_base & 0xffffffff00000000) == 0)
192                                 mv64340_base |= 0xffffffff00000000;
193
194                         printk("mv64340_base set to 0x%016lx\n", mv64340_base);
195                 }
196                 if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
197                         cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
198                                                         NULL, 10);
199                         printk("cpu_clock set to %d\n", cpu_clock);
200                 }
201                 i++;
202         }
203         printk("arcs_cmdline: %s\n", arcs_cmdline);
204
205 #else   /* CONFIG_MIPS64 */
206         /* save the PROM vectors for debugging use */
207         debug_vectors = cv;
208
209         /* arg[0] is "g", the rest is boot parameters */
210         arcs_cmdline[0] = '\0';
211         for (i = 1; i < argc; i++) {
212                 if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
213                     >= sizeof(arcs_cmdline))
214                         break;
215                 strcat(arcs_cmdline, arg[i]);
216                 strcat(arcs_cmdline, " ");
217         }
218
219         while (*env) {
220                 if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
221                         mv64340_base = simple_strtol(*env + strlen("gtbase="),
222                                                         NULL, 16);
223                 }
224                 if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
225                         cpu_clock = simple_strtol(*env + strlen("cpuclock="),
226                                                         NULL, 10);
227                 }
228                 env++;
229         }
230 #endif /* CONFIG_MIPS64 */
231         mips_machgroup = MACH_GROUP_MOMENCO;
232         mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
233
234 #ifdef CONFIG_MV64340_ETH
235         /* get the base MAC address for on-board ethernet ports */
236         get_mac(prom_mac_addr_base);
237 #endif
238 }
239
240 void __init prom_free_prom_memory(void)
241 {
242 }
243
244 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
245 {
246 }
247
248 /*
249  * SMP support
250  */
251 int prom_setup_smp(void)
252 {
253         int     num_cpus = 2;
254
255         /*
256          * We know that the RM9000 on the Jaguar ATX board has 2 cores.
257          * Hence, this can be hardcoded for now.
258          */
259         return num_cpus;
260 }
261
262 int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
263 {
264         /* Clear the semaphore */
265         *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
266
267         return 1;
268 }
269
270 void prom_init_secondary(void)
271 {
272         clear_c0_config(CONF_CM_CMASK);
273         set_c0_config(0x2);
274
275         clear_c0_status(ST0_IM);
276         set_c0_status(0x1ffff);
277 }
278
279 void prom_smp_finish(void)
280 {
281 }