From patchwork Thu May 17 13:24:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 915446 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=st.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40msVZ1nM1z9s33 for ; Thu, 17 May 2018 23:25:10 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id B13EDC21F18; Thu, 17 May 2018 13:24:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 362F0C21F01; Thu, 17 May 2018 13:24:34 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 4F600C21E08; Thu, 17 May 2018 13:24:31 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by lists.denx.de (Postfix) with ESMTPS id F29F1C21DB5 for ; Thu, 17 May 2018 13:24:30 +0000 (UTC) Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w4HDIlN7014069 for ; Thu, 17 May 2018 15:24:30 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2j1ab6g2y4-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 17 May 2018 15:24:30 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id C104849 for ; Thu, 17 May 2018 13:24:29 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6C57D2B65 for ; Thu, 17 May 2018 13:24:29 +0000 (GMT) Received: from localhost (10.75.127.44) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 17 May 2018 15:24:28 +0200 From: Patrice Chotard To: Date: Thu, 17 May 2018 15:24:04 +0200 Message-ID: <1526563447-1323-2-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> References: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG7NODE3.st.com (10.75.127.21) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-17_07:, , signatures=0 Subject: [U-Boot] [PATCH v1 1/4] stm32mp1: remove the second TAMP_BOOT_CONTEXT update X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrick Delaunay The register TAMP_BOOT_CONTEXT is already updated in get_bootmode() in cpu.c and no need to be done twice. Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard --- arch/arm/mach-stm32mp/spl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c index b56f0c5381c3..790973e8b6e9 100644 --- a/arch/arm/mach-stm32mp/spl.c +++ b/arch/arm/mach-stm32mp/spl.c @@ -14,9 +14,6 @@ u32 spl_boot_device(void) boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT; - clrsetbits_le32(TAMP_BOOT_CONTEXT, - TAMP_BOOT_MODE_MASK, - boot_mode << TAMP_BOOT_MODE_SHIFT); switch (boot_mode) { case BOOT_FLASH_SD_1: From patchwork Thu May 17 13:24:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 915447 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=st.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40msWC6LPqz9s1B for ; Thu, 17 May 2018 23:25:43 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5F29BC21F00; Thu, 17 May 2018 13:25:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 0172CC21F45; Thu, 17 May 2018 13:24:37 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6AE9BC21EE0; Thu, 17 May 2018 13:24:36 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx08-00178001.pphosted.com [91.207.212.93]) by lists.denx.de (Postfix) with ESMTPS id 1BF90C21EE5 for ; Thu, 17 May 2018 13:24:32 +0000 (UTC) Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w4HDOKVK026642 for ; Thu, 17 May 2018 15:24:31 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2j1a880437-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 17 May 2018 15:24:31 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 18BC331 for ; Thu, 17 May 2018 13:24:31 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id F25002B63 for ; Thu, 17 May 2018 13:24:30 +0000 (GMT) Received: from localhost (10.75.127.46) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 17 May 2018 15:24:30 +0200 From: Patrice Chotard To: Date: Thu, 17 May 2018 15:24:05 +0200 Message-ID: <1526563447-1323-3-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> References: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.46] X-ClientProxiedBy: SFHDAG7NODE1.st.com (10.75.127.19) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-17_07:, , signatures=0 Subject: [U-Boot] [PATCH v1 2/4] stm32mp1: add bsec driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrick Delaunay Add a MISC driver with read and write access to BSEC IP (Boot and Security and OTP control) - offset 0: shadowed values - offset 0x80000000: OTP fuse box values (SAFMEM) Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard --- arch/arm/mach-stm32mp/Makefile | 8 +- arch/arm/mach-stm32mp/bsec.c | 431 +++++++++++++++++++++++++++++ arch/arm/mach-stm32mp/include/mach/stm32.h | 5 + 3 files changed, 442 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-stm32mp/bsec.c diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index 08ee642d9086..f59ced5ee1b1 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/arch/arm/mach-stm32mp/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0+ # # Copyright (C) 2018, STMicroelectronics - All Rights Reserved # @@ -7,6 +7,10 @@ obj-y += cpu.o obj-y += dram_init.o obj-y += syscon.o -obj-$(CONFIG_SPL_BUILD) += spl.o +ifdef CONFIG_SPL_BUILD +obj-y += spl.o +else +obj-y += bsec.o +endif obj-$(CONFIG_ARMV7_PSCI) += psci.o obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c new file mode 100644 index 000000000000..0e152efc045f --- /dev/null +++ b/arch/arm/mach-stm32mp/bsec.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include + +#define BSEC_OTP_MAX_VALUE 95 + +#define BSEC_TIMEOUT_US 10000 + +/* BSEC REGISTER OFFSET (base relative) */ +#define BSEC_OTP_CONF_OFF 0x000 +#define BSEC_OTP_CTRL_OFF 0x004 +#define BSEC_OTP_WRDATA_OFF 0x008 +#define BSEC_OTP_STATUS_OFF 0x00C +#define BSEC_OTP_LOCK_OFF 0x010 +#define BSEC_DISTURBED_OFF 0x01C +#define BSEC_ERROR_OFF 0x034 +#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky lock */ +#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky lock */ +#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock */ +#define BSEC_OTP_DATA_OFF 0x200 + +/* BSEC_CONFIGURATION Register MASK */ +#define BSEC_CONF_POWER_UP 0x001 + +/* BSEC_CONTROL Register */ +#define BSEC_READ 0x000 +#define BSEC_WRITE 0x100 + +/* LOCK Register */ +#define OTP_LOCK_MASK 0x1F +#define OTP_LOCK_BANK_SHIFT 0x05 +#define OTP_LOCK_BIT_MASK 0x01 + +/* STATUS Register */ +#define BSEC_MODE_BUSY_MASK 0x08 +#define BSEC_MODE_PROGFAIL_MASK 0x10 +#define BSEC_MODE_PWR_MASK 0x20 + +/* + * OTP Lock services definition + * Value must corresponding to the bit number in the register + */ +#define BSEC_LOCK_PROGRAM 0x04 + +/** + * bsec_check_error() - Check status of one otp + * @base: base address of bsec IP + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: 0 if no error, -EAGAIN or -ENOTSUPP + */ +static u32 bsec_check_error(u32 base, u32 otp) +{ + u32 bit; + u32 bank; + + bit = 1 << (otp & OTP_LOCK_MASK); + bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); + + if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) + return -EAGAIN; + else if (readl(base + BSEC_ERROR_OFF + bank) & bit) + return -ENOTSUPP; + + return 0; +} + +/** + * bsec_lock() - manage lock for each type SR/SP/SW + * @address: address of bsec IP register + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: true if locked else false + */ +static bool bsec_read_lock(u32 address, u32 otp) +{ + u32 bit; + u32 bank; + + bit = 1 << (otp & OTP_LOCK_MASK); + bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); + + return !!(readl(address + bank) & bit); +} + +/** + * bsec_read_SR_lock() - read SR lock (Shadowing) + * @base: base address of bsec IP + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: true if locked else false + */ +static bool bsec_read_SR_lock(u32 base, u32 otp) +{ + return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp); +} + +/** + * bsec_read_SP_lock() - read SP lock (program Lock) + * @base: base address of bsec IP + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: true if locked else false + */ +static bool bsec_read_SP_lock(u32 base, u32 otp) +{ + return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp); +} + +/** + * bsec_SW_lock() - manage SW lock (Write in Shadow) + * @base: base address of bsec IP + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: true if locked else false + */ +static bool bsec_read_SW_lock(u32 base, u32 otp) +{ + return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp); +} + +/** + * bsec_power_safmem() - Activate or deactivate safmem power + * @base: base address of bsec IP + * @power: true to power up , false to power down + * Return: 0 if succeed + */ +static int bsec_power_safmem(u32 base, bool power) +{ + u32 val; + u32 mask; + + if (power) { + setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP); + mask = BSEC_MODE_PWR_MASK; + } else { + clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP); + mask = 0; + } + + /* waiting loop */ + return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF, + val, (val & BSEC_MODE_PWR_MASK) == mask, + BSEC_TIMEOUT_US); +} + +/** + * bsec_shadow_register() - copy safmen otp to bsec data + * @base: base address of bsec IP + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: 0 if no error + */ +static int bsec_shadow_register(u32 base, u32 otp) +{ + u32 val; + int ret; + bool power_up = false; + + /* check if shadowing of otp is locked */ + if (bsec_read_SR_lock(base, otp)) + pr_debug("bsec : OTP %d is locked and refreshed with 0\n", otp); + + /* check if safemem is power up */ + val = readl(base + BSEC_OTP_STATUS_OFF); + if (!(val & BSEC_MODE_PWR_MASK)) { + ret = bsec_power_safmem(base, true); + if (ret) + return ret; + power_up = 1; + } + /* set BSEC_OTP_CTRL_OFF with the otp value*/ + writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF); + + /* check otp status*/ + ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF, + val, (val & BSEC_MODE_BUSY_MASK) == 0, + BSEC_TIMEOUT_US); + if (ret) + return ret; + + ret = bsec_check_error(base, otp); + + if (power_up) + bsec_power_safmem(base, false); + + return ret; +} + +/** + * bsec_read_shadow() - read an otp data value from shadow + * @base: base address of bsec IP + * @val: read value + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: 0 if no error + */ +static int bsec_read_shadow(u32 base, u32 *val, u32 otp) +{ + *val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32)); + + return bsec_check_error(base, otp); +} + +/** + * bsec_write_shadow() - write value in BSEC data register in shadow + * @base: base address of bsec IP + * @val: value to write + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * Return: 0 if no error + */ +static int bsec_write_shadow(u32 base, u32 val, u32 otp) +{ + /* check if programming of otp is locked */ + if (bsec_read_SW_lock(base, otp)) + pr_debug("bsec : OTP %d is lock, write will be ignore\n", otp); + + writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32)); + + return bsec_check_error(base, otp); +} + +/** + * bsec_program_otp() - program a bit in SAFMEM + * @base: base address of bsec IP + * @val: value to program + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) + * after the function the otp data is not refreshed in shadow + * Return: 0 if no error + */ +static int bsec_program_otp(long base, u32 val, u32 otp) +{ + u32 ret; + bool power_up = false; + + if (bsec_read_SP_lock(base, otp)) + pr_debug("bsec : OTP %d locked, prog will be ignore\n", otp); + + if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM)) + pr_debug("bsec : Global lock, prog will be ignore\n"); + + /* check if safemem is power up */ + if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) { + ret = bsec_power_safmem(base, true); + if (ret) + return ret; + + power_up = true; + } + /* set value in write register*/ + writel(val, base + BSEC_OTP_WRDATA_OFF); + + /* set BSEC_OTP_CTRL_OFF with the otp value */ + writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF); + + /* check otp status*/ + ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF, + val, (val & BSEC_MODE_BUSY_MASK) == 0, + BSEC_TIMEOUT_US); + if (ret) + return ret; + + if (val & BSEC_MODE_PROGFAIL_MASK) + ret = -EACCES; + else + ret = bsec_check_error(base, otp); + + if (power_up) + bsec_power_safmem(base, false); + + return ret; +} + +/* BSEC MISC driver *******************************************************/ +struct stm32mp_bsec_platdata { + u32 base; +}; + +static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + u32 tmp_data = 0; + int ret; + + /* read current shadow value */ + ret = bsec_read_shadow(plat->base, &tmp_data, otp); + if (ret) + return ret; + + /* copy otp in shadow */ + ret = bsec_shadow_register(plat->base, otp); + if (ret) + return ret; + + ret = bsec_read_shadow(plat->base, val, otp); + if (ret) + return ret; + + /* restore shadow value */ + ret = bsec_write_shadow(plat->base, tmp_data, otp); + return ret; +} + +static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + return bsec_read_shadow(plat->base, val, otp); +} + +static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + return bsec_program_otp(plat->base, val, otp); +} + +static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + return bsec_write_shadow(plat->base, val, otp); +} + +static int stm32mp_bsec_read(struct udevice *dev, int offset, + void *buf, int size) +{ + int ret; + int i; + bool shadow = true; + int nb_otp = size / sizeof(u32); + int otp; + + if (offset >= STM32_BSEC_OTP_OFFSET) { + offset -= STM32_BSEC_OTP_OFFSET; + shadow = false; + } + otp = offset / sizeof(u32); + + if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) { + dev_err(dev, "wrong value for otp, max value : %i\n", + BSEC_OTP_MAX_VALUE); + return -EINVAL; + } + + for (i = otp; i < (otp + nb_otp); i++) { + u32 *addr = &((u32 *)buf)[i - otp]; + + if (shadow) + ret = stm32mp_bsec_read_shadow(dev, addr, i); + else + ret = stm32mp_bsec_read_otp(dev, addr, i); + + if (ret) + break; + } + return ret; +} + +static int stm32mp_bsec_write(struct udevice *dev, int offset, + const void *buf, int size) +{ + int ret = 0; + int i; + bool shadow = true; + int nb_otp = size / sizeof(u32); + int otp; + + if (offset >= STM32_BSEC_OTP_OFFSET) { + offset -= STM32_BSEC_OTP_OFFSET; + shadow = false; + } + otp = offset / sizeof(u32); + + if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) { + dev_err(dev, "wrong value for otp, max value : %d\n", + BSEC_OTP_MAX_VALUE); + return -EINVAL; + } + + for (i = otp; i < otp + nb_otp; i++) { + u32 *val = &((u32 *)buf)[i - otp]; + + if (shadow) + ret = stm32mp_bsec_write_shadow(dev, *val, i); + else + ret = stm32mp_bsec_write_otp(dev, *val, i); + if (ret) + break; + } + return ret; +} + +static const struct misc_ops stm32mp_bsec_ops = { + .read = stm32mp_bsec_read, + .write = stm32mp_bsec_write, +}; + +static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + plat->base = (u32)dev_read_addr_ptr(dev); + + return 0; +} + +static const struct udevice_id stm32mp_bsec_ids[] = { + { .compatible = "st,stm32mp-bsec" }, + {} +}; + +U_BOOT_DRIVER(stm32mp_bsec) = { + .name = "stm32mp_bsec", + .id = UCLASS_MISC, + .of_match = stm32mp_bsec_ids, + .ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata), + .ops = &stm32mp_bsec_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* bsec IP is not present in device tee, manage IP address by platdata */ +static struct stm32mp_bsec_platdata stm32_bsec_platdata = { + .base = STM32_BSEC_BASE, +}; + +U_BOOT_DEVICE(stm32mp_bsec) = { + .name = "stm32mp_bsec", + .platdata = &stm32_bsec_platdata, +}; diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 129f9f558eac..5d0bdca1787d 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -13,6 +13,7 @@ #define STM32_RCC_BASE 0x50000000 #define STM32_PWR_BASE 0x50001000 #define STM32_DBGMCU_BASE 0x50081000 +#define STM32_BSEC_BASE 0x5C005000 #define STM32_TZC_BASE 0x5C006000 #define STM32_ETZPC_BASE 0x5C007000 #define STM32_TAMP_BASE 0x5C00A000 @@ -95,5 +96,9 @@ enum boot_device { #define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4) #define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0) +/* offset used for BSEC driver: misc_read and misc_write */ +#define STM32_BSEC_SHADOW_OFFSET 0x0 +#define STM32_BSEC_OTP_OFFSET 0x80000000 + #endif /* __ASSEMBLY__*/ #endif /* _MACH_STM32_H_ */ From patchwork Thu May 17 13:24:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 915449 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=st.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40msXc0yz5z9s33 for ; Thu, 17 May 2018 23:26:55 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id B8433C21F6D; Thu, 17 May 2018 13:26:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 95D79C21F29; Thu, 17 May 2018 13:24:47 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 348D6C21F53; Thu, 17 May 2018 13:24:37 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by lists.denx.de (Postfix) with ESMTPS id DF127C21F1A for ; Thu, 17 May 2018 13:24:32 +0000 (UTC) Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w4HDIlN9014069 for ; Thu, 17 May 2018 15:24:32 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2j1ab6g2y5-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 17 May 2018 15:24:32 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 17D083F for ; Thu, 17 May 2018 13:24:32 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 05EC12B63 for ; Thu, 17 May 2018 13:24:32 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 17 May 2018 15:24:31 +0200 From: Patrice Chotard To: Date: Thu, 17 May 2018 15:24:06 +0200 Message-ID: <1526563447-1323-4-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> References: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG1NODE1.st.com (10.75.127.1) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-17_07:, , signatures=0 Subject: [U-Boot] [PATCH v1 3/4] stm32mp1: add FUSE command support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrick Delaunay Add support of fuse command (read/write/program/sense) on bank 0 to access to BSEC SAFMEM (4096 OTP bits). Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard --- MAINTAINERS | 1 + arch/arm/Kconfig | 1 + configs/stm32mp15_basic_defconfig | 1 + drivers/misc/Kconfig | 9 +++ drivers/misc/Makefile | 1 + drivers/misc/stm32mp_fuse.c | 116 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 129 insertions(+) create mode 100644 drivers/misc/stm32mp_fuse.c diff --git a/MAINTAINERS b/MAINTAINERS index 5670917b41b9..3209dcd31844 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -204,6 +204,7 @@ M: Patrick Delaunay S: Maintained F: arch/arm/mach-stm32mp F: drivers/clk/clk_stm32mp1.c +F: drivers/misc/stm32mp_fuse.c F: drivers/ram/stm32mp1/ ARM STM STV0991 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c9d6e0a42418..5bd6749309b7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1214,6 +1214,7 @@ config ARCH_STM32MP select DM_SERIAL select OF_CONTROL select OF_LIBFDT + select MISC select PINCTRL select REGMAP select SUPPORT_SPL diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index b1c3690c0094..9e43cc969850 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -18,6 +18,7 @@ CONFIG_SYS_PROMPT="STM32MP> " # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set CONFIG_CMD_MEMINFO=y +CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index be900cf4d6ec..17b3a805a2d5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -158,6 +158,15 @@ config PCA9551_I2C_ADDR help The I2C address of the PCA9551 LED controller. +config STM32MP_FUSE + bool "Enable STM32MP fuse wrapper providing the fuse API" + depends on ARCH_STM32MP && MISC + default y if CMD_FUSE + help + If you say Y here, you will get support for the fuse API (OTP) + for STM32MP architecture. + This API is needed for CMD_FUSE. + config STM32_RCC bool "Enable RCC driver for the STM32 SoC's family" depends on STM32 && MISC diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index e362609d62a4..4ce9d213f06f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -51,5 +51,6 @@ obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o obj-$(CONFIG_STM32_RCC) += stm32_rcc.o +obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c new file mode 100644 index 000000000000..2d661351a17c --- /dev/null +++ b/drivers/misc/stm32mp_fuse.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include + +#define STM32MP_OTP_BANK 0 + +/* + * The 'fuse' command API + */ +int fuse_read(u32 bank, u32 word, u32 *val) +{ + int ret = 0; + struct udevice *dev; + + switch (bank) { + case STM32MP_OTP_BANK: + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, + val, 4); + break; + + default: + printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); + ret = -EINVAL; + break; + } + + return ret; +} + +int fuse_prog(u32 bank, u32 word, u32 val) +{ + struct udevice *dev; + int ret; + + switch (bank) { + case STM32MP_OTP_BANK: + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET, + &val, 4); + break; + + default: + printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); + ret = -EINVAL; + break; + } + + return ret; +} + +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + struct udevice *dev; + int ret; + + switch (bank) { + case STM32MP_OTP_BANK: + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4); + break; + + default: + printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); + ret = -EINVAL; + break; + } + + return ret; +} + +int fuse_override(u32 bank, u32 word, u32 val) +{ + struct udevice *dev; + int ret; + + switch (bank) { + case STM32MP_OTP_BANK: + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, + &val, 4); + break; + + default: + printf("stm32mp %s: wrong value for bank %i\n", + __func__, bank); + ret = -EINVAL; + break; + } + + return ret; +} From patchwork Thu May 17 13:24:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 915448 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=st.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40msXL4Rgdz9s3B for ; Thu, 17 May 2018 23:26:42 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3B06DC21DB5; Thu, 17 May 2018 13:25:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id C99E4C21F63; Thu, 17 May 2018 13:24:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id BB956C21F67; Thu, 17 May 2018 13:24:39 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by lists.denx.de (Postfix) with ESMTPS id 6BD1DC21F35 for ; Thu, 17 May 2018 13:24:34 +0000 (UTC) Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w4HDIlNA014069 for ; Thu, 17 May 2018 15:24:34 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2j1ab6g2y8-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 17 May 2018 15:24:34 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 2388A3F for ; Thu, 17 May 2018 13:24:33 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 109272B64 for ; Thu, 17 May 2018 13:24:33 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 17 May 2018 15:24:32 +0200 From: Patrice Chotard To: Date: Thu, 17 May 2018 15:24:07 +0200 Message-ID: <1526563447-1323-5-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> References: <1526563447-1323-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG3NODE1.st.com (10.75.127.7) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-17_07:, , signatures=0 Subject: [U-Boot] [PATCH v1 4/4] stm32mp1: use OTP to configure MAC address and serial number X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrick Delaunay Use OTP57 and 58 for MAC address - OTP57 = MAC address bits [31:0] - OTP58 = MAC address bit [47:32] stored in OTP LSB's Use manufacture information in OTP13 to OTP15 to build unique chip id saved in env variable "serial#" (used for USB device enumeration) Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard --- arch/arm/mach-stm32mp/cpu.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 2deee0961822..0e01f8e61385 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -5,9 +5,12 @@ #include #include #include +#include +#include #include #include #include +#include #include /* RCC register */ @@ -51,6 +54,10 @@ #define BOOTROM_INSTANCE_MASK GENMASK(31, 16) #define BOOTROM_INSTANCE_SHIFT 16 +/* BSEC OTP index */ +#define BSEC_OTP_SERIAL 13 +#define BSEC_OTP_MAC 57 + #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) static void security_init(void) { @@ -274,9 +281,83 @@ static void setup_boot_mode(void) } } +/* + * If there is no MAC address in the environment, then it will be initialized + * (silently) from the value in the OTP. + */ +static int setup_mac_address(void) +{ +#if defined(CONFIG_NET) + int ret; + int i; + u32 otp[2]; + uchar enetaddr[6]; + struct udevice *dev; + + /* MAC already in environment */ + if (eth_env_get_enetaddr("ethaddr", enetaddr)) + return 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET, + otp, sizeof(otp)); + if (ret) + return ret; + + for (i = 0; i < 6; i++) + enetaddr[i] = ((uint8_t *)&otp)[i]; + + if (!is_valid_ethaddr(enetaddr)) { + pr_err("invalid MAC address in OTP %pM", enetaddr); + return -EINVAL; + } + pr_debug("OTP MAC address = %pM\n", enetaddr); + ret = !eth_env_set_enetaddr("ethaddr", enetaddr); + if (!ret) + pr_err("Failed to set mac address %pM from OTP: %d\n", + enetaddr, ret); +#endif + + return 0; +} + +static int setup_serial_number(void) +{ + char serial_string[25]; + u32 otp[3] = {0, 0, 0 }; + struct udevice *dev; + int ret; + + if (env_get("serial#")) + return 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET, + otp, sizeof(otp)); + if (ret) + return ret; + + sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]); + env_set("serial#", serial_string); + + return 0; +} + int arch_misc_init(void) { setup_boot_mode(); + setup_mac_address(); + setup_serial_number(); return 0; }