static int __devinit msm_iommu_probe(struct platform_device *pdev) { struct iommu_pmon *pmon_info; struct msm_iommu_drvdata *drvdata; struct resource *r; int ret, needs_alt_core_clk; drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iommu_base"); if (!r) return -EINVAL; drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!drvdata->base) return -ENOMEM; drvdata->glb_base = drvdata->base; if (of_get_property(pdev->dev.of_node, "vdd-supply", NULL)) { drvdata->gdsc = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(drvdata->gdsc)) return PTR_ERR(drvdata->gdsc); drvdata->alt_gdsc = devm_regulator_get(&pdev->dev, "qcom,alt-vdd"); if (IS_ERR(drvdata->alt_gdsc)) drvdata->alt_gdsc = NULL; } else { pr_debug("Warning: No regulator specified for IOMMU\n"); } drvdata->pclk = devm_clk_get(&pdev->dev, "iface_clk"); if (IS_ERR(drvdata->pclk)) return PTR_ERR(drvdata->pclk); drvdata->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(drvdata->clk)) return PTR_ERR(drvdata->clk); needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node, "qcom,needs-alt-core-clk"); if (needs_alt_core_clk) { drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk"); if (IS_ERR(drvdata->aclk)) return PTR_ERR(drvdata->aclk); } if (clk_get_rate(drvdata->clk) == 0) { ret = clk_round_rate(drvdata->clk, 1000); clk_set_rate(drvdata->clk, ret); } if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) { ret = clk_round_rate(drvdata->aclk, 1000); clk_set_rate(drvdata->aclk, ret); } ret = msm_iommu_parse_dt(pdev, drvdata); if (ret) return ret; dev_info(&pdev->dev, "device %s mapped at %p, with %d ctx banks\n", drvdata->name, drvdata->base, drvdata->ncb); platform_set_drvdata(pdev, drvdata); pmon_info = msm_iommu_pm_alloc(&pdev->dev); if (pmon_info != NULL) { ret = msm_iommu_pmon_parse_dt(pdev, pmon_info); if (ret) { msm_iommu_pm_free(&pdev->dev); pr_info("%s: pmon not available.\n", drvdata->name); } else { pmon_info->iommu.base = drvdata->base; pmon_info->iommu.ops = msm_get_iommu_access_ops(); pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v1(); pmon_info->iommu.iommu_name = drvdata->name; ret = msm_iommu_pm_iommu_register(pmon_info); if (ret) { pr_err("%s iommu register fail\n", drvdata->name); msm_iommu_pm_free(&pdev->dev); } else { pr_debug("%s iommu registered for pmon\n", pmon_info->iommu.iommu_name); } } } return 0; }
static int msm_iommu_probe(struct platform_device *pdev) { struct iommu_pmon *pmon_info; struct msm_iommu_drvdata *drvdata; struct resource *r; int ret, needs_alt_core_clk, needs_alt_iface_clk; int global_cfg_irq, global_client_irq; u32 temp; drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iommu_base"); if (!r) return -EINVAL; drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!drvdata->base) return -ENOMEM; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smmu_local_base"); if (r) { drvdata->smmu_local_base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!drvdata->smmu_local_base) return -ENOMEM; } drvdata->glb_base = drvdata->base; if (of_get_property(pdev->dev.of_node, "vdd-supply", NULL)) { drvdata->gdsc = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(drvdata->gdsc)) return PTR_ERR(drvdata->gdsc); drvdata->alt_gdsc = devm_regulator_get(&pdev->dev, "qcom,alt-vdd"); if (IS_ERR(drvdata->alt_gdsc)) drvdata->alt_gdsc = NULL; } else { pr_debug("Warning: No regulator specified for IOMMU\n"); } drvdata->pclk = devm_clk_get(&pdev->dev, "iface_clk"); if (IS_ERR(drvdata->pclk)) return PTR_ERR(drvdata->pclk); drvdata->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(drvdata->clk)) return PTR_ERR(drvdata->clk); needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node, "qcom,needs-alt-core-clk"); if (needs_alt_core_clk) { drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk"); if (IS_ERR(drvdata->aclk)) return PTR_ERR(drvdata->aclk); } needs_alt_iface_clk = of_property_read_bool(pdev->dev.of_node, "qcom,needs-alt-iface-clk"); if (needs_alt_iface_clk) { drvdata->aiclk = devm_clk_get(&pdev->dev, "alt_iface_clk"); if (IS_ERR(drvdata->aclk)) return PTR_ERR(drvdata->aiclk); } drvdata->no_atos_support = of_property_read_bool(pdev->dev.of_node, "qcom,no-atos-support"); if (!of_property_read_u32(pdev->dev.of_node, "qcom,cb-base-offset", &temp)) drvdata->cb_base = drvdata->base + temp; else drvdata->cb_base = drvdata->base + 0x8000; if (clk_get_rate(drvdata->clk) == 0) { ret = clk_round_rate(drvdata->clk, 1000); clk_set_rate(drvdata->clk, ret); } if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) { ret = clk_round_rate(drvdata->aclk, 1000); clk_set_rate(drvdata->aclk, ret); } if (drvdata->aiclk && clk_get_rate(drvdata->aiclk) == 0) { ret = clk_round_rate(drvdata->aiclk, 1000); clk_set_rate(drvdata->aiclk, ret); } ret = msm_iommu_parse_dt(pdev, drvdata); if (ret) return ret; dev_info(&pdev->dev, "device %s mapped at %p, with %d ctx banks\n", drvdata->name, drvdata->base, drvdata->ncb); platform_set_drvdata(pdev, drvdata); pmon_info = msm_iommu_pm_alloc(&pdev->dev); if (pmon_info != NULL) { ret = msm_iommu_pmon_parse_dt(pdev, pmon_info); if (ret) { msm_iommu_pm_free(&pdev->dev); pr_info("%s: pmon not available.\n", drvdata->name); } else { pmon_info->iommu.base = drvdata->base; pmon_info->iommu.ops = msm_get_iommu_access_ops(); pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v1(); pmon_info->iommu.iommu_name = drvdata->name; ret = msm_iommu_pm_iommu_register(pmon_info); if (ret) { pr_err("%s iommu register fail\n", drvdata->name); msm_iommu_pm_free(&pdev->dev); } else { pr_debug("%s iommu registered for pmon\n", pmon_info->iommu.iommu_name); } } } global_cfg_irq = platform_get_irq_byname(pdev, "global_cfg_NS_irq"); if (global_cfg_irq > 0) { ret = devm_request_threaded_irq(&pdev->dev, global_cfg_irq, NULL, msm_iommu_global_fault_handler, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING, "msm_iommu_global_cfg_irq", pdev); if (ret < 0) pr_err("Request Global CFG IRQ %d failed with ret=%d\n", global_cfg_irq, ret); } global_client_irq = platform_get_irq_byname(pdev, "global_client_NS_irq"); if (global_client_irq > 0) { ret = devm_request_threaded_irq(&pdev->dev, global_client_irq, NULL, msm_iommu_global_fault_handler, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING, "msm_iommu_global_client_irq", pdev); if (ret < 0) pr_err("Request Global Client IRQ %d failed with ret=%d\n", global_client_irq, ret); } return 0; }
static int msm_iommu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct iommu_pmon *pmon_info; struct msm_iommu_drvdata *drvdata; struct resource *res; int ret; int global_cfg_irq, global_client_irq; u32 temp; unsigned long rate; if (!qcom_scm_is_available()) return -EPROBE_DEFER; msm_iommu_check_scm_call_avail(); msm_set_iommu_access_ops(&iommu_access_ops_v1); msm_iommu_sec_set_access_ops(&iommu_access_ops_v1); drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; drvdata->dev = dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iommu_base"); drvdata->base = devm_ioremap_resource(dev, res); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); drvdata->glb_base = drvdata->base; drvdata->phys_base = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smmu_local_base"); drvdata->smmu_local_base = devm_ioremap_resource(dev, res); if (IS_ERR(drvdata->smmu_local_base) && PTR_ERR(drvdata->smmu_local_base) != -EPROBE_DEFER) drvdata->smmu_local_base = NULL; if (of_device_is_compatible(np, "qcom,msm-mmu-500")) drvdata->model = MMU_500; drvdata->iface = devm_clk_get(dev, "iface_clk"); if (IS_ERR(drvdata->iface)) return PTR_ERR(drvdata->iface); drvdata->core = devm_clk_get(dev, "core_clk"); if (IS_ERR(drvdata->core)) return PTR_ERR(drvdata->core); if (!of_property_read_u32(np, "qcom,cb-base-offset", &temp)) drvdata->cb_base = drvdata->base + temp; else drvdata->cb_base = drvdata->base + 0x8000; rate = clk_get_rate(drvdata->core); if (!rate) { rate = clk_round_rate(drvdata->core, 1000); clk_set_rate(drvdata->core, rate); } dev_info(&pdev->dev, "iface: %lu, core: %lu\n", clk_get_rate(drvdata->iface), clk_get_rate(drvdata->core)); ret = msm_iommu_parse_dt(pdev, drvdata); if (ret) return ret; dev_info(dev, "device %s (model: %d) mapped at %p, with %d ctx banks\n", drvdata->name, drvdata->model, drvdata->base, drvdata->ncb); if (drvdata->sec_id != -1) { ret = msm_iommu_sec_ptbl_init(dev); if (ret) return ret; } platform_set_drvdata(pdev, drvdata); pmon_info = msm_iommu_pm_alloc(dev); if (pmon_info) { ret = msm_iommu_pmon_parse_dt(pdev, pmon_info); if (ret) { msm_iommu_pm_free(dev); dev_info(dev, "%s: pmon not available\n", drvdata->name); } else { pmon_info->iommu.base = drvdata->base; pmon_info->iommu.ops = msm_get_iommu_access_ops(); pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v1(); pmon_info->iommu.iommu_name = drvdata->name; ret = msm_iommu_pm_iommu_register(pmon_info); if (ret) { dev_err(dev, "%s iommu register fail\n", drvdata->name); msm_iommu_pm_free(dev); } else { dev_dbg(dev, "%s iommu registered for pmon\n", pmon_info->iommu.iommu_name); } } } global_cfg_irq = platform_get_irq_byname(pdev, "global_cfg_NS_irq"); if (global_cfg_irq < 0 && global_cfg_irq == -EPROBE_DEFER) return -EPROBE_DEFER; if (global_cfg_irq > 0) { ret = devm_request_threaded_irq(dev, global_cfg_irq, NULL, msm_iommu_global_fault_handler, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING, "msm_iommu_global_cfg_irq", pdev); if (ret < 0) dev_err(dev, "Request Global CFG IRQ %d failed with ret=%d\n", global_cfg_irq, ret); } global_client_irq = platform_get_irq_byname(pdev, "global_client_NS_irq"); if (global_client_irq < 0 && global_client_irq == -EPROBE_DEFER) return -EPROBE_DEFER; if (global_client_irq > 0) { ret = devm_request_threaded_irq(dev, global_client_irq, NULL, msm_iommu_global_fault_handler, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING, "msm_iommu_global_client_irq", pdev); if (ret < 0) dev_err(dev, "Request Global Client IRQ %d failed with ret=%d\n", global_client_irq, ret); } ret = of_platform_populate(np, msm_iommu_ctx_match_table, NULL, dev); if (ret) dev_err(dev, "Failed to create iommu context device\n"); return ret; }