aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal van Leeuwen <pvanleeuwen@insidesecure.com>2019-08-19 10:40:26 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-08-30 04:05:28 -0400
commitf6cc45c854da0c964d1541712bb3326c72020a1c (patch)
tree17d34f77cd452ea42959f91c16422b3b318cafdc
parent625f269a5a7a3643771320387e474bd0a61d9654 (diff)
crypto: inside-secure - add support for using the EIP197 without vendor firmware
Until now, the inside-secure driver required a set of firmware images supplied by the silicon vendor, typically under NDA, to be present in /lib/firmware/inside-secure in order to be able to function. This patch removes the dependence on this official vendor firmware by falling back to generic "mini" FW - developed specifically for this driver - that can be provided under GPL 2.0 through linux-firmwares. Signed-off-by: Pascal van Leeuwen <pvanleeuwen@verimatrix.com> Acked-by: Antoine Tenart <antoine.tenart@bootlin.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/inside-secure/safexcel.c194
-rw-r--r--drivers/crypto/inside-secure/safexcel.h12
2 files changed, 161 insertions, 45 deletions
diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
index dfe22d2d7161..e12a2a3a5422 100644
--- a/drivers/crypto/inside-secure/safexcel.c
+++ b/drivers/crypto/inside-secure/safexcel.c
@@ -108,44 +108,143 @@ static void eip197_trc_cache_init(struct safexcel_crypto_priv *priv)
108 writel(val, priv->base + EIP197_TRC_PARAMS); 108 writel(val, priv->base + EIP197_TRC_PARAMS);
109} 109}
110 110
111static void eip197_write_firmware(struct safexcel_crypto_priv *priv, 111static void eip197_init_firmware(struct safexcel_crypto_priv *priv)
112 const struct firmware *fw, int pe, u32 ctrl,
113 u32 prog_en)
114{ 112{
115 const u32 *data = (const u32 *)fw->data; 113 int pe, i;
116 u32 val; 114 u32 val;
117 int i;
118 115
119 /* Reset the engine to make its program memory accessible */ 116 for (pe = 0; pe < priv->config.pes; pe++) {
120 writel(EIP197_PE_ICE_x_CTRL_SW_RESET | 117 /* Configure the token FIFO's */
121 EIP197_PE_ICE_x_CTRL_CLR_ECC_CORR | 118 writel(3, EIP197_PE(priv) + EIP197_PE_ICE_PUTF_CTRL(pe));
122 EIP197_PE_ICE_x_CTRL_CLR_ECC_NON_CORR, 119 writel(0, EIP197_PE(priv) + EIP197_PE_ICE_PPTF_CTRL(pe));
123 EIP197_PE(priv) + ctrl); 120
121 /* Clear the ICE scratchpad memory */
122 val = readl(EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));
123 val |= EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_TIMER |
124 EIP197_PE_ICE_SCRATCH_CTRL_TIMER_EN |
125 EIP197_PE_ICE_SCRATCH_CTRL_SCRATCH_ACCESS |
126 EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_ACCESS;
127 writel(val, EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));
128
129 /* clear the scratchpad RAM using 32 bit writes only */
130 for (i = 0; i < EIP197_NUM_OF_SCRATCH_BLOCKS; i++)
131 writel(0, EIP197_PE(priv) +
132 EIP197_PE_ICE_SCRATCH_RAM(pe) + (i<<2));
133
134 /* Reset the IFPP engine to make its program mem accessible */
135 writel(EIP197_PE_ICE_x_CTRL_SW_RESET |
136 EIP197_PE_ICE_x_CTRL_CLR_ECC_CORR |
137 EIP197_PE_ICE_x_CTRL_CLR_ECC_NON_CORR,
138 EIP197_PE(priv) + EIP197_PE_ICE_FPP_CTRL(pe));
139
140 /* Reset the IPUE engine to make its program mem accessible */
141 writel(EIP197_PE_ICE_x_CTRL_SW_RESET |
142 EIP197_PE_ICE_x_CTRL_CLR_ECC_CORR |
143 EIP197_PE_ICE_x_CTRL_CLR_ECC_NON_CORR,
144 EIP197_PE(priv) + EIP197_PE_ICE_PUE_CTRL(pe));
145
146 /* Enable access to all IFPP program memories */
147 writel(EIP197_PE_ICE_RAM_CTRL_FPP_PROG_EN,
148 EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));
149 }
150
151}
124 152
125 /* Enable access to the program memory */ 153static int eip197_write_firmware(struct safexcel_crypto_priv *priv,
126 writel(prog_en, EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe)); 154 const struct firmware *fw)
155{
156 const u32 *data = (const u32 *)fw->data;
157 int i;
127 158
128 /* Write the firmware */ 159 /* Write the firmware */
129 for (i = 0; i < fw->size / sizeof(u32); i++) 160 for (i = 0; i < fw->size / sizeof(u32); i++)
130 writel(be32_to_cpu(data[i]), 161 writel(be32_to_cpu(data[i]),
131 priv->base + EIP197_CLASSIFICATION_RAMS + i * sizeof(u32)); 162 priv->base + EIP197_CLASSIFICATION_RAMS + i * sizeof(u32));
132 163
133 /* Disable access to the program memory */ 164 /* Exclude final 2 NOPs from size */
134 writel(0, EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe)); 165 return i - EIP197_FW_TERMINAL_NOPS;
166}
167
168/*
169 * If FW is actual production firmware, then poll for its initialization
170 * to complete and check if it is good for the HW, otherwise just return OK.
171 */
172static bool poll_fw_ready(struct safexcel_crypto_priv *priv, int fpp)
173{
174 int pe, pollcnt;
175 u32 base, pollofs;
176
177 if (fpp)
178 pollofs = EIP197_FW_FPP_READY;
179 else
180 pollofs = EIP197_FW_PUE_READY;
135 181
136 /* Release engine from reset */ 182 for (pe = 0; pe < priv->config.pes; pe++) {
137 val = readl(EIP197_PE(priv) + ctrl); 183 base = EIP197_PE_ICE_SCRATCH_RAM(pe);
138 val &= ~EIP197_PE_ICE_x_CTRL_SW_RESET; 184 pollcnt = EIP197_FW_START_POLLCNT;
139 writel(val, EIP197_PE(priv) + ctrl); 185 while (pollcnt &&
186 (readl_relaxed(EIP197_PE(priv) + base +
187 pollofs) != 1)) {
188 pollcnt--;
189 }
190 if (!pollcnt) {
191 dev_err(priv->dev, "FW(%d) for PE %d failed to start\n",
192 fpp, pe);
193 return false;
194 }
195 }
196 return true;
197}
198
199static bool eip197_start_firmware(struct safexcel_crypto_priv *priv,
200 int ipuesz, int ifppsz, int minifw)
201{
202 int pe;
203 u32 val;
204
205 for (pe = 0; pe < priv->config.pes; pe++) {
206 /* Disable access to all program memory */
207 writel(0, EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));
208
209 /* Start IFPP microengines */
210 if (minifw)
211 val = 0;
212 else
213 val = EIP197_PE_ICE_UENG_START_OFFSET((ifppsz - 1) &
214 EIP197_PE_ICE_UENG_INIT_ALIGN_MASK) |
215 EIP197_PE_ICE_UENG_DEBUG_RESET;
216 writel(val, EIP197_PE(priv) + EIP197_PE_ICE_FPP_CTRL(pe));
217
218 /* Start IPUE microengines */
219 if (minifw)
220 val = 0;
221 else
222 val = EIP197_PE_ICE_UENG_START_OFFSET((ipuesz - 1) &
223 EIP197_PE_ICE_UENG_INIT_ALIGN_MASK) |
224 EIP197_PE_ICE_UENG_DEBUG_RESET;
225 writel(val, EIP197_PE(priv) + EIP197_PE_ICE_PUE_CTRL(pe));
226 }
227
228 /* For miniFW startup, there is no initialization, so always succeed */
229 if (minifw)
230 return true;
231
232 /* Wait until all the firmwares have properly started up */
233 if (!poll_fw_ready(priv, 1))
234 return false;
235 if (!poll_fw_ready(priv, 0))
236 return false;
237
238 return true;
140} 239}
141 240
142static int eip197_load_firmwares(struct safexcel_crypto_priv *priv) 241static int eip197_load_firmwares(struct safexcel_crypto_priv *priv)
143{ 242{
144 const char *fw_name[] = {"ifpp.bin", "ipue.bin"}; 243 const char *fw_name[] = {"ifpp.bin", "ipue.bin"};
145 const struct firmware *fw[FW_NB]; 244 const struct firmware *fw[FW_NB];
146 char fw_path[31], *dir = NULL; 245 char fw_path[37], *dir = NULL;
147 int i, j, ret = 0, pe; 246 int i, j, ret = 0, pe;
148 u32 val; 247 int ipuesz, ifppsz, minifw = 0;
149 248
150 if (priv->version == EIP197D_MRVL) 249 if (priv->version == EIP197D_MRVL)
151 dir = "eip197d"; 250 dir = "eip197d";
@@ -155,51 +254,56 @@ static int eip197_load_firmwares(struct safexcel_crypto_priv *priv)
155 else 254 else
156 return -ENODEV; 255 return -ENODEV;
157 256
257retry_fw:
158 for (i = 0; i < FW_NB; i++) { 258 for (i = 0; i < FW_NB; i++) {
159 snprintf(fw_path, 31, "inside-secure/%s/%s", dir, fw_name[i]); 259 snprintf(fw_path, 37, "inside-secure/%s/%s", dir, fw_name[i]);
160 ret = request_firmware(&fw[i], fw_path, priv->dev); 260 ret = firmware_request_nowarn(&fw[i], fw_path, priv->dev);
161 if (ret) { 261 if (ret) {
162 if (priv->version != EIP197B_MRVL) 262 if (minifw || priv->version != EIP197B_MRVL)
163 goto release_fw; 263 goto release_fw;
164 264
165 /* Fallback to the old firmware location for the 265 /* Fallback to the old firmware location for the
166 * EIP197b. 266 * EIP197b.
167 */ 267 */
168 ret = request_firmware(&fw[i], fw_name[i], priv->dev); 268 ret = firmware_request_nowarn(&fw[i], fw_name[i],
169 if (ret) { 269 priv->dev);
170 dev_err(priv->dev, 270 if (ret)
171 "Failed to request firmware %s (%d)\n",
172 fw_name[i], ret);
173 goto release_fw; 271 goto release_fw;
174 }
175 } 272 }
176 } 273 }
177 274
178 for (pe = 0; pe < priv->config.pes; pe++) { 275 eip197_init_firmware(priv);
179 /* Clear the scratchpad memory */
180 val = readl(EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));
181 val |= EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_TIMER |
182 EIP197_PE_ICE_SCRATCH_CTRL_TIMER_EN |
183 EIP197_PE_ICE_SCRATCH_CTRL_SCRATCH_ACCESS |
184 EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_ACCESS;
185 writel(val, EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));
186 276
187 memset_io(EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_RAM(pe), 0, 277 ifppsz = eip197_write_firmware(priv, fw[FW_IFPP]);
188 EIP197_NUM_OF_SCRATCH_BLOCKS * sizeof(u32));
189 278
190 eip197_write_firmware(priv, fw[FW_IFPP], pe, 279 /* Enable access to IPUE program memories */
191 EIP197_PE_ICE_FPP_CTRL(pe), 280 for (pe = 0; pe < priv->config.pes; pe++)
192 EIP197_PE_ICE_RAM_CTRL_FPP_PROG_EN); 281 writel(EIP197_PE_ICE_RAM_CTRL_PUE_PROG_EN,
282 EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));
193 283
194 eip197_write_firmware(priv, fw[FW_IPUE], pe, 284 ipuesz = eip197_write_firmware(priv, fw[FW_IPUE]);
195 EIP197_PE_ICE_PUE_CTRL(pe), 285
196 EIP197_PE_ICE_RAM_CTRL_PUE_PROG_EN); 286 if (eip197_start_firmware(priv, ipuesz, ifppsz, minifw)) {
287 dev_dbg(priv->dev, "Firmware loaded successfully");
288 return 0;
197 } 289 }
198 290
291 ret = -ENODEV;
292
199release_fw: 293release_fw:
200 for (j = 0; j < i; j++) 294 for (j = 0; j < i; j++)
201 release_firmware(fw[j]); 295 release_firmware(fw[j]);
202 296
297 if (!minifw) {
298 /* Retry with minifw path */
299 dev_dbg(priv->dev, "Firmware set not (fully) present or init failed, falling back to BCLA mode\n");
300 dir = "eip197_minifw";
301 minifw = 1;
302 goto retry_fw;
303 }
304
305 dev_dbg(priv->dev, "Firmware load failed.\n");
306
203 return ret; 307 return ret;
204} 308}
205 309
diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h
index 2db2a9636eb7..33e5f663c249 100644
--- a/drivers/crypto/inside-secure/safexcel.h
+++ b/drivers/crypto/inside-secure/safexcel.h
@@ -136,8 +136,10 @@
136#define EIP197_PE_IN_TBUF_THRES(n) (0x0100 + (0x2000 * (n))) 136#define EIP197_PE_IN_TBUF_THRES(n) (0x0100 + (0x2000 * (n)))
137#define EIP197_PE_ICE_SCRATCH_RAM(n) (0x0800 + (0x2000 * (n))) 137#define EIP197_PE_ICE_SCRATCH_RAM(n) (0x0800 + (0x2000 * (n)))
138#define EIP197_PE_ICE_PUE_CTRL(n) (0x0c80 + (0x2000 * (n))) 138#define EIP197_PE_ICE_PUE_CTRL(n) (0x0c80 + (0x2000 * (n)))
139#define EIP197_PE_ICE_PUTF_CTRL(n) (0x0d00 + (0x2000 * (n)))
139#define EIP197_PE_ICE_SCRATCH_CTRL(n) (0x0d04 + (0x2000 * (n))) 140#define EIP197_PE_ICE_SCRATCH_CTRL(n) (0x0d04 + (0x2000 * (n)))
140#define EIP197_PE_ICE_FPP_CTRL(n) (0x0d80 + (0x2000 * (n))) 141#define EIP197_PE_ICE_FPP_CTRL(n) (0x0d80 + (0x2000 * (n)))
142#define EIP197_PE_ICE_PPTF_CTRL(n) (0x0e00 + (0x2000 * (n)))
141#define EIP197_PE_ICE_RAM_CTRL(n) (0x0ff0 + (0x2000 * (n))) 143#define EIP197_PE_ICE_RAM_CTRL(n) (0x0ff0 + (0x2000 * (n)))
142#define EIP197_PE_EIP96_TOKEN_CTRL(n) (0x1000 + (0x2000 * (n))) 144#define EIP197_PE_EIP96_TOKEN_CTRL(n) (0x1000 + (0x2000 * (n)))
143#define EIP197_PE_EIP96_FUNCTION_EN(n) (0x1004 + (0x2000 * (n))) 145#define EIP197_PE_EIP96_FUNCTION_EN(n) (0x1004 + (0x2000 * (n)))
@@ -228,6 +230,11 @@
228#define EIP197_DxE_THR_CTRL_EN BIT(30) 230#define EIP197_DxE_THR_CTRL_EN BIT(30)
229#define EIP197_DxE_THR_CTRL_RESET_PE BIT(31) 231#define EIP197_DxE_THR_CTRL_RESET_PE BIT(31)
230 232
233/* EIP197_PE_ICE_PUE/FPP_CTRL */
234#define EIP197_PE_ICE_UENG_START_OFFSET(n) ((n) << 16)
235#define EIP197_PE_ICE_UENG_INIT_ALIGN_MASK 0x7ff0
236#define EIP197_PE_ICE_UENG_DEBUG_RESET BIT(3)
237
231/* EIP197_HIA_AIC_G_ENABLED_STAT */ 238/* EIP197_HIA_AIC_G_ENABLED_STAT */
232#define EIP197_G_IRQ_DFE(n) BIT((n) << 1) 239#define EIP197_G_IRQ_DFE(n) BIT((n) << 1)
233#define EIP197_G_IRQ_DSE(n) BIT(((n) << 1) + 1) 240#define EIP197_G_IRQ_DSE(n) BIT(((n) << 1) + 1)
@@ -503,6 +510,11 @@ struct safexcel_command_desc {
503 * Internal structures & functions 510 * Internal structures & functions
504 */ 511 */
505 512
513#define EIP197_FW_TERMINAL_NOPS 2
514#define EIP197_FW_START_POLLCNT 16
515#define EIP197_FW_PUE_READY 0x14
516#define EIP197_FW_FPP_READY 0x18
517
506enum eip197_fw { 518enum eip197_fw {
507 FW_IFPP = 0, 519 FW_IFPP = 0,
508 FW_IPUE, 520 FW_IPUE,