Example #1
0
int smmu_driver_probe(struct platform_device *pdev)
{
	static void __iomem *regs_base;
	struct resource *r;
	struct smmu_device *smmu_dev = pdev->dev.platform_data;
	struct clk *smmu_clk = NULL;
	int irq = 0;
	int ret;
	int ncb, nm2v;
	struct smmu_driver *drv = NULL;
	resource_size_t	len;

	if (pdev->id != -1) {
		if (!smmu_dev) {
			pr_err("smmu device lacks platform data\n");
			goto fail_nodev;
		}

		if (smmu_dev->clk) {
			smmu_clk = clk_get(NULL, smmu_dev->clk);

			if (!smmu_clk) {
				pr_err("clock defined but not present\n");
				goto fail_nodev;
			}

			if (smmu_dev->clk_rate != 0)
				clk_set_rate(smmu_clk, smmu_dev->clk_rate);

			clk_enable(smmu_clk);
			clk_put(smmu_clk);
		}

		drv = kzalloc(sizeof(struct smmu_driver), GFP_KERNEL);

		if (!drv) {
			pr_err("could not allocate memory\n");
			goto fail_nomem;
		}

		r = platform_get_resource_byname(pdev,
						 IORESOURCE_MEM,
						 "physbase");
		if (!r) {
			pr_err("could not get resources\n");
			goto fail_nodev;
		}

		len = r->end - r->start + 1;

		r = request_mem_region(r->start, len, r->name);
		if (!r) {
			pr_err("could not request memory region: "
			"start=%p, len=%d\n", (void *) r->start, len);
			goto fail_busy;
		}

		regs_base = ioremap(r->start, len);

		if (!regs_base) {
			pr_err("could not ioremap: start=%p, len=%d\n",
				 (void *) r->start, len);
			goto fail_busy;
		}

		irq = platform_get_irq_byname(pdev, "secure_irq");
		if (irq < 0) {
			pr_err("could not retrieve irq\n");
			goto fail_nodev;
		}

		mb();

		if (GET_IDR((unsigned long) regs_base) == 0) {
			pr_err("IDR reads as 0\n");
			goto fail_nodev;
		}

		ret = smmu_drvdata_init(drv, (unsigned long) regs_base, irq);
		if (ret != 0) {
			pr_err("could not init drvdata: error %d\n", ret);
			goto fail_nodev;
		}

		nm2v = GET_NM2VCBMT((unsigned long) regs_base);
		ncb = GET_NCB((unsigned long) regs_base);

		printk(KERN_INFO "Registered driver for %s at %lx, "
				 "irq %d (%d cb, %d m2v) \n",
		       pdev->name, (unsigned long) regs_base,
		       irq, ncb+1, nm2v+1);

		platform_set_drvdata(pdev, drv);
	} else {
		printk(KERN_INFO "Registered SMMU root device.\n");
		ret = vcm_setup_tex_classes();

		if (ret != 0) {
			pr_err("vcm_setup_tex_classes: returned %d\n", ret);
			goto fail_nodev;
		}
		all_smmus = pdev;
	}

	return 0;

fail_busy:
	kfree(drv);
	return -EBUSY;

fail_nodev:
	kfree(drv);
	return -ENODEV;

fail_nomem:
	return -ENOMEM;
}
static int msm_iommu_probe(struct platform_device *pdev)
{
	struct resource *r;
	struct clk *iommu_clk;
	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 = 0, ncb, nm2v, irq;

	if (pdev->id != -1) {
		drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);

		if (!drvdata) {
			ret = -ENOMEM;
			goto fail;
		}

		if (!iommu_dev) {
			ret = -ENODEV;
			goto fail;
		}

		if (iommu_dev->clk_rate != 0) {
			iommu_clk = clk_get(&pdev->dev, "iommu_clk");

			if (IS_ERR(iommu_clk)) {
				ret = -ENODEV;
				goto fail;
			}

			if (iommu_dev->clk_rate > 0) {
				ret = clk_set_rate(iommu_clk,
							iommu_dev->clk_rate);
				if (ret) {
					clk_put(iommu_clk);
					goto fail;
				}
			}

			ret = clk_enable(iommu_clk);
			if (ret) {
				clk_put(iommu_clk);
				goto fail;
			}
			clk_put(iommu_clk);
		}

		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						 "physbase");
		if (!r) {
			ret = -ENODEV;
			goto fail;
		}

		len = r->end - r->start + 1;

		r = request_mem_region(r->start, len, r->name);
		if (!r) {
			pr_err("Could not request memory region: "
			"start=%p, len=%d\n", (void *) r->start, len);
			ret = -EBUSY;
			goto fail;
		}

		regs_base = ioremap(r->start, len);

		if (!regs_base) {
			pr_err("Could not ioremap: start=%p, len=%d\n",
				 (void *) r->start, len);
			ret = -EBUSY;
			goto fail;
		}

		irq = platform_get_irq_byname(pdev, "secure_irq");
		if (irq < 0) {
			ret = -ENODEV;
			goto fail;
		}

		mb();

		if (GET_IDR(regs_base) == 0) {
			pr_err("Invalid IDR value detected\n");
			ret = -ENODEV;
			goto fail;
		}

		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;
		}

		msm_iommu_reset(regs_base);
		drvdata->base = regs_base;
		drvdata->irq = irq;

		nm2v = GET_NM2VCBMT((unsigned long) regs_base);
		ncb = GET_NCB((unsigned long) regs_base);

		pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
			iommu_dev->name, regs_base, irq, ncb+1);

		platform_set_drvdata(pdev, drvdata);
	} else
		msm_iommu_root_dev = pdev;

	return 0;

fail:
	kfree(drvdata);
	return ret;
}