ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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
29 #include "jaguar_atx_fpga.h"
30
31 extern void ja_setup_console(void);
32
33 struct callvectors {
34         int     (*open) (char*, int, int);              /*       0 */
35         int     (*close) (int);                         /*       4 */
36         int     (*read) (int, void*, int);              /*       8 */
37         int     (*write) (int, void*, int);             /*      12 */
38         off_t   (*lseek) (int, off_t, int);             /*      16 */
39         int     (*printf) (const char*, ...);           /*      20 */
40         void    (*cacheflush) (void);                   /*      24 */
41         char*   (*gets) (char*);                        /*      28 */
42 };
43
44 struct callvectors *debug_vectors;
45
46 extern unsigned long mv64340_base;
47 extern unsigned long cpu_clock;
48
49 const char *get_system_type(void)
50 {
51         return "Momentum Jaguar-ATX";
52 }
53
54 #ifdef CONFIG_MV64340_ETH
55 extern unsigned char prom_mac_addr_base[6];
56
57 static void burn_clocks(void)
58 {
59         int i;
60
61         /* this loop should burn at least 1us -- this should be plenty */
62         for (i = 0; i < 0x10000; i++)
63                 ;
64 }
65
66 static u8 exchange_bit(u8 val, u8 cs)
67 {
68         /* place the data */
69         JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
70         burn_clocks();
71
72         /* turn the clock on */
73         JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
74         burn_clocks();
75
76         /* turn the clock off and read-strobe */
77         JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
78         
79         /* return the data */
80         return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
81 }
82
83 void get_mac(char dest[6])
84 {
85         u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
86         int i,j;
87
88         for (i = 0; i < 12; i++)
89                 exchange_bit(read_opcode[i], 1);
90
91         for (j = 0; j < 6; j++) {
92                 dest[j] = 0;
93                 for (i = 0; i < 8; i++) {
94                         dest[j] <<= 1;
95                         dest[j] |= exchange_bit(0, 1);
96                 }
97         }
98
99         /* turn off CS */
100         exchange_bit(0,0);
101 }
102 #endif
103
104 #ifdef CONFIG_MIPS64
105
106 unsigned long signext(unsigned long addr)
107 {
108         addr &= 0xffffffff;
109         return (unsigned long)((int)addr);
110 }
111
112 void *get_arg(unsigned long args, int arc)
113 {
114         unsigned long ul;
115         unsigned char *puc, uc;
116
117         args += (arc * 4);
118         ul = (unsigned long)signext(args);
119         puc = (unsigned char *)ul;
120         if (puc == 0)
121                 return (void *)0;
122
123 #ifdef CONFIG_CPU_LITTLE_ENDIAN
124         uc = *puc++;
125         l = (unsigned long)uc;
126         uc = *puc++;
127         ul |= (((unsigned long)uc) << 8);
128         uc = *puc++;
129         ul |= (((unsigned long)uc) << 16);
130         uc = *puc++;
131         ul |= (((unsigned long)uc) << 24);
132 #else
133         uc = *puc++;
134         ul = ((unsigned long)uc) << 24;
135         uc = *puc++;
136         ul |= (((unsigned long)uc) << 16);
137         uc = *puc++;
138         ul |= (((unsigned long)uc) << 8);
139         uc = *puc++;
140         ul |= ((unsigned long)uc);
141 #endif
142         ul = signext(ul);
143
144         return (void *)ul;
145 }
146
147 char *arg64(unsigned long addrin, int arg_index)
148 {
149         unsigned long args;
150         char *p;
151
152         args = signext(addrin);
153         p = (char *)get_arg(args, arg_index);
154
155         return p;
156 }
157 #endif  /* CONFIG_MIPS64 */
158
159 /* PMON passes arguments in C main() style */
160 void __init prom_init(void)
161 {
162         int argc = fw_arg0;
163         char **arg = (char **) fw_arg1;
164         char **env = (char **) fw_arg2;
165         struct callvectors *cv = (struct callvectors *) fw_arg3;
166         int i;
167
168 #ifdef CONFIG_SERIAL_8250_CONSOLE
169 //      ja_setup_console();     /* The very first thing.  */
170 #endif
171
172 #ifdef CONFIG_MIPS64
173         char *ptr;
174
175         printk("Mips64 Jaguar-ATX\n");
176         /* save the PROM vectors for debugging use */
177         debug_vectors = (struct callvectors *)signext((unsigned long)cv);
178
179         /* arg[0] is "g", the rest is boot parameters */
180         arcs_cmdline[0] = '\0';
181
182         for (i = 1; i < argc; i++) {
183                 ptr = (char *)arg64((unsigned long)arg, i);
184                 if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
185                     sizeof(arcs_cmdline))
186                         break;
187                 strcat(arcs_cmdline, ptr);
188                 strcat(arcs_cmdline, " ");
189         }
190
191         i = 0;
192         while (1) {
193                 ptr = (char *)arg64((unsigned long)env, i);
194                 if (! ptr)
195                         break;
196
197                 if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
198                         mv64340_base = simple_strtol(ptr + strlen("gtbase="),
199                                                         NULL, 16);
200
201                         if ((mv64340_base & 0xffffffff00000000) == 0)
202                                 mv64340_base |= 0xffffffff00000000;
203
204                         printk("mv64340_base set to 0x%016lx\n", mv64340_base);
205                 }
206                 if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
207                         cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
208                                                         NULL, 10);
209                         printk("cpu_clock set to %d\n", cpu_clock);
210                 }
211                 i++;
212         }
213         printk("arcs_cmdline: %s\n", arcs_cmdline);
214
215 #else   /* CONFIG_MIPS64 */
216         /* save the PROM vectors for debugging use */
217         debug_vectors = cv;
218
219         /* arg[0] is "g", the rest is boot parameters */
220         arcs_cmdline[0] = '\0';
221         for (i = 1; i < argc; i++) {
222                 if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
223                     >= sizeof(arcs_cmdline))
224                         break;
225                 strcat(arcs_cmdline, arg[i]);
226                 strcat(arcs_cmdline, " ");
227         }
228
229         while (*env) {
230                 if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
231                         mv64340_base = simple_strtol(*env + strlen("gtbase="),
232                                                         NULL, 16);
233                 }
234                 if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
235                         cpu_clock = simple_strtol(*env + strlen("cpuclock="),
236                                                         NULL, 10);
237                 }
238                 env++;
239         }
240 #endif /* CONFIG_MIPS64 */
241         mips_machgroup = MACH_GROUP_MOMENCO;
242         mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
243
244 #ifdef CONFIG_MV64340_ETH
245         /* get the base MAC address for on-board ethernet ports */
246         get_mac(prom_mac_addr_base);
247 #endif
248 }
249
250 void __init prom_free_prom_memory(void)
251 {
252 }
253
254 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
255 {
256 }
257
258 /*
259  * SMP support
260  */
261 int prom_setup_smp(void)
262 {
263         int     num_cpus = 2;
264
265         /*
266          * We know that the RM9000 on the Jaguar ATX board has 2 cores.
267          * Hence, this can be hardcoded for now.
268          */
269         return num_cpus;
270 }
271
272 int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
273 {
274         /* Clear the semaphore */
275         *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
276
277         return 1;
278 }
279
280 void prom_init_secondary(void)
281 {
282         clear_c0_config(CONF_CM_CMASK);
283         set_c0_config(0x2);
284
285         clear_c0_status(ST0_IM);
286         set_c0_status(0x1ffff);
287 }
288
289 void prom_smp_finish(void)
290 {
291 }