aboutsummaryrefslogtreecommitdiff
path: root/drivers/crypto/aspeed/aspeed_acry.c
blob: c28cdf374b688ae8bfba6750b903b2f3859f7af4 (plain)
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
190
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2021 ASPEED Technology Inc.
 */
#include <config.h>
#include <common.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_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,
};