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