static int msm_iommu_probe(struct platform_device *pdev) { struct resource *r, *r2; struct clk *iommu_clk = NULL; struct clk *iommu_pclk = NULL; struct msm_iommu_drvdata *drvdata; struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data; void __iomem *regs_base; resource_size_t len; int ret, par; if (pdev->id == -1) { msm_iommu_root_dev = pdev; return 0; } drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { ret = -ENOMEM; goto fail; } if (!iommu_dev) { ret = -ENODEV; goto fail; } iommu_pclk = clk_get_sys("msm_iommu", "iface_clk"); if (IS_ERR(iommu_pclk)) { ret = -ENODEV; goto fail; } ret = clk_prepare_enable(iommu_pclk); if (ret) goto fail_enable; iommu_clk = clk_get(&pdev->dev, "core_clk"); if (!IS_ERR(iommu_clk)) { if (clk_get_rate(iommu_clk) == 0) { ret = clk_round_rate(iommu_clk, 1); clk_set_rate(iommu_clk, ret); } ret = clk_prepare_enable(iommu_clk); if (ret) { clk_put(iommu_clk); goto fail_pclk; } } else iommu_clk = NULL; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase"); if (!r) { ret = -ENODEV; goto fail_clk; } len = resource_size(r); r2 = request_mem_region(r->start, len, r->name); if (!r2) { pr_err("Could not request memory region: start=%p, len=%d\n", (void *) r->start, len); ret = -EBUSY; goto fail_clk; } regs_base = ioremap(r2->start, len); if (!regs_base) { pr_err("Could not ioremap: start=%p, len=%d\n", (void *) r2->start, len); ret = -EBUSY; goto fail_mem; } msm_iommu_reset(regs_base, iommu_dev->ncb); SET_M(regs_base, 0, 1); SET_PAR(regs_base, 0, 0); SET_V2PCFG(regs_base, 0, 1); SET_V2PPR(regs_base, 0, 0); mb(); par = GET_PAR(regs_base, 0); SET_V2PCFG(regs_base, 0, 0); SET_M(regs_base, 0, 0); mb(); if (!par) { pr_err("%s: Invalid PAR value detected\n", iommu_dev->name); ret = -ENODEV; goto fail_io; } drvdata->pclk = iommu_pclk; drvdata->clk = iommu_clk; drvdata->base = regs_base; drvdata->ncb = iommu_dev->ncb; drvdata->ttbr_split = iommu_dev->ttbr_split; drvdata->name = iommu_dev->name; pr_info("device %s mapped at %p, with %d ctx banks\n", iommu_dev->name, regs_base, iommu_dev->ncb); platform_set_drvdata(pdev, drvdata); if (iommu_clk) clk_disable_unprepare(iommu_clk); clk_disable_unprepare(iommu_pclk); return 0; fail_io: iounmap(regs_base); fail_mem: release_mem_region(r->start, len); fail_clk: if (iommu_clk) { clk_disable_unprepare(iommu_clk); clk_put(iommu_clk); } fail_pclk: clk_disable_unprepare(iommu_pclk); fail_enable: clk_put(iommu_pclk); fail: kfree(drvdata); return ret; }
static int msm_iommu_probe(struct platform_device *pdev) { struct resource *r; struct clk *iommu_clk; struct clk *iommu_pclk; struct msm_iommu_drvdata *drvdata; struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data; void __iomem *regs_base; int ret, irq, par; if (pdev->id == -1) { msm_iommu_root_dev = pdev; return 0; } drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { ret = -ENOMEM; goto fail; } if (!iommu_dev) { ret = -ENODEV; goto fail; } iommu_pclk = clk_get(NULL, "smmu_pclk"); if (IS_ERR(iommu_pclk)) { ret = -ENODEV; goto fail; } ret = clk_prepare_enable(iommu_pclk); if (ret) goto fail_enable; iommu_clk = clk_get(&pdev->dev, "iommu_clk"); if (!IS_ERR(iommu_clk)) { if (clk_get_rate(iommu_clk) == 0) clk_set_rate(iommu_clk, 1); ret = clk_prepare_enable(iommu_clk); if (ret) { clk_put(iommu_clk); goto fail_pclk; } } else iommu_clk = NULL; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase"); regs_base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(regs_base)) { ret = PTR_ERR(regs_base); goto fail_clk; } irq = platform_get_irq_byname(pdev, "secure_irq"); if (irq < 0) { ret = -ENODEV; goto fail_clk; } msm_iommu_reset(regs_base, iommu_dev->ncb); SET_M(regs_base, 0, 1); SET_PAR(regs_base, 0, 0); SET_V2PCFG(regs_base, 0, 1); SET_V2PPR(regs_base, 0, 0); par = GET_PAR(regs_base, 0); SET_V2PCFG(regs_base, 0, 0); SET_M(regs_base, 0, 0); if (!par) { pr_err("%s: Invalid PAR value detected\n", iommu_dev->name); ret = -ENODEV; goto fail_clk; } ret = request_irq(irq, msm_iommu_fault_handler, 0, "msm_iommu_secure_irpt_handler", drvdata); if (ret) { pr_err("Request IRQ %d failed with ret=%d\n", irq, ret); goto fail_clk; } drvdata->pclk = iommu_pclk; drvdata->clk = iommu_clk; drvdata->base = regs_base; drvdata->irq = irq; drvdata->ncb = iommu_dev->ncb; pr_info("device %s mapped at %p, irq %d with %d ctx banks\n", iommu_dev->name, regs_base, irq, iommu_dev->ncb); platform_set_drvdata(pdev, drvdata); if (iommu_clk) clk_disable(iommu_clk); clk_disable(iommu_pclk); return 0; fail_clk: if (iommu_clk) { clk_disable(iommu_clk); clk_put(iommu_clk); } fail_pclk: clk_disable_unprepare(iommu_pclk); fail_enable: clk_put(iommu_pclk); fail: kfree(drvdata); return ret; }