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