uboot/board/keymile/common/common.c
<<
>>
Prefs
   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#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
  39#include <i2c.h>
  40
  41extern int i2c_soft_read_pin (void);
  42
  43int 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
  73static 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
  86static 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", __FUNCTION__, 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 INVENTORYBLOCKSIZE      0x100
 107#define INVENTORYDATAADDRESS    0x21
 108#define INVENTORYDATASIZE       (INVENTORYBLOCKSIZE - INVENTORYDATAADDRESS - 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
 123static char convert_char (char c)
 124{
 125        return (c < ' ' || c > '~') ? '.' : c;
 126}
 127
 128static 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 = INVENTORYDATAADDRESS;
 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        /* the expected number of CR was found until the end of the IVM
 160         *  content --> fill string */
 161        if (addr < INVENTORYDATASIZE) {
 162                /* Copy the IVM string in the corresponding string */
 163                for (; (buf[addr] != '\r')                      &&
 164                        ((buf[addr] != ';') ||  (!stop))        &&
 165                        (size < (maxlen - 1)                    &&
 166                        (addr < INVENTORYDATASIZE)); addr++)
 167                {
 168                        size += sprintf((char *)string + size, "%c",
 169                                                convert_char (buf[addr]));
 170                }
 171
 172                /* copy phase is done: check if everything is ok. If not,
 173                 * the inventory data is most probably corrupted: tell
 174                 * the world there is a problem! */
 175                if (addr == INVENTORYDATASIZE) {
 176                        xcode = -1;
 177                        printf ("Error end of string not found\n");
 178                } else if ((size >= (maxlen - 1)) &&
 179                           (buf[addr] != '\r')) {
 180                        xcode = -1;
 181                        printf ("string too long till next CR\n");
 182                }
 183        } else {
 184                /* some CR are missing...
 185                 * the inventory data is most probably corrupted */
 186                xcode = -1;
 187                printf ("not enough cr found\n");
 188        }
 189        return xcode;
 190}
 191
 192#define GET_STRING(name, which, len) \
 193        if (ivm_findinventorystring (which, valbuf, len, buf) == 0) { \
 194                ivm_set_value (name, (char *)valbuf); \
 195        }
 196
 197static int ivm_check_crc (unsigned char *buf, int block)
 198{
 199        unsigned long   crc;
 200        unsigned long   crceeprom;
 201
 202        crc = ivm_calc_crc (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
 203        crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
 204                        buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
 205        if (crc != crceeprom) {
 206                if (block == 0)
 207                        printf ("Error CRC Block: %d EEprom: calculated: \
 208                        %lx EEprom: %lx\n", block, crc, crceeprom);
 209                return -1;
 210        }
 211        return 0;
 212}
 213
 214static int ivm_analyze_block2 (unsigned char *buf, int len)
 215{
 216        unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
 217        unsigned long   count;
 218
 219        /* IVM_MacAddress */
 220        sprintf ((char *)valbuf, "%02X:%02X:%02X:%02X:%02X:%02X",
 221                        buf[1],
 222                        buf[2],
 223                        buf[3],
 224                        buf[4],
 225                        buf[5],
 226                        buf[6]);
 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
 242int 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, "IVM_BoardId", 0, 1);
 252        val = ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_HWKey", 6, 1);
 253        if (val != 0xffff) {
 254                sprintf ((char *)valbuf, "%x", ((val /100) % 10));
 255                ivm_set_value ("IVM_HWVariant", (char *)valbuf);
 256                sprintf ((char *)valbuf, "%x", (val % 100));
 257                ivm_set_value ("IVM_HWVersion", (char *)valbuf);
 258        }
 259        ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_Functions", 12, 0);
 260
 261        GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
 262        GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
 263        tmp = (unsigned char *) getenv("IVM_DeviceName");
 264        if (tmp) {
 265                int     len = strlen ((char *)tmp);
 266                int     i = 0;
 267
 268                while (i < len) {
 269                        if (tmp[i] == ';') {
 270                                ivm_set_value ("IVM_ShortText", (char *)&tmp[i + 1]);
 271                                break;
 272                        }
 273                        i++;
 274                }
 275                if (i >= len)
 276                        ivm_set_value ("IVM_ShortText", NULL);
 277        } else {
 278                ivm_set_value ("IVM_ShortText", NULL);
 279        }
 280        GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
 281        GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
 282        GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
 283        GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
 284        GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
 285        GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
 286        GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
 287        GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
 288        GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
 289
 290        if (ivm_check_crc (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
 291                return 0;
 292        ivm_analyze_block2 (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
 293
 294        return 0;
 295}
 296
 297int ivm_read_eeprom (void)
 298{
 299#if defined(CONFIG_I2C_MUX)
 300        I2C_MUX_DEVICE *dev = NULL;
 301#endif
 302        uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
 303        uchar   *buf;
 304        unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
 305
 306#if defined(CONFIG_I2C_MUX)
 307        /* First init the Bus, select the Bus */
 308#if defined(CONFIG_SYS_I2C_IVM_BUS)
 309        dev = i2c_mux_ident_muxstring ((uchar *)CONFIG_SYS_I2C_IVM_BUS);
 310#else
 311        buf = (unsigned char *) getenv ("EEprom_ivm");
 312        if (buf != NULL)
 313                dev = i2c_mux_ident_muxstring (buf);
 314#endif
 315        if (dev == NULL) {
 316                printf ("Error couldnt add Bus for IVM\n");
 317                return -1;
 318        }
 319        i2c_set_bus_num (dev->busid);
 320#endif
 321
 322        buf = (unsigned char *) getenv ("EEprom_ivm_addr");
 323        if (buf != NULL)
 324                dev_addr = simple_strtoul ((char *)buf, NULL, 16);
 325
 326        if (i2c_read(dev_addr, 0, 1, i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN) != 0) {
 327                printf ("Error reading EEprom\n");
 328                return -2;
 329        }
 330
 331        return ivm_analyze_eeprom (i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 332}
 333
 334#if defined(CONFIG_SYS_I2C_INIT_BOARD)
 335#define DELAY_ABORT_SEQ         62
 336#define DELAY_HALF_PERIOD       (500 / (CONFIG_SYS_I2C_SPEED / 1000))
 337
 338#if defined(CONFIG_MGCOGE)
 339#define SDA_MASK        0x00010000
 340#define SCL_MASK        0x00020000
 341static void set_pin (int state, unsigned long mask)
 342{
 343        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 344
 345        if (state)
 346                iop->pdat |= (mask);
 347        else
 348                iop->pdat &= ~(mask);
 349
 350        iop->pdir |= (mask);
 351}
 352
 353static int get_pin (unsigned long mask)
 354{
 355        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 356
 357        iop->pdir &= ~(mask);
 358        return (0 != (iop->pdat & (mask)));
 359}
 360
 361static void set_sda (int state)
 362{
 363        set_pin (state, SDA_MASK);
 364}
 365
 366static void set_scl (int state)
 367{
 368        set_pin (state, SCL_MASK);
 369}
 370
 371static int get_sda (void)
 372{
 373        return get_pin (SDA_MASK);
 374}
 375
 376static int get_scl (void)
 377{
 378        return get_pin (SCL_MASK);
 379}
 380
 381#if defined(CONFIG_HARD_I2C)
 382static void setports (int gpio)
 383{
 384        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 385
 386        if (gpio) {
 387                iop->ppar &= ~(SDA_MASK | SCL_MASK);
 388                iop->podr &= ~(SDA_MASK | SCL_MASK);
 389        } else {
 390                iop->ppar |= (SDA_MASK | SCL_MASK);
 391                iop->pdir &= ~(SDA_MASK | SCL_MASK);
 392                iop->podr |= (SDA_MASK | SCL_MASK);
 393        }
 394}
 395#endif
 396#endif
 397
 398#if defined(CONFIG_KM8XX)
 399static void set_sda (int state)
 400{
 401        I2C_SDA(state);
 402}
 403
 404static void set_scl (int state)
 405{
 406        I2C_SCL(state);
 407}
 408
 409static int get_sda (void)
 410{
 411        return I2C_READ;
 412}
 413
 414static int get_scl (void)
 415{
 416        int     val;
 417
 418        *(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF;
 419        udelay (1);
 420        val = *(unsigned char *)(I2C_BASE_PORT);
 421
 422        return ((val & SCL_BIT) == SCL_BIT);
 423}
 424
 425#endif
 426
 427#if !defined(CONFIG_KMETER1)
 428static void writeStartSeq (void)
 429{
 430        set_sda (1);
 431        udelay (DELAY_HALF_PERIOD);
 432        set_scl (1);
 433        udelay (DELAY_HALF_PERIOD);
 434        set_sda (0);
 435        udelay (DELAY_HALF_PERIOD);
 436        set_scl (0);
 437        udelay (DELAY_HALF_PERIOD);
 438}
 439
 440/* I2C is a synchronous protocol and resets of the processor in the middle
 441   of an access can block the I2C Bus until a powerdown of the full unit is
 442   done. This function toggles the SCL until the SCL and SCA line are
 443   released, but max. 16 times, after this a I2C start-sequence is sent.
 444   This I2C Deblocking mechanism was developed by Keymile in association
 445   with Anatech and Atmel in 1998.
 446 */
 447static int i2c_make_abort (void)
 448{
 449        int     scl_state = 0;
 450        int     sda_state = 0;
 451        int     i = 0;
 452        int     ret = 0;
 453
 454        if (!get_sda ()) {
 455                ret = -1;
 456                while (i < 16) {
 457                        i++;
 458                        set_scl (0);
 459                        udelay (DELAY_ABORT_SEQ);
 460                        set_scl (1);
 461                        udelay (DELAY_ABORT_SEQ);
 462                        scl_state = get_scl ();
 463                        sda_state = get_sda ();
 464                        if (scl_state && sda_state) {
 465                                ret = 0;
 466                                break;
 467                        }
 468                }
 469        }
 470        if (ret == 0) {
 471                for (i =0; i < 5; i++) {
 472                        writeStartSeq ();
 473                }
 474        }
 475        get_sda ();
 476        return ret;
 477}
 478#endif
 479
 480/**
 481 * i2c_init_board - reset i2c bus. When the board is powercycled during a
 482 * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
 483 */
 484void i2c_init_board(void)
 485{
 486#if defined(CONFIG_KMETER1)
 487        struct fsl_i2c *dev;
 488        dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
 489        uchar   dummy;
 490
 491        out_8 (&dev->cr, (I2C_CR_MSTA));
 492        out_8 (&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
 493        dummy = in_8(&dev->dr);
 494        dummy = in_8(&dev->dr);
 495        if (dummy != 0xff) {
 496                dummy = in_8(&dev->dr);
 497        }
 498        out_8 (&dev->cr, (I2C_CR_MEN));
 499        out_8 (&dev->cr, 0x00);
 500        out_8 (&dev->cr, (I2C_CR_MEN));
 501
 502#else
 503#if defined(CONFIG_HARD_I2C)
 504        volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
 505        volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
 506
 507        /* disable I2C controller first, otherwhise it thinks we want to    */
 508        /* talk to the slave port...                                        */
 509        i2c->i2c_i2mod &= ~0x01;
 510
 511        /* Set the PortPins to GPIO */
 512        setports (1);
 513#endif
 514
 515        /* Now run the AbortSequence() */
 516        i2c_make_abort ();
 517
 518#if defined(CONFIG_HARD_I2C)
 519        /* Set the PortPins back to use for I2C */
 520        setports (0);
 521#endif
 522#endif
 523}
 524#endif
 525#endif
 526
 527#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
 528int fdt_set_node_and_value (void *blob,
 529                                char *nodename,
 530                                char *regname,
 531                                void *var,
 532                                int size)
 533{
 534        int ret = 0;
 535        int nodeoffset = 0;
 536
 537        nodeoffset = fdt_path_offset (blob, nodename);
 538        if (nodeoffset >= 0) {
 539                ret = fdt_setprop (blob, nodeoffset, regname, var,
 540                                        size);
 541                if (ret < 0)
 542                        printf("ft_blob_update(): cannot set %s/%s "
 543                                "property err:%s\n", nodename, regname,
 544                                fdt_strerror (ret));
 545        } else {
 546                printf("ft_blob_update(): cannot find %s node "
 547                        "err:%s\n", nodename, fdt_strerror (nodeoffset));
 548        }
 549        return ret;
 550}
 551int fdt_get_node_and_value (void *blob,
 552                                char *nodename,
 553                                char *propname,
 554                                void **var)
 555{
 556        int len;
 557        int nodeoffset = 0;
 558
 559        nodeoffset = fdt_path_offset (blob, nodename);
 560        if (nodeoffset >= 0) {
 561                *var = (void *)fdt_getprop (blob, nodeoffset, propname, &len);
 562                if (len == 0) {
 563                        /* no value */
 564                        printf ("%s no value\n", __FUNCTION__);
 565                        return -1;
 566                } else if (len > 0) {
 567                        return len;
 568                } else {
 569                        printf ("libfdt fdt_getprop(): %s\n",
 570                                fdt_strerror(len));
 571                        return -2;
 572                }
 573        } else {
 574                printf("%s: cannot find %s node err:%s\n", __FUNCTION__,
 575                        nodename, fdt_strerror (nodeoffset));
 576                return -3;
 577        }
 578}
 579#endif
 580
 581int ethernet_present (void)
 582{
 583        return (in_8((u8 *)CONFIG_SYS_PIGGY_BASE + CONFIG_SYS_SLOT_ID_OFF) & 0x80);
 584}
 585
 586int board_eth_init (bd_t *bis)
 587{
 588#ifdef CONFIG_KEYMILE_HDLC_ENET
 589        (void)keymile_hdlc_enet_initialize (bis);
 590#endif
 591        if (ethernet_present ()) {
 592                return -1;
 593        }
 594        return 0;
 595}
 596