示例#1
0
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;
}
示例#2
0
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;
}