uboot/board/keymile/common/common.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008
   3 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
   4 *
   5 * (C) Copyright 2011
   6 * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <ioports.h>
  29#include <command.h>
  30#include <malloc.h>
  31#include <hush.h>
  32#include <net.h>
  33#include <netdev.h>
  34#include <asm/io.h>
  35#include <linux/ctype.h>
  36
  37#include "common.h"
  38#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
  39#include <i2c.h>
  40#endif
  41
  42#if !defined(CONFIG_MPC83xx)
  43static void i2c_write_start_seq(void);
  44#endif
  45
  46DECLARE_GLOBAL_DATA_PTR;
  47
  48/*
  49 * Set Keymile specific environment variables
  50 * Currently only some memory layout variables are calculated here
  51 * ... ------------------------------------------------
  52 * ... |@rootfsaddr |@pnvramaddr |@varaddr |@reserved |@END_OF_RAM
  53 * ... |<------------------- pram ------------------->|
  54 * ... ------------------------------------------------
  55 * @END_OF_RAM: denotes the RAM size
  56 * @pnvramaddr: Startadress of pseudo non volatile RAM in hex
  57 * @pram      : preserved ram size in k
  58 * @varaddr   : startadress for /var mounted into RAM
  59 */
  60int set_km_env(void)
  61{
  62        uchar buf[32];
  63        unsigned int pnvramaddr;
  64        unsigned int pram;
  65        unsigned int varaddr;
  66        unsigned int kernelmem;
  67        char *p;
  68        unsigned long rootfssize = 0;
  69
  70        pnvramaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM
  71                        - CONFIG_KM_PNVRAM;
  72        sprintf((char *)buf, "0x%x", pnvramaddr);
  73        setenv("pnvramaddr", (char *)buf);
  74
  75        /* try to read rootfssize (ram image) from envrionment */
  76        p = getenv("rootfssize");
  77        if (p != NULL)
  78                strict_strtoul(p, 16, &rootfssize);
  79        pram = (rootfssize + CONFIG_KM_RESERVED_PRAM + CONFIG_KM_PHRAM +
  80                CONFIG_KM_PNVRAM) / 0x400;
  81        sprintf((char *)buf, "0x%x", pram);
  82        setenv("pram", (char *)buf);
  83
  84        varaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM;
  85        sprintf((char *)buf, "0x%x", varaddr);
  86        setenv("varaddr", (char *)buf);
  87
  88        kernelmem = gd->ram_size - 0x400 * pram;
  89        sprintf((char *)buf, "0x%x", kernelmem);
  90        setenv("kernelmem", (char *)buf);
  91
  92        return 0;
  93}
  94
  95#if defined(CONFIG_SYS_I2C_INIT_BOARD)
  96#if !defined(CONFIG_MPC83xx)
  97static void i2c_write_start_seq(void)
  98{
  99        set_sda(1);
 100        udelay(DELAY_HALF_PERIOD);
 101        set_scl(1);
 102        udelay(DELAY_HALF_PERIOD);
 103        set_sda(0);
 104        udelay(DELAY_HALF_PERIOD);
 105        set_scl(0);
 106        udelay(DELAY_HALF_PERIOD);
 107}
 108
 109/*
 110 * I2C is a synchronous protocol and resets of the processor in the middle
 111 * of an access can block the I2C Bus until a powerdown of the full unit is
 112 * done. This function toggles the SCL until the SCL and SCA line are
 113 * released, but max. 16 times, after this a I2C start-sequence is sent.
 114 * This I2C Deblocking mechanism was developed by Keymile in association
 115 * with Anatech and Atmel in 1998.
 116 */
 117int i2c_make_abort(void)
 118{
 119
 120#if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD)
 121        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
 122        i2c8260_t *i2c  = (i2c8260_t *)&immap->im_i2c;
 123
 124        /*
 125         * disable I2C controller first, otherwhise it thinks we want to
 126         * talk to the slave port...
 127         */
 128        clrbits_8(&i2c->i2c_i2mod, 0x01);
 129
 130        /* Set the PortPins to GPIO */
 131        setports(1);
 132#endif
 133
 134        int     scl_state = 0;
 135        int     sda_state = 0;
 136        int     i = 0;
 137        int     ret = 0;
 138
 139        if (!get_sda()) {
 140                ret = -1;
 141                while (i < 16) {
 142                        i++;
 143                        set_scl(0);
 144                        udelay(DELAY_ABORT_SEQ);
 145                        set_scl(1);
 146                        udelay(DELAY_ABORT_SEQ);
 147                        scl_state = get_scl();
 148                        sda_state = get_sda();
 149                        if (scl_state && sda_state) {
 150                                ret = 0;
 151                                printf("[INFO] i2c abort after %d clocks\n", i);
 152                                break;
 153                        }
 154                }
 155        }
 156        if (ret == 0)
 157                for (i = 0; i < 5; i++)
 158                        i2c_write_start_seq();
 159        else
 160                printf("[ERROR] i2c abort failed\n");
 161
 162        /* respect stop setup time */
 163        udelay(DELAY_ABORT_SEQ);
 164        set_scl(1);
 165        udelay(DELAY_ABORT_SEQ);
 166        set_sda(1);
 167        get_sda();
 168
 169#if defined(CONFIG_HARD_I2C)
 170        /* Set the PortPins back to use for I2C */
 171        setports(0);
 172#endif
 173        return ret;
 174}
 175#endif
 176
 177/**
 178 * i2c_init_board - reset i2c bus. When the board is powercycled during a
 179 * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
 180 */
 181void i2c_init_board(void)
 182{
 183        /* Now run the AbortSequence() */
 184        i2c_make_abort();
 185}
 186#endif
 187
 188
 189#if !defined(MACH_TYPE_KM_KIRKWOOD)
 190int ethernet_present(void)
 191{
 192        struct km_bec_fpga *base =
 193                (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE;
 194
 195        return in_8(&base->bprth) & PIGGY_PRESENT;
 196}
 197#endif
 198
 199int board_eth_init(bd_t *bis)
 200{
 201        if (ethernet_present())
 202                return cpu_eth_init(bis);
 203
 204        return -1;
 205}
 206
 207/*
 208 * do_setboardid command
 209 * read out the board id and the hw key from the intventory EEPROM and set
 210 * this values as environment variables.
 211 */
 212static int do_setboardid(cmd_tbl_t *cmdtp, int flag, int argc,
 213                                char *const argv[])
 214{
 215        unsigned char buf[32];
 216        char *p;
 217
 218        p = get_local_var("IVM_BoardId");
 219        if (p == NULL) {
 220                printf("can't get the IVM_Boardid\n");
 221                return 1;
 222        }
 223        sprintf((char *)buf, "%s", p);
 224        setenv("boardid", (char *)buf);
 225        printf("set boardid=%s\n", buf);
 226
 227        p = get_local_var("IVM_HWKey");
 228        if (p == NULL) {
 229                printf("can't get the IVM_HWKey\n");
 230                return 1;
 231        }
 232        sprintf((char *)buf, "%s", p);
 233        setenv("hwkey", (char *)buf);
 234        printf("set hwkey=%s\n", buf);
 235        printf("Execute manually saveenv for persistent storage.\n");
 236
 237        return 0;
 238}
 239
 240U_BOOT_CMD(km_setboardid, 1, 0, do_setboardid, "setboardid", "read out bid and "
 241                                 "hwkey from IVM and set in environment");
 242
 243/*
 244 * command km_checkbidhwk
 245 *      if "boardid" and "hwkey" are not already set in the environment, do:
 246 *              if a "boardIdListHex" exists in the environment:
 247 *                      - read ivm data for boardid and hwkey
 248 *                      - compare each entry of the boardIdListHex with the
 249 *                              IVM data:
 250 *                      if match:
 251 *                              set environment variables boardid, boardId,
 252 *                              hwkey, hwKey to the found values
 253 *                              both (boardid and boardId) are set because
 254 *                              they might be used differently in the
 255 *                              application and in the init scripts (?)
 256 *      return 0 in case of match, 1 if not match or error
 257 */
 258int do_checkboardidhwk(cmd_tbl_t *cmdtp, int flag, int argc,
 259                        char *const argv[])
 260{
 261        unsigned long ivmbid = 0, ivmhwkey = 0;
 262        unsigned long envbid = 0, envhwkey = 0;
 263        char *p;
 264        int verbose = argc > 1 && *argv[1] == 'v';
 265        int rc = 0;
 266
 267        /*
 268         * first read out the real inventory values, these values are
 269         * already stored in the local hush variables
 270         */
 271        p = get_local_var("IVM_BoardId");
 272        if (p == NULL) {
 273                printf("can't get the IVM_Boardid\n");
 274                return 1;
 275        }
 276        rc = strict_strtoul(p, 16, &ivmbid);
 277
 278        p = get_local_var("IVM_HWKey");
 279        if (p == NULL) {
 280                printf("can't get the IVM_HWKey\n");
 281                return 1;
 282        }
 283        rc = strict_strtoul(p, 16, &ivmhwkey);
 284
 285        if (!ivmbid || !ivmhwkey) {
 286                printf("Error: IVM_BoardId and/or IVM_HWKey not set!\n");
 287                return rc;
 288        }
 289
 290        /* now try to read values from environment if available */
 291        p = getenv("boardid");
 292        if (p != NULL)
 293                rc = strict_strtoul(p, 16, &envbid);
 294        p = getenv("hwkey");
 295        if (p != NULL)
 296                rc = strict_strtoul(p, 16, &envhwkey);
 297
 298        if (rc != 0) {
 299                printf("strict_strtoul returns error: %d", rc);
 300                return rc;
 301        }
 302
 303        if (!envbid || !envhwkey) {
 304                /*
 305                 * BoardId/HWkey not available in the environment, so try the
 306                 * environment variable for BoardId/HWkey list
 307                 */
 308                char *bidhwklist = getenv("boardIdListHex");
 309
 310                if (bidhwklist) {
 311                        int found = 0;
 312                        char *rest = bidhwklist;
 313                        char *endp;
 314
 315                        if (verbose) {
 316                                printf("IVM_BoardId: %ld, IVM_HWKey=%ld\n",
 317                                        ivmbid, ivmhwkey);
 318                                printf("boardIdHwKeyList: %s\n",
 319                                        bidhwklist);
 320                        }
 321                        while (!found) {
 322                                /* loop over each bid/hwkey pair in the list */
 323                                unsigned long bid   = 0;
 324                                unsigned long hwkey = 0;
 325
 326                                while (*rest && !isxdigit(*rest))
 327                                        rest++;
 328                                /*
 329                                 * use simple_strtoul because we need &end and
 330                                 * we know we got non numeric char at the end
 331                                 */
 332                                bid = simple_strtoul(rest, &endp, 16);
 333                                /* BoardId and HWkey are separated with a "_" */
 334                                if (*endp == '_') {
 335                                        rest  = endp + 1;
 336                                        /*
 337                                         * use simple_strtoul because we need
 338                                         * &end
 339                                         */
 340                                        hwkey = simple_strtoul(rest, &endp, 16);
 341                                        rest  = endp;
 342                                        while (*rest && !isxdigit(*rest))
 343                                                rest++;
 344                                }
 345                                if ((!bid) || (!hwkey)) {
 346                                        /* end of list */
 347                                        break;
 348                                }
 349                                if (verbose) {
 350                                        printf("trying bid=0x%lX, hwkey=%ld\n",
 351                                                bid, hwkey);
 352                                }
 353                                /*
 354                                 * Compare the values of the found entry in the
 355                                 * list with the valid values which are stored
 356                                 * in the inventory eeprom. If they are equal
 357                                 * set the values in environment variables.
 358                                 */
 359                                if ((bid == ivmbid) && (hwkey == ivmhwkey)) {
 360                                        char buf[10];
 361
 362                                        found = 1;
 363                                        envbid   = bid;
 364                                        envhwkey = hwkey;
 365                                        sprintf(buf, "%lx", bid);
 366                                        setenv("boardid", buf);
 367                                        sprintf(buf, "%lx", hwkey);
 368                                        setenv("hwkey", buf);
 369                                }
 370                        } /* end while( ! found ) */
 371                }
 372        }
 373
 374        /* compare now the values */
 375        if ((ivmbid == envbid) && (ivmhwkey == envhwkey)) {
 376                printf("boardid=0x%3lX, hwkey=%ld\n", envbid, envhwkey);
 377                rc = 0; /* match */
 378        } else {
 379                printf("Error: env boardid=0x%3lX, hwkey=%ld\n", envbid,
 380                        envhwkey);
 381                printf("       IVM bId=0x%3lX, hwKey=%ld\n", ivmbid, ivmhwkey);
 382                rc = 1; /* don't match */
 383        }
 384        return rc;
 385}
 386
 387U_BOOT_CMD(km_checkbidhwk, 2, 0, do_checkboardidhwk,
 388                "check boardid and hwkey",
 389                "[v]\n  - check environment parameter "\
 390                "\"boardIdListHex\" against stored boardid and hwkey "\
 391                "from the IVM\n    v: verbose output"
 392);
 393