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