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