Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccree - check that cryptocell reset completed

In case of driver probe and pm resume we need to check that the cryptocell
hardware reset cycle is completed. during the reset cycle that Cryptocell
provide read only access to the APB interface which allows to verify
through the CC registers that the reset is completed. Until reset
completion we assume that any write/crypto operation is blocked.

Signed-off-by: Ofir Drang <ofir.drang@arm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ofir Drang and committed by
Herbert Xu
d84f6269 0b970d54

+43 -1
+32 -1
drivers/crypto/ccree/cc_driver.c
··· 48 48 }; 49 49 50 50 #define CC_NUM_IDRS 4 51 + #define CC_HW_RESET_LOOP_COUNT 10 51 52 52 53 /* Note: PIDR3 holds CMOD/Rev so ignored for HW identification purposes */ 53 54 static const u32 pidr_0124_offsets[CC_NUM_IDRS] = { ··· 187 186 } 188 187 189 188 return IRQ_HANDLED; 189 + } 190 + 191 + bool cc_wait_for_reset_completion(struct cc_drvdata *drvdata) 192 + { 193 + unsigned int val; 194 + unsigned int i; 195 + 196 + /* 712/710/63 has no reset completion indication, always return true */ 197 + if (drvdata->hw_rev <= CC_HW_REV_712) 198 + return true; 199 + 200 + for (i = 0; i < CC_HW_RESET_LOOP_COUNT; i++) { 201 + /* in cc7x3 NVM_IS_IDLE indicates that CC reset is 202 + * completed and device is fully functional 203 + */ 204 + val = cc_ioread(drvdata, CC_REG(NVM_IS_IDLE)); 205 + if (val & CC_NVM_IS_IDLE_MASK) { 206 + /* hw indicate reset completed */ 207 + return true; 208 + } 209 + /* allow scheduling other process on the processor */ 210 + schedule(); 211 + } 212 + /* reset not completed */ 213 + return false; 190 214 } 191 215 192 216 int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe) ··· 369 343 370 344 new_drvdata->sec_disabled = cc_sec_disable; 371 345 346 + /* wait for Crytpcell reset completion */ 347 + if (!cc_wait_for_reset_completion(new_drvdata)) { 348 + dev_err(dev, "Cryptocell reset not completed"); 349 + } 350 + 372 351 if (hw_rev->rev <= CC_HW_REV_712) { 373 352 /* Verify correct mapping */ 374 353 val = cc_ioread(new_drvdata, new_drvdata->sig_offset); ··· 429 398 if (rc) { 430 399 dev_err(dev, "Could not register to interrupt %d\n", 431 400 new_drvdata->irq); 432 - return rc; 401 + goto post_clk_err; 433 402 } 434 403 dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq); 435 404
+3
drivers/crypto/ccree/cc_driver.h
··· 67 67 68 68 #define CC_SECURITY_DISABLED_MASK BIT(CC_SECURITY_DISABLED_VALUE_BIT_SHIFT) 69 69 70 + #define CC_NVM_IS_IDLE_MASK BIT(CC_NVM_IS_IDLE_VALUE_BIT_SHIFT) 71 + 70 72 #define AXIM_MON_COMP_VALUE GENMASK(CC_AXIM_MON_COMP_VALUE_BIT_SIZE + \ 71 73 CC_AXIM_MON_COMP_VALUE_BIT_SHIFT, \ 72 74 CC_AXIM_MON_COMP_VALUE_BIT_SHIFT) ··· 218 216 __dump_byte_array(name, the_array, size); 219 217 } 220 218 219 + bool cc_wait_for_reset_completion(struct cc_drvdata *drvdata); 221 220 int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe); 222 221 void fini_cc_regs(struct cc_drvdata *drvdata); 223 222 int cc_clk_on(struct cc_drvdata *drvdata);
+3
drivers/crypto/ccree/cc_host_regs.h
··· 114 114 #define CC_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE 0x1UL 115 115 #define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT 0x17UL 116 116 #define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE 0x1UL 117 + #define CC_NVM_IS_IDLE_REG_OFFSET 0x0A10UL 118 + #define CC_NVM_IS_IDLE_VALUE_BIT_SHIFT 0x0UL 119 + #define CC_NVM_IS_IDLE_VALUE_BIT_SIZE 0x1UL 117 120 #define CC_SECURITY_DISABLED_REG_OFFSET 0x0A1CUL 118 121 #define CC_SECURITY_DISABLED_VALUE_BIT_SHIFT 0x0UL 119 122 #define CC_SECURITY_DISABLED_VALUE_BIT_SIZE 0x1UL
+5
drivers/crypto/ccree/cc_pm.c
··· 49 49 dev_err(dev, "failed getting clock back on. We're toast.\n"); 50 50 return rc; 51 51 } 52 + /* wait for Crytpcell reset completion */ 53 + if (!cc_wait_for_reset_completion(drvdata)) { 54 + dev_err(dev, "Cryptocell reset not completed"); 55 + return -EBUSY; 56 + } 52 57 53 58 cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); 54 59 rc = init_cc_regs(drvdata, false);