]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/keymile/common/common.c
ppc: add support for ppc based board mgcoge2ne
[karo-tx-uboot.git] / board / keymile / common / common.c
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 #if defined(CONFIG_MGCOGE) || defined(CONFIG_MGCOGE2NE)
26 #include <mpc8260.h>
27 #endif
28 #include <ioports.h>
29 #include <malloc.h>
30 #include <hush.h>
31 #include <net.h>
32 #include <netdev.h>
33 #include <asm/io.h>
34
35 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
36 #include <libfdt.h>
37 #endif
38
39 #include "../common/common.h"
40 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
41 #include <i2c.h>
42
43 int ivm_calc_crc(unsigned char *buf, int len)
44 {
45         const unsigned short crc_tab[16] = {
46                 0x0000, 0xCC01, 0xD801, 0x1400,
47                 0xF001, 0x3C00, 0x2800, 0xE401,
48                 0xA001, 0x6C00, 0x7800, 0xB401,
49                 0x5000, 0x9C01, 0x8801, 0x4400};
50
51         unsigned short crc     = 0;   /* final result */
52         unsigned short r1      = 0;   /* temp */
53         unsigned char  byte    = 0;   /* input buffer */
54         int     i;
55
56         /* calculate CRC from array data */
57         for (i = 0; i < len; i++) {
58                 byte = buf[i];
59
60                 /* lower 4 bits */
61                 r1 = crc_tab[crc & 0xF];
62                 crc = ((crc) >> 4) & 0x0FFF;
63                 crc = crc ^ r1 ^ crc_tab[byte & 0xF];
64
65                 /* upper 4 bits */
66                 r1 = crc_tab[crc & 0xF];
67                 crc = (crc >> 4) & 0x0FFF;
68                 crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF];
69         }
70         return crc;
71 }
72
73 static int ivm_set_value(char *name, char *value)
74 {
75         char tempbuf[256];
76
77         if (value != NULL) {
78                 sprintf(tempbuf, "%s=%s", name, value);
79                 return set_local_var(tempbuf, 0);
80         } else {
81                 unset_local_var(name);
82         }
83         return 0;
84 }
85
86 static int ivm_get_value(unsigned char *buf, int len, char *name, int off,
87                                 int check)
88 {
89         unsigned short  val;
90         unsigned char   valbuf[30];
91
92         if ((buf[off + 0] != buf[off + 2]) &&
93             (buf[off + 2] != buf[off + 4])) {
94                 printf("%s Error corrupted %s\n", __func__, name);
95                 val = -1;
96         } else {
97                 val = buf[off + 0] + (buf[off + 1] << 8);
98                 if ((val == 0) && (check == 1))
99                         val = -1;
100         }
101         sprintf((char *)valbuf, "%x", val);
102         ivm_set_value(name, (char *)valbuf);
103         return val;
104 }
105
106 #define INV_BLOCKSIZE           0x100
107 #define INV_DATAADDRESS         0x21
108 #define INVENTORYDATASIZE       (INV_BLOCKSIZE - INV_DATAADDRESS - 3)
109
110 #define IVM_POS_SHORT_TEXT              0
111 #define IVM_POS_MANU_ID                 1
112 #define IVM_POS_MANU_SERIAL             2
113 #define IVM_POS_PART_NUMBER             3
114 #define IVM_POS_BUILD_STATE             4
115 #define IVM_POS_SUPPLIER_PART_NUMBER    5
116 #define IVM_POS_DELIVERY_DATE           6
117 #define IVM_POS_SUPPLIER_BUILD_STATE    7
118 #define IVM_POS_CUSTOMER_ID             8
119 #define IVM_POS_CUSTOMER_PROD_ID        9
120 #define IVM_POS_HISTORY                 10
121 #define IVM_POS_SYMBOL_ONLY             11
122
123 static char convert_char(char c)
124 {
125         return (c < ' ' || c > '~') ? '.' : c;
126 }
127
128 static int ivm_findinventorystring(int type,
129                                         unsigned char* const string,
130                                         unsigned long maxlen,
131                                         unsigned char *buf)
132 {
133         int xcode = 0;
134         unsigned long cr = 0;
135         unsigned long addr = INV_DATAADDRESS;
136         unsigned long size = 0;
137         unsigned long nr = type;
138         int stop = 0;   /* stop on semicolon */
139
140         memset(string, '\0', maxlen);
141         switch (type) {
142                 case IVM_POS_SYMBOL_ONLY:
143                         nr = 0;
144                         stop= 1;
145                 break;
146                 default:
147                         nr = type;
148                         stop = 0;
149         }
150
151         /* Look for the requested number of CR. */
152         while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
153                 if ((buf[addr] == '\r')) {
154                         cr++;
155                 }
156                 addr++;
157         }
158
159         /*
160          * the expected number of CR was found until the end of the IVM
161          *  content --> fill string
162          */
163         if (addr < INVENTORYDATASIZE) {
164                 /* Copy the IVM string in the corresponding string */
165                 for (; (buf[addr] != '\r')                      &&
166                         ((buf[addr] != ';') ||  (!stop))        &&
167                         (size < (maxlen - 1)                    &&
168                         (addr < INVENTORYDATASIZE)); addr++)
169                 {
170                         size += sprintf((char *)string + size, "%c",
171                                                 convert_char (buf[addr]));
172                 }
173
174                 /*
175                  * copy phase is done: check if everything is ok. If not,
176                  * the inventory data is most probably corrupted: tell
177                  * the world there is a problem!
178                  */
179                 if (addr == INVENTORYDATASIZE) {
180                         xcode = -1;
181                         printf("Error end of string not found\n");
182                 } else if ((size >= (maxlen - 1)) &&
183                            (buf[addr] != '\r')) {
184                         xcode = -1;
185                         printf("string too long till next CR\n");
186                 }
187         } else {
188                 /*
189                  * some CR are missing...
190                  * the inventory data is most probably corrupted
191                  */
192                 xcode = -1;
193                 printf("not enough cr found\n");
194         }
195         return xcode;
196 }
197
198 #define GET_STRING(name, which, len) \
199         if (ivm_findinventorystring(which, valbuf, len, buf) == 0) { \
200                 ivm_set_value(name, (char *)valbuf); \
201         }
202
203 static int ivm_check_crc(unsigned char *buf, int block)
204 {
205         unsigned long   crc;
206         unsigned long   crceeprom;
207
208         crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
209         crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
210                         buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
211         if (crc != crceeprom) {
212                 if (block == 0)
213                         printf("Error CRC Block: %d EEprom: calculated: \
214                         %lx EEprom: %lx\n", block, crc, crceeprom);
215                 return -1;
216         }
217         return 0;
218 }
219
220 static int ivm_analyze_block2(unsigned char *buf, int len)
221 {
222         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
223         unsigned long   count;
224
225         /* IVM_MacAddress */
226         sprintf((char *)valbuf, "%pM", buf);
227         ivm_set_value("IVM_MacAddress", (char *)valbuf);
228         if (getenv("ethaddr") == NULL)
229                 setenv((char *)"ethaddr", (char *)valbuf);
230         /* IVM_MacCount */
231         count = (buf[10] << 24) +
232                    (buf[11] << 16) +
233                    (buf[12] << 8)  +
234                     buf[13];
235         if (count == 0xffffffff)
236                 count = 1;
237         sprintf((char *)valbuf, "%lx", count);
238         ivm_set_value("IVM_MacCount", (char *)valbuf);
239         return 0;
240 }
241
242 int ivm_analyze_eeprom(unsigned char *buf, int len)
243 {
244         unsigned short  val;
245         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
246         unsigned char   *tmp;
247
248         if (ivm_check_crc(buf, 0) != 0)
249                 return -1;
250
251         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
252                         "IVM_BoardId", 0, 1);
253         val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
254                         "IVM_HWKey", 6, 1);
255         if (val != 0xffff) {
256                 sprintf((char *)valbuf, "%x", ((val / 100) % 10));
257                 ivm_set_value("IVM_HWVariant", (char *)valbuf);
258                 sprintf((char *)valbuf, "%x", (val % 100));
259                 ivm_set_value("IVM_HWVersion", (char *)valbuf);
260         }
261         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
262                 "IVM_Functions", 12, 0);
263
264         GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
265         GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
266         tmp = (unsigned char *) getenv("IVM_DeviceName");
267         if (tmp) {
268                 int     len = strlen((char *)tmp);
269                 int     i = 0;
270
271                 while (i < len) {
272                         if (tmp[i] == ';') {
273                                 ivm_set_value("IVM_ShortText",
274                                         (char *)&tmp[i + 1]);
275                                 break;
276                         }
277                         i++;
278                 }
279                 if (i >= len)
280                         ivm_set_value("IVM_ShortText", NULL);
281         } else {
282                 ivm_set_value("IVM_ShortText", NULL);
283         }
284         GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
285         GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
286         GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
287         GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
288         GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
289         GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
290         GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
291         GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
292         GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
293
294         if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
295                 return 0;
296         ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2],
297                 CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
298
299         return 0;
300 }
301
302 int ivm_read_eeprom(void)
303 {
304 #if defined(CONFIG_I2C_MUX)
305         I2C_MUX_DEVICE *dev = NULL;
306 #endif
307         uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
308         uchar   *buf;
309         unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
310         int ret;
311
312 #if defined(CONFIG_I2C_MUX)
313         /* First init the Bus, select the Bus */
314 #if defined(CONFIG_SYS_I2C_IVM_BUS)
315         dev = i2c_mux_ident_muxstring((uchar *)CONFIG_SYS_I2C_IVM_BUS);
316 #else
317         buf = (unsigned char *) getenv("EEprom_ivm");
318         if (buf != NULL)
319                 dev = i2c_mux_ident_muxstring(buf);
320 #endif
321         if (dev == NULL) {
322                 printf("Error couldnt add Bus for IVM\n");
323                 return -1;
324         }
325         i2c_set_bus_num(dev->busid);
326 #endif
327
328         buf = (unsigned char *) getenv("EEprom_ivm_addr");
329         if (buf != NULL)
330                 dev_addr = simple_strtoul((char *)buf, NULL, 16);
331
332         ret = i2c_read(dev_addr, 0, 1, i2c_buffer,
333                         CONFIG_SYS_IVM_EEPROM_MAX_LEN);
334         if (ret != 0) {
335                 printf ("Error reading EEprom\n");
336                 return -2;
337         }
338
339         return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
340 }
341
342 #if defined(CONFIG_SYS_I2C_INIT_BOARD)
343 #define DELAY_ABORT_SEQ         62
344 #define DELAY_HALF_PERIOD       (500 / (CONFIG_SYS_I2C_SPEED / 1000))
345
346 #if defined(CONFIG_MGCOGE) || defined(CONFIG_MGCOGE2NE)
347 #define SDA_MASK        0x00010000
348 #define SCL_MASK        0x00020000
349 static void set_pin(int state, unsigned long mask)
350 {
351         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
352
353         if (state)
354                 setbits_be32(&iop->pdat, mask);
355         else
356                 clrbits_be32(&iop->pdat, mask);
357
358         setbits_be32(&iop->pdir, mask);
359 }
360
361 static int get_pin(unsigned long mask)
362 {
363         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
364
365         clrbits_be32(&iop->pdir, mask);
366         return 0 != (in_be32(&iop->pdat) & mask);
367 }
368
369 static void set_sda(int state)
370 {
371         set_pin(state, SDA_MASK);
372 }
373
374 static void set_scl(int state)
375 {
376         set_pin(state, SCL_MASK);
377 }
378
379 static int get_sda(void)
380 {
381         return get_pin(SDA_MASK);
382 }
383
384 static int get_scl(void)
385 {
386         return get_pin(SCL_MASK);
387 }
388
389 #if defined(CONFIG_HARD_I2C)
390 static void setports(int gpio)
391 {
392         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
393
394         if (gpio) {
395                 clrbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
396                 clrbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
397         } else {
398                 setbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
399                 clrbits_be32(&iop->pdir, (SDA_MASK | SCL_MASK));
400                 setbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
401         }
402 }
403 #endif
404 #endif
405
406 #if !defined(CONFIG_MPC83xx)
407 static void writeStartSeq(void)
408 {
409         set_sda(1);
410         udelay(DELAY_HALF_PERIOD);
411         set_scl(1);
412         udelay(DELAY_HALF_PERIOD);
413         set_sda(0);
414         udelay(DELAY_HALF_PERIOD);
415         set_scl(0);
416         udelay(DELAY_HALF_PERIOD);
417 }
418
419 /*
420  * I2C is a synchronous protocol and resets of the processor in the middle
421  * of an access can block the I2C Bus until a powerdown of the full unit is
422  * done. This function toggles the SCL until the SCL and SCA line are
423  * released, but max. 16 times, after this a I2C start-sequence is sent.
424  * This I2C Deblocking mechanism was developed by Keymile in association
425  * with Anatech and Atmel in 1998.
426  */
427 static int i2c_make_abort(void)
428 {
429         int     scl_state = 0;
430         int     sda_state = 0;
431         int     i = 0;
432         int     ret = 0;
433
434         if (!get_sda()) {
435                 ret = -1;
436                 while (i < 16) {
437                         i++;
438                         set_scl(0);
439                         udelay(DELAY_ABORT_SEQ);
440                         set_scl(1);
441                         udelay(DELAY_ABORT_SEQ);
442                         scl_state = get_scl();
443                         sda_state = get_sda();
444                         if (scl_state && sda_state) {
445                                 ret = 0;
446                                 break;
447                         }
448                 }
449         }
450         if (ret == 0)
451                 for (i = 0; i < 5; i++)
452                         writeStartSeq();
453
454         get_sda();
455         return ret;
456 }
457 #endif
458
459 /*
460  * i2c_init_board - reset i2c bus. When the board is powercycled during a
461  * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
462  */
463 void i2c_init_board(void)
464 {
465 #if defined(CONFIG_MPC83xx)
466         struct fsl_i2c *dev;
467         dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
468         uchar   dummy;
469
470         out_8(&dev->cr, (I2C_CR_MSTA));
471         out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
472         dummy = in_8(&dev->dr);
473         dummy = in_8(&dev->dr);
474         if (dummy != 0xff) {
475                 dummy = in_8(&dev->dr);
476         }
477         out_8(&dev->cr, (I2C_CR_MEN));
478         out_8(&dev->cr, 0x00);
479         out_8(&dev->cr, (I2C_CR_MEN));
480 #else
481 #if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD)
482         immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
483         i2c8260_t *i2c  = (i2c8260_t *)&immap->im_i2c;
484
485         /*
486          * disable I2C controller first, otherwhise it thinks we want to
487          * talk to the slave port...
488          */
489         clrbits_8(&i2c->i2c_i2mod, 0x01);
490
491         /* Set the PortPins to GPIO */
492         setports(1);
493 #endif
494
495         /* Now run the AbortSequence() */
496         i2c_make_abort();
497
498 #if defined(CONFIG_HARD_I2C)
499         /* Set the PortPins back to use for I2C */
500         setports(0);
501 #endif
502 #endif
503 }
504 #endif
505 #endif
506
507 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
508 int fdt_set_node_and_value(void *blob,
509                                 char *nodename,
510                                 char *regname,
511                                 void *var,
512                                 int size)
513 {
514         int ret = 0;
515         int nodeoffset = 0;
516
517         nodeoffset = fdt_path_offset(blob, nodename);
518         if (nodeoffset >= 0) {
519                 ret = fdt_setprop(blob, nodeoffset, regname, var,
520                                         size);
521                 if (ret < 0)
522                         printf("ft_blob_update(): cannot set %s/%s "
523                                 "property err:%s\n", nodename, regname,
524                                 fdt_strerror(ret));
525         } else {
526                 printf("ft_blob_update(): cannot find %s node "
527                         "err:%s\n", nodename, fdt_strerror(nodeoffset));
528         }
529         return ret;
530 }
531
532 int fdt_get_node_and_value(void *blob,
533                                 char *nodename,
534                                 char *propname,
535                                 void **var)
536 {
537         int len;
538         int nodeoffset = 0;
539
540         nodeoffset = fdt_path_offset(blob, nodename);
541         if (nodeoffset >= 0) {
542                 *var = (void *)fdt_getprop(blob, nodeoffset, propname, &len);
543                 if (len == 0) {
544                         /* no value */
545                         printf("%s no value\n", __func__);
546                         return -1;
547                 } else if (len > 0) {
548                         return len;
549                 } else {
550                         printf("libfdt fdt_getprop(): %s\n",
551                                 fdt_strerror(len));
552                         return -2;
553                 }
554         } else {
555                 printf("%s: cannot find %s node err:%s\n", __func__,
556                         nodename, fdt_strerror(nodeoffset));
557                 return -3;
558         }
559 }
560 #endif
561
562 #if !defined(MACH_TYPE_KM_KIRKWOOD)
563 int ethernet_present(void)
564 {
565         struct km_bec_fpga *base = (struct km_bec_fpga *)CONFIG_SYS_PIGGY_BASE;
566
567         return in_8(&base->bprth) & PIGGY_PRESENT;
568 }
569 #endif
570
571 int board_eth_init(bd_t *bis)
572 {
573 #ifdef CONFIG_KEYMILE_HDLC_ENET
574         (void)keymile_hdlc_enet_initialize(bis);
575 #endif
576         if (ethernet_present())
577                 return cpu_eth_init(bis);
578
579         return -1;
580 }