From fedb4dd7eb53fd02ff50e7fc45b7ffa8c800e793 Mon Sep 17 00:00:00 2001 From: Steve Cornelius Date: Wed, 18 Apr 2012 14:23:34 -0700 Subject: [PATCH] ENGR00180943-11: Add non-device-tree platform property detection Add non-device-tree platform property detection for driver startup and initialization for iMX6 family, including clock control, job ring detection and initialization, and interrupt mapping. Signed-off-by: Steve Cornelius --- drivers/crypto/caam/ctrl.c | 129 ++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index efb490b8d59b..7c1132097c0f 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -22,6 +22,9 @@ static int caam_remove(struct platform_device *pdev) ctrlpriv = dev_get_drvdata(ctrldev); topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; +#ifndef CONFIG_OF + caam_algapi_shutdown(pdev); +#endif /* shut down JobRs */ for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) { ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]); @@ -37,6 +40,9 @@ static int caam_remove(struct platform_device *pdev) /* Unmap controller region */ iounmap(&topregs->ctrl); + /* shut clocks off before finalizing shutdown */ + clk_disable(ctrlpriv->caam_clk); + kfree(ctrlpriv->jrdev); kfree(ctrlpriv); @@ -48,7 +54,7 @@ static int caam_probe(struct platform_device *pdev) { int d, ring, rspec; struct device *dev; - struct device_node *nprop, *np; + struct device_node *np; struct caam_ctrl __iomem *ctrl; struct caam_full __iomem *topregs; struct caam_drv_private *ctrlpriv; @@ -57,6 +63,15 @@ static int caam_probe(struct platform_device *pdev) #ifdef CONFIG_DEBUG_FS struct caam_perfmon *perfmon; #endif +#ifdef CONFIG_OF + struct device_node *nprop; +#else + struct resource *res; + char *rname, inst; +#endif +#ifdef CONFIG_ARM + int ret = 0; +#endif ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL); if (!ctrlpriv) @@ -65,22 +80,71 @@ static int caam_probe(struct platform_device *pdev) dev = &pdev->dev; dev_set_drvdata(dev, ctrlpriv); ctrlpriv->pdev = pdev; - nprop = pdev->dev.of_node; /* Get configuration properties from device tree */ /* First, get register page */ +#ifdef CONFIG_OF + nprop = pdev->dev.of_node; ctrl = of_iomap(nprop, 0); if (ctrl == NULL) { dev_err(dev, "caam: of_iomap() failed\n"); return -ENOMEM; } +#else + /* Get the named resource for the controller base address */ + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "iobase_caam"); + if (!res) { + dev_err(dev, "caam: invalid address resource type\n"); + return -ENODEV; + } + ctrl = ioremap(res->start, SZ_64K); + if (ctrl == NULL) { + dev_err(dev, "caam: ioremap() failed\n"); + return -ENOMEM; + } +#endif + ctrlpriv->ctrl = (struct caam_ctrl __force *)ctrl; /* topregs used to derive pointers to CAAM sub-blocks only */ topregs = (struct caam_full __iomem *)ctrl; /* Get the IRQ of the controller (for security violations only) */ +#ifdef CONFIG_OF ctrlpriv->secvio_irq = of_irq_to_resource(nprop, 0, NULL); +#else + res = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "irq_sec_vio"); + if (!res) { + dev_err(dev, "caam: invalid IRQ resource type\n"); + return -ENODEV; + } + ctrlpriv->secvio_irq = res->start; +#endif + +/* + * ARM targets tend to have clock control subsystems that can + * enable/disable clocking to our device. Turn clocking on to proceed + */ +#ifdef CONFIG_ARM + ctrlpriv->caam_clk = clk_get(&ctrlpriv->pdev->dev, "caam_clk"); + if (IS_ERR(ctrlpriv->caam_clk)) { + ret = PTR_ERR(ctrlpriv->caam_clk); + dev_err(&ctrlpriv->pdev->dev, + "can't identify CAAM bus clk: %d\n", ret); + return -ENODEV; + } + + ret = clk_enable(ctrlpriv->caam_clk); + if (ret < 0) { + dev_err(&pdev->dev, "can't enable CAAM bus clock: %d\n", ret); + return -ENODEV; + } + + pr_debug("%s caam_clk:%d\n", __func__, + (int)clk_get_rate(ctrlpriv->caam_clk)); +#endif /* * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel, @@ -89,8 +153,11 @@ static int caam_probe(struct platform_device *pdev) setbits32(&topregs->ctrl.mcr, MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0)); + /* Set DMA masks according to platform ranging */ if (sizeof(dma_addr_t) == sizeof(u64)) dma_set_mask(dev, DMA_BIT_MASK(36)); + else + dma_set_mask(dev, DMA_BIT_MASK(32)); /* Find out how many DECOs are present */ deconum = (rd_reg64(&topregs->ctrl.perfmon.cha_num) & @@ -102,15 +169,41 @@ static int caam_probe(struct platform_device *pdev) deco = (struct caam_deco __force **)&topregs->deco; for (d = 0; d < deconum; d++) ctrlpriv->deco[d] = deco[d]; - /* * Detect and enable JobRs * First, find out how many ring spec'ed, allocate references * for all, then go probe each one. */ rspec = 0; +#ifdef CONFIG_OF for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") rspec++; +#else + np = NULL; + + /* Build the name of the IRQ platform resources to identify */ + rname = kzalloc(strlen(JR_IRQRES_NAME_ROOT) + 1, 0); + if (rname == NULL) { + iounmap(&topregs->ctrl); + return -ENOMEM; + } + + /* + * Emulate behavor of for_each_compatible_node() for non OF targets + * Identify all IRQ platform resources present + */ + for (d = 0; d < 4; d++) { + rname[0] = 0; + inst = '0' + d; + strcat(rname, JR_IRQRES_NAME_ROOT); + strncat(rname, &inst, 1); + res = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, rname); + if (res) + rspec++; + } + kfree(rname); +#endif ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL); if (ctrlpriv->jrdev == NULL) { iounmap(&topregs->ctrl); @@ -119,7 +212,11 @@ static int caam_probe(struct platform_device *pdev) ring = 0; ctrlpriv->total_jobrs = 0; +#ifdef CONFIG_OF for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") { +#else + for (d = 0; d < rspec; d++) { +#endif caam_jr_probe(pdev, np, ring); ctrlpriv->total_jobrs++; ring++; @@ -232,9 +329,22 @@ static int caam_probe(struct platform_device *pdev) ctrlpriv->ctl, &ctrlpriv->ctl_tdsk_wrap); #endif + +/* + * Non OF configurations use plaform_device, and therefore cannot simply + * go and get a device node by name, which the algapi module startup code + * assumes is possible. Therefore, non OF configurations will have to + * start up the API code explicitly, and forego modularization + */ +#ifndef CONFIG_OF + /* FIXME: check status */ + caam_algapi_startup(pdev); +#endif + return 0; } +#ifdef CONFIG_OF static struct of_device_id caam_match[] = { { .compatible = "fsl,sec-v4.0", @@ -242,12 +352,17 @@ static struct of_device_id caam_match[] = { {}, }; MODULE_DEVICE_TABLE(of, caam_match); +#endif /* CONFIG_OF */ static struct platform_driver caam_driver = { .driver = { .name = "caam", .owner = THIS_MODULE, +#ifdef CONFIG_OF .of_match_table = caam_match, +#else + +#endif }, .probe = caam_probe, .remove = __devexit_p(caam_remove), @@ -255,12 +370,20 @@ static struct platform_driver caam_driver = { static int __init caam_base_init(void) { +#ifdef CONFIG_OF + return of_register_platform_driver(&caam_driver); +#else return platform_driver_register(&caam_driver); +#endif } static void __exit caam_base_exit(void) { +#ifdef CONFIG_OF + return of_unregister_platform_driver(&caam_driver); +#else return platform_driver_unregister(&caam_driver); +#endif } module_init(caam_base_init); -- 2.39.5