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