1b1e0b11cSLionel Debieve /* 2*33667d29SYann Gautier * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved 3b1e0b11cSLionel Debieve * 4b1e0b11cSLionel Debieve * SPDX-License-Identifier: BSD-3-Clause 5b1e0b11cSLionel Debieve */ 6b1e0b11cSLionel Debieve 7b1e0b11cSLionel Debieve #include <assert.h> 8b1e0b11cSLionel Debieve #include <errno.h> 9b1e0b11cSLionel Debieve #include <stdint.h> 10b1e0b11cSLionel Debieve 11b1e0b11cSLionel Debieve #include <libfdt.h> 12b1e0b11cSLionel Debieve 13b1e0b11cSLionel Debieve #include <platform_def.h> 14b1e0b11cSLionel Debieve 15b1e0b11cSLionel Debieve #include <arch_helpers.h> 16b1e0b11cSLionel Debieve #include <common/debug.h> 17*33667d29SYann Gautier #include <drivers/clk.h> 18b1e0b11cSLionel Debieve #include <drivers/delay_timer.h> 19b1e0b11cSLionel Debieve #include <drivers/st/stm32_hash.h> 20b1e0b11cSLionel Debieve #include <drivers/st/stm32mp_reset.h> 21b1e0b11cSLionel Debieve #include <lib/mmio.h> 22b1e0b11cSLionel Debieve #include <lib/utils.h> 23b1e0b11cSLionel Debieve #include <plat/common/platform.h> 24b1e0b11cSLionel Debieve 25b1e0b11cSLionel Debieve #define DT_HASH_COMPAT "st,stm32f756-hash" 26b1e0b11cSLionel Debieve 27b1e0b11cSLionel Debieve #define HASH_CR 0x00U 28b1e0b11cSLionel Debieve #define HASH_DIN 0x04U 29b1e0b11cSLionel Debieve #define HASH_STR 0x08U 30b1e0b11cSLionel Debieve #define HASH_SR 0x24U 31b1e0b11cSLionel Debieve #define HASH_HREG(x) (0x310U + ((x) * 0x04U)) 32b1e0b11cSLionel Debieve 33b1e0b11cSLionel Debieve /* Control Register */ 34b1e0b11cSLionel Debieve #define HASH_CR_INIT BIT(2) 35b1e0b11cSLionel Debieve #define HASH_CR_DATATYPE_SHIFT U(4) 36b1e0b11cSLionel Debieve 37b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA1 0x0U 38b1e0b11cSLionel Debieve #define HASH_CR_ALGO_MD5 BIT(7) 39b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA224 BIT(18) 40b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) 41b1e0b11cSLionel Debieve 42b1e0b11cSLionel Debieve /* Status Flags */ 43b1e0b11cSLionel Debieve #define HASH_SR_DCIS BIT(1) 44b1e0b11cSLionel Debieve #define HASH_SR_BUSY BIT(3) 45b1e0b11cSLionel Debieve 46b1e0b11cSLionel Debieve /* STR Register */ 47b1e0b11cSLionel Debieve #define HASH_STR_NBLW_MASK GENMASK(4, 0) 48b1e0b11cSLionel Debieve #define HASH_STR_DCAL BIT(8) 49b1e0b11cSLionel Debieve 50b1e0b11cSLionel Debieve #define MD5_DIGEST_SIZE 16U 51b1e0b11cSLionel Debieve #define SHA1_DIGEST_SIZE 20U 52b1e0b11cSLionel Debieve #define SHA224_DIGEST_SIZE 28U 53b1e0b11cSLionel Debieve #define SHA256_DIGEST_SIZE 32U 54b1e0b11cSLionel Debieve 5545c70e68SEtienne Carriere #define RESET_TIMEOUT_US_1MS 1000U 56b1e0b11cSLionel Debieve #define HASH_TIMEOUT_US 10000U 57b1e0b11cSLionel Debieve 58b1e0b11cSLionel Debieve enum stm32_hash_data_format { 59b1e0b11cSLionel Debieve HASH_DATA_32_BITS, 60b1e0b11cSLionel Debieve HASH_DATA_16_BITS, 61b1e0b11cSLionel Debieve HASH_DATA_8_BITS, 62b1e0b11cSLionel Debieve HASH_DATA_1_BIT 63b1e0b11cSLionel Debieve }; 64b1e0b11cSLionel Debieve 65b1e0b11cSLionel Debieve struct stm32_hash_instance { 66b1e0b11cSLionel Debieve uintptr_t base; 67b1e0b11cSLionel Debieve unsigned int clock; 68b1e0b11cSLionel Debieve size_t digest_size; 69b1e0b11cSLionel Debieve }; 70b1e0b11cSLionel Debieve 71b1e0b11cSLionel Debieve struct stm32_hash_remain { 72b1e0b11cSLionel Debieve uint32_t buffer; 73b1e0b11cSLionel Debieve size_t length; 74b1e0b11cSLionel Debieve }; 75b1e0b11cSLionel Debieve 76b1e0b11cSLionel Debieve /* Expect a single HASH peripheral */ 77b1e0b11cSLionel Debieve static struct stm32_hash_instance stm32_hash; 78b1e0b11cSLionel Debieve static struct stm32_hash_remain stm32_remain; 79b1e0b11cSLionel Debieve 80b1e0b11cSLionel Debieve static uintptr_t hash_base(void) 81b1e0b11cSLionel Debieve { 82b1e0b11cSLionel Debieve return stm32_hash.base; 83b1e0b11cSLionel Debieve } 84b1e0b11cSLionel Debieve 85b1e0b11cSLionel Debieve static int hash_wait_busy(void) 86b1e0b11cSLionel Debieve { 87b1e0b11cSLionel Debieve uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 88b1e0b11cSLionel Debieve 89b1e0b11cSLionel Debieve while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { 90b1e0b11cSLionel Debieve if (timeout_elapsed(timeout)) { 91b1e0b11cSLionel Debieve ERROR("%s: busy timeout\n", __func__); 92b1e0b11cSLionel Debieve return -ETIMEDOUT; 93b1e0b11cSLionel Debieve } 94b1e0b11cSLionel Debieve } 95b1e0b11cSLionel Debieve 96b1e0b11cSLionel Debieve return 0; 97b1e0b11cSLionel Debieve } 98b1e0b11cSLionel Debieve 99b1e0b11cSLionel Debieve static int hash_wait_computation(void) 100b1e0b11cSLionel Debieve { 101b1e0b11cSLionel Debieve uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 102b1e0b11cSLionel Debieve 103b1e0b11cSLionel Debieve while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { 104b1e0b11cSLionel Debieve if (timeout_elapsed(timeout)) { 105b1e0b11cSLionel Debieve ERROR("%s: busy timeout\n", __func__); 106b1e0b11cSLionel Debieve return -ETIMEDOUT; 107b1e0b11cSLionel Debieve } 108b1e0b11cSLionel Debieve } 109b1e0b11cSLionel Debieve 110b1e0b11cSLionel Debieve return 0; 111b1e0b11cSLionel Debieve } 112b1e0b11cSLionel Debieve 113b1e0b11cSLionel Debieve static int hash_write_data(uint32_t data) 114b1e0b11cSLionel Debieve { 115b1e0b11cSLionel Debieve int ret; 116b1e0b11cSLionel Debieve 117b1e0b11cSLionel Debieve ret = hash_wait_busy(); 118b1e0b11cSLionel Debieve if (ret != 0) { 119b1e0b11cSLionel Debieve return ret; 120b1e0b11cSLionel Debieve } 121b1e0b11cSLionel Debieve 122b1e0b11cSLionel Debieve mmio_write_32(hash_base() + HASH_DIN, data); 123b1e0b11cSLionel Debieve 124b1e0b11cSLionel Debieve return 0; 125b1e0b11cSLionel Debieve } 126b1e0b11cSLionel Debieve 127b1e0b11cSLionel Debieve static void hash_hw_init(enum stm32_hash_algo_mode mode) 128b1e0b11cSLionel Debieve { 129b1e0b11cSLionel Debieve uint32_t reg; 130b1e0b11cSLionel Debieve 131b1e0b11cSLionel Debieve reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); 132b1e0b11cSLionel Debieve 133b1e0b11cSLionel Debieve switch (mode) { 134b1e0b11cSLionel Debieve case HASH_MD5SUM: 135b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_MD5; 136b1e0b11cSLionel Debieve stm32_hash.digest_size = MD5_DIGEST_SIZE; 137b1e0b11cSLionel Debieve break; 138b1e0b11cSLionel Debieve case HASH_SHA1: 139b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA1; 140b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA1_DIGEST_SIZE; 141b1e0b11cSLionel Debieve break; 142b1e0b11cSLionel Debieve case HASH_SHA224: 143b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA224; 144b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA224_DIGEST_SIZE; 145b1e0b11cSLionel Debieve break; 146b1e0b11cSLionel Debieve /* Default selected algo is SHA256 */ 147b1e0b11cSLionel Debieve case HASH_SHA256: 148b1e0b11cSLionel Debieve default: 149b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA256; 150b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA256_DIGEST_SIZE; 151b1e0b11cSLionel Debieve break; 152b1e0b11cSLionel Debieve } 153b1e0b11cSLionel Debieve 154b1e0b11cSLionel Debieve mmio_write_32(hash_base() + HASH_CR, reg); 155b1e0b11cSLionel Debieve } 156b1e0b11cSLionel Debieve 157b1e0b11cSLionel Debieve static int hash_get_digest(uint8_t *digest) 158b1e0b11cSLionel Debieve { 159b1e0b11cSLionel Debieve int ret; 160b1e0b11cSLionel Debieve uint32_t i; 161b1e0b11cSLionel Debieve uint32_t dsg; 162b1e0b11cSLionel Debieve 163b1e0b11cSLionel Debieve ret = hash_wait_computation(); 164b1e0b11cSLionel Debieve if (ret != 0) { 165b1e0b11cSLionel Debieve return ret; 166b1e0b11cSLionel Debieve } 167b1e0b11cSLionel Debieve 168b1e0b11cSLionel Debieve for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { 169b1e0b11cSLionel Debieve dsg = __builtin_bswap32(mmio_read_32(hash_base() + 170b1e0b11cSLionel Debieve HASH_HREG(i))); 171b1e0b11cSLionel Debieve memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); 172b1e0b11cSLionel Debieve } 173b1e0b11cSLionel Debieve 174b1e0b11cSLionel Debieve #if defined(IMAGE_BL2) 175b1e0b11cSLionel Debieve /* 176b1e0b11cSLionel Debieve * Clean hardware context as HASH could be used later 177b1e0b11cSLionel Debieve * by non-secure software 178b1e0b11cSLionel Debieve */ 179b1e0b11cSLionel Debieve hash_hw_init(HASH_SHA256); 180b1e0b11cSLionel Debieve #endif 181b1e0b11cSLionel Debieve return 0; 182b1e0b11cSLionel Debieve } 183b1e0b11cSLionel Debieve 184b1e0b11cSLionel Debieve int stm32_hash_update(const uint8_t *buffer, size_t length) 185b1e0b11cSLionel Debieve { 186b1e0b11cSLionel Debieve size_t remain_length = length; 187b1e0b11cSLionel Debieve int ret = 0; 188b1e0b11cSLionel Debieve 189b1e0b11cSLionel Debieve if ((length == 0U) || (buffer == NULL)) { 190b1e0b11cSLionel Debieve return 0; 191b1e0b11cSLionel Debieve } 192b1e0b11cSLionel Debieve 193*33667d29SYann Gautier clk_enable(stm32_hash.clock); 194b1e0b11cSLionel Debieve 195b1e0b11cSLionel Debieve if (stm32_remain.length != 0U) { 196b1e0b11cSLionel Debieve uint32_t copysize; 197b1e0b11cSLionel Debieve 198b1e0b11cSLionel Debieve copysize = MIN((sizeof(uint32_t) - stm32_remain.length), 199b1e0b11cSLionel Debieve length); 200b1e0b11cSLionel Debieve memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, 201b1e0b11cSLionel Debieve buffer, copysize); 202b1e0b11cSLionel Debieve remain_length -= copysize; 203b1e0b11cSLionel Debieve buffer += copysize; 204b1e0b11cSLionel Debieve if (stm32_remain.length == sizeof(uint32_t)) { 205b1e0b11cSLionel Debieve ret = hash_write_data(stm32_remain.buffer); 206b1e0b11cSLionel Debieve if (ret != 0) { 207b1e0b11cSLionel Debieve goto exit; 208b1e0b11cSLionel Debieve } 209b1e0b11cSLionel Debieve 210b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 211b1e0b11cSLionel Debieve } 212b1e0b11cSLionel Debieve } 213b1e0b11cSLionel Debieve 214b1e0b11cSLionel Debieve while (remain_length / sizeof(uint32_t) != 0U) { 215b1e0b11cSLionel Debieve uint32_t tmp_buf; 216b1e0b11cSLionel Debieve 217b1e0b11cSLionel Debieve memcpy(&tmp_buf, buffer, sizeof(uint32_t)); 218b1e0b11cSLionel Debieve ret = hash_write_data(tmp_buf); 219b1e0b11cSLionel Debieve if (ret != 0) { 220b1e0b11cSLionel Debieve goto exit; 221b1e0b11cSLionel Debieve } 222b1e0b11cSLionel Debieve 223b1e0b11cSLionel Debieve buffer += sizeof(uint32_t); 224b1e0b11cSLionel Debieve remain_length -= sizeof(uint32_t); 225b1e0b11cSLionel Debieve } 226b1e0b11cSLionel Debieve 227b1e0b11cSLionel Debieve if (remain_length != 0U) { 228b1e0b11cSLionel Debieve assert(stm32_remain.length == 0U); 229b1e0b11cSLionel Debieve 230b1e0b11cSLionel Debieve memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); 231b1e0b11cSLionel Debieve stm32_remain.length = remain_length; 232b1e0b11cSLionel Debieve } 233b1e0b11cSLionel Debieve 234b1e0b11cSLionel Debieve exit: 235*33667d29SYann Gautier clk_disable(stm32_hash.clock); 236b1e0b11cSLionel Debieve 237b1e0b11cSLionel Debieve return ret; 238b1e0b11cSLionel Debieve } 239b1e0b11cSLionel Debieve 240b1e0b11cSLionel Debieve int stm32_hash_final(uint8_t *digest) 241b1e0b11cSLionel Debieve { 242b1e0b11cSLionel Debieve int ret; 243b1e0b11cSLionel Debieve 244*33667d29SYann Gautier clk_enable(stm32_hash.clock); 245b1e0b11cSLionel Debieve 246b1e0b11cSLionel Debieve if (stm32_remain.length != 0U) { 247b1e0b11cSLionel Debieve ret = hash_write_data(stm32_remain.buffer); 248b1e0b11cSLionel Debieve if (ret != 0) { 249*33667d29SYann Gautier clk_disable(stm32_hash.clock); 250b1e0b11cSLionel Debieve return ret; 251b1e0b11cSLionel Debieve } 252b1e0b11cSLionel Debieve 253b1e0b11cSLionel Debieve mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, 254b1e0b11cSLionel Debieve 8U * stm32_remain.length); 255b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 256662c1f5cSLionel Debieve } else { 257662c1f5cSLionel Debieve mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); 258b1e0b11cSLionel Debieve } 259b1e0b11cSLionel Debieve 260b1e0b11cSLionel Debieve mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); 261b1e0b11cSLionel Debieve 262b1e0b11cSLionel Debieve ret = hash_get_digest(digest); 263b1e0b11cSLionel Debieve 264*33667d29SYann Gautier clk_disable(stm32_hash.clock); 265b1e0b11cSLionel Debieve 266b1e0b11cSLionel Debieve return ret; 267b1e0b11cSLionel Debieve } 268b1e0b11cSLionel Debieve 269b1e0b11cSLionel Debieve int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, 270b1e0b11cSLionel Debieve uint8_t *digest) 271b1e0b11cSLionel Debieve { 272b1e0b11cSLionel Debieve int ret; 273b1e0b11cSLionel Debieve 274b1e0b11cSLionel Debieve ret = stm32_hash_update(buffer, length); 275b1e0b11cSLionel Debieve if (ret != 0) { 276b1e0b11cSLionel Debieve return ret; 277b1e0b11cSLionel Debieve } 278b1e0b11cSLionel Debieve 279b1e0b11cSLionel Debieve return stm32_hash_final(digest); 280b1e0b11cSLionel Debieve } 281b1e0b11cSLionel Debieve 282b1e0b11cSLionel Debieve void stm32_hash_init(enum stm32_hash_algo_mode mode) 283b1e0b11cSLionel Debieve { 284*33667d29SYann Gautier clk_enable(stm32_hash.clock); 285b1e0b11cSLionel Debieve 286b1e0b11cSLionel Debieve hash_hw_init(mode); 287b1e0b11cSLionel Debieve 288*33667d29SYann Gautier clk_disable(stm32_hash.clock); 289b1e0b11cSLionel Debieve 290b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 291b1e0b11cSLionel Debieve } 292b1e0b11cSLionel Debieve 293b1e0b11cSLionel Debieve int stm32_hash_register(void) 294b1e0b11cSLionel Debieve { 295b1e0b11cSLionel Debieve struct dt_node_info hash_info; 296b1e0b11cSLionel Debieve int node; 297b1e0b11cSLionel Debieve 298b1e0b11cSLionel Debieve for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); 299b1e0b11cSLionel Debieve node != -FDT_ERR_NOTFOUND; 300b1e0b11cSLionel Debieve node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { 301b1e0b11cSLionel Debieve #if defined(IMAGE_BL2) 302b1e0b11cSLionel Debieve if (hash_info.status != DT_DISABLED) { 303b1e0b11cSLionel Debieve break; 304b1e0b11cSLionel Debieve } 305b1e0b11cSLionel Debieve #else 3063d0d0a1bSEtienne Carriere /* BL32 uses hash if it is assigned only to secure world */ 307b1e0b11cSLionel Debieve if (hash_info.status == DT_SECURE) { 3083d0d0a1bSEtienne Carriere stm32mp_register_secure_periph_iomem(hash_info.base); 309b1e0b11cSLionel Debieve break; 310b1e0b11cSLionel Debieve } 311b1e0b11cSLionel Debieve #endif 312b1e0b11cSLionel Debieve } 313b1e0b11cSLionel Debieve 314b1e0b11cSLionel Debieve if (node == -FDT_ERR_NOTFOUND) { 315b1e0b11cSLionel Debieve return -ENODEV; 316b1e0b11cSLionel Debieve } 317b1e0b11cSLionel Debieve 318b1e0b11cSLionel Debieve if (hash_info.clock < 0) { 319b1e0b11cSLionel Debieve return -EINVAL; 320b1e0b11cSLionel Debieve } 321b1e0b11cSLionel Debieve 322b1e0b11cSLionel Debieve stm32_hash.base = hash_info.base; 323b1e0b11cSLionel Debieve stm32_hash.clock = hash_info.clock; 324b1e0b11cSLionel Debieve 325*33667d29SYann Gautier clk_enable(stm32_hash.clock); 326b1e0b11cSLionel Debieve 327b1e0b11cSLionel Debieve if (hash_info.reset >= 0) { 32845c70e68SEtienne Carriere uint32_t id = (uint32_t)hash_info.reset; 32945c70e68SEtienne Carriere 33045c70e68SEtienne Carriere if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) { 33145c70e68SEtienne Carriere panic(); 33245c70e68SEtienne Carriere } 333b1e0b11cSLionel Debieve udelay(20); 33445c70e68SEtienne Carriere if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) { 33545c70e68SEtienne Carriere panic(); 33645c70e68SEtienne Carriere } 337b1e0b11cSLionel Debieve } 338b1e0b11cSLionel Debieve 339*33667d29SYann Gautier clk_disable(stm32_hash.clock); 340b1e0b11cSLionel Debieve 341b1e0b11cSLionel Debieve return 0; 342b1e0b11cSLionel Debieve } 343