Commit d84f6269 authored by Ofir Drang's avatar Ofir Drang Committed by Herbert Xu

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: default avatarOfir Drang <ofir.drang@arm.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0b970d54
...@@ -48,6 +48,7 @@ struct cc_hw_data { ...@@ -48,6 +48,7 @@ struct cc_hw_data {
}; };
#define CC_NUM_IDRS 4 #define CC_NUM_IDRS 4
#define CC_HW_RESET_LOOP_COUNT 10
/* Note: PIDR3 holds CMOD/Rev so ignored for HW identification purposes */ /* Note: PIDR3 holds CMOD/Rev so ignored for HW identification purposes */
static const u32 pidr_0124_offsets[CC_NUM_IDRS] = { static const u32 pidr_0124_offsets[CC_NUM_IDRS] = {
...@@ -188,6 +189,31 @@ static irqreturn_t cc_isr(int irq, void *dev_id) ...@@ -188,6 +189,31 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
bool cc_wait_for_reset_completion(struct cc_drvdata *drvdata)
{
unsigned int val;
unsigned int i;
/* 712/710/63 has no reset completion indication, always return true */
if (drvdata->hw_rev <= CC_HW_REV_712)
return true;
for (i = 0; i < CC_HW_RESET_LOOP_COUNT; i++) {
/* in cc7x3 NVM_IS_IDLE indicates that CC reset is
* completed and device is fully functional
*/
val = cc_ioread(drvdata, CC_REG(NVM_IS_IDLE));
if (val & CC_NVM_IS_IDLE_MASK) {
/* hw indicate reset completed */
return true;
}
/* allow scheduling other process on the processor */
schedule();
}
/* reset not completed */
return false;
}
int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe) int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe)
{ {
unsigned int val, cache_params; unsigned int val, cache_params;
...@@ -343,6 +369,11 @@ static int init_cc_resources(struct platform_device *plat_dev) ...@@ -343,6 +369,11 @@ static int init_cc_resources(struct platform_device *plat_dev)
new_drvdata->sec_disabled = cc_sec_disable; new_drvdata->sec_disabled = cc_sec_disable;
/* wait for Crytpcell reset completion */
if (!cc_wait_for_reset_completion(new_drvdata)) {
dev_err(dev, "Cryptocell reset not completed");
}
if (hw_rev->rev <= CC_HW_REV_712) { if (hw_rev->rev <= CC_HW_REV_712) {
/* Verify correct mapping */ /* Verify correct mapping */
val = cc_ioread(new_drvdata, new_drvdata->sig_offset); val = cc_ioread(new_drvdata, new_drvdata->sig_offset);
...@@ -398,7 +429,7 @@ static int init_cc_resources(struct platform_device *plat_dev) ...@@ -398,7 +429,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
if (rc) { if (rc) {
dev_err(dev, "Could not register to interrupt %d\n", dev_err(dev, "Could not register to interrupt %d\n",
new_drvdata->irq); new_drvdata->irq);
return rc; goto post_clk_err;
} }
dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq); dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq);
......
...@@ -67,6 +67,8 @@ enum cc_std_body { ...@@ -67,6 +67,8 @@ enum cc_std_body {
#define CC_SECURITY_DISABLED_MASK BIT(CC_SECURITY_DISABLED_VALUE_BIT_SHIFT) #define CC_SECURITY_DISABLED_MASK BIT(CC_SECURITY_DISABLED_VALUE_BIT_SHIFT)
#define CC_NVM_IS_IDLE_MASK BIT(CC_NVM_IS_IDLE_VALUE_BIT_SHIFT)
#define AXIM_MON_COMP_VALUE GENMASK(CC_AXIM_MON_COMP_VALUE_BIT_SIZE + \ #define AXIM_MON_COMP_VALUE GENMASK(CC_AXIM_MON_COMP_VALUE_BIT_SIZE + \
CC_AXIM_MON_COMP_VALUE_BIT_SHIFT, \ CC_AXIM_MON_COMP_VALUE_BIT_SHIFT, \
CC_AXIM_MON_COMP_VALUE_BIT_SHIFT) CC_AXIM_MON_COMP_VALUE_BIT_SHIFT)
...@@ -216,6 +218,7 @@ static inline void dump_byte_array(const char *name, const u8 *the_array, ...@@ -216,6 +218,7 @@ static inline void dump_byte_array(const char *name, const u8 *the_array,
__dump_byte_array(name, the_array, size); __dump_byte_array(name, the_array, size);
} }
bool cc_wait_for_reset_completion(struct cc_drvdata *drvdata);
int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe); int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe);
void fini_cc_regs(struct cc_drvdata *drvdata); void fini_cc_regs(struct cc_drvdata *drvdata);
int cc_clk_on(struct cc_drvdata *drvdata); int cc_clk_on(struct cc_drvdata *drvdata);
......
...@@ -114,6 +114,9 @@ ...@@ -114,6 +114,9 @@
#define CC_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE 0x1UL #define CC_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE 0x1UL
#define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT 0x17UL #define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT 0x17UL
#define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE 0x1UL #define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE 0x1UL
#define CC_NVM_IS_IDLE_REG_OFFSET 0x0A10UL
#define CC_NVM_IS_IDLE_VALUE_BIT_SHIFT 0x0UL
#define CC_NVM_IS_IDLE_VALUE_BIT_SIZE 0x1UL
#define CC_SECURITY_DISABLED_REG_OFFSET 0x0A1CUL #define CC_SECURITY_DISABLED_REG_OFFSET 0x0A1CUL
#define CC_SECURITY_DISABLED_VALUE_BIT_SHIFT 0x0UL #define CC_SECURITY_DISABLED_VALUE_BIT_SHIFT 0x0UL
#define CC_SECURITY_DISABLED_VALUE_BIT_SIZE 0x1UL #define CC_SECURITY_DISABLED_VALUE_BIT_SIZE 0x1UL
......
...@@ -49,6 +49,11 @@ int cc_pm_resume(struct device *dev) ...@@ -49,6 +49,11 @@ int cc_pm_resume(struct device *dev)
dev_err(dev, "failed getting clock back on. We're toast.\n"); dev_err(dev, "failed getting clock back on. We're toast.\n");
return rc; return rc;
} }
/* wait for Crytpcell reset completion */
if (!cc_wait_for_reset_completion(drvdata)) {
dev_err(dev, "Cryptocell reset not completed");
return -EBUSY;
}
cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE);
rc = init_cc_regs(drvdata, false); rc = init_cc_regs(drvdata, false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment