diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2017-07-20 10:15:40 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-07-28 17:45:13 -0700 |
commit | a35218e20499a95ec7706f87cb48ff39c5451663 (patch) | |
tree | e99e8d4d9d25b9f00d20cdf447da750397f14c7d | |
parent | 1b25735b732e7766aceb3f060e4ca205aba6d358 (diff) | |
download | chrome-ec-a35218e20499a95ec7706f87cb48ff39c5451663.tar.gz |
stm32f4: Add OTP support.
Add support for OTP memory: if needed store serial number in first bank.
BUG=chromium:746471
BRANCH=none
TEST=On sweetberry, check we can write serial number with serialno
command. Check serial number survive a firmware update.
First, check without write protect, check we can write 0s (but not 1s)
serialno
Serial number: NNNNNNNNNNNNNNNNNNNNNN
>
> serial set MMMMMMMMMMMMMMMMMMMMMMMMMMMMM
Saving serial number
Serial number: LLLLLLLLLLLLLLLLLLLLLL
After lock enabled, check we can not overwrite.
> serial set AMMMMMMMMMMMMMMMMMMMMMMMMMMMM
Saving serial number
Serial number: LLLLLLLLLLLLLLLLLLLLLL
Access Denied
Check that serialno returns "Uninitialized" if it was never set.
Change-Id: I9ab08486a7c3e1958e964649640d69b5b70947e3
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/580290
Reviewed-by: Nick Sanders <nsanders@chromium.org>
-rw-r--r-- | chip/stm32/build.mk | 1 | ||||
-rw-r--r-- | chip/stm32/config-stm32f446.h | 3 | ||||
-rw-r--r-- | chip/stm32/otp-stm32f4.c | 119 | ||||
-rw-r--r-- | chip/stm32/registers.h | 13 |
4 files changed, 136 insertions, 0 deletions
diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk index b44b3ac2fe..c339885816 100644 --- a/chip/stm32/build.mk +++ b/chip/stm32/build.mk @@ -56,6 +56,7 @@ endif chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o chip-$(CONFIG_STM32_CHARGER_DETECT)+=charger_detect.o chip-$(CONFIG_DEBUG_PRINTF)+=debug_printf.o +chip-$(CONFIG_OTP)+=otp-$(CHIP_FAMILY).o chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_RNG)+=trng.o diff --git a/chip/stm32/config-stm32f446.h b/chip/stm32/config-stm32f446.h index 27ee939521..ee43b4fb9b 100644 --- a/chip/stm32/config-stm32f446.h +++ b/chip/stm32/config-stm32f446.h @@ -54,5 +54,8 @@ #define CONFIG_FLASH_PSTATE #undef CONFIG_FLASH_PSTATE_BANK +/* Use OTP regions */ +#define CONFIG_OTP + /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 97 diff --git a/chip/stm32/otp-stm32f4.c b/chip/stm32/otp-stm32f4.c new file mode 100644 index 0000000000..a993af7042 --- /dev/null +++ b/chip/stm32/otp-stm32f4.c @@ -0,0 +1,119 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* OTP implementation for STM32F411 */ + +#include "common.h" +#include "console.h" +#include "flash.h" +#include "otp.h" +#include "registers.h" +#include "util.h" + +/* + * OTP is only used for saving the USB serial number. + */ +#ifdef CONFIG_SERIALNO_LEN +/* Which block to use */ +#define OTP_SERIAL_BLOCK 0 +#define OTP_SERIAL_ADDR \ + REG32_ADDR(STM32_OTP_BLOCK_DATA(OTP_SERIAL_BLOCK, 0)) + +/* Number of word used in the block */ +#define OTP_SERIAL_BLOCK_SIZE (CONFIG_SERIALNO_LEN / sizeof(uint32_t)) +BUILD_ASSERT(CONFIG_SERIALNO_LEN % sizeof(uint32_t) == 0); +BUILD_ASSERT(OTP_SERIAL_BLOCK_SIZE < STM32_OTP_BLOCK_SIZE); + +/* + * Write an OTP block + * + * @param block block to write. + * @param size Number of words to write. + * @param data Destination buffer for data. + */ +static int otp_write(uint8_t block, int size, const char *data) +{ + if (block >= STM32_OTP_BLOCK_NB) + return EC_ERROR_PARAM1; + if (size >= STM32_OTP_BLOCK_SIZE) + return EC_ERROR_PARAM2; + return flash_physical_write(STM32_OTP_BLOCK_DATA(block, 0) - + CONFIG_PROGRAM_MEMORY_BASE, + size * sizeof(uint32_t), data); +} + +/* + * Check if an OTP block is protected. + * + * @param block protected block. + * @return non-zero if that block is read only. + */ +static int otp_get_protect(uint8_t block) +{ + uint32_t lock; + + lock = REG32(STM32_OTP_LOCK(block)); + return ((lock & STM32_OPT_LOCK_MASK(block)) == 0); +} + +/* + * Set a particular OTP block as read only. + * + * @param block block to protect. + */ +static int otp_set_protect(uint8_t block) +{ + int rv; + uint32_t lock; + + if (otp_get_protect(block)) + return EC_SUCCESS; + + lock = REG32(STM32_OTP_LOCK(block)); + lock &= ~STM32_OPT_LOCK_MASK(block); + rv = flash_physical_write(STM32_OTP_LOCK(block) - + CONFIG_PROGRAM_MEMORY_BASE, + sizeof(uint32_t), (char *)&lock); + if (rv) + return rv; + else + return EC_SUCCESS; +} + +const char *otp_read_serial(void) +{ + int i; + + for (i = 0; i < OTP_SERIAL_BLOCK_SIZE; i++) { + if (OTP_SERIAL_ADDR[i] != -1) + return (char *)OTP_SERIAL_ADDR; + } + return NULL; +} + +int otp_write_serial(const char *serialno) +{ + int i, ret; + char otp_serial[CONFIG_SERIALNO_LEN]; + + if (otp_get_protect(OTP_SERIAL_BLOCK)) + return EC_ERROR_ACCESS_DENIED; + + /* Copy in serialno. */ + for (i = 0; i < CONFIG_SERIALNO_LEN - 1; i++) { + otp_serial[i] = serialno[i]; + if (serialno[i] == 0) + break; + } + for (; i < CONFIG_SERIALNO_LEN; i++) + otp_serial[i] = 0; + + ret = otp_write(OTP_SERIAL_BLOCK, OTP_SERIAL_BLOCK_SIZE, otp_serial); + if (ret == EC_SUCCESS) + return otp_set_protect(OTP_SERIAL_BLOCK); + else + return ret; +} +#endif diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 764dc79af6..3e1bf1df14 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1479,6 +1479,19 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_OPTB_COMPL_SHIFT 8 +#define STM32_OTP_BASE 0x1FFF7800 +#define STM32_OTP_BLOCK_NB 16 +#define STM32_OTP_BLOCK_SIZE 32 +#define STM32_OTP_BLOCK_DATA(_block, _offset) \ + (STM32_OTP_BASE + STM32_OTP_BLOCK_SIZE * (_block) + (_offset) * 4) +#define STM32_OTP_UNLOCK_BYTE 0x00 +#define STM32_OTP_LOCK_BYTE 0xFF +#define STM32_OTP_LOCK_BASE \ + (STM32_OTP_BASE + STM32_OTP_BLOCK_NB * STM32_OTP_BLOCK_SIZE) +#define STM32_OTP_LOCK(_block) \ + (STM32_OTP_LOCK_BASE + ((_block) / 4) * 4) +#define STM32_OPT_LOCK_MASK(_block) ((0xFF << ((_block) % 4) * 8)) + #else #error Unsupported chip variant #endif |