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#include "../common/common.h"
  39#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
  40#include <i2c.h>
  41
  42extern int i2c_soft_read_pin (void);
  43
  44int ivm_calc_crc (unsigned char *buf, int len)
  45{
  46        const unsigned short crc_tab[16] = {
  47                0x0000, 0xCC01, 0xD801, 0x1400,
  48                0xF001, 0x3C00, 0x2800, 0xE401,
  49                0xA001, 0x6C00, 0x7800, 0xB401,
  50                0x5000, 0x9C01, 0x8801, 0x4400};
  51
  52        unsigned short crc     = 0;   /* final result */
  53        unsigned short r1      = 0;   /* temp */
  54        unsigned char  byte    = 0;   /* input buffer */
  55        int     i;
  56
  57        /* calculate CRC from array data */
  58        for (i = 0; i < len; i++) {
  59                byte = buf[i];
  60
  61                /* lower 4 bits */
  62                r1 = crc_tab[crc & 0xF];
  63                crc = ((crc) >> 4) & 0x0FFF;
  64                crc = crc ^ r1 ^ crc_tab[byte & 0xF];
  65
  66                /* upper 4 bits */
  67                r1 = crc_tab[crc & 0xF];
  68                crc = (crc >> 4) & 0x0FFF;
  69                crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF];
  70        }
  71        return crc;
  72}
  73
  74static int  ivm_set_value (char *name, char *value)
  75{
  76        char tempbuf[256];
  77
  78        if (value != NULL) {
  79                sprintf (tempbuf, "%s=%s", name, value);
  80                return set_local_var (tempbuf, 0);
  81        } else {
  82                unset_local_var (name);
  83        }
  84        return 0;
  85}
  86
  87static int ivm_get_value (unsigned char *buf, int len, char *name, int off,
  88                                int check)
  89{
  90        unsigned short  val;
  91        unsigned char   valbuf[30];
  92
  93        if ((buf[off + 0] != buf[off + 2]) &&
  94            (buf[off + 2] != buf[off + 4])) {
  95                printf ("%s Error corrupted %s\n", __FUNCTION__, name);
  96                val = -1;
  97        } else {
  98                val = buf[off + 0] + (buf[off + 1] << 8);
  99                if ((val == 0) && (check == 1))
 100                        val = -1;
 101        }
 102        sprintf ((char *)valbuf, "%x", val);
 103        ivm_set_value (name, (char *)valbuf);
 104        return val;
 105}
 106
 107#define INVENTORYBLOCKSIZE      0x100
 108#define INVENTORYDATAADDRESS    0x21
 109#define INVENTORYDATASIZE       (INVENTORYBLOCKSIZE - INVENTORYDATAADDRESS - 3)
 110
 111#define IVM_POS_SHORT_TEXT              0
 112#define IVM_POS_MANU_ID                 1
 113#define IVM_POS_MANU_SERIAL             2
 114#define IVM_POS_PART_NUMBER             3
 115#define IVM_POS_BUILD_STATE             4
 116#define IVM_POS_SUPPLIER_PART_NUMBER    5
 117#define IVM_POS_DELIVERY_DATE           6
 118#define IVM_POS_SUPPLIER_BUILD_STATE    7
 119#define IVM_POS_CUSTOMER_ID             8
 120#define IVM_POS_CUSTOMER_PROD_ID        9
 121#define IVM_POS_HISTORY                 10
 122#define IVM_POS_SYMBOL_ONLY             11
 123
 124static char convert_char (char c)
 125{
 126        return (c < ' ' || c > '~') ? '.' : c;
 127}
 128
 129static int ivm_findinventorystring (int type,
 130                                        unsigned char* const string,
 131                                        unsigned long maxlen,
 132                                        unsigned char *buf)
 133{
 134        int xcode = 0;
 135        unsigned long cr = 0;
 136        unsigned long addr = INVENTORYDATAADDRESS;
 137        unsigned long size = 0;
 138        unsigned long nr = type;
 139        int stop = 0;   /* stop on semicolon */
 140
 141        memset(string, '\0', maxlen);
 142        switch (type) {
 143                case IVM_POS_SYMBOL_ONLY:
 144                        nr = 0;
 145                        stop= 1;
 146                break;
 147                default:
 148                        nr = type;
 149                        stop = 0;
 150        }
 151
 152        /* Look for the requested number of CR. */
 153        while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
 154                if ((buf[addr] == '\r')) {
 155                        cr++;
 156                }
 157                addr++;
 158        }
 159
 160        /* the expected number of CR was found until the end of the IVM
 161         *  content --> fill string */
 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                /* copy phase is done: check if everything is ok. If not,
 174                 * the inventory data is most probably corrupted: tell
 175                 * the world there is a problem! */
 176                if (addr == INVENTORYDATASIZE) {
 177                        xcode = -1;
 178                        printf ("Error end of string not found\n");
 179                } else if ((size >= (maxlen - 1)) &&
 180                           (buf[addr] != '\r')) {
 181                        xcode = -1;
 182                        printf ("string too long till next CR\n");
 183                }
 184        } else {
 185                /* some CR are missing...
 186                 * the inventory data is most probably corrupted */
 187                xcode = -1;
 188                printf ("not enough cr found\n");
 189        }
 190        return xcode;
 191}
 192
 193#define GET_STRING(name, which, len) \
 194        if (ivm_findinventorystring (which, valbuf, len, buf) == 0) { \
 195                ivm_set_value (name, (char *)valbuf); \
 196        }
 197
 198static int ivm_check_crc (unsigned char *buf, int block)
 199{
 200        unsigned long   crc;
 201        unsigned long   crceeprom;
 202
 203        crc = ivm_calc_crc (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
 204        crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
 205                        buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
 206        if (crc != crceeprom) {
 207                if (block == 0)
 208                        printf ("Error CRC Block: %d EEprom: calculated: \
 209                        %lx EEprom: %lx\n", block, crc, crceeprom);
 210                return -1;
 211        }
 212        return 0;
 213}
 214
 215static int ivm_analyze_block2 (unsigned char *buf, int len)
 216{
 217        unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
 218        unsigned long   count;
 219
 220        /* IVM_MacAddress */
 221        sprintf ((char *)valbuf, "%02X:%02X:%02X:%02X:%02X:%02X",
 222                        buf[1],
 223                        buf[2],
 224                        buf[3],
 225                        buf[4],
 226                        buf[5],
 227                        buf[6]);
 228        ivm_set_value ("IVM_MacAddress", (char *)valbuf);
 229        if (getenv ("ethaddr") == NULL)
 230                setenv ((char *)"ethaddr", (char *)valbuf);
 231        /* IVM_MacCount */
 232        count = (buf[10] << 24) +
 233                   (buf[11] << 16) +
 234                   (buf[12] << 8)  +
 235                    buf[13];
 236        if (count == 0xffffffff)
 237                count = 1;
 238        sprintf ((char *)valbuf, "%lx", count);
 239        ivm_set_value ("IVM_MacCount", (char *)valbuf);
 240        return 0;
 241}
 242
 243int ivm_analyze_eeprom (unsigned char *buf, int len)
 244{
 245        unsigned short  val;
 246        unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
 247        unsigned char   *tmp;
 248
 249        if (ivm_check_crc (buf, 0) != 0)
 250                return -1;
 251
 252        ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "IVM_BoardId", 0, 1);
 253        val = ivm_get_value (buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, "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, "IVM_Functions", 12, 0);
 261
 262        GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
 263        GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
 264        tmp = (unsigned char *) getenv("IVM_DeviceName");
 265        if (tmp) {
 266                int     len = strlen ((char *)tmp);
 267                int     i = 0;
 268
 269                while (i < len) {
 270                        if (tmp[i] == ';') {
 271                                ivm_set_value ("IVM_ShortText", (char *)&tmp[i + 1]);
 272                                break;
 273                        }
 274                        i++;
 275                }
 276                if (i >= len)
 277                        ivm_set_value ("IVM_ShortText", NULL);
 278        } else {
 279                ivm_set_value ("IVM_ShortText", NULL);
 280        }
 281        GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
 282        GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
 283        GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
 284        GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
 285        GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
 286        GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
 287        GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
 288        GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
 289        GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
 290
 291        if (ivm_check_crc (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
 292                return 0;
 293        ivm_analyze_block2 (&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
 294
 295        return 0;
 296}
 297
 298int ivm_read_eeprom (void)
 299{
 300#if defined(CONFIG_I2C_MUX)
 301        I2C_MUX_DEVICE *dev = NULL;
 302#endif
 303        uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
 304        uchar   *buf;
 305        unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
 306
 307#if defined(CONFIG_I2C_MUX)
 308        /* First init the Bus, select the Bus */
 309#if defined(CONFIG_SYS_I2C_IVM_BUS)
 310        dev = i2c_mux_ident_muxstring ((uchar *)CONFIG_SYS_I2C_IVM_BUS);
 311#else
 312        buf = (unsigned char *) getenv ("EEprom_ivm");
 313        if (buf != NULL)
 314                dev = i2c_mux_ident_muxstring (buf);
 315#endif
 316        if (dev == NULL) {
 317                printf ("Error couldnt add Bus for IVM\n");
 318                return -1;
 319        }
 320        i2c_set_bus_num (dev->busid);
 321#endif
 322
 323        buf = (unsigned char *) getenv ("EEprom_ivm_addr");
 324        if (buf != NULL)
 325                dev_addr = simple_strtoul ((char *)buf, NULL, 16);
 326
 327        if (i2c_read(dev_addr, 0, 1, i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN) != 0) {
 328                printf ("Error reading EEprom\n");
 329                return -2;
 330        }
 331
 332        return ivm_analyze_eeprom (i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 333}
 334
 335#if defined(CONFIG_SYS_I2C_INIT_BOARD)
 336#define DELAY_ABORT_SEQ         62
 337#define DELAY_HALF_PERIOD       (500 / (CONFIG_SYS_I2C_SPEED / 1000))
 338
 339#if defined(CONFIG_MGCOGE)
 340#define SDA_MASK        0x00010000
 341#define SCL_MASK        0x00020000
 342static void set_pin (int state, unsigned long mask)
 343{
 344        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 345
 346        if (state)
 347                iop->pdat |= (mask);
 348        else
 349                iop->pdat &= ~(mask);
 350
 351        iop->pdir |= (mask);
 352}
 353
 354static int get_pin (unsigned long mask)
 355{
 356        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 357
 358        iop->pdir &= ~(mask);
 359        return (0 != (iop->pdat & (mask)));
 360}
 361
 362static void set_sda (int state)
 363{
 364        set_pin (state, SDA_MASK);
 365}
 366
 367static void set_scl (int state)
 368{
 369        set_pin (state, SCL_MASK);
 370}
 371
 372static int get_sda (void)
 373{
 374        return get_pin (SDA_MASK);
 375}
 376
 377static int get_scl (void)
 378{
 379        return get_pin (SCL_MASK);
 380}
 381
 382#if defined(CONFIG_HARD_I2C)
 383static void setports (int gpio)
 384{
 385        volatile ioport_t *iop = ioport_addr ((immap_t *)CONFIG_SYS_IMMR, 3);
 386
 387        if (gpio) {
 388                iop->ppar &= ~(SDA_MASK | SCL_MASK);
 389                iop->podr &= ~(SDA_MASK | SCL_MASK);
 390        } else {
 391                iop->ppar |= (SDA_MASK | SCL_MASK);
 392                iop->pdir &= ~(SDA_MASK | SCL_MASK);
 393                iop->podr |= (SDA_MASK | SCL_MASK);
 394        }
 395}
 396#endif
 397#endif
 398
 399#if defined(CONFIG_KM8XX)
 400static void set_sda (int state)
 401{
 402        I2C_SDA(state);
 403}
 404
 405static void set_scl (int state)
 406{
 407        I2C_SCL(state);
 408}
 409
 410static int get_sda (void)
 411{
 412        return I2C_READ;
 413}
 414
 415static int get_scl (void)
 416{
 417        int     val;
 418
 419        *(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF;
 420        udelay (1);
 421        val = *(unsigned char *)(I2C_BASE_PORT);
 422
 423        return ((val & SCL_BIT) == SCL_BIT);
 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) && !defined(CONFIG_MACH_SUEN3)
 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
 581#if !defined(CONFIG_MACH_SUEN3)
 582int ethernet_present (void)
 583{
 584        return (in_8((u8 *)CONFIG_SYS_PIGGY_BASE + CONFIG_SYS_SLOT_ID_OFF) & 0x80);
 585}
 586#endif
 587
 588int board_eth_init (bd_t *bis)
 589{
 590#ifdef CONFIG_KEYMILE_HDLC_ENET
 591        (void)keymile_hdlc_enet_initialize (bis);
 592#endif
 593        if (ethernet_present ()) {
 594                return -1;
 595        }
 596        return 0;
 597}
 598