diff --git a/board/nm/nmhw21/Makefile b/board/nm/nmhw21/Makefile index 98c6bf7e80..2c20c72d38 100644 --- a/board/nm/nmhw21/Makefile +++ b/board/nm/nmhw21/Makefile @@ -10,4 +10,4 @@ ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) obj-y := mux.o endif -obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o ../common/da9063.o fileaccess.o sja1105.o ui.o um.o +obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o ../common/da9063.o fileaccess.o sja1105.o ui.o um.o fct_atecc.o diff --git a/board/nm/nmhw21/fct_atecc.c b/board/nm/nmhw21/fct_atecc.c new file mode 100644 index 0000000000..1173938ed3 --- /dev/null +++ b/board/nm/nmhw21/fct_atecc.c @@ -0,0 +1,204 @@ +/* + * fct_atecc.c + * + * Microchip ATECC608 test + * + * Copyright (C) 2018-2020 NetModule AG - http://www.netmodule.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include "fct_atecc.h" + + +#define REG_SLEEP 0x01 +#define REG_COMMAND 0x03 + +#define WAKE_DELAY_US 1500 + +#define RNG_MAX_EXEC_TIME_MS 23 +#define READ_MAX_EXEC_TIME_MS 1 /* 4 bytes read, 32 bytes = ? */ + + +static void wake_chip(void) +{ + int j; + + + i2c_set_bus_speed(50000); + + /* wake up sequence, same as i2c probe on command line (proven to work) */ + for (j = 0; j < 128; j++) { + i2c_probe(j); + } + + udelay(WAKE_DELAY_US+1000); + + i2c_set_bus_speed(400000); +} + +static int put_in_sleep(void) +{ + uchar temp[1]; + int ret; + + /* put back into sleep mode */ + ret = i2c_write(CONFIG_ATECC_I2C_ADDR, REG_SLEEP, 1, temp, 0); + if (ret != 0) { + puts("can't put device in sleep mode\n"); + } + + return ret; +} + +static int test_rng(void) +{ + uchar rng_cmd[7] = { 7, 0x1B, 0x00, 0x00, 0x00, 0x24, 0xCD }; + uchar temp[32+3]; + int ret; + + + ret = i2c_write(CONFIG_ATECC_I2C_ADDR, REG_COMMAND, 1, rng_cmd, 7); + if (ret != 0) { + puts("error sending command\n"); + goto abort; + } + + mdelay(RNG_MAX_EXEC_TIME_MS+10); + + /* + * Get random number + * will be ff ff 00 00 ff ff 00 00 .. if chip is unlocked + */ + memset(temp, 0x00, sizeof(temp)); + ret = i2c_read(CONFIG_ATECC_I2C_ADDR, 0x00, 0, temp, 32+3); + if (ret != 0) { + puts("error reading RNG response\n"); + goto abort; + } +#if 0 + for (i=0; i<32+3; i++) { + printf("%02x ", temp[i]); + } + puts("\n"); +#endif + if (temp[0] != 0x23 || temp[33] != 0x41 || temp[34] != 0x1a) { + puts("invalid data returned\n"); + goto abort; + } + + if (temp[33] == 0x41 && temp[34] == 0x1a) { + puts("RNG: ok (chip unlocked)\n"); + } + else { + puts("RNG: ok (chip locked)\n"); + } + +abort: + return ret; +} + +static int test_serial_num(void) +{ + uchar read_cfg32_cmd[7] = { 7, 0x02, 0x80, 0x00, 0x00, 0x09, 0xAD }; + uchar temp[32+3]; + uchar sn[9]; + int ret; + int i; + + + /* + * Read beginning of config zone, get S/N + * S/N = 0..3, 8..12 + */ + ret = i2c_write(CONFIG_ATECC_I2C_ADDR, REG_COMMAND, 1, read_cfg32_cmd, 7); + if (ret != 0) { + puts("error sending READ command\n"); + goto abort; + } + + mdelay(READ_MAX_EXEC_TIME_MS+10); + + memset(temp, 0x00, sizeof(temp)); + ret = i2c_read(CONFIG_ATECC_I2C_ADDR, 0x00, 0, temp, 32+3); + if (ret != 0) { + puts("error reading response\n"); + goto abort; + } +#if 0 + for (i=0; i<32+3; i++) { + printf("%02x ", temp[i]); + } + puts("\n"); +#endif + memcpy(&sn[0], &temp[1], 4); + memcpy(&sn[4], &temp[9], 5); + puts("S/N: "); + for (i=0; i<9; i++) { + printf("%02x ", sn[i]); + } + puts("\n"); + +abort: + return ret; +} + + +static int do_atecc_test(void) +{ + int ret; + + i2c_set_bus_num(CONFIG_ATECC_I2C_BUS); + + wake_chip(); + + ret = test_rng(); + if (ret != 0) { + goto abort; + } + + ret = test_serial_num(); + if (ret != 0) { + goto abort; + } + + ret = put_in_sleep(); + if (ret != 0) { + goto abort; + } + + i2c_set_bus_speed(100000); + + puts("test passed\n"); + return 0; + +abort: + i2c_set_bus_speed(100000); + + puts("test failed\n"); + return 1; +} + +static int do_fct_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc != 2) + goto cmd_usage; + + do_atecc_test(); + + return 0; + +cmd_usage: + return cmd_usage(cmdtp); +} + + +U_BOOT_CMD( + fct, 2, 1, do_fct_test, + "factory test subsystem\n", + "atecc - tests ATECC chip" +); diff --git a/board/nm/nmhw21/fct_atecc.h b/board/nm/nmhw21/fct_atecc.h new file mode 100644 index 0000000000..6d86d60734 --- /dev/null +++ b/board/nm/nmhw21/fct_atecc.h @@ -0,0 +1,19 @@ +/* + * fct_atecc.c + * + * Microchip ATECC608 test + * + * Copyright (C) 2018-2020 NetModule AG - http://www.netmodule.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef FCT_ATECC_H +#define FCT_ATECC_H + + +#define CONFIG_ATECC_I2C_BUS 0 +#define CONFIG_ATECC_I2C_ADDR 0x60 + + +#endif /* FCT_ATECC_H */