xref: /openbmc/u-boot/board/keymile/common/common.c (revision 6d0f6bcf)
1 /*
2  * (C) Copyright 2008
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 #include <mpc8260.h>
26 #include <ioports.h>
27 #include <malloc.h>
28 #include <hush.h>
29 
30 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
31 #include <libfdt.h>
32 #endif
33 
34 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
35 #include <i2c.h>
36 #endif
37 
38 extern int i2c_soft_read_pin (void);
39 
40 int ivm_calc_crc (unsigned char *buf, int len)
41 {
42 	const unsigned short crc_tab[16] = {
43 		0x0000, 0xCC01, 0xD801, 0x1400,
44 		0xF001, 0x3C00, 0x2800, 0xE401,
45 		0xA001, 0x6C00, 0x7800, 0xB401,
46 		0x5000, 0x9C01, 0x8801, 0x4400};
47 
48 	unsigned short crc     = 0;   /* final result */
49 	unsigned short r1      = 0;   /* temp */
50 	unsigned char  byte    = 0;   /* input buffer */
51 	int	i;
52 
53 	/* calculate CRC from array data */
54 	for (i = 0; i < len; i++) {
55 		byte = buf[i];
56 
57 		/* lower 4 bits */
58 		r1 = crc_tab[crc & 0xF];
59 		crc = ((crc) >> 4) & 0x0FFF;
60 		crc = crc ^ r1 ^ crc_tab[byte & 0xF];
61 
62 		/* upper 4 bits */
63 		r1 = crc_tab[crc & 0xF];
64 		crc = (crc >> 4) & 0x0FFF;
65 		crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF];
66 	}
67 	return crc;
68 }
69 
70 static int  ivm_set_value (char *name, char *value)
71 {
72 	char tempbuf[256];
73 
74 	if (value != NULL) {
75 		sprintf (tempbuf, "%s=%s", name, value);
76 		return set_local_var (tempbuf, 0);
77 	} else {
78 		unset_local_var (name);
79 	}
80 	return 0;
81 }
82 
83 static int ivm_get_value (unsigned char *buf, int len, char *name, int off,
84 				int check)
85 {
86 	unsigned short	val;
87 	unsigned char	valbuf[30];
88 
89 	if ((buf[off + 0] != buf[off + 2]) &&
90 	    (buf[off + 2] != buf[off + 4])) {
91 		printf ("%s Error corrupted %s\n", __FUNCTION__, name);
92 		val = -1;
93 	} else {
94 		val = buf[off + 0] + (buf[off + 1] << 8);
95 		if ((val == 0) && (check == 1))
96 			val = -1;
97 	}
98 	sprintf ((char *)valbuf, "%x", val);
99 	ivm_set_value (name, (char *)valbuf);
100 	return val;
101 }
102 
103 #define INVENTORYBLOCKSIZE	0x100
104 #define INVENTORYDATAADDRESS	0x21
105 #define INVENTORYDATASIZE	(INVENTORYBLOCKSIZE - INVENTORYDATAADDRESS - 3)
106 
107 #define IVM_POS_SHORT_TEXT		0
108 #define IVM_POS_MANU_ID			1
109 #define IVM_POS_MANU_SERIAL		2
110 #define IVM_POS_PART_NUMBER		3
111 #define IVM_POS_BUILD_STATE		4
112 #define IVM_POS_SUPPLIER_PART_NUMBER	5
113 #define IVM_POS_DELIVERY_DATE		6
114 #define IVM_POS_SUPPLIER_BUILD_STATE	7
115 #define IVM_POS_CUSTOMER_ID		8
116 #define IVM_POS_CUSTOMER_PROD_ID	9
117 #define IVM_POS_HISTORY			10
118 #define IVM_POS_SYMBOL_ONLY		11
119 
120 static char convert_char (char c)
121 {
122 	return (c < ' ' || c > '~') ? '.' : c;
123 }
124 
125 static int ivm_findinventorystring (int type,
126 					unsigned char* const string,
127 					unsigned long maxlen,
128 					unsigned char *buf)
129 {
130 	int xcode = 0;
131 	unsigned long cr = 0;
132 	unsigned long addr = INVENTORYDATAADDRESS;
133 	unsigned long size = 0;
134 	unsigned long nr = type;
135 	int stop = 0; 	/* stop on semicolon */
136 
137 	memset(string, '\0', maxlen);
138 	switch (type) {
139 		case IVM_POS_SYMBOL_ONLY:
140 			nr = 0;
141 			stop= 1;
142 		break;
143 		default:
144 			nr = type;
145 			stop = 0;
146 	}
147 
148 	/* Look for the requested number of CR. */
149 	while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
150 		if ((buf[addr] == '\r')) {
151 			cr++;
152 		}
153 		addr++;
154 	}
155 
156 	/* the expected number of CR was found until the end of the IVM
157 	 *  content --> fill string */
158 	if (addr < INVENTORYDATASIZE) {
159 		/* Copy the IVM string in the corresponding string */
160 		for (; (buf[addr] != '\r')			&&
161 			((buf[addr] != ';') ||  (!stop))	&&
162 			(size < (maxlen - 1)			&&
163 			(addr < INVENTORYDATASIZE)); addr++)
164 		{
165 			size += sprintf((char *)string + size, "%c",
166 						convert_char (buf[addr]));
167 		}
168 
169 		/* copy phase is done: check if everything is ok. If not,
170 		 * the inventory data is most probably corrupted: tell
171 		 * the world there is a problem! */
172 		if (addr == INVENTORYDATASIZE) {
173 			xcode = -1;
174 			printf ("Error end of string not found\n");
175 		} else if ((size >= (maxlen - 1)) &&
176 			   (buf[addr] != '\r')) {
177 			xcode = -1;
178 			printf ("string too long till next CR\n");
179 		}
180 	} else {
181 		/* some CR are missing...
182 		 * the inventory data is most probably corrupted */
183 		xcode = -1;
184 		printf ("not enough cr found\n");
185 	}
186 	return xcode;
187 }
188 
189 #define GET_STRING(name, which, len) \
190 	if (ivm_findinventorystring (which, valbuf, len, buf) == 0) { \
191 		ivm_set_value (name, (char *)valbuf); \
192 	}
193 
194 static int ivm_check_crc (unsigned char *buf, int block)
195 {
196 	unsigned long	crc;
197 	unsigned long	crceeprom;
198 
199 	crc = ivm_calc_crc (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
200 	crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
201 			buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
202 	if (crc != crceeprom) {
203 		printf ("Error CRC Block: %d EEprom: calculated: %lx EEprom: %lx\n",
204 			block, crc, crceeprom);
205 		return -1;
206 	}
207 	return 0;
208 }
209 
210 static int ivm_analyze_block2 (unsigned char *buf, int len)
211 {
212 	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
213 	unsigned long	count;
214 
215 	/* IVM_MacAddress */
216 	sprintf ((char *)valbuf, "%02X:%02X:%02X:%02X:%02X:%02X",
217 			buf[1],
218 			buf[2],
219 			buf[3],
220 			buf[4],
221 			buf[5],
222 			buf[6]);
223 	ivm_set_value ("IVM_MacAddress", (char *)valbuf);
224 	if (getenv ("ethaddr") == NULL)
225 		setenv ((char *)"ethaddr", (char *)valbuf);
226 	/* IVM_MacCount */
227 	count = (buf[10] << 24) +
228 		   (buf[11] << 16) +
229 		   (buf[12] << 8)  +
230 		    buf[13];
231 	if (count == 0xffffffff)
232 		count = 1;
233 	sprintf ((char *)valbuf, "%lx", count);
234 	ivm_set_value ("IVM_MacCount", (char *)valbuf);
235 	return 0;
236 }
237 
238 int ivm_analyze_eeprom (unsigned char *buf, int len)
239 {
240 	unsigned short	val;
241 	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
242 	unsigned char	*tmp;
243 
244 	if (ivm_check_crc (buf, 0) != 0)
245 		return -1;
246 
247 	ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_BoardId", 0, 1);
248 	val = ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_HWKey", 6, 1);
249 	if (val != 0xffff) {
250 		sprintf ((char *)valbuf, "%x", ((val /100) % 10));
251 		ivm_set_value ("IVM_HWVariant", (char *)valbuf);
252 		sprintf ((char *)valbuf, "%x", (val % 100));
253 		ivm_set_value ("IVM_HWVersion", (char *)valbuf);
254 	}
255 	ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_Functions", 12, 0);
256 
257 	GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
258 	GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
259 	tmp = (unsigned char *) getenv("IVM_DeviceName");
260 	if (tmp) {
261 		int	len = strlen ((char *)tmp);
262 		int	i = 0;
263 
264 		while (i < len) {
265 			if (tmp[i] == ';') {
266 				ivm_set_value ("IVM_ShortText", (char *)&tmp[i + 1]);
267 				break;
268 			}
269 			i++;
270 		}
271 		if (i >= len)
272 			ivm_set_value ("IVM_ShortText", NULL);
273 	} else {
274 		ivm_set_value ("IVM_ShortText", NULL);
275 	}
276 	GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
277 	GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
278 	GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
279 	GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
280 	GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
281 	GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
282 	GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
283 	GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
284 	GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
285 
286 	if (ivm_check_crc (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
287 		return -2;
288 	ivm_analyze_block2 (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
289 
290 	return 0;
291 }
292 
293 int ivm_read_eeprom (void)
294 {
295 	I2C_MUX_DEVICE *dev = NULL;
296 	uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
297 	uchar	*buf;
298 	unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
299 
300 	/* First init the Bus, select the Bus */
301 #if defined(CONFIG_SYS_I2C_IVM_BUS)
302 	dev = i2c_mux_ident_muxstring ((uchar *)CONFIG_SYS_I2C_IVM_BUS);
303 #else
304 	buf = (unsigned char *) getenv ("EEprom_ivm");
305 	if (buf != NULL)
306 		dev = i2c_mux_ident_muxstring (buf);
307 #endif
308 	if (dev == NULL) {
309 		printf ("Error couldnt add Bus for IVM\n");
310 		return -1;
311 	}
312 	i2c_set_bus_num (dev->busid);
313 
314 	buf = (unsigned char *) getenv ("EEprom_ivm_addr");
315 	if (buf != NULL)
316 		dev_addr = simple_strtoul ((char *)buf, NULL, 16);
317 
318 	if (eeprom_read (dev_addr, 0, i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN) != 0) {
319 		printf ("Error reading EEprom\n");
320 		return -2;
321 	}
322 
323 	return ivm_analyze_eeprom (i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
324 }
325 
326 #if defined(CONFIG_SYS_I2C_INIT_BOARD)
327 #define DELAY_ABORT_SEQ		62
328 #define DELAY_HALF_PERIOD	(500 / (CONFIG_SYS_I2C_SPEED / 1000))
329 
330 #if defined(CONFIG_MGCOGE)
331 #define SDA_MASK	0x00010000
332 #define SCL_MASK	0x00020000
333 static void set_pin (int state, unsigned long mask)
334 {
335 	volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
336 
337 	if (state)
338 		iop->pdat |= (mask);
339 	else
340 		iop->pdat &= ~(mask);
341 
342 	iop->pdir |= (mask);
343 }
344 
345 static int get_pin (unsigned long mask)
346 {
347 	volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
348 
349 	iop->pdir &= ~(mask);
350 	return (0 != (iop->pdat & (mask)));
351 }
352 
353 static void set_sda (int state)
354 {
355 	set_pin (state, SDA_MASK);
356 }
357 
358 static void set_scl (int state)
359 {
360 	set_pin (state, SCL_MASK);
361 }
362 
363 static int get_sda (void)
364 {
365 	return get_pin (SDA_MASK);
366 }
367 
368 static int get_scl (void)
369 {
370 	return get_pin (SCL_MASK);
371 }
372 
373 #if defined(CONFIG_HARD_I2C)
374 static void setports (int gpio)
375 {
376 	volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
377 
378 	if (gpio) {
379 		iop->ppar &= ~(SDA_MASK | SCL_MASK);
380 		iop->podr &= ~(SDA_MASK | SCL_MASK);
381 	} else {
382 		iop->ppar |= (SDA_MASK | SCL_MASK);
383 		iop->pdir &= ~(SDA_MASK | SCL_MASK);
384 		iop->podr |= (SDA_MASK | SCL_MASK);
385 	}
386 }
387 #endif
388 #endif
389 
390 #if defined(CONFIG_MGSUVD)
391 static void set_sda (int state)
392 {
393 	I2C_SDA(state);
394 }
395 
396 static void set_scl (int state)
397 {
398 	I2C_SCL(state);
399 }
400 
401 static int get_sda (void)
402 {
403 	return i2c_soft_read_pin ();
404 }
405 
406 static int get_scl (void)
407 {
408 	int	val;
409 
410 	*(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF;
411 	udelay (1);
412 	val = *(unsigned char *)(I2C_BASE_PORT);
413 
414 	return ((val & SCL_BIT) == SCL_BIT);
415 }
416 
417 #endif
418 
419 static void writeStartSeq (void)
420 {
421 	set_sda (1);
422 	udelay (DELAY_HALF_PERIOD);
423 	set_scl (1);
424 	udelay (DELAY_HALF_PERIOD);
425 	set_sda (0);
426 	udelay (DELAY_HALF_PERIOD);
427 	set_scl (0);
428 	udelay (DELAY_HALF_PERIOD);
429 }
430 
431 /* I2C is a synchronous protocol and resets of the processor in the middle
432    of an access can block the I2C Bus until a powerdown of the full unit is
433    done. This function toggles the SCL until the SCL and SCA line are
434    released, but max. 16 times, after this a I2C start-sequence is sent.
435    This I2C Deblocking mechanism was developed by Keymile in association
436    with Anatech and Atmel in 1998.
437  */
438 static int i2c_make_abort (void)
439 {
440 	int	scl_state = 0;
441 	int	sda_state = 0;
442 	int	i = 0;
443 	int	ret = 0;
444 
445 	if (!get_sda ()) {
446 		ret = -1;
447 		while (i < 16) {
448 			i++;
449 			set_scl (0);
450 			udelay (DELAY_ABORT_SEQ);
451 			set_scl (1);
452 			udelay (DELAY_ABORT_SEQ);
453 			scl_state = get_scl ();
454 			sda_state = get_sda ();
455 			if (scl_state && sda_state) {
456 				ret = 0;
457 				break;
458 			}
459 		}
460 	}
461 	if (ret == 0) {
462 		for (i =0; i < 5; i++) {
463 			writeStartSeq ();
464 		}
465 	}
466 	get_sda ();
467 	return ret;
468 }
469 
470 /**
471  * i2c_init_board - reset i2c bus. When the board is powercycled during a
472  * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
473  */
474 void i2c_init_board(void)
475 {
476 #if defined(CONFIG_HARD_I2C)
477 	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
478 	volatile i2c8260_t *i2c	= (i2c8260_t *)&immap->im_i2c;
479 
480 	/* disable I2C controller first, otherwhise it thinks we want to    */
481 	/* talk to the slave port...                                        */
482 	i2c->i2c_i2mod &= ~0x01;
483 
484 	/* Set the PortPins to GPIO */
485 	setports (1);
486 #endif
487 
488 	/* Now run the AbortSequence() */
489 	i2c_make_abort ();
490 
491 #if defined(CONFIG_HARD_I2C)
492 	/* Set the PortPins back to use for I2C */
493 	setports (0);
494 #endif
495 }
496 #endif
497