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