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