From patchwork Tue Feb 27 14:09:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 10245429 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C566560211 for ; Tue, 27 Feb 2018 14:13:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B409228863 for ; Tue, 27 Feb 2018 14:13:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A80D928872; Tue, 27 Feb 2018 14:13:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7464D28863 for ; Tue, 27 Feb 2018 14:13:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ggS2HAbQeRBtO+rCSwIzxvVPhaKF0ZtWe64HT+gIfxc=; b=XrYkYmzQo3xuuT93WZYdPRIHIv /wnUP7iPFLl4eL0KCeCci6vIewcztJif/HrMXp3wxXB0fWHAgoiaKocq8I0Xn4g9uIfqrJNaKzcXz PkvcNhGBpTw7QzLGHDVK7YGw2+7YNR1/TRCRtzxInHHD3UK6FtQcVsWFzpZJ3idvRS1VO+cND8hCj Tam+tMRsg63ElE6GJ89cJCSsMCuTys7DJ56MfE/Dw3PgKdvsaRWExe+b386cZygPVg21j9/7hebHD fZezKJivpd3NQoEEJcH51QzF0qCHOGIfq871iEEFM6QbB+wWMHvcT38UNfxKgSKpHeVV+MCf9089m o36e7VhA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eqg0C-0007WE-L8; Tue, 27 Feb 2018 14:13:08 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eqfxC-0004T9-UG for linux-arm-kernel@bombadil.infradead.org; Tue, 27 Feb 2018 14:10:03 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=gc6NNO1syOIXlGo1WCmvPm40tqGPqmW1inEbZr6mIQk=; b=LiG985pirjqFB9zRwRTFEs4fT D24ZU3Cxj+eIz88kJ6n1FNFzQZ1+/t1G+cE8LDKFqhdIHqnL9K40jyQxFZSIS1HzeUjBu0uPqlFeb dSmolXFIZ5oEjSPLKtdj4EX650L/LuJPubNj4O4RU7QH4AJumm53ZVuo+On7+EvMVXLo3MEDNLZxk a4wxfUyfktkY7/N4D1A7Vp1BN3bX9YRnTwh/boSGfLraqXElH3bbNWeILdwQQSS0oUq/NX/Ndj69y ZVfWxeazrquBO3LMdQ+2uEJ4NFTxmrC2rh62SMwciSjBJpqhQNteGVjqkRUmPt86L/FUqcUxDvIRE fi9GBDKJg==; Received: from mail-wr0-x241.google.com ([2a00:1450:400c:c0c::241]) by merlin.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eqfx8-0007Ly-Ch for linux-arm-kernel@lists.infradead.org; Tue, 27 Feb 2018 14:10:00 +0000 Received: by mail-wr0-x241.google.com with SMTP id p104so24969209wrc.12 for ; Tue, 27 Feb 2018 06:09:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gc6NNO1syOIXlGo1WCmvPm40tqGPqmW1inEbZr6mIQk=; b=HDJDhm+ADubdvpUfblAOwDw7fouM7TQPctHJo2P4jw/DOvvLq9kX19o/E/TC9T5lrM HpwF8GYE9DmIEcJy9FSUVQ4Hz25/VDSrr+vOzdTKR3P8Hw5wGOkgW3ZmccTaNpEk5fpf XjTEpjm8lMurS+u6vdw3ID6FJHaFwjGfmbdhc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gc6NNO1syOIXlGo1WCmvPm40tqGPqmW1inEbZr6mIQk=; b=iPDLU4lhnFVpnB/VV6mYmNX4CkLiua2wgqGt+PUDxb1kuQ0emFU6cK4cYivdOMzjTF 3+RLAh/rcDgBI4WA1aV8u1IUzWLz1I3PbwG/JEXwi/7LEpuSRDZrdnLe3EHvfGtBxWUy RG7aIhbYwSzvle/fieGMyHhGG0eXr+mOcBOedVOa+6IwDy8siP0ynq7BfBZ8B/p6C0kd mmxMCnwn/WrcROURn/4HDR0HD0/wCXBiMA7VXdZDSyHC2qwjgJ8/2DlqCcMPfmKIjWv9 JYSExktAckzZ96E40xF2609PTfxazk2Ytl/s6VwP2uMYBK2lloZDJ0lG24E0MRVnneNu yESw== X-Gm-Message-State: APf1xPCFsI47ZQ+Wao6pXxJPkxmeyrTJKXfJ1s5Ib69whP97qLAzBkA1 2XTrn0Aa5/hh2fbTFoKWsWOr32u6aJU= X-Google-Smtp-Source: AH8x225bE9EwIo9/OVaYeCPDhcfc/yp23yJsoUPL9uM+BsZQumRfgbGPIJYd+UsT+2IYD2822OyGXA== X-Received: by 10.223.130.21 with SMTP id 21mr12011319wrb.16.1519740585621; Tue, 27 Feb 2018 06:09:45 -0800 (PST) Received: from lmecxl0911.lme.st.com ([80.214.71.157]) by smtp.gmail.com with ESMTPSA id 59sm6514496wro.57.2018.02.27.06.09.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 27 Feb 2018 06:09:45 -0800 (PST) From: Benjamin Gaignard X-Google-Original-From: Benjamin Gaignard To: gregkh@linuxfoundation.org, robh+dt@kernel.org, mark.rutland@arm.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com Subject: [PATCH 3/3] ARM: mach-stm32: Add Extended TrustZone Protection driver Date: Tue, 27 Feb 2018 15:09:26 +0100 Message-Id: <20180227140926.22996-4-benjamin.gaignard@st.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20180227140926.22996-1-benjamin.gaignard@st.com> References: <20180227140926.22996-1-benjamin.gaignard@st.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180227_090958_564341_9479A961 X-CRM114-Status: GOOD ( 25.55 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Benjamin Gaignard MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Before binding a driver Extended TrustZone Protection (ETZPC) driver checks that the hardware block is accessible to non-secure world. Hardware blocks split between secure and non-secure is done at early boot stage so the driver only needs to read the status (2 bits) for each of the block. Hardware blocks status bits location in the registers is computed from device address index in the array. To avoid to bind a device which will not be accessible ETZPC driver must be probed early, at least before platform driver, so just after core initialisation. Signed-off-by: Benjamin Gaignard --- arch/arm/mach-stm32/Kconfig | 7 ++ arch/arm/mach-stm32/Makefile | 1 + arch/arm/mach-stm32/stm32-etzpc.c | 252 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+) create mode 100644 arch/arm/mach-stm32/stm32-etzpc.c diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig index 5bc7f5ab61cd..a3ef308642be 100644 --- a/arch/arm/mach-stm32/Kconfig +++ b/arch/arm/mach-stm32/Kconfig @@ -44,6 +44,13 @@ config MACH_STM32MP157 bool "STMicroelectronics STM32MP157" default y +config STM32_ETZPC + bool "STM32 Extended TrustZone Protection" + depends on MACH_STM32MP157 + help + Select y to enable STM32 Extended TrustZone Protection + Controller (ETZPC) + endif # ARMv7-A endif diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile index bd0b7b5d6e9d..2e1e729a68c9 100644 --- a/arch/arm/mach-stm32/Makefile +++ b/arch/arm/mach-stm32/Makefile @@ -1 +1,2 @@ obj-y += board-dt.o +obj-$(CONFIG_STM32_ETZPC) += stm32-etzpc.o diff --git a/arch/arm/mach-stm32/stm32-etzpc.c b/arch/arm/mach-stm32/stm32-etzpc.c new file mode 100644 index 000000000000..b338d219d5a8 --- /dev/null +++ b/arch/arm/mach-stm32/stm32-etzpc.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Benjamin Gaignard for STMicroelectronics. + */ +#include +#include +#include +#include +#include +#include + +#define ETZPC_DECPROT0 0x10 +#define ETZPC_IP_VER 0x3F4 + +#define IP_VER_MP1 0x00000020 + +#define DECPROT_MASK 0x03 +#define NB_PROT_PER_REG 0x10 +#define DECPROT_NB_BITS 2 + +struct stm32_etzpc_cfg { + const u32 *addr; + const int size; + const int version; +}; + +struct stm32_etzpc { + void __iomem *base; + const struct stm32_etzpc_cfg *cfg; + struct notifier_block nb; +}; + +static inline struct stm32_etzpc *to_stm32_etzpc(struct notifier_block *nb) +{ + return container_of(nb, struct stm32_etzpc, nb); +} + +static const u32 stm32mp1_ip_addr[] = { + 0x5c008000, /* 00 stgenc */ + 0x54000000, /* 01 bkpsram */ + 0x5c003000, /* 02 iwdg1 */ + 0x5c000000, /* 03 usart1 */ + 0x5c001000, /* 04 spi6 */ + 0x5c002000, /* 05 i2c4 */ + 0xffffffff, /* 06 reserved */ + 0x54003000, /* 07 rng1 */ + 0x54002000, /* 08 hash1 */ + 0x54001000, /* 09 cryp1 */ + 0x5a003000, /* 0A ddrctrl */ + 0x5a004000, /* 0B ddrphyc */ + 0x5c009000, /* 0C i2c6 */ + 0xffffffff, /* 0D reserved */ + 0xffffffff, /* 0E reserved */ + 0xffffffff, /* 0F reserved */ + 0x40000000, /* 10 tim2 */ + 0x40001000, /* 11 tim3 */ + 0x40002000, /* 12 tim4 */ + 0x40003000, /* 13 tim5 */ + 0x40004000, /* 14 tim6 */ + 0x40005000, /* 15 tim7 */ + 0x40006000, /* 16 tim12 */ + 0x40007000, /* 17 tim13 */ + 0x40008000, /* 18 tim14 */ + 0x40009000, /* 19 lptim1 */ + 0x4000a000, /* 1A wwdg1 */ + 0x4000b000, /* 1B spi2 */ + 0x4000c000, /* 1C spi3 */ + 0x4000d000, /* 1D spdifrx */ + 0x4000e000, /* 1E usart2 */ + 0x4000f000, /* 1F usart3 */ + 0x40010000, /* 20 uart4 */ + 0x40011000, /* 21 uart5 */ + 0x40012000, /* 22 i2c1 */ + 0x40013000, /* 23 i2c2 */ + 0x40014000, /* 24 i2c3 */ + 0x40015000, /* 25 i2c5 */ + 0x40016000, /* 26 cec */ + 0x40017000, /* 27 dac */ + 0x40018000, /* 28 uart7 */ + 0x40019000, /* 29 uart8 */ + 0xffffffff, /* 2A reserved */ + 0xffffffff, /* 2B reserved */ + 0x4001c000, /* 2C mdios */ + 0xffffffff, /* 2D reserved */ + 0xffffffff, /* 2E reserved */ + 0xffffffff, /* 2F reserved */ + 0x44000000, /* 30 tim1 */ + 0x44001000, /* 31 tim8 */ + 0xffffffff, /* 32 reserved */ + 0x44003000, /* 33 usart6 */ + 0x44004000, /* 34 spi1 */ + 0x44005000, /* 35 spi4 */ + 0x44006000, /* 36 tim15 */ + 0x44007000, /* 37 tim16 */ + 0x44008000, /* 38 tim17 */ + 0x44009000, /* 39 spi5 */ + 0x4400a000, /* 3A sai1 */ + 0x4400b000, /* 3B sai2 */ + 0x4400c000, /* 3C sai3 */ + 0x4400d000, /* 3D dfsdm */ + 0x4400e000, /* 3E tt_fdcan */ + 0xffffffff, /* 3F reserved */ + 0x50021000, /* 40 lptim2 */ + 0x50022000, /* 41 lptim3 */ + 0x50023000, /* 42 lptim4 */ + 0x50024000, /* 43 lptim5 */ + 0x50027000, /* 44 sai4 */ + 0x50025000, /* 45 vrefbuf */ + 0x4c006000, /* 46 dcmi */ + 0x4c004000, /* 47 crc2 */ + 0x48003000, /* 48 adc */ + 0x4c002000, /* 49 hash2 */ + 0x4c003000, /* 4A rng2 */ + 0x4c005000, /* 4B cryp2 */ + 0xffffffff, /* 4C reserved */ + 0xffffffff, /* 4D reserved */ + 0xffffffff, /* 4E reserved */ + 0xffffffff, /* 4F reserved */ + 0xffffffff, /* 50 sram1 */ + 0xffffffff, /* 51 sram2 */ + 0xffffffff, /* 52 sram3 */ + 0xffffffff, /* 53 sram4 */ + 0xffffffff, /* 54 retram */ + 0x49000000, /* 55 otg */ + 0x48004000, /* 56 sdmmc3 */ + 0x48005000, /* 57 dlybsd3 */ + 0x48000000, /* 58 dma1 */ + 0x48001000, /* 59 dma2 */ + 0x48002000, /* 5A dmamux */ + 0x58002000, /* 5B fmc */ + 0x58003000, /* 5C qspi */ + 0x58004000, /* 5D dlybq */ + 0x5800a000, /* 5E eth */ + 0xffffffff, /* 5F reserved */ +}; + +static const struct stm32_etzpc_cfg stm32_etzpc_mp1_cfg = { + .addr = stm32mp1_ip_addr, + .size = ARRAY_SIZE(stm32mp1_ip_addr), + .version = IP_VER_MP1 +}; + +static const struct of_device_id stm32_etzpc_of_match[] = { + { + .compatible = "st,stm32mp1-etzpc", + .data = (void *)&stm32_etzpc_mp1_cfg, + }, + { /* end node */ }, +}; +MODULE_DEVICE_TABLE(of, stm32_etzpc_of_match); + +static int stm32_etzpc_notifier_call(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct stm32_etzpc *etzpc = to_stm32_etzpc(nb); + struct device *dev = data; + struct resource res; + int i; + + if (event != BUS_NOTIFY_BIND_DRIVER) + return NOTIFY_DONE; + + if (of_address_to_resource(dev->of_node, 0, &res)) + return NOTIFY_DONE; + + for (i = 0; i < etzpc->cfg->size; i++) { + if (etzpc->cfg->addr[i] == res.start) { + /* + * Each hardware block protection status is defined by + * a 2 bits field and all of them are packed into + * 32 bits registers. Do some computation to get + * register offset and the shift. + */ + u32 status; + int offset = (i / NB_PROT_PER_REG) * sizeof(u32); + int shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS; + + status = readl(etzpc->base + ETZPC_DECPROT0 + offset); + status &= DECPROT_MASK << shift; + + return (status == DECPROT_MASK << shift) ? + NOTIFY_DONE : NOTIFY_BAD; + } + } + + return NOTIFY_DONE; +} + +static int stm32_etzpc_probe(struct device_node *np, + const struct of_device_id *match) +{ + struct stm32_etzpc *etzpc; + int version, ret; + + etzpc = kzalloc(sizeof(*etzpc), GFP_KERNEL); + if (!etzpc) + return -ENOMEM; + + etzpc->base = of_iomap(np, 0); + if (IS_ERR(etzpc->base)) { + ret = PTR_ERR(etzpc->base); + goto failed; + } + + etzpc->cfg = (const struct stm32_etzpc_cfg *)match->data; + + version = readl(etzpc->base + ETZPC_IP_VER); + if (version != etzpc->cfg->version) { + pr_err("Wrong ETZPC version\n"); + ret = -EINVAL; + goto failed; + } + + etzpc->nb.notifier_call = stm32_etzpc_notifier_call, + ret = bus_register_notifier(&platform_bus_type, &etzpc->nb); + if (!ret) + return 0; + +failed: + kfree(etzpc); + return ret; +} + +/* + * stm32_etzpc_init needs to be called before starting to probe + * platform drivers to be able to catch all bind notifications + * that's why it is tagged as postcore_initcall + */ +static int __init stm32_etzpc_init(void) +{ + struct device_node *np; + const struct of_device_id *m; + int ret; + + np = of_find_matching_node_and_match(NULL, stm32_etzpc_of_match, &m); + + if (!np) + return -ENODEV; + + if (!of_device_is_available(np)) { + of_node_put(np); + return -ENODEV; + } + + ret = stm32_etzpc_probe(np, m); + + of_node_put(np); + + return ret; +} +postcore_initcall(stm32_etzpc_init);