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