1b1e0b11cSLionel Debieve /* 268039f2dSNicolas Toromanoff * Copyright (c) 2019-2022, 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 <arch_helpers.h> 12b1e0b11cSLionel Debieve #include <common/debug.h> 1333667d29SYann Gautier #include <drivers/clk.h> 14b1e0b11cSLionel Debieve #include <drivers/delay_timer.h> 15b1e0b11cSLionel Debieve #include <drivers/st/stm32_hash.h> 16b1e0b11cSLionel Debieve #include <drivers/st/stm32mp_reset.h> 17b1e0b11cSLionel Debieve #include <lib/mmio.h> 18b1e0b11cSLionel Debieve #include <lib/utils.h> 1968039f2dSNicolas Toromanoff #include <libfdt.h> 20b1e0b11cSLionel Debieve #include <plat/common/platform.h> 21b1e0b11cSLionel Debieve 2268039f2dSNicolas Toromanoff #include <platform_def.h> 2368039f2dSNicolas Toromanoff 2468039f2dSNicolas Toromanoff #if STM32_HASH_VER == 2 25b1e0b11cSLionel Debieve #define DT_HASH_COMPAT "st,stm32f756-hash" 2668039f2dSNicolas Toromanoff #endif 2768039f2dSNicolas Toromanoff #if STM32_HASH_VER == 4 2868039f2dSNicolas Toromanoff #define DT_HASH_COMPAT "st,stm32mp13-hash" 2968039f2dSNicolas Toromanoff #endif 30b1e0b11cSLionel Debieve 31b1e0b11cSLionel Debieve #define HASH_CR 0x00U 32b1e0b11cSLionel Debieve #define HASH_DIN 0x04U 33b1e0b11cSLionel Debieve #define HASH_STR 0x08U 34b1e0b11cSLionel Debieve #define HASH_SR 0x24U 35b1e0b11cSLionel Debieve #define HASH_HREG(x) (0x310U + ((x) * 0x04U)) 36b1e0b11cSLionel Debieve 37b1e0b11cSLionel Debieve /* Control Register */ 38b1e0b11cSLionel Debieve #define HASH_CR_INIT BIT(2) 39b1e0b11cSLionel Debieve #define HASH_CR_DATATYPE_SHIFT U(4) 4068039f2dSNicolas Toromanoff #if STM32_HASH_VER == 2 41b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA1 0x0U 42b1e0b11cSLionel Debieve #define HASH_CR_ALGO_MD5 BIT(7) 43b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA224 BIT(18) 44b1e0b11cSLionel Debieve #define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) 4568039f2dSNicolas Toromanoff #endif 4668039f2dSNicolas Toromanoff #if STM32_HASH_VER == 4 4768039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHIFT U(17) 4868039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA1 (0x0U << HASH_CR_ALGO_SHIFT) 4968039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA224 (0x2U << HASH_CR_ALGO_SHIFT) 5068039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA256 (0x3U << HASH_CR_ALGO_SHIFT) 5168039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA384 (0xCU << HASH_CR_ALGO_SHIFT) 5268039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA512_224 (0xDU << HASH_CR_ALGO_SHIFT) 5368039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA512_256 (0xEU << HASH_CR_ALGO_SHIFT) 5468039f2dSNicolas Toromanoff #define HASH_CR_ALGO_SHA512 (0xFU << HASH_CR_ALGO_SHIFT) 5568039f2dSNicolas Toromanoff #endif 56b1e0b11cSLionel Debieve 57b1e0b11cSLionel Debieve /* Status Flags */ 58b1e0b11cSLionel Debieve #define HASH_SR_DCIS BIT(1) 59b1e0b11cSLionel Debieve #define HASH_SR_BUSY BIT(3) 60b1e0b11cSLionel Debieve 61b1e0b11cSLionel Debieve /* STR Register */ 62b1e0b11cSLionel Debieve #define HASH_STR_NBLW_MASK GENMASK(4, 0) 63b1e0b11cSLionel Debieve #define HASH_STR_DCAL BIT(8) 64b1e0b11cSLionel Debieve 65b1e0b11cSLionel Debieve #define MD5_DIGEST_SIZE 16U 66b1e0b11cSLionel Debieve #define SHA1_DIGEST_SIZE 20U 67b1e0b11cSLionel Debieve #define SHA224_DIGEST_SIZE 28U 68b1e0b11cSLionel Debieve #define SHA256_DIGEST_SIZE 32U 6968039f2dSNicolas Toromanoff #define SHA384_DIGEST_SIZE 48U 7068039f2dSNicolas Toromanoff #define SHA512_224_DIGEST_SIZE 28U 7168039f2dSNicolas Toromanoff #define SHA512_256_DIGEST_SIZE 32U 7268039f2dSNicolas Toromanoff #define SHA512_DIGEST_SIZE 64U 73b1e0b11cSLionel Debieve 7445c70e68SEtienne Carriere #define RESET_TIMEOUT_US_1MS 1000U 75b1e0b11cSLionel Debieve #define HASH_TIMEOUT_US 10000U 76b1e0b11cSLionel Debieve 77b1e0b11cSLionel Debieve enum stm32_hash_data_format { 78b1e0b11cSLionel Debieve HASH_DATA_32_BITS, 79b1e0b11cSLionel Debieve HASH_DATA_16_BITS, 80b1e0b11cSLionel Debieve HASH_DATA_8_BITS, 81b1e0b11cSLionel Debieve HASH_DATA_1_BIT 82b1e0b11cSLionel Debieve }; 83b1e0b11cSLionel Debieve 84b1e0b11cSLionel Debieve struct stm32_hash_instance { 85b1e0b11cSLionel Debieve uintptr_t base; 86b1e0b11cSLionel Debieve unsigned int clock; 87b1e0b11cSLionel Debieve size_t digest_size; 88b1e0b11cSLionel Debieve }; 89b1e0b11cSLionel Debieve 90b1e0b11cSLionel Debieve struct stm32_hash_remain { 91b1e0b11cSLionel Debieve uint32_t buffer; 92b1e0b11cSLionel Debieve size_t length; 93b1e0b11cSLionel Debieve }; 94b1e0b11cSLionel Debieve 95b1e0b11cSLionel Debieve /* Expect a single HASH peripheral */ 96b1e0b11cSLionel Debieve static struct stm32_hash_instance stm32_hash; 97b1e0b11cSLionel Debieve static struct stm32_hash_remain stm32_remain; 98b1e0b11cSLionel Debieve 99b1e0b11cSLionel Debieve static uintptr_t hash_base(void) 100b1e0b11cSLionel Debieve { 101b1e0b11cSLionel Debieve return stm32_hash.base; 102b1e0b11cSLionel Debieve } 103b1e0b11cSLionel Debieve 104b1e0b11cSLionel Debieve static int hash_wait_busy(void) 105b1e0b11cSLionel Debieve { 106b1e0b11cSLionel Debieve uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 107b1e0b11cSLionel Debieve 108b1e0b11cSLionel Debieve while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { 109b1e0b11cSLionel Debieve if (timeout_elapsed(timeout)) { 110b1e0b11cSLionel Debieve ERROR("%s: busy timeout\n", __func__); 111b1e0b11cSLionel Debieve return -ETIMEDOUT; 112b1e0b11cSLionel Debieve } 113b1e0b11cSLionel Debieve } 114b1e0b11cSLionel Debieve 115b1e0b11cSLionel Debieve return 0; 116b1e0b11cSLionel Debieve } 117b1e0b11cSLionel Debieve 118b1e0b11cSLionel Debieve static int hash_wait_computation(void) 119b1e0b11cSLionel Debieve { 120b1e0b11cSLionel Debieve uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 121b1e0b11cSLionel Debieve 122b1e0b11cSLionel Debieve while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { 123b1e0b11cSLionel Debieve if (timeout_elapsed(timeout)) { 124b1e0b11cSLionel Debieve ERROR("%s: busy timeout\n", __func__); 125b1e0b11cSLionel Debieve return -ETIMEDOUT; 126b1e0b11cSLionel Debieve } 127b1e0b11cSLionel Debieve } 128b1e0b11cSLionel Debieve 129b1e0b11cSLionel Debieve return 0; 130b1e0b11cSLionel Debieve } 131b1e0b11cSLionel Debieve 132b1e0b11cSLionel Debieve static int hash_write_data(uint32_t data) 133b1e0b11cSLionel Debieve { 134b1e0b11cSLionel Debieve int ret; 135b1e0b11cSLionel Debieve 136b1e0b11cSLionel Debieve ret = hash_wait_busy(); 137b1e0b11cSLionel Debieve if (ret != 0) { 138b1e0b11cSLionel Debieve return ret; 139b1e0b11cSLionel Debieve } 140b1e0b11cSLionel Debieve 141b1e0b11cSLionel Debieve mmio_write_32(hash_base() + HASH_DIN, data); 142b1e0b11cSLionel Debieve 143b1e0b11cSLionel Debieve return 0; 144b1e0b11cSLionel Debieve } 145b1e0b11cSLionel Debieve 146b1e0b11cSLionel Debieve static void hash_hw_init(enum stm32_hash_algo_mode mode) 147b1e0b11cSLionel Debieve { 148b1e0b11cSLionel Debieve uint32_t reg; 149b1e0b11cSLionel Debieve 150b1e0b11cSLionel Debieve reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); 151b1e0b11cSLionel Debieve 152b1e0b11cSLionel Debieve switch (mode) { 15368039f2dSNicolas Toromanoff #if STM32_HASH_VER == 2 154b1e0b11cSLionel Debieve case HASH_MD5SUM: 155b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_MD5; 156b1e0b11cSLionel Debieve stm32_hash.digest_size = MD5_DIGEST_SIZE; 157b1e0b11cSLionel Debieve break; 15868039f2dSNicolas Toromanoff #endif 159b1e0b11cSLionel Debieve case HASH_SHA1: 160b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA1; 161b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA1_DIGEST_SIZE; 162b1e0b11cSLionel Debieve break; 163b1e0b11cSLionel Debieve case HASH_SHA224: 164b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA224; 165b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA224_DIGEST_SIZE; 166b1e0b11cSLionel Debieve break; 16768039f2dSNicolas Toromanoff #if STM32_HASH_VER == 4 16868039f2dSNicolas Toromanoff case HASH_SHA384: 16968039f2dSNicolas Toromanoff reg |= HASH_CR_ALGO_SHA384; 17068039f2dSNicolas Toromanoff stm32_hash.digest_size = SHA384_DIGEST_SIZE; 17168039f2dSNicolas Toromanoff break; 17268039f2dSNicolas Toromanoff case HASH_SHA512: 17368039f2dSNicolas Toromanoff reg |= HASH_CR_ALGO_SHA512; 17468039f2dSNicolas Toromanoff stm32_hash.digest_size = SHA512_DIGEST_SIZE; 17568039f2dSNicolas Toromanoff break; 17668039f2dSNicolas Toromanoff #endif 177b1e0b11cSLionel Debieve /* Default selected algo is SHA256 */ 178b1e0b11cSLionel Debieve case HASH_SHA256: 179b1e0b11cSLionel Debieve default: 180b1e0b11cSLionel Debieve reg |= HASH_CR_ALGO_SHA256; 181b1e0b11cSLionel Debieve stm32_hash.digest_size = SHA256_DIGEST_SIZE; 182b1e0b11cSLionel Debieve break; 183b1e0b11cSLionel Debieve } 184b1e0b11cSLionel Debieve 185b1e0b11cSLionel Debieve mmio_write_32(hash_base() + HASH_CR, reg); 186b1e0b11cSLionel Debieve } 187b1e0b11cSLionel Debieve 188b1e0b11cSLionel Debieve static int hash_get_digest(uint8_t *digest) 189b1e0b11cSLionel Debieve { 190b1e0b11cSLionel Debieve int ret; 191b1e0b11cSLionel Debieve uint32_t i; 192b1e0b11cSLionel Debieve uint32_t dsg; 193b1e0b11cSLionel Debieve 194b1e0b11cSLionel Debieve ret = hash_wait_computation(); 195b1e0b11cSLionel Debieve if (ret != 0) { 196b1e0b11cSLionel Debieve return ret; 197b1e0b11cSLionel Debieve } 198b1e0b11cSLionel Debieve 199b1e0b11cSLionel Debieve for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { 200b1e0b11cSLionel Debieve dsg = __builtin_bswap32(mmio_read_32(hash_base() + 201b1e0b11cSLionel Debieve HASH_HREG(i))); 202b1e0b11cSLionel Debieve memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); 203b1e0b11cSLionel Debieve } 204b1e0b11cSLionel Debieve 205b1e0b11cSLionel Debieve /* 206b1e0b11cSLionel Debieve * Clean hardware context as HASH could be used later 207b1e0b11cSLionel Debieve * by non-secure software 208b1e0b11cSLionel Debieve */ 209b1e0b11cSLionel Debieve hash_hw_init(HASH_SHA256); 210*6b5fc192SLionel Debieve 211b1e0b11cSLionel Debieve return 0; 212b1e0b11cSLionel Debieve } 213b1e0b11cSLionel Debieve 214b1e0b11cSLionel Debieve int stm32_hash_update(const uint8_t *buffer, size_t length) 215b1e0b11cSLionel Debieve { 216b1e0b11cSLionel Debieve size_t remain_length = length; 217b1e0b11cSLionel Debieve int ret = 0; 218b1e0b11cSLionel Debieve 219b1e0b11cSLionel Debieve if ((length == 0U) || (buffer == NULL)) { 220b1e0b11cSLionel Debieve return 0; 221b1e0b11cSLionel Debieve } 222b1e0b11cSLionel Debieve 22333667d29SYann Gautier clk_enable(stm32_hash.clock); 224b1e0b11cSLionel Debieve 225b1e0b11cSLionel Debieve if (stm32_remain.length != 0U) { 226b1e0b11cSLionel Debieve uint32_t copysize; 227b1e0b11cSLionel Debieve 228b1e0b11cSLionel Debieve copysize = MIN((sizeof(uint32_t) - stm32_remain.length), 229b1e0b11cSLionel Debieve length); 230b1e0b11cSLionel Debieve memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, 231b1e0b11cSLionel Debieve buffer, copysize); 232b1e0b11cSLionel Debieve remain_length -= copysize; 233b1e0b11cSLionel Debieve buffer += copysize; 234b1e0b11cSLionel Debieve if (stm32_remain.length == sizeof(uint32_t)) { 235b1e0b11cSLionel Debieve ret = hash_write_data(stm32_remain.buffer); 236b1e0b11cSLionel Debieve if (ret != 0) { 237b1e0b11cSLionel Debieve goto exit; 238b1e0b11cSLionel Debieve } 239b1e0b11cSLionel Debieve 240b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 241b1e0b11cSLionel Debieve } 242b1e0b11cSLionel Debieve } 243b1e0b11cSLionel Debieve 244b1e0b11cSLionel Debieve while (remain_length / sizeof(uint32_t) != 0U) { 245b1e0b11cSLionel Debieve uint32_t tmp_buf; 246b1e0b11cSLionel Debieve 247b1e0b11cSLionel Debieve memcpy(&tmp_buf, buffer, sizeof(uint32_t)); 248b1e0b11cSLionel Debieve ret = hash_write_data(tmp_buf); 249b1e0b11cSLionel Debieve if (ret != 0) { 250b1e0b11cSLionel Debieve goto exit; 251b1e0b11cSLionel Debieve } 252b1e0b11cSLionel Debieve 253b1e0b11cSLionel Debieve buffer += sizeof(uint32_t); 254b1e0b11cSLionel Debieve remain_length -= sizeof(uint32_t); 255b1e0b11cSLionel Debieve } 256b1e0b11cSLionel Debieve 257b1e0b11cSLionel Debieve if (remain_length != 0U) { 258b1e0b11cSLionel Debieve assert(stm32_remain.length == 0U); 259b1e0b11cSLionel Debieve 260b1e0b11cSLionel Debieve memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); 261b1e0b11cSLionel Debieve stm32_remain.length = remain_length; 262b1e0b11cSLionel Debieve } 263b1e0b11cSLionel Debieve 264b1e0b11cSLionel Debieve exit: 26533667d29SYann Gautier clk_disable(stm32_hash.clock); 266b1e0b11cSLionel Debieve 267b1e0b11cSLionel Debieve return ret; 268b1e0b11cSLionel Debieve } 269b1e0b11cSLionel Debieve 270b1e0b11cSLionel Debieve int stm32_hash_final(uint8_t *digest) 271b1e0b11cSLionel Debieve { 272b1e0b11cSLionel Debieve int ret; 273b1e0b11cSLionel Debieve 27433667d29SYann Gautier clk_enable(stm32_hash.clock); 275b1e0b11cSLionel Debieve 276b1e0b11cSLionel Debieve if (stm32_remain.length != 0U) { 277b1e0b11cSLionel Debieve ret = hash_write_data(stm32_remain.buffer); 278b1e0b11cSLionel Debieve if (ret != 0) { 27933667d29SYann Gautier clk_disable(stm32_hash.clock); 280b1e0b11cSLionel Debieve return ret; 281b1e0b11cSLionel Debieve } 282b1e0b11cSLionel Debieve 283b1e0b11cSLionel Debieve mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, 284b1e0b11cSLionel Debieve 8U * stm32_remain.length); 285b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 286662c1f5cSLionel Debieve } else { 287662c1f5cSLionel Debieve mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); 288b1e0b11cSLionel Debieve } 289b1e0b11cSLionel Debieve 290b1e0b11cSLionel Debieve mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); 291b1e0b11cSLionel Debieve 292b1e0b11cSLionel Debieve ret = hash_get_digest(digest); 293b1e0b11cSLionel Debieve 29433667d29SYann Gautier clk_disable(stm32_hash.clock); 295b1e0b11cSLionel Debieve 296b1e0b11cSLionel Debieve return ret; 297b1e0b11cSLionel Debieve } 298b1e0b11cSLionel Debieve 299b1e0b11cSLionel Debieve int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, 300b1e0b11cSLionel Debieve uint8_t *digest) 301b1e0b11cSLionel Debieve { 302b1e0b11cSLionel Debieve int ret; 303b1e0b11cSLionel Debieve 304b1e0b11cSLionel Debieve ret = stm32_hash_update(buffer, length); 305b1e0b11cSLionel Debieve if (ret != 0) { 306b1e0b11cSLionel Debieve return ret; 307b1e0b11cSLionel Debieve } 308b1e0b11cSLionel Debieve 309b1e0b11cSLionel Debieve return stm32_hash_final(digest); 310b1e0b11cSLionel Debieve } 311b1e0b11cSLionel Debieve 312b1e0b11cSLionel Debieve void stm32_hash_init(enum stm32_hash_algo_mode mode) 313b1e0b11cSLionel Debieve { 31433667d29SYann Gautier clk_enable(stm32_hash.clock); 315b1e0b11cSLionel Debieve 316b1e0b11cSLionel Debieve hash_hw_init(mode); 317b1e0b11cSLionel Debieve 31833667d29SYann Gautier clk_disable(stm32_hash.clock); 319b1e0b11cSLionel Debieve 320b1e0b11cSLionel Debieve zeromem(&stm32_remain, sizeof(stm32_remain)); 321b1e0b11cSLionel Debieve } 322b1e0b11cSLionel Debieve 323b1e0b11cSLionel Debieve int stm32_hash_register(void) 324b1e0b11cSLionel Debieve { 325b1e0b11cSLionel Debieve struct dt_node_info hash_info; 326b1e0b11cSLionel Debieve int node; 327b1e0b11cSLionel Debieve 328b1e0b11cSLionel Debieve for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); 329b1e0b11cSLionel Debieve node != -FDT_ERR_NOTFOUND; 330b1e0b11cSLionel Debieve node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { 331b1e0b11cSLionel Debieve if (hash_info.status != DT_DISABLED) { 332b1e0b11cSLionel Debieve break; 333b1e0b11cSLionel Debieve } 334b1e0b11cSLionel Debieve } 335b1e0b11cSLionel Debieve 336b1e0b11cSLionel Debieve if (node == -FDT_ERR_NOTFOUND) { 337b1e0b11cSLionel Debieve return -ENODEV; 338b1e0b11cSLionel Debieve } 339b1e0b11cSLionel Debieve 340b1e0b11cSLionel Debieve if (hash_info.clock < 0) { 341b1e0b11cSLionel Debieve return -EINVAL; 342b1e0b11cSLionel Debieve } 343b1e0b11cSLionel Debieve 344b1e0b11cSLionel Debieve stm32_hash.base = hash_info.base; 345b1e0b11cSLionel Debieve stm32_hash.clock = hash_info.clock; 346b1e0b11cSLionel Debieve 34733667d29SYann Gautier clk_enable(stm32_hash.clock); 348b1e0b11cSLionel Debieve 349b1e0b11cSLionel Debieve if (hash_info.reset >= 0) { 35045c70e68SEtienne Carriere uint32_t id = (uint32_t)hash_info.reset; 35145c70e68SEtienne Carriere 35245c70e68SEtienne Carriere if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) { 35345c70e68SEtienne Carriere panic(); 35445c70e68SEtienne Carriere } 355b1e0b11cSLionel Debieve udelay(20); 35645c70e68SEtienne Carriere if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) { 35745c70e68SEtienne Carriere panic(); 35845c70e68SEtienne Carriere } 359b1e0b11cSLionel Debieve } 360b1e0b11cSLionel Debieve 36133667d29SYann Gautier clk_disable(stm32_hash.clock); 362b1e0b11cSLionel Debieve 363b1e0b11cSLionel Debieve return 0; 364b1e0b11cSLionel Debieve } 365