Merge branch 'linus' into core/softirq
[linux-2.6] / arch / mips / lasat / lasat_board.c
1 /*
2  * Thomas Horsten <thh@lasat.com>
3  * Copyright (C) 2000 LASAT Networks A/S.
4  *
5  *  This program is free software; you can distribute it and/or modify it
6  *  under the terms of the GNU General Public License (Version 2) as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope it will be useful, but WITHOUT
10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  *  for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17  *
18  * Routines specific to the LASAT boards
19  */
20 #include <linux/types.h>
21 #include <linux/crc32.h>
22 #include <asm/lasat/lasat.h>
23 #include <linux/kernel.h>
24 #include <linux/string.h>
25 #include <linux/ctype.h>
26 #include <linux/mutex.h>
27 #include <asm/bootinfo.h>
28 #include <asm/addrspace.h>
29 #include "at93c.h"
30 /* New model description table */
31 #include "lasat_models.h"
32
33 static DEFINE_MUTEX(lasat_eeprom_mutex);
34
35 #define EEPROM_CRC(data, len) (~crc32(~0, data, len))
36
37 struct lasat_info lasat_board_info;
38
39 int EEPROMRead(unsigned int pos, unsigned char *data, int len)
40 {
41         int i;
42
43         for (i = 0; i < len; i++)
44                 *data++ = at93c_read(pos++);
45
46         return 0;
47 }
48
49 int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
50 {
51         int i;
52
53         for (i = 0; i < len; i++)
54                 at93c_write(pos++, *data++);
55
56         return 0;
57 }
58
59 static void init_flash_sizes(void)
60 {
61         unsigned long *lb = lasat_board_info.li_flashpart_base;
62         unsigned long *ls = lasat_board_info.li_flashpart_size;
63         int i;
64
65         ls[LASAT_MTD_BOOTLOADER] = 0x40000;
66         ls[LASAT_MTD_SERVICE] = 0xC0000;
67         ls[LASAT_MTD_NORMAL] = 0x100000;
68
69         if (mips_machtype == MACH_LASAT_100) {
70                 lasat_board_info.li_flash_base = 0x1e000000;
71
72                 lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
73
74                 if (lasat_board_info.li_flash_size > 0x200000) {
75                         ls[LASAT_MTD_CONFIG] = 0x100000;
76                         ls[LASAT_MTD_FS] = 0x500000;
77                 }
78         } else {
79                 lasat_board_info.li_flash_base = 0x10000000;
80
81                 if (lasat_board_info.li_flash_size < 0x1000000) {
82                         lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
83                         ls[LASAT_MTD_CONFIG] = 0x100000;
84                         if (lasat_board_info.li_flash_size >= 0x400000)
85                                 ls[LASAT_MTD_FS] =
86                                      lasat_board_info.li_flash_size - 0x300000;
87                 }
88         }
89
90         for (i = 1; i < LASAT_MTD_LAST; i++)
91                 lb[i] = lb[i-1] + ls[i-1];
92 }
93
94 int lasat_init_board_info(void)
95 {
96         int c;
97         unsigned long crc;
98         unsigned long cfg0, cfg1;
99         const struct product_info   *ppi;
100         int i_n_base_models = N_BASE_MODELS;
101         const char * const * i_txt_base_models = txt_base_models;
102         int i_n_prids = N_PRIDS;
103
104         memset(&lasat_board_info, 0, sizeof(lasat_board_info));
105
106         /* First read the EEPROM info */
107         EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
108                    sizeof(struct lasat_eeprom_struct));
109
110         /* Check the CRC */
111         crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
112                     sizeof(struct lasat_eeprom_struct) - 4);
113
114         if (crc != lasat_board_info.li_eeprom_info.crc32) {
115                 printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
116                        "not match calculated, attempting to soldier on...\n");
117         }
118
119         if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
120                 printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
121                        "%d, wanted version %d, attempting to soldier on...\n",
122                        (unsigned int)lasat_board_info.li_eeprom_info.version,
123                        LASAT_EEPROM_VERSION);
124         }
125
126         cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
127         cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
128
129         if (LASAT_W0_DSCTYPE(cfg0) != 1) {
130                 printk(KERN_WARNING "WARNING...\nWARNING...\n"
131                        "Invalid configuration read from EEPROM, attempting to "
132                        "soldier on...");
133         }
134         /* We have a valid configuration */
135
136         switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
137         case 0:
138                 lasat_board_info.li_memsize = 0x0800000;
139                 break;
140         case 1:
141                 lasat_board_info.li_memsize = 0x1000000;
142                 break;
143         case 2:
144                 lasat_board_info.li_memsize = 0x2000000;
145                 break;
146         case 3:
147                 lasat_board_info.li_memsize = 0x4000000;
148                 break;
149         case 4:
150                 lasat_board_info.li_memsize = 0x8000000;
151                 break;
152         default:
153                 lasat_board_info.li_memsize = 0;
154         }
155
156         switch (LASAT_W0_SDRAMBANKS(cfg0)) {
157         case 0:
158                 break;
159         case 1:
160                 lasat_board_info.li_memsize *= 2;
161                 break;
162         default:
163                 break;
164         }
165
166         switch (LASAT_W0_BUSSPEED(cfg0)) {
167         case 0x0:
168                 lasat_board_info.li_bus_hz = 60000000;
169                 break;
170         case 0x1:
171                 lasat_board_info.li_bus_hz = 66000000;
172                 break;
173         case 0x2:
174                 lasat_board_info.li_bus_hz = 66666667;
175                 break;
176         case 0x3:
177                 lasat_board_info.li_bus_hz = 80000000;
178                 break;
179         case 0x4:
180                 lasat_board_info.li_bus_hz = 83333333;
181                 break;
182         case 0x5:
183                 lasat_board_info.li_bus_hz = 100000000;
184                 break;
185         }
186
187         switch (LASAT_W0_CPUCLK(cfg0)) {
188         case 0x0:
189                 lasat_board_info.li_cpu_hz =
190                         lasat_board_info.li_bus_hz;
191                 break;
192         case 0x1:
193                 lasat_board_info.li_cpu_hz =
194                         lasat_board_info.li_bus_hz +
195                         (lasat_board_info.li_bus_hz >> 1);
196                 break;
197         case 0x2:
198                 lasat_board_info.li_cpu_hz =
199                         lasat_board_info.li_bus_hz +
200                         lasat_board_info.li_bus_hz;
201                 break;
202         case 0x3:
203                 lasat_board_info.li_cpu_hz =
204                         lasat_board_info.li_bus_hz +
205                         lasat_board_info.li_bus_hz +
206                         (lasat_board_info.li_bus_hz >> 1);
207                 break;
208         case 0x4:
209                 lasat_board_info.li_cpu_hz =
210                         lasat_board_info.li_bus_hz +
211                         lasat_board_info.li_bus_hz +
212                         lasat_board_info.li_bus_hz;
213                 break;
214         }
215
216         /* Flash size */
217         switch (LASAT_W1_FLASHSIZE(cfg1)) {
218         case 0:
219                 lasat_board_info.li_flash_size = 0x200000;
220                 break;
221         case 1:
222                 lasat_board_info.li_flash_size = 0x400000;
223                 break;
224         case 2:
225                 lasat_board_info.li_flash_size = 0x800000;
226                 break;
227         case 3:
228                 lasat_board_info.li_flash_size = 0x1000000;
229                 break;
230         case 4:
231                 lasat_board_info.li_flash_size = 0x2000000;
232                 break;
233         }
234
235         init_flash_sizes();
236
237         lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
238         lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
239         if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
240                 lasat_board_info.li_prid = lasat_board_info.li_bmid;
241
242         /* Base model stuff */
243         if (lasat_board_info.li_bmid > i_n_base_models)
244                 lasat_board_info.li_bmid = i_n_base_models;
245         strcpy(lasat_board_info.li_bmstr,
246                i_txt_base_models[lasat_board_info.li_bmid]);
247
248         /* Product ID dependent values */
249         c = lasat_board_info.li_prid;
250         if (c >= i_n_prids) {
251                 strcpy(lasat_board_info.li_namestr, "Unknown Model");
252                 strcpy(lasat_board_info.li_typestr, "Unknown Type");
253         } else {
254                 ppi = &vendor_info_table[0].vi_product_info[c];
255                 strcpy(lasat_board_info.li_namestr, ppi->pi_name);
256                 if (ppi->pi_type)
257                         strcpy(lasat_board_info.li_typestr, ppi->pi_type);
258                 else
259                         sprintf(lasat_board_info.li_typestr, "%d", 10 * c);
260         }
261
262         return 0;
263 }
264
265 void lasat_write_eeprom_info(void)
266 {
267         unsigned long crc;
268
269         mutex_lock(&lasat_eeprom_mutex);
270
271         /* Generate the CRC */
272         crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
273                     sizeof(struct lasat_eeprom_struct) - 4);
274         lasat_board_info.li_eeprom_info.crc32 = crc;
275
276         /* Write the EEPROM info */
277         EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
278                     sizeof(struct lasat_eeprom_struct));
279
280         mutex_unlock(&lasat_eeprom_mutex);
281 }