in ccree/cc_driver.c [307:581]
static int init_cc_resources(struct platform_device *plat_dev)
{
struct resource *req_mem_cc_regs = NULL;
struct cc_drvdata *new_drvdata;
struct device *dev = &plat_dev->dev;
struct device_node *np = dev->of_node;
u32 val, hw_rev_pidr, sig_cidr;
u64 dma_mask;
const struct cc_hw_data *hw_rev;
struct clk *clk;
int irq;
int rc = 0;
new_drvdata = devm_kzalloc(dev, sizeof(*new_drvdata), GFP_KERNEL);
if (!new_drvdata)
return -ENOMEM;
hw_rev = of_device_get_match_data(dev);
new_drvdata->hw_rev_name = hw_rev->name;
new_drvdata->hw_rev = hw_rev->rev;
new_drvdata->std_bodies = hw_rev->std_bodies;
if (hw_rev->rev >= CC_HW_REV_712) {
new_drvdata->axim_mon_offset = CC_REG(AXIM_MON_COMP);
new_drvdata->sig_offset = CC_REG(HOST_SIGNATURE_712);
new_drvdata->ver_offset = CC_REG(HOST_VERSION_712);
} else {
new_drvdata->axim_mon_offset = CC_REG(AXIM_MON_COMP8);
new_drvdata->sig_offset = CC_REG(HOST_SIGNATURE_630);
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;
clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "Error getting clock\n");
new_drvdata->clk = clk;
new_drvdata->coherent = of_dma_is_coherent(np);
/* Get device resources */
/* First CC registers space */
req_mem_cc_regs = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
/* Map registers space */
new_drvdata->cc_base = devm_ioremap_resource(dev, req_mem_cc_regs);
if (IS_ERR(new_drvdata->cc_base))
return PTR_ERR(new_drvdata->cc_base);
dev_dbg(dev, "Got MEM resource (%s): %pR\n", req_mem_cc_regs->name,
req_mem_cc_regs);
dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n",
&req_mem_cc_regs->start, new_drvdata->cc_base);
/* Then IRQ */
irq = platform_get_irq(plat_dev, 0);
if (irq < 0)
return irq;
init_completion(&new_drvdata->hw_queue_avail);
if (!dev->dma_mask)
dev->dma_mask = &dev->coherent_dma_mask;
dma_mask = DMA_BIT_MASK(DMA_BIT_MASK_LEN);
while (dma_mask > 0x7fffffffUL) {
if (dma_supported(dev, dma_mask)) {
rc = dma_set_coherent_mask(dev, dma_mask);
if (!rc)
break;
}
dma_mask >>= 1;
}
if (rc) {
dev_err(dev, "Failed in dma_set_mask, mask=%llx\n", dma_mask);
return rc;
}
rc = clk_prepare_enable(new_drvdata->clk);
if (rc) {
dev_err(dev, "Failed to enable clock");
return rc;
}
new_drvdata->sec_disabled = cc_sec_disable;
pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
rc = pm_runtime_get_sync(dev);
if (rc < 0) {
dev_err(dev, "pm_runtime_get_sync() failed: %d\n", rc);
goto post_pm_err;
}
/* Wait for Cryptocell 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) {
/* Verify correct mapping */
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",
val, hw_rev->sig);
rc = -EINVAL;
goto post_pm_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_pm_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_pm_err;
}
sig_cidr = val;
/* Check HW engine configuration */
val = cc_ioread(new_drvdata, CC_REG(HOST_REMOVE_INPUT_PINS));
switch (val) {
case CC_PINS_FULL:
/* This is fine */
break;
case CC_PINS_SLIM:
if (new_drvdata->std_bodies & CC_STD_NIST) {
dev_warn(dev, "703 mode forced due to HW configuration.\n");
new_drvdata->std_bodies = CC_STD_OSCCA;
}
break;
default:
dev_err(dev, "Unsupported engines configuration.\n");
rc = -EINVAL;
goto post_pm_err;
}
/* 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/0x%8X, Driver version %s\n",
hw_rev->name, hw_rev_pidr, sig_cidr, DRV_MODULE_VERSION);
/* register the driver isr function */
rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "ccree",
new_drvdata);
if (rc) {
dev_err(dev, "Could not register to interrupt %d\n", irq);
goto post_pm_err;
}
dev_dbg(dev, "Registered to IRQ: %d\n", irq);
init_cc_cache_params(new_drvdata);
rc = init_cc_regs(new_drvdata);
if (rc) {
dev_err(dev, "init_cc_regs failed\n");
goto post_pm_err;
}
rc = cc_debugfs_init(new_drvdata);
if (rc) {
dev_err(dev, "Failed registering debugfs interface\n");
goto post_regs_err;
}
rc = cc_fips_init(new_drvdata);
if (rc) {
dev_err(dev, "cc_fips_init failed 0x%x\n", rc);
goto post_debugfs_err;
}
rc = cc_sram_mgr_init(new_drvdata);
if (rc) {
dev_err(dev, "cc_sram_mgr_init failed\n");
goto post_fips_init_err;
}
new_drvdata->mlli_sram_addr =
cc_sram_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE);
if (new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR) {
rc = -ENOMEM;
goto post_fips_init_err;
}
rc = cc_req_mgr_init(new_drvdata);
if (rc) {
dev_err(dev, "cc_req_mgr_init failed\n");
goto post_fips_init_err;
}
rc = cc_buffer_mgr_init(new_drvdata);
if (rc) {
dev_err(dev, "cc_buffer_mgr_init failed\n");
goto post_req_mgr_err;
}
/* Allocate crypto algs */
rc = cc_cipher_alloc(new_drvdata);
if (rc) {
dev_err(dev, "cc_cipher_alloc failed\n");
goto post_buf_mgr_err;
}
/* hash must be allocated before aead since hash exports APIs */
rc = cc_hash_alloc(new_drvdata);
if (rc) {
dev_err(dev, "cc_hash_alloc failed\n");
goto post_cipher_err;
}
rc = cc_aead_alloc(new_drvdata);
if (rc) {
dev_err(dev, "cc_aead_alloc failed\n");
goto post_hash_err;
}
/* If we got here and FIPS mode is enabled
* it means all FIPS test passed, so let TEE
* know we're good.
*/
cc_set_ree_fips_status(new_drvdata, true);
pm_runtime_put(dev);
return 0;
post_hash_err:
cc_hash_free(new_drvdata);
post_cipher_err:
cc_cipher_free(new_drvdata);
post_buf_mgr_err:
cc_buffer_mgr_fini(new_drvdata);
post_req_mgr_err:
cc_req_mgr_fini(new_drvdata);
post_fips_init_err:
cc_fips_fini(new_drvdata);
post_debugfs_err:
cc_debugfs_fini(new_drvdata);
post_regs_err:
fini_cc_regs(new_drvdata);
post_pm_err:
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
clk_disable_unprepare(new_drvdata->clk);
return rc;
}