diff options
Diffstat (limited to 'drivers/crypto/ccree/cc_driver.c')
| -rw-r--r-- | drivers/crypto/ccree/cc_driver.c | 120 | 
1 files changed, 97 insertions, 23 deletions
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 3bcc6c76e090..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]; @@ -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; +		} +		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;  		} -		dev_dbg(dev, "CC SIGNATURE=0x%08X\n", signature_val); +		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) {  | 
