diff options
Diffstat (limited to 'drivers/crypto/ccree/cc_driver.c')
-rw-r--r-- | drivers/crypto/ccree/cc_driver.c | 140 |
1 files changed, 105 insertions, 35 deletions
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 8ada308d72ee..86ac7b443355 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */ +/* Copyright (C) 2012-2019 ARM Limited or its affiliates. */ #include <linux/kernel.h> #include <linux/module.h> @@ -30,27 +30,47 @@ bool cc_dump_desc; module_param_named(dump_desc, cc_dump_desc, bool, 0600); MODULE_PARM_DESC(cc_dump_desc, "Dump descriptors to kernel log as debugging aid"); - bool cc_dump_bytes; module_param_named(dump_bytes, cc_dump_bytes, bool, 0600); MODULE_PARM_DESC(cc_dump_bytes, "Dump buffers to kernel log as debugging aid"); +static bool cc_sec_disable; +module_param_named(sec_disable, cc_sec_disable, bool, 0600); +MODULE_PARM_DESC(cc_sec_disable, "Disable security functions"); + struct cc_hw_data { char *name; enum cc_hw_rev rev; u32 sig; + u32 cidr_0123; + u32 pidr_0124; int std_bodies; }; +#define CC_NUM_IDRS 4 + +/* Note: PIDR3 holds CMOD/Rev so ignored for HW identification purposes */ +static const u32 pidr_0124_offsets[CC_NUM_IDRS] = { + CC_REG(PERIPHERAL_ID_0), CC_REG(PERIPHERAL_ID_1), + CC_REG(PERIPHERAL_ID_2), CC_REG(PERIPHERAL_ID_4) +}; + +static const u32 cidr_0123_offsets[CC_NUM_IDRS] = { + CC_REG(COMPONENT_ID_0), CC_REG(COMPONENT_ID_1), + CC_REG(COMPONENT_ID_2), CC_REG(COMPONENT_ID_3) +}; + /* Hardware revisions defs. */ /* The 703 is a OSCCA only variant of the 713 */ static const struct cc_hw_data cc703_hw = { - .name = "703", .rev = CC_HW_REV_713, .std_bodies = CC_STD_OSCCA + .name = "703", .rev = CC_HW_REV_713, .cidr_0123 = 0xB105F00DU, + .pidr_0124 = 0x040BB0D0U, .std_bodies = CC_STD_OSCCA }; static const struct cc_hw_data cc713_hw = { - .name = "713", .rev = CC_HW_REV_713, .std_bodies = CC_STD_ALL + .name = "713", .rev = CC_HW_REV_713, .cidr_0123 = 0xB105F00DU, + .pidr_0124 = 0x040BB0D0U, .std_bodies = CC_STD_ALL }; static const struct cc_hw_data cc712_hw = { @@ -78,6 +98,20 @@ static const struct of_device_id arm_ccree_dev_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_ccree_dev_of_match); +static u32 cc_read_idr(struct cc_drvdata *drvdata, const u32 *idr_offsets) +{ + int i; + union { + u8 regs[CC_NUM_IDRS]; + __le32 val; + } idr; + + for (i = 0; i < CC_NUM_IDRS; ++i) + idr.regs[i] = cc_ioread(drvdata, idr_offsets[i]); + + return le32_to_cpu(idr.val); +} + void __dump_byte_array(const char *name, const u8 *buf, size_t len) { char prefix[64]; @@ -103,10 +137,10 @@ static irqreturn_t cc_isr(int irq, void *dev_id) /* read the interrupt status */ irr = cc_ioread(drvdata, CC_REG(HOST_IRR)); dev_dbg(dev, "Got IRR=0x%08X\n", irr); - if (irr == 0) { /* Probably shared interrupt line */ - dev_err(dev, "Got interrupt with empty IRR\n"); + + if (irr == 0) /* Probably shared interrupt line */ return IRQ_NONE; - } + imr = cc_ioread(drvdata, CC_REG(HOST_IMR)); /* clear interrupt - must be before processing events */ @@ -114,12 +148,12 @@ static irqreturn_t cc_isr(int irq, void *dev_id) drvdata->irq = irr; /* Completion interrupt - most probable */ - if (irr & CC_COMP_IRQ_MASK) { - /* Mask AXI completion interrupt - will be unmasked in - * Deferred service handler + if (irr & drvdata->comp_mask) { + /* Mask all completion interrupts - will be unmasked in + * deferred service handler */ - cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | CC_COMP_IRQ_MASK); - irr &= ~CC_COMP_IRQ_MASK; + cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | drvdata->comp_mask); + irr &= ~drvdata->comp_mask; complete_request(drvdata); } #ifdef CONFIG_CRYPTO_FIPS @@ -159,11 +193,14 @@ int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe) unsigned int val, cache_params; struct device *dev = drvdata_to_dev(drvdata); - /* Unmask all AXI interrupt sources AXI_CFG1 register */ - val = cc_ioread(drvdata, CC_REG(AXIM_CFG)); - cc_iowrite(drvdata, CC_REG(AXIM_CFG), val & ~CC_AXI_IRQ_MASK); - dev_dbg(dev, "AXIM_CFG=0x%08X\n", - cc_ioread(drvdata, CC_REG(AXIM_CFG))); + /* Unmask all AXI interrupt sources AXI_CFG1 register */ + /* AXI interrupt config are obsoleted startign at cc7x3 */ + if (drvdata->hw_rev <= CC_HW_REV_712) { + val = cc_ioread(drvdata, CC_REG(AXIM_CFG)); + cc_iowrite(drvdata, CC_REG(AXIM_CFG), val & ~CC_AXI_IRQ_MASK); + dev_dbg(dev, "AXIM_CFG=0x%08X\n", + cc_ioread(drvdata, CC_REG(AXIM_CFG))); + } /* Clear all pending interrupts */ val = cc_ioread(drvdata, CC_REG(HOST_IRR)); @@ -171,7 +208,7 @@ int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe) cc_iowrite(drvdata, CC_REG(HOST_ICR), val); /* Unmask relevant interrupt cause */ - val = CC_COMP_IRQ_MASK | CC_AXI_ERR_IRQ_MASK; + val = drvdata->comp_mask | CC_AXI_ERR_IRQ_MASK; if (drvdata->hw_rev >= CC_HW_REV_712) val |= CC_GPR0_IRQ_MASK; @@ -201,7 +238,7 @@ static int init_cc_resources(struct platform_device *plat_dev) struct cc_drvdata *new_drvdata; struct device *dev = &plat_dev->dev; struct device_node *np = dev->of_node; - u32 signature_val; + u32 val, hw_rev_pidr, sig_cidr; u64 dma_mask; const struct cc_hw_data *hw_rev; const struct of_device_id *dev_id; @@ -231,6 +268,8 @@ static int init_cc_resources(struct platform_device *plat_dev) new_drvdata->ver_offset = CC_REG(HOST_VERSION_630); } + new_drvdata->comp_mask = CC_COMP_IRQ_MASK; + platform_set_drvdata(plat_dev, new_drvdata); new_drvdata->plat_dev = plat_dev; @@ -311,22 +350,57 @@ static int init_cc_resources(struct platform_device *plat_dev) return rc; } + new_drvdata->sec_disabled = cc_sec_disable; + if (hw_rev->rev <= CC_HW_REV_712) { /* Verify correct mapping */ - signature_val = cc_ioread(new_drvdata, new_drvdata->sig_offset); - if (signature_val != hw_rev->sig) { + val = cc_ioread(new_drvdata, new_drvdata->sig_offset); + if (val != hw_rev->sig) { dev_err(dev, "Invalid CC signature: SIGNATURE=0x%08X != expected=0x%08X\n", - signature_val, hw_rev->sig); + val, hw_rev->sig); rc = -EINVAL; goto post_clk_err; } - dev_dbg(dev, "CC SIGNATURE=0x%08X\n", signature_val); + sig_cidr = val; + hw_rev_pidr = cc_ioread(new_drvdata, new_drvdata->ver_offset); + } else { + /* Verify correct mapping */ + val = cc_read_idr(new_drvdata, pidr_0124_offsets); + if (val != hw_rev->pidr_0124) { + dev_err(dev, "Invalid CC PIDR: PIDR0124=0x%08X != expected=0x%08X\n", + val, hw_rev->pidr_0124); + rc = -EINVAL; + goto post_clk_err; + } + hw_rev_pidr = val; + + val = cc_read_idr(new_drvdata, cidr_0123_offsets); + if (val != hw_rev->cidr_0123) { + dev_err(dev, "Invalid CC CIDR: CIDR0123=0x%08X != expected=0x%08X\n", + val, hw_rev->cidr_0123); + rc = -EINVAL; + goto post_clk_err; + } + sig_cidr = val; + + /* Check security disable state */ + val = cc_ioread(new_drvdata, CC_REG(SECURITY_DISABLED)); + val &= CC_SECURITY_DISABLED_MASK; + new_drvdata->sec_disabled |= !!val; + + if (!new_drvdata->sec_disabled) { + new_drvdata->comp_mask |= CC_CPP_SM4_ABORT_MASK; + if (new_drvdata->std_bodies & CC_STD_NIST) + new_drvdata->comp_mask |= CC_CPP_AES_ABORT_MASK; + } } + if (new_drvdata->sec_disabled) + dev_info(dev, "Security Disabled mode is in effect. Security functions disabled.\n"); + /* Display HW versions */ - dev_info(dev, "ARM CryptoCell %s Driver: HW version 0x%08X, Driver version %s\n", - hw_rev->name, cc_ioread(new_drvdata, new_drvdata->ver_offset), - DRV_MODULE_VERSION); + dev_info(dev, "ARM CryptoCell %s Driver: HW version 0x%08X/0x%8X, Driver version %s\n", + hw_rev->name, hw_rev_pidr, sig_cidr, DRV_MODULE_VERSION); rc = init_cc_regs(new_drvdata, true); if (rc) { @@ -380,7 +454,7 @@ static int init_cc_resources(struct platform_device *plat_dev) rc = cc_ivgen_init(new_drvdata); if (rc) { dev_err(dev, "cc_ivgen_init failed\n"); - goto post_power_mgr_err; + goto post_buf_mgr_err; } /* Allocate crypto algs */ @@ -403,6 +477,9 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_hash_err; } + /* All set, we can allow autosuspend */ + cc_pm_go(new_drvdata); + /* If we got here and FIPS mode is enabled * it means all FIPS test passed, so let TEE * know we're good. @@ -417,8 +494,6 @@ post_cipher_err: cc_cipher_free(new_drvdata); post_ivgen_err: cc_ivgen_fini(new_drvdata); -post_power_mgr_err: - cc_pm_fini(new_drvdata); post_buf_mgr_err: cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: @@ -538,13 +613,8 @@ static struct platform_driver ccree_driver = { static int __init ccree_init(void) { - int ret; - cc_hash_global_init(); - - ret = cc_debugfs_global_init(); - if (ret) - return ret; + cc_debugfs_global_init(); return platform_driver_register(&ccree_driver); } |