more changes on original files
[linux-2.4.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 #include <linux/config.h>
18 #include <linux/init.h>
19 #include <linux/mm.h>
20 #include <linux/sched.h>
21 #include <linux/bootmem.h>
22
23 #include <asm/addrspace.h>
24 #include <asm/bootinfo.h>
25 #include <asm/mv64340.h>
26
27 #include "jaguar_atx_fpga.h"
28
29
30 struct callvectors {
31         int     (*open) (char*, int, int);
32         int     (*close) (int);
33         int     (*read) (int, void*, int);
34         int     (*write) (int, void*, int);
35         off_t   (*lseek) (int, off_t, int);
36         int     (*printf) (const char*, ...);
37         void    (*cacheflush) (void);
38         char*   (*gets) (char*);
39 };
40
41 struct callvectors* debug_vectors;
42 char arcs_cmdline[CL_SIZE];
43
44 extern unsigned long mv64340_base;
45 extern unsigned long cpu_clock;
46
47 #ifdef CONFIG_MV64340_ETH
48 extern unsigned char prom_mac_addr_base[6];
49 #endif
50
51 const char *get_system_type(void)
52 {
53         return "Momentum Jaguar-ATX";
54 }
55
56 #ifdef CONFIG_MV64340_ETH
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
105 #ifdef CONFIG_MIPS64
106
107 unsigned long signext(unsigned long addr)
108 {
109   addr &= 0xffffffff;
110   return (unsigned long)((int)addr);
111 }
112
113 void *get_arg(unsigned long args, int arc)
114 {
115   unsigned long ul;
116   unsigned char *puc, uc;
117
118   args += (arc * 4);
119   ul = (unsigned long)signext(args);
120   puc = (unsigned char *)ul;
121   if (puc == 0)
122     return (void *)0;
123
124 #ifdef CONFIG_CPU_LITTLE_ENDIAN
125   uc = *puc++;
126   ul = (unsigned long)uc;
127   uc = *puc++;
128   ul |= (((unsigned long)uc) << 8);
129   uc = *puc++;
130   ul |= (((unsigned long)uc) << 16);
131   uc = *puc++;
132   ul |= (((unsigned long)uc) << 24);
133 #else
134   uc = *puc++;
135   ul = ((unsigned long)uc) << 24;
136   uc = *puc++;
137   ul |= (((unsigned long)uc) << 16);
138   uc = *puc++;
139   ul |= (((unsigned long)uc) << 8);
140   uc = *puc++;
141   ul |= ((unsigned long)uc);
142 #endif
143   ul = signext(ul);
144   return (void *)ul;
145 }
146
147 char *arg64(unsigned long addrin, int arg_index)
148 {
149   unsigned long args;
150   char *p;
151   args = signext(addrin);
152   p = (char *)get_arg(args, arg_index);
153   return p;
154 }
155 #endif  /* CONFIG_MIPS64 */
156
157 /* PMON passes arguments in C main() style */
158 void __init prom_init(int argc, char **arg, char **env, struct callvectors *cv)
159 {
160         int i;
161 #ifdef CONFIG_MIPS64
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                         mv64340_base = simple_strtol(ptr + strlen("gtbase="),
188                                                         NULL, 16);
189
190                         if ((mv64340_base & 0xffffffff00000000) == 0)
191                                 mv64340_base |= 0xffffffff00000000;
192
193                         printk("mv64340_base set to 0x%016lx\n", mv64340_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_MIPS64 */
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                         mv64340_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_MIPS64 */
230         mips_machgroup = MACH_GROUP_MOMENCO;
231         mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
232
233 #ifdef CONFIG_MV64340_ETH
234         /* get the base MAC address for on-board ethernet ports */
235         get_mac(prom_mac_addr_base);
236 #endif
237
238 #ifndef CONFIG_MIPS64
239         debug_vectors->printf("Booting Linux kernel...\n");
240 #endif
241 }
242
243 void __init prom_free_prom_memory(void)
244 {
245 }
246
247 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
248 {
249 }