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