1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright 2021 ASPEED Technology Inc. 4 */ 5#include <config.h> 6#include <common.h> 7#include <clk.h> 8#include <dm.h> 9#include <asm/types.h> 10#include <asm/io.h> 11#include <dm/device.h> 12#include <dm/fdtaddr.h> 13#include <linux/delay.h> 14#include <u-boot/rsa-mod-exp.h> 15 16/* ACRY register offsets */ 17#define ACRY_CTRL1 0x00 18#define ACRY_CTRL1_RSA_DMA BIT(1) 19#define ACRY_CTRL1_RSA_START BIT(0) 20#define ACRY_CTRL2 0x44 21#define ACRY_CTRL3 0x48 22#define ACRY_CTRL3_SRAM_AHB_ACCESS BIT(8) 23#define ACRY_CTRL3_ECC_RSA_MODE_MASK GENMASK(5, 4) 24#define ACRY_CTRL3_ECC_RSA_MODE_SHIFT 4 25#define ACRY_DMA_DRAM_SADDR 0x4c 26#define ACRY_DMA_DMEM_TADDR 0x50 27#define ACRY_DMA_DMEM_TADDR_LEN_MASK GENMASK(15, 0) 28#define ACRY_DMA_DMEM_TADDR_LEN_SHIFT 0 29#define ACRY_RSA_PARAM 0x58 30#define ACRY_RSA_PARAM_EXP_MASK GENMASK(31, 16) 31#define ACRY_RSA_PARAM_EXP_SHIFT 16 32#define ACRY_RSA_PARAM_MOD_MASK GENMASK(15, 0) 33#define ACRY_RSA_PARAM_MOD_SHIFT 0 34#define ACRY_RSA_INT_EN 0x3f8 35#define ACRY_RSA_INT_EN_RSA_READY BIT(2) 36#define ACRY_RSA_INT_EN_RSA_CMPLT BIT(1) 37#define ACRY_RSA_INT_STS 0x3fc 38#define ACRY_RSA_INT_STS_RSA_READY BIT(2) 39#define ACRY_RSA_INT_STS_RSA_CMPLT BIT(1) 40 41/* misc. constant */ 42#define ACRY_ECC_MODE 2 43#define ACRY_RSA_MODE 3 44#define ACRY_CTX_BUFSZ 0x600 45 46struct aspeed_acry { 47 phys_addr_t base; 48 phys_addr_t sram_base; /* internal sram */ 49 struct clk clk; 50}; 51 52static int aspeed_acry_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, 53 struct key_prop *prop, uint8_t *out) 54{ 55 int i, j; 56 u8 *ctx; 57 u8 *ptr; 58 u32 reg; 59 struct aspeed_acry *acry = dev_get_priv(dev); 60 61 ctx = memalign(16, ACRY_CTX_BUFSZ); 62 if (!ctx) 63 return -ENOMEM; 64 65 memset(ctx, 0, ACRY_CTX_BUFSZ); 66 67 ptr = (u8 *)prop->public_exponent; 68 for (i = prop->exp_len - 1, j = 0; i >= 0; --i) { 69 ctx[j] = ptr[i]; 70 j++; 71 j = (j % 16) ? j : j + 32; 72 } 73 74 ptr = (u8 *)prop->modulus; 75 for (i = (prop->num_bits >> 3) - 1, j = 0; i >= 0; --i) { 76 ctx[j + 16] = ptr[i]; 77 j++; 78 j = (j % 16) ? j : j + 32; 79 } 80 81 ptr = (u8 *)sig; 82 for (i = sig_len - 1, j = 0; i >= 0; --i) { 83 ctx[j + 32] = ptr[i]; 84 j++; 85 j = (j % 16) ? j : j + 32; 86 } 87 88 writel((u32)ctx, acry->base + ACRY_DMA_DRAM_SADDR); 89 90 reg = (((prop->exp_len << 3) << ACRY_RSA_PARAM_EXP_SHIFT) & ACRY_RSA_PARAM_EXP_MASK) | 91 ((prop->num_bits << ACRY_RSA_PARAM_MOD_SHIFT) & ACRY_RSA_PARAM_MOD_MASK); 92 writel(reg, acry->base + ACRY_RSA_PARAM); 93 94 reg = (ACRY_CTX_BUFSZ << ACRY_DMA_DMEM_TADDR_LEN_SHIFT) & ACRY_DMA_DMEM_TADDR_LEN_MASK; 95 writel(reg, acry->base + ACRY_DMA_DMEM_TADDR); 96 97 reg = (ACRY_RSA_MODE << ACRY_CTRL3_ECC_RSA_MODE_SHIFT) & ACRY_CTRL3_ECC_RSA_MODE_MASK; 98 writel(reg, acry->base + ACRY_CTRL3); 99 100 writel(ACRY_CTRL1_RSA_DMA | ACRY_CTRL1_RSA_START, acry->base + ACRY_CTRL1); 101 102 /* polling RSA status */ 103 while (1) { 104 reg = readl(acry->base + ACRY_RSA_INT_STS); 105 if ((reg & ACRY_RSA_INT_STS_RSA_READY) && (reg & ACRY_RSA_INT_STS_RSA_CMPLT)) { 106 writel(reg, acry->base + ACRY_RSA_INT_STS); 107 break; 108 } 109 udelay(20); 110 } 111 112 /* grant SRAM access permission to CPU */ 113 writel(0x0, acry->base + ACRY_CTRL1); 114 writel(ACRY_CTRL3_SRAM_AHB_ACCESS, acry->base + ACRY_CTRL3); 115 udelay(20); 116 117 for (i = (prop->num_bits / 8) - 1, j = 0; i >= 0; --i) { 118 out[i] = readb(acry->sram_base + (j + 32)); 119 j++; 120 j = (j % 16) ? j : j + 32; 121 } 122 123 /* return SRAM access permission to ACRY */ 124 writel(0, acry->base + ACRY_CTRL3); 125 126 free(ctx); 127 128 return 0; 129} 130 131static int aspeed_acry_probe(struct udevice *dev) 132{ 133 struct aspeed_acry *acry = dev_get_priv(dev); 134 int ret; 135 136 ret = clk_get_by_index(dev, 0, &acry->clk); 137 if (ret < 0) { 138 debug("Can't get clock for %s: %d\n", dev->name, ret); 139 return ret; 140 } 141 142 ret = clk_enable(&acry->clk); 143 if (ret) { 144 debug("Failed to enable acry clock (%d)\n", ret); 145 return ret; 146 } 147 148 acry->base = devfdt_get_addr_index(dev, 0); 149 if (acry->base == FDT_ADDR_T_NONE) { 150 debug("Failed to get acry base\n"); 151 return acry->base; 152 } 153 154 acry->sram_base = devfdt_get_addr_index(dev, 1); 155 if (acry->sram_base == FDT_ADDR_T_NONE) { 156 debug("Failed to get acry SRAM base\n"); 157 return acry->sram_base; 158 } 159 160 return ret; 161} 162 163static int aspeed_acry_remove(struct udevice *dev) 164{ 165 struct aspeed_acry *acry = dev_get_priv(dev); 166 167 clk_disable(&acry->clk); 168 169 return 0; 170} 171 172static const struct mod_exp_ops aspeed_acry_ops = { 173 .mod_exp = aspeed_acry_mod_exp, 174}; 175 176static const struct udevice_id aspeed_acry_ids[] = { 177 { .compatible = "aspeed,ast2600-acry" }, 178 { } 179}; 180 181U_BOOT_DRIVER(aspeed_acry) = { 182 .name = "aspeed_acry", 183 .id = UCLASS_MOD_EXP, 184 .of_match = aspeed_acry_ids, 185 .probe = aspeed_acry_probe, 186 .remove = aspeed_acry_remove, 187 .priv_auto = sizeof(struct aspeed_acry), 188 .ops = &aspeed_acry_ops, 189 .flags = DM_FLAG_PRE_RELOC, 190}; 191