diff options
Diffstat (limited to 'drivers/crypto/caam/ctrl.c')
| -rw-r--r-- | drivers/crypto/caam/ctrl.c | 255 | 
1 files changed, 133 insertions, 122 deletions
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 4e43ca4d3656..db22777d59b4 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -26,16 +26,6 @@ EXPORT_SYMBOL(caam_dpaa2);  #endif  /* - * i.MX targets tend to have clock control subsystems that can - * enable/disable clocking to our device. - */ -static inline struct clk *caam_drv_identify_clk(struct device *dev, -						char *clk_name) -{ -	return caam_imx ? devm_clk_get(dev, clk_name) : NULL; -} - -/*   * Descriptor to instantiate RNG State Handle 0 in normal mode and   * load the JDKEK, TDKEK and TDSK registers   */ @@ -107,7 +97,12 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,  	int i; -	if (ctrlpriv->virt_en == 1) { +	if (ctrlpriv->virt_en == 1 || +	    /* +	     * Apparently on i.MX8MQ it doesn't matter if virt_en == 1 +	     * and the following steps should be performed regardless +	     */ +	    of_machine_is_compatible("fsl,imx8mq")) {  		clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);  		while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) && @@ -342,13 +337,6 @@ static int caam_remove(struct platform_device *pdev)  	/* Unmap controller region */  	iounmap(ctrl); -	/* shut clocks off before finalizing shutdown */ -	clk_disable_unprepare(ctrlpriv->caam_ipg); -	if (ctrlpriv->caam_mem) -		clk_disable_unprepare(ctrlpriv->caam_mem); -	clk_disable_unprepare(ctrlpriv->caam_aclk); -	if (ctrlpriv->caam_emi_slow) -		clk_disable_unprepare(ctrlpriv->caam_emi_slow);  	return 0;  } @@ -497,20 +485,99 @@ static const struct of_device_id caam_match[] = {  };  MODULE_DEVICE_TABLE(of, caam_match); +struct caam_imx_data { +	const struct clk_bulk_data *clks; +	int num_clks; +}; + +static const struct clk_bulk_data caam_imx6_clks[] = { +	{ .id = "ipg" }, +	{ .id = "mem" }, +	{ .id = "aclk" }, +	{ .id = "emi_slow" }, +}; + +static const struct caam_imx_data caam_imx6_data = { +	.clks = caam_imx6_clks, +	.num_clks = ARRAY_SIZE(caam_imx6_clks), +}; + +static const struct clk_bulk_data caam_imx7_clks[] = { +	{ .id = "ipg" }, +	{ .id = "aclk" }, +}; + +static const struct caam_imx_data caam_imx7_data = { +	.clks = caam_imx7_clks, +	.num_clks = ARRAY_SIZE(caam_imx7_clks), +}; + +static const struct clk_bulk_data caam_imx6ul_clks[] = { +	{ .id = "ipg" }, +	{ .id = "mem" }, +	{ .id = "aclk" }, +}; + +static const struct caam_imx_data caam_imx6ul_data = { +	.clks = caam_imx6ul_clks, +	.num_clks = ARRAY_SIZE(caam_imx6ul_clks), +}; + +static const struct soc_device_attribute caam_imx_soc_table[] = { +	{ .soc_id = "i.MX6UL", .data = &caam_imx6ul_data }, +	{ .soc_id = "i.MX6*",  .data = &caam_imx6_data }, +	{ .soc_id = "i.MX7*",  .data = &caam_imx7_data }, +	{ .soc_id = "i.MX8MQ", .data = &caam_imx7_data }, +	{ .family = "Freescale i.MX" }, +	{ /* sentinel */ } +}; + +static void disable_clocks(void *data) +{ +	struct caam_drv_private *ctrlpriv = data; + +	clk_bulk_disable_unprepare(ctrlpriv->num_clks, ctrlpriv->clks); +} + +static int init_clocks(struct device *dev, const struct caam_imx_data *data) +{ +	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); +	int ret; + +	ctrlpriv->num_clks = data->num_clks; +	ctrlpriv->clks = devm_kmemdup(dev, data->clks, +				      data->num_clks * sizeof(data->clks[0]), +				      GFP_KERNEL); +	if (!ctrlpriv->clks) +		return -ENOMEM; + +	ret = devm_clk_bulk_get(dev, ctrlpriv->num_clks, ctrlpriv->clks); +	if (ret) { +		dev_err(dev, +			"Failed to request all necessary clocks\n"); +		return ret; +	} + +	ret = clk_bulk_prepare_enable(ctrlpriv->num_clks, ctrlpriv->clks); +	if (ret) { +		dev_err(dev, +			"Failed to prepare/enable all necessary clocks\n"); +		return ret; +	} + +	return devm_add_action_or_reset(dev, disable_clocks, ctrlpriv); +} +  /* Probe routine for CAAM top (controller) level */  static int caam_probe(struct platform_device *pdev)  {  	int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;  	u64 caam_id; -	static const struct soc_device_attribute imx_soc[] = { -		{.family = "Freescale i.MX"}, -		{}, -	}; +	const struct soc_device_attribute *imx_soc_match;  	struct device *dev;  	struct device_node *nprop, *np;  	struct caam_ctrl __iomem *ctrl;  	struct caam_drv_private *ctrlpriv; -	struct clk *clk;  #ifdef CONFIG_DEBUG_FS  	struct caam_perfmon *perfmon;  #endif @@ -527,103 +594,68 @@ static int caam_probe(struct platform_device *pdev)  	dev_set_drvdata(dev, ctrlpriv);  	nprop = pdev->dev.of_node; -	caam_imx = (bool)soc_device_match(imx_soc); +	imx_soc_match = soc_device_match(caam_imx_soc_table); +	caam_imx = (bool)imx_soc_match; -	/* Enable clocking */ -	clk = caam_drv_identify_clk(&pdev->dev, "ipg"); -	if (IS_ERR(clk)) { -		ret = PTR_ERR(clk); -		dev_err(&pdev->dev, -			"can't identify CAAM ipg clk: %d\n", ret); -		return ret; -	} -	ctrlpriv->caam_ipg = clk; - -	if (!of_machine_is_compatible("fsl,imx7d") && -	    !of_machine_is_compatible("fsl,imx7s") && -	    !of_machine_is_compatible("fsl,imx7ulp")) { -		clk = caam_drv_identify_clk(&pdev->dev, "mem"); -		if (IS_ERR(clk)) { -			ret = PTR_ERR(clk); -			dev_err(&pdev->dev, -				"can't identify CAAM mem clk: %d\n", ret); -			return ret; +	if (imx_soc_match) { +		if (!imx_soc_match->data) { +			dev_err(dev, "No clock data provided for i.MX SoC"); +			return -EINVAL;  		} -		ctrlpriv->caam_mem = clk; -	} -	clk = caam_drv_identify_clk(&pdev->dev, "aclk"); -	if (IS_ERR(clk)) { -		ret = PTR_ERR(clk); -		dev_err(&pdev->dev, -			"can't identify CAAM aclk clk: %d\n", ret); -		return ret; -	} -	ctrlpriv->caam_aclk = clk; - -	if (!of_machine_is_compatible("fsl,imx6ul") && -	    !of_machine_is_compatible("fsl,imx7d") && -	    !of_machine_is_compatible("fsl,imx7s") && -	    !of_machine_is_compatible("fsl,imx7ulp")) { -		clk = caam_drv_identify_clk(&pdev->dev, "emi_slow"); -		if (IS_ERR(clk)) { -			ret = PTR_ERR(clk); -			dev_err(&pdev->dev, -				"can't identify CAAM emi_slow clk: %d\n", ret); +		ret = init_clocks(dev, imx_soc_match->data); +		if (ret)  			return ret; -		} -		ctrlpriv->caam_emi_slow = clk; -	} - -	ret = clk_prepare_enable(ctrlpriv->caam_ipg); -	if (ret < 0) { -		dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret); -		return ret; -	} - -	if (ctrlpriv->caam_mem) { -		ret = clk_prepare_enable(ctrlpriv->caam_mem); -		if (ret < 0) { -			dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n", -				ret); -			goto disable_caam_ipg; -		}  	} -	ret = clk_prepare_enable(ctrlpriv->caam_aclk); -	if (ret < 0) { -		dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret); -		goto disable_caam_mem; -	} - -	if (ctrlpriv->caam_emi_slow) { -		ret = clk_prepare_enable(ctrlpriv->caam_emi_slow); -		if (ret < 0) { -			dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n", -				ret); -			goto disable_caam_aclk; -		} -	}  	/* Get configuration properties from device tree */  	/* First, get register page */  	ctrl = of_iomap(nprop, 0); -	if (ctrl == NULL) { +	if (!ctrl) {  		dev_err(dev, "caam: of_iomap() failed\n"); -		ret = -ENOMEM; -		goto disable_caam_emi_slow; +		return -ENOMEM;  	}  	caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) &  				  (CSTA_PLEND | CSTA_ALT_PLEND)); - -	/* Finding the page size for using the CTPR_MS register */  	comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms); -	pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT; +	if (comp_params & CTPR_MS_PS && rd_reg32(&ctrl->mcr) & MCFGR_LONG_PTR) +		caam_ptr_sz = sizeof(u64); +	else +		caam_ptr_sz = sizeof(u32); +	caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2); +	ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK); + +#ifdef CONFIG_CAAM_QI +	/* If (DPAA 1.x) QI present, check whether dependencies are available */ +	if (ctrlpriv->qi_present && !caam_dpaa2) { +		ret = qman_is_probed(); +		if (!ret) { +			ret = -EPROBE_DEFER; +			goto iounmap_ctrl; +		} else if (ret < 0) { +			dev_err(dev, "failing probe due to qman probe error\n"); +			ret = -ENODEV; +			goto iounmap_ctrl; +		} + +		ret = qman_portals_probed(); +		if (!ret) { +			ret = -EPROBE_DEFER; +			goto iounmap_ctrl; +		} else if (ret < 0) { +			dev_err(dev, "failing probe due to qman portals probe error\n"); +			ret = -ENODEV; +			goto iounmap_ctrl; +		} +	} +#endif  	/* Allocating the BLOCK_OFFSET based on the supported page size on  	 * the platform  	 */ +	pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT;  	if (pg_size == 0)  		BLOCK_OFFSET = PG_SIZE_4K;  	else @@ -648,7 +680,6 @@ static int caam_probe(struct platform_device *pdev)  	 * In case of SoCs with Management Complex, MC f/w performs  	 * the configuration.  	 */ -	caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2);  	np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-mc");  	ctrlpriv->mc_en = !!np;  	of_node_put(np); @@ -688,16 +719,7 @@ static int caam_probe(struct platform_device *pdev)  			      JRSTART_JR1_START | JRSTART_JR2_START |  			      JRSTART_JR3_START); -	if (sizeof(dma_addr_t) == sizeof(u64)) { -		if (caam_dpaa2) -			ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(49)); -		else if (of_device_is_compatible(nprop, "fsl,sec-v5.0")) -			ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); -		else -			ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36)); -	} else { -		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); -	} +	ret = dma_set_mask_and_coherent(dev, caam_get_dma_mask(dev));  	if (ret) {  		dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);  		goto iounmap_ctrl; @@ -719,7 +741,6 @@ static int caam_probe(struct platform_device *pdev)  #endif  	/* Check to see if (DPAA 1.x) QI present. If so, enable */ -	ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK);  	if (ctrlpriv->qi_present && !caam_dpaa2) {  		ctrlpriv->qi = (struct caam_queue_if __iomem __force *)  			       ((__force uint8_t *)ctrl + @@ -908,16 +929,6 @@ shutdown_qi:  #endif  iounmap_ctrl:  	iounmap(ctrl); -disable_caam_emi_slow: -	if (ctrlpriv->caam_emi_slow) -		clk_disable_unprepare(ctrlpriv->caam_emi_slow); -disable_caam_aclk: -	clk_disable_unprepare(ctrlpriv->caam_aclk); -disable_caam_mem: -	if (ctrlpriv->caam_mem) -		clk_disable_unprepare(ctrlpriv->caam_mem); -disable_caam_ipg: -	clk_disable_unprepare(ctrlpriv->caam_ipg);  	return ret;  }  |