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