1c2485364SHeiko Schocher /* 2c2485364SHeiko Schocher * (C) Copyright 2008 3c2485364SHeiko Schocher * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4c2485364SHeiko Schocher * 54f745bf4SHolger Brunck * (C) Copyright 2011 64f745bf4SHolger Brunck * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com 74f745bf4SHolger Brunck * 8c2485364SHeiko Schocher * See file CREDITS for list of people who contributed to this 9c2485364SHeiko Schocher * project. 10c2485364SHeiko Schocher * 11c2485364SHeiko Schocher * This program is free software; you can redistribute it and/or 12c2485364SHeiko Schocher * modify it under the terms of the GNU General Public License as 13c2485364SHeiko Schocher * published by the Free Software Foundation; either version 2 of 14c2485364SHeiko Schocher * the License, or (at your option) any later version. 15c2485364SHeiko Schocher * 16c2485364SHeiko Schocher * This program is distributed in the hope that it will be useful, 17c2485364SHeiko Schocher * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c2485364SHeiko Schocher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c2485364SHeiko Schocher * GNU General Public License for more details. 20c2485364SHeiko Schocher * 21c2485364SHeiko Schocher * You should have received a copy of the GNU General Public License 22c2485364SHeiko Schocher * along with this program; if not, write to the Free Software 23c2485364SHeiko Schocher * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24c2485364SHeiko Schocher * MA 02111-1307 USA 25c2485364SHeiko Schocher */ 26c2485364SHeiko Schocher 27c2485364SHeiko Schocher #include <common.h> 28c2485364SHeiko Schocher #include <ioports.h> 29a9417ce7SHolger Brunck #include <command.h> 30c2485364SHeiko Schocher #include <malloc.h> 318f64da7fSHeiko Schocher #include <hush.h> 32210c8c00SHeiko Schocher #include <net.h> 3362ddcf05SHeiko Schocher #include <netdev.h> 34210c8c00SHeiko Schocher #include <asm/io.h> 3592c91080SThomas Herzmann #include <linux/ctype.h> 36c2485364SHeiko Schocher 37c2485364SHeiko Schocher #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) 38c2485364SHeiko Schocher #include <libfdt.h> 39c2485364SHeiko Schocher #endif 40c2485364SHeiko Schocher 414f745bf4SHolger Brunck #include "common.h" 42c2485364SHeiko Schocher #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) 43c2485364SHeiko Schocher #include <i2c.h> 441adfd9ddSHolger Brunck #endif 45c2485364SHeiko Schocher 466c11aeafSHeiko Schocher static void i2c_write_start_seq(void); 47f1fef1d8SHeiko Schocher DECLARE_GLOBAL_DATA_PTR; 486c11aeafSHeiko Schocher 49f1fef1d8SHeiko Schocher /* 50f1fef1d8SHeiko Schocher * Set Keymile specific environment variables 51f1fef1d8SHeiko Schocher * Currently only some memory layout variables are calculated here 52f1fef1d8SHeiko Schocher * ... ------------------------------------------------ 53f1fef1d8SHeiko Schocher * ... |@rootfsaddr |@pnvramaddr |@varaddr |@reserved |@END_OF_RAM 54f1fef1d8SHeiko Schocher * ... |<------------------- pram ------------------->| 55f1fef1d8SHeiko Schocher * ... ------------------------------------------------ 56f1fef1d8SHeiko Schocher * @END_OF_RAM: denotes the RAM size 57f1fef1d8SHeiko Schocher * @pnvramaddr: Startadress of pseudo non volatile RAM in hex 58f1fef1d8SHeiko Schocher * @pram : preserved ram size in k 59f1fef1d8SHeiko Schocher * @varaddr : startadress for /var mounted into RAM 60f1fef1d8SHeiko Schocher */ 61f1fef1d8SHeiko Schocher int set_km_env(void) 62f1fef1d8SHeiko Schocher { 63f1fef1d8SHeiko Schocher uchar buf[32]; 64f1fef1d8SHeiko Schocher unsigned int pnvramaddr; 65f1fef1d8SHeiko Schocher unsigned int pram; 66f1fef1d8SHeiko Schocher unsigned int varaddr; 67*2a7714ceSAndreas Huber unsigned int kernelmem; 68*2a7714ceSAndreas Huber char *p; 69*2a7714ceSAndreas Huber unsigned long rootfssize = 0; 70f1fef1d8SHeiko Schocher 71f1fef1d8SHeiko Schocher pnvramaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM 72f1fef1d8SHeiko Schocher - CONFIG_KM_PNVRAM; 73f1fef1d8SHeiko Schocher sprintf((char *)buf, "0x%x", pnvramaddr); 74f1fef1d8SHeiko Schocher setenv("pnvramaddr", (char *)buf); 75f1fef1d8SHeiko Schocher 76*2a7714ceSAndreas Huber /* try to read rootfssize (ram image) from envrionment */ 77*2a7714ceSAndreas Huber p = getenv("rootfssize"); 78*2a7714ceSAndreas Huber if (p != NULL) 79*2a7714ceSAndreas Huber strict_strtoul(p, 16, &rootfssize); 80*2a7714ceSAndreas Huber pram = (rootfssize + CONFIG_KM_RESERVED_PRAM + CONFIG_KM_PHRAM + 81*2a7714ceSAndreas Huber CONFIG_KM_PNVRAM) / 0x400; 82f1fef1d8SHeiko Schocher sprintf((char *)buf, "0x%x", pram); 83f1fef1d8SHeiko Schocher setenv("pram", (char *)buf); 84f1fef1d8SHeiko Schocher 85f1fef1d8SHeiko Schocher varaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM; 86f1fef1d8SHeiko Schocher sprintf((char *)buf, "0x%x", varaddr); 87f1fef1d8SHeiko Schocher setenv("varaddr", (char *)buf); 88*2a7714ceSAndreas Huber 89*2a7714ceSAndreas Huber kernelmem = gd->ram_size - 0x400 * pram; 90*2a7714ceSAndreas Huber sprintf((char *)buf, "0x%x", kernelmem); 91*2a7714ceSAndreas Huber setenv("kernelmem", (char *)buf); 92*2a7714ceSAndreas Huber 93f1fef1d8SHeiko Schocher return 0; 94f1fef1d8SHeiko Schocher } 95f1fef1d8SHeiko Schocher 966c11aeafSHeiko Schocher #define DELAY_ABORT_SEQ 62 /* @200kHz 9 clocks = 44us, 62us is ok */ 976d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define DELAY_HALF_PERIOD (500 / (CONFIG_SYS_I2C_SPEED / 1000)) 98c2485364SHeiko Schocher 9962ddcf05SHeiko Schocher #if !defined(CONFIG_MPC83xx) 1006c11aeafSHeiko Schocher static void i2c_write_start_seq(void) 101c2485364SHeiko Schocher { 102c2485364SHeiko Schocher set_sda(1); 103c2485364SHeiko Schocher udelay(DELAY_HALF_PERIOD); 104c2485364SHeiko Schocher set_scl(1); 105c2485364SHeiko Schocher udelay(DELAY_HALF_PERIOD); 106c2485364SHeiko Schocher set_sda(0); 107c2485364SHeiko Schocher udelay(DELAY_HALF_PERIOD); 108c2485364SHeiko Schocher set_scl(0); 109c2485364SHeiko Schocher udelay(DELAY_HALF_PERIOD); 110c2485364SHeiko Schocher } 111c2485364SHeiko Schocher 112b11f53f3SHeiko Schocher /* 113b11f53f3SHeiko Schocher * I2C is a synchronous protocol and resets of the processor in the middle 114b11f53f3SHeiko Schocher * of an access can block the I2C Bus until a powerdown of the full unit is 115b11f53f3SHeiko Schocher * done. This function toggles the SCL until the SCL and SCA line are 116b11f53f3SHeiko Schocher * released, but max. 16 times, after this a I2C start-sequence is sent. 117b11f53f3SHeiko Schocher * This I2C Deblocking mechanism was developed by Keymile in association 118b11f53f3SHeiko Schocher * with Anatech and Atmel in 1998. 119c2485364SHeiko Schocher */ 1204f745bf4SHolger Brunck int i2c_make_abort(void) 121c2485364SHeiko Schocher { 1226c11aeafSHeiko Schocher 1236c11aeafSHeiko Schocher #if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD) 1246c11aeafSHeiko Schocher immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ; 1256c11aeafSHeiko Schocher i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c; 1266c11aeafSHeiko Schocher 1276c11aeafSHeiko Schocher /* 1286c11aeafSHeiko Schocher * disable I2C controller first, otherwhise it thinks we want to 1296c11aeafSHeiko Schocher * talk to the slave port... 1306c11aeafSHeiko Schocher */ 1316c11aeafSHeiko Schocher clrbits_8(&i2c->i2c_i2mod, 0x01); 1326c11aeafSHeiko Schocher 1336c11aeafSHeiko Schocher /* Set the PortPins to GPIO */ 1346c11aeafSHeiko Schocher setports(1); 1356c11aeafSHeiko Schocher #endif 1366c11aeafSHeiko Schocher 137c2485364SHeiko Schocher int scl_state = 0; 138c2485364SHeiko Schocher int sda_state = 0; 139c2485364SHeiko Schocher int i = 0; 140c2485364SHeiko Schocher int ret = 0; 141c2485364SHeiko Schocher 142c2485364SHeiko Schocher if (!get_sda()) { 143c2485364SHeiko Schocher ret = -1; 144c2485364SHeiko Schocher while (i < 16) { 145c2485364SHeiko Schocher i++; 146c2485364SHeiko Schocher set_scl(0); 147c2485364SHeiko Schocher udelay(DELAY_ABORT_SEQ); 148c2485364SHeiko Schocher set_scl(1); 149c2485364SHeiko Schocher udelay(DELAY_ABORT_SEQ); 150c2485364SHeiko Schocher scl_state = get_scl(); 151c2485364SHeiko Schocher sda_state = get_sda(); 152c2485364SHeiko Schocher if (scl_state && sda_state) { 153c2485364SHeiko Schocher ret = 0; 154c7506c2bSStefan Bigler printf("[INFO] i2c abort after %d clocks\n", i); 155c2485364SHeiko Schocher break; 156c2485364SHeiko Schocher } 157c2485364SHeiko Schocher } 158c2485364SHeiko Schocher } 159b11f53f3SHeiko Schocher if (ret == 0) 160b11f53f3SHeiko Schocher for (i = 0; i < 5; i++) 1616c11aeafSHeiko Schocher i2c_write_start_seq(); 162c7506c2bSStefan Bigler else 163c7506c2bSStefan Bigler printf("[ERROR] i2c abort failed\n"); 164b11f53f3SHeiko Schocher 1656c11aeafSHeiko Schocher /* respect stop setup time */ 1666c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 1676c11aeafSHeiko Schocher set_scl(1); 1686c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 1696c11aeafSHeiko Schocher set_sda(1); 170c2485364SHeiko Schocher get_sda(); 171c2485364SHeiko Schocher 172c2485364SHeiko Schocher #if defined(CONFIG_HARD_I2C) 173c2485364SHeiko Schocher /* Set the PortPins back to use for I2C */ 174c2485364SHeiko Schocher setports(0); 175c2485364SHeiko Schocher #endif 1766c11aeafSHeiko Schocher return ret; 1776c11aeafSHeiko Schocher } 1781adfd9ddSHolger Brunck #endif /* !MPC83xx */ 1796c11aeafSHeiko Schocher 1806c11aeafSHeiko Schocher #if defined(CONFIG_MPC83xx) 1816c11aeafSHeiko Schocher static void i2c_write_start_seq(void) 1826c11aeafSHeiko Schocher { 1836c11aeafSHeiko Schocher struct fsl_i2c *dev; 1846c11aeafSHeiko Schocher dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); 1856c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 1866c11aeafSHeiko Schocher out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA)); 1876c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 1886c11aeafSHeiko Schocher out_8(&dev->cr, (I2C_CR_MEN)); 1896c11aeafSHeiko Schocher } 1906c11aeafSHeiko Schocher 1914f745bf4SHolger Brunck int i2c_make_abort(void) 1926c11aeafSHeiko Schocher { 1936c11aeafSHeiko Schocher struct fsl_i2c *dev; 1946c11aeafSHeiko Schocher dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); 1956c11aeafSHeiko Schocher uchar dummy; 1966c11aeafSHeiko Schocher uchar last; 1976c11aeafSHeiko Schocher int nbr_read = 0; 1986c11aeafSHeiko Schocher int i = 0; 1996c11aeafSHeiko Schocher int ret = 0; 2006c11aeafSHeiko Schocher 2016c11aeafSHeiko Schocher /* wait after each operation to finsh with a delay */ 2026c11aeafSHeiko Schocher out_8(&dev->cr, (I2C_CR_MSTA)); 2036c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2046c11aeafSHeiko Schocher out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA)); 2056c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2066c11aeafSHeiko Schocher dummy = in_8(&dev->dr); 2076c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2086c11aeafSHeiko Schocher last = in_8(&dev->dr); 2096c11aeafSHeiko Schocher nbr_read++; 2106c11aeafSHeiko Schocher 2116c11aeafSHeiko Schocher /* 2126c11aeafSHeiko Schocher * do read until the last bit is 1, but stop if the full eeprom is 2136c11aeafSHeiko Schocher * read. 2146c11aeafSHeiko Schocher */ 2156c11aeafSHeiko Schocher while (((last & 0x01) != 0x01) && 2166c11aeafSHeiko Schocher (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) { 2176c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2186c11aeafSHeiko Schocher last = in_8(&dev->dr); 2196c11aeafSHeiko Schocher nbr_read++; 2206c11aeafSHeiko Schocher } 2216c11aeafSHeiko Schocher if ((last & 0x01) != 0x01) 2226c11aeafSHeiko Schocher ret = -2; 2236c11aeafSHeiko Schocher if ((last != 0xff) || (nbr_read > 1)) 2246c11aeafSHeiko Schocher printf("[INFO] i2c abort after %d bytes (0x%02x)\n", 2256c11aeafSHeiko Schocher nbr_read, last); 2266c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2276c11aeafSHeiko Schocher out_8(&dev->cr, (I2C_CR_MEN)); 2286c11aeafSHeiko Schocher udelay(DELAY_ABORT_SEQ); 2296c11aeafSHeiko Schocher /* clear status reg */ 2306c11aeafSHeiko Schocher out_8(&dev->sr, 0); 2316c11aeafSHeiko Schocher 2326c11aeafSHeiko Schocher for (i = 0; i < 5; i++) 2336c11aeafSHeiko Schocher i2c_write_start_seq(); 2346c11aeafSHeiko Schocher if (ret != 0) 2356c11aeafSHeiko Schocher printf("[ERROR] i2c abort failed after %d bytes (0x%02x)\n", 2366c11aeafSHeiko Schocher nbr_read, last); 2376c11aeafSHeiko Schocher 2386c11aeafSHeiko Schocher return ret; 2396c11aeafSHeiko Schocher } 2406c11aeafSHeiko Schocher #endif 2416c11aeafSHeiko Schocher 2426c11aeafSHeiko Schocher /** 2436c11aeafSHeiko Schocher * i2c_init_board - reset i2c bus. When the board is powercycled during a 2446c11aeafSHeiko Schocher * bus transfer it might hang; for details see doc/I2C_Edge_Conditions. 2456c11aeafSHeiko Schocher */ 2466c11aeafSHeiko Schocher void i2c_init_board(void) 2476c11aeafSHeiko Schocher { 2486c11aeafSHeiko Schocher /* Now run the AbortSequence() */ 2496c11aeafSHeiko Schocher i2c_make_abort(); 250c2485364SHeiko Schocher } 2516250f0f6SHeiko Schocher 252802d9963SHolger Brunck #if !defined(MACH_TYPE_KM_KIRKWOOD) 253210c8c00SHeiko Schocher int ethernet_present(void) 254210c8c00SHeiko Schocher { 2558ed74341SHeiko Schocher struct km_bec_fpga *base = 2568ed74341SHeiko Schocher (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE; 257b11f53f3SHeiko Schocher 258b11f53f3SHeiko Schocher return in_8(&base->bprth) & PIGGY_PRESENT; 259210c8c00SHeiko Schocher } 26067fa8c25SHeiko Schocher #endif 261210c8c00SHeiko Schocher 262210c8c00SHeiko Schocher int board_eth_init(bd_t *bis) 263210c8c00SHeiko Schocher { 264b11f53f3SHeiko Schocher if (ethernet_present()) 26562ddcf05SHeiko Schocher return cpu_eth_init(bis); 26662ddcf05SHeiko Schocher 267210c8c00SHeiko Schocher return -1; 268210c8c00SHeiko Schocher } 269a9417ce7SHolger Brunck 270a9417ce7SHolger Brunck /* 271a9417ce7SHolger Brunck * do_setboardid command 272a9417ce7SHolger Brunck * read out the board id and the hw key from the intventory EEPROM and set 273a9417ce7SHolger Brunck * this values as environment variables. 274a9417ce7SHolger Brunck */ 275a9417ce7SHolger Brunck static int do_setboardid(cmd_tbl_t *cmdtp, int flag, int argc, 276a9417ce7SHolger Brunck char *const argv[]) 277a9417ce7SHolger Brunck { 278a9417ce7SHolger Brunck unsigned char buf[32]; 279a9417ce7SHolger Brunck char *p; 280a9417ce7SHolger Brunck 281a9417ce7SHolger Brunck p = get_local_var("IVM_BoardId"); 282a9417ce7SHolger Brunck if (p == NULL) { 283a9417ce7SHolger Brunck printf("can't get the IVM_Boardid\n"); 284a9417ce7SHolger Brunck return 1; 285a9417ce7SHolger Brunck } 286a9417ce7SHolger Brunck sprintf((char *)buf, "%s", p); 287a9417ce7SHolger Brunck setenv("boardid", (char *)buf); 2889485e779SHolger Brunck printf("set boardid=%s\n", buf); 289a9417ce7SHolger Brunck 290a9417ce7SHolger Brunck p = get_local_var("IVM_HWKey"); 291a9417ce7SHolger Brunck if (p == NULL) { 292a9417ce7SHolger Brunck printf("can't get the IVM_HWKey\n"); 293a9417ce7SHolger Brunck return 1; 294a9417ce7SHolger Brunck } 295a9417ce7SHolger Brunck sprintf((char *)buf, "%s", p); 296a9417ce7SHolger Brunck setenv("hwkey", (char *)buf); 2979485e779SHolger Brunck printf("set hwkey=%s\n", buf); 2989485e779SHolger Brunck printf("Execute manually saveenv for persistent storage.\n"); 299a9417ce7SHolger Brunck 300a9417ce7SHolger Brunck return 0; 301a9417ce7SHolger Brunck } 302a9417ce7SHolger Brunck 303a9417ce7SHolger Brunck U_BOOT_CMD(km_setboardid, 1, 0, do_setboardid, "setboardid", "read out bid and " 304a9417ce7SHolger Brunck "hwkey from IVM and set in environment"); 30592c91080SThomas Herzmann 30692c91080SThomas Herzmann /* 30792c91080SThomas Herzmann * command km_checkbidhwk 30892c91080SThomas Herzmann * if "boardid" and "hwkey" are not already set in the environment, do: 30992c91080SThomas Herzmann * if a "boardIdListHex" exists in the environment: 31092c91080SThomas Herzmann * - read ivm data for boardid and hwkey 31192c91080SThomas Herzmann * - compare each entry of the boardIdListHex with the 31292c91080SThomas Herzmann * IVM data: 31392c91080SThomas Herzmann * if match: 31492c91080SThomas Herzmann * set environment variables boardid, boardId, 31592c91080SThomas Herzmann * hwkey, hwKey to the found values 31692c91080SThomas Herzmann * both (boardid and boardId) are set because 31792c91080SThomas Herzmann * they might be used differently in the 31892c91080SThomas Herzmann * application and in the init scripts (?) 31992c91080SThomas Herzmann * return 0 in case of match, 1 if not match or error 32092c91080SThomas Herzmann */ 32192c91080SThomas Herzmann int do_checkboardidhwk(cmd_tbl_t *cmdtp, int flag, int argc, 32292c91080SThomas Herzmann char *const argv[]) 32392c91080SThomas Herzmann { 32492c91080SThomas Herzmann unsigned long ivmbid = 0, ivmhwkey = 0; 32592c91080SThomas Herzmann unsigned long envbid = 0, envhwkey = 0; 32692c91080SThomas Herzmann char *p; 32792c91080SThomas Herzmann int verbose = argc > 1 && *argv[1] == 'v'; 32892c91080SThomas Herzmann int rc = 0; 32992c91080SThomas Herzmann 33092c91080SThomas Herzmann /* 33192c91080SThomas Herzmann * first read out the real inventory values, these values are 33292c91080SThomas Herzmann * already stored in the local hush variables 33392c91080SThomas Herzmann */ 33492c91080SThomas Herzmann p = get_local_var("IVM_BoardId"); 33592c91080SThomas Herzmann if (p == NULL) { 33692c91080SThomas Herzmann printf("can't get the IVM_Boardid\n"); 33792c91080SThomas Herzmann return 1; 33892c91080SThomas Herzmann } 33992c91080SThomas Herzmann rc = strict_strtoul(p, 16, &ivmbid); 34092c91080SThomas Herzmann 34192c91080SThomas Herzmann p = get_local_var("IVM_HWKey"); 34292c91080SThomas Herzmann if (p == NULL) { 34392c91080SThomas Herzmann printf("can't get the IVM_HWKey\n"); 34492c91080SThomas Herzmann return 1; 34592c91080SThomas Herzmann } 34692c91080SThomas Herzmann rc = strict_strtoul(p, 16, &ivmhwkey); 34792c91080SThomas Herzmann 34892c91080SThomas Herzmann if (!ivmbid || !ivmhwkey) { 34992c91080SThomas Herzmann printf("Error: IVM_BoardId and/or IVM_HWKey not set!\n"); 35092c91080SThomas Herzmann return rc; 35192c91080SThomas Herzmann } 35292c91080SThomas Herzmann 35392c91080SThomas Herzmann /* now try to read values from environment if available */ 35492c91080SThomas Herzmann p = getenv("boardid"); 35592c91080SThomas Herzmann if (p != NULL) 35692c91080SThomas Herzmann rc = strict_strtoul(p, 16, &envbid); 35792c91080SThomas Herzmann p = getenv("hwkey"); 35892c91080SThomas Herzmann if (p != NULL) 35992c91080SThomas Herzmann rc = strict_strtoul(p, 16, &envhwkey); 36092c91080SThomas Herzmann 36192c91080SThomas Herzmann if (rc != 0) { 36292c91080SThomas Herzmann printf("strict_strtoul returns error: %d", rc); 36392c91080SThomas Herzmann return rc; 36492c91080SThomas Herzmann } 36592c91080SThomas Herzmann 36692c91080SThomas Herzmann if (!envbid || !envhwkey) { 36792c91080SThomas Herzmann /* 36892c91080SThomas Herzmann * BoardId/HWkey not available in the environment, so try the 36992c91080SThomas Herzmann * environment variable for BoardId/HWkey list 37092c91080SThomas Herzmann */ 37192c91080SThomas Herzmann char *bidhwklist = getenv("boardIdListHex"); 37292c91080SThomas Herzmann 37392c91080SThomas Herzmann if (bidhwklist) { 37492c91080SThomas Herzmann int found = 0; 37592c91080SThomas Herzmann char *rest = bidhwklist; 37692c91080SThomas Herzmann char *endp; 37792c91080SThomas Herzmann 37892c91080SThomas Herzmann if (verbose) { 37992c91080SThomas Herzmann printf("IVM_BoardId: %ld, IVM_HWKey=%ld\n", 38092c91080SThomas Herzmann ivmbid, ivmhwkey); 38192c91080SThomas Herzmann printf("boardIdHwKeyList: %s\n", 38292c91080SThomas Herzmann bidhwklist); 38392c91080SThomas Herzmann } 38492c91080SThomas Herzmann while (!found) { 38592c91080SThomas Herzmann /* loop over each bid/hwkey pair in the list */ 38692c91080SThomas Herzmann unsigned long bid = 0; 38792c91080SThomas Herzmann unsigned long hwkey = 0; 38892c91080SThomas Herzmann 38992c91080SThomas Herzmann while (*rest && !isxdigit(*rest)) 39092c91080SThomas Herzmann rest++; 39192c91080SThomas Herzmann /* 39292c91080SThomas Herzmann * use simple_strtoul because we need &end and 39392c91080SThomas Herzmann * we know we got non numeric char at the end 39492c91080SThomas Herzmann */ 39592c91080SThomas Herzmann bid = simple_strtoul(rest, &endp, 16); 39692c91080SThomas Herzmann /* BoardId and HWkey are separated with a "_" */ 39792c91080SThomas Herzmann if (*endp == '_') { 39892c91080SThomas Herzmann rest = endp + 1; 39992c91080SThomas Herzmann /* 40092c91080SThomas Herzmann * use simple_strtoul because we need 40192c91080SThomas Herzmann * &end 40292c91080SThomas Herzmann */ 40392c91080SThomas Herzmann hwkey = simple_strtoul(rest, &endp, 16); 40492c91080SThomas Herzmann rest = endp; 40592c91080SThomas Herzmann while (*rest && !isxdigit(*rest)) 40692c91080SThomas Herzmann rest++; 40792c91080SThomas Herzmann } 40892c91080SThomas Herzmann if ((!bid) || (!hwkey)) { 40992c91080SThomas Herzmann /* end of list */ 41092c91080SThomas Herzmann break; 41192c91080SThomas Herzmann } 41292c91080SThomas Herzmann if (verbose) { 41392c91080SThomas Herzmann printf("trying bid=0x%lX, hwkey=%ld\n", 41492c91080SThomas Herzmann bid, hwkey); 41592c91080SThomas Herzmann } 41692c91080SThomas Herzmann /* 41792c91080SThomas Herzmann * Compare the values of the found entry in the 41892c91080SThomas Herzmann * list with the valid values which are stored 41992c91080SThomas Herzmann * in the inventory eeprom. If they are equal 420ba8be32aSHolger Brunck * set the values in environment variables. 42192c91080SThomas Herzmann */ 42292c91080SThomas Herzmann if ((bid == ivmbid) && (hwkey == ivmhwkey)) { 42392c91080SThomas Herzmann char buf[10]; 42492c91080SThomas Herzmann 42592c91080SThomas Herzmann found = 1; 42692c91080SThomas Herzmann envbid = bid; 42792c91080SThomas Herzmann envhwkey = hwkey; 42892c91080SThomas Herzmann sprintf(buf, "%lx", bid); 42992c91080SThomas Herzmann setenv("boardid", buf); 43092c91080SThomas Herzmann sprintf(buf, "%lx", hwkey); 43192c91080SThomas Herzmann setenv("hwkey", buf); 43292c91080SThomas Herzmann } 43392c91080SThomas Herzmann } /* end while( ! found ) */ 43492c91080SThomas Herzmann } 43592c91080SThomas Herzmann } 43692c91080SThomas Herzmann 43792c91080SThomas Herzmann /* compare now the values */ 43892c91080SThomas Herzmann if ((ivmbid == envbid) && (ivmhwkey == envhwkey)) { 43992c91080SThomas Herzmann printf("boardid=0x%3lX, hwkey=%ld\n", envbid, envhwkey); 44092c91080SThomas Herzmann rc = 0; /* match */ 44192c91080SThomas Herzmann } else { 4429485e779SHolger Brunck printf("Error: env boardid=0x%3lX, hwkey=%ld\n", envbid, 4439485e779SHolger Brunck envhwkey); 44492c91080SThomas Herzmann printf(" IVM bId=0x%3lX, hwKey=%ld\n", ivmbid, ivmhwkey); 44592c91080SThomas Herzmann rc = 1; /* don't match */ 44692c91080SThomas Herzmann } 44792c91080SThomas Herzmann return rc; 44892c91080SThomas Herzmann } 44992c91080SThomas Herzmann 45092c91080SThomas Herzmann U_BOOT_CMD(km_checkbidhwk, 2, 0, do_checkboardidhwk, 45192c91080SThomas Herzmann "check boardid and hwkey", 45292c91080SThomas Herzmann "[v]\n - check environment parameter "\ 45392c91080SThomas Herzmann "\"boardIdListHex\" against stored boardid and hwkey "\ 45492c91080SThomas Herzmann "from the IVM\n v: verbose output" 45592c91080SThomas Herzmann ); 456