static int mdss_pll_resource_parse(struct platform_device *pdev, struct mdss_pll_resources *pll_res) { int rc = 0; const char *compatible_stream; if (!pdev || !pll_res) { pr_err("Invalid input parameters\n"); return -EINVAL; } rc = mdss_pll_util_resource_parse(pdev, pll_res); if (rc) { pr_err("Failed to parse the resources rc=%d\n", rc); goto end; } compatible_stream = of_get_property(pdev->dev.of_node, "compatible", NULL); if (!compatible_stream) { pr_err("Failed to parse the compatible stream\n"); goto err; } if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8916")) { pll_res->pll_interface_type = MDSS_DSI_PLL_LPM; pll_res->target_id = MDSS_PLL_TARGET_8916; } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8939")) { pll_res->pll_interface_type = MDSS_DSI_PLL_LPM; pll_res->target_id = MDSS_PLL_TARGET_8939; } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8909")) { pll_res->pll_interface_type = MDSS_DSI_PLL_LPM; pll_res->target_id = MDSS_PLL_TARGET_8909; } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8974")) { pll_res->pll_interface_type = MDSS_DSI_PLL_HPM; pll_res->target_id = MDSS_PLL_TARGET_8974; } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8994")) { pll_res->pll_interface_type = MDSS_DSI_PLL_20NM; pll_res->target_id = MDSS_PLL_TARGET_8994; } else if (!strcmp(compatible_stream, "qcom,mdss_edp_pll")) { pll_res->pll_interface_type = MDSS_EDP_PLL; } else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll")) { pll_res->pll_interface_type = MDSS_HDMI_PLL; } else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_8994")) { pll_res->pll_interface_type = MDSS_HDMI_PLL_20NM; } else { goto err; } return rc; err: mdss_pll_resource_release(pdev, pll_res); end: return rc; }
static int mdss_pll_remove(struct platform_device *pdev) { struct mdss_pll_resources *pll_res; pll_res = platform_get_drvdata(pdev); if (!pll_res) { pr_err("Invalid PLL resource data"); return 0; } mdss_pll_resource_deinit(pdev, pll_res); if (pll_res->phy_base) iounmap(pll_res->phy_base); mdss_pll_resource_release(pdev, pll_res); iounmap(pll_res->pll_base); devm_kfree(&pdev->dev, pll_res); return 0; }
static int mdss_pll_probe(struct platform_device *pdev) { int rc = 0; const char *label; struct resource *pll_base_reg; struct resource *phy_base_reg; struct resource *dynamic_pll_base_reg; struct resource *gdsc_base_reg; struct mdss_pll_resources *pll_res; #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) struct samsung_display_driver_data *vdd = samsung_get_vdd(); #endif if (!pdev->dev.of_node) { pr_err("MDSS pll driver only supports device tree probe\n"); rc = -ENOTSUPP; goto error; } label = of_get_property(pdev->dev.of_node, "label", NULL); if (!label) pr_info("%d: MDSS pll label not specified\n", __LINE__); else pr_info("MDSS pll label = %s\n", label); pll_res = devm_kzalloc(&pdev->dev, sizeof(struct mdss_pll_resources), GFP_KERNEL); if (!pll_res) { pr_err("Failed to allocate the clock pll\n"); rc = -ENOMEM; goto error; } platform_set_drvdata(pdev, pll_res); rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &pll_res->index); if (rc) { pr_err("Unable to get the cell-index rc=%d\n", rc); pll_res->index = 0; } pll_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_base"); if (!pll_base_reg) { pr_err("Unable to get the pll base resources\n"); rc = -ENOMEM; goto io_error; } pll_res->pll_base = ioremap(pll_base_reg->start, resource_size(pll_base_reg)); if (!pll_res->pll_base) { pr_err("Unable to remap pll base resources\n"); rc = -ENOMEM; goto io_error; } #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if (!strcmp(label, "MDSS DSI 0 PLL") || !strcmp(label, "MDSS DSI 1 PLL")) vdd->dump_info[pll_res->index].dsi_pll.virtual_addr = (size_t)pll_res->pll_base; #endif rc = mdss_pll_resource_parse(pdev, pll_res); if (rc) { pr_err("Pll resource parsing from dt failed rc=%d\n", rc); goto res_parse_error; } /* * DSI PLL 1 is leaking current whenever MDSS GDSC is toggled. Need to * map PLL1 registers along with the PLl0 so that we can manually turn * off PLL1. */ if (pll_res->pll_interface_type == MDSS_DSI_PLL_20NM) { struct resource *pll_1_base_reg; pll_1_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_1_base"); if (pll_1_base_reg) { pll_res->pll_1_base = ioremap(pll_1_base_reg->start, resource_size(pll_1_base_reg)); if (!pll_res->pll_1_base) pr_err("Unable to remap pll 1 base resources\n"); } else { pr_err("Unable to get the pll 1 base resource\n"); } } phy_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_base"); if (!phy_base_reg) { /* This resource is mandatory for HDMI pll */ if (pll_res->pll_interface_type == MDSS_HDMI_PLL) { pr_err("Unable to get the phy base resources\n"); rc = -ENOMEM; goto phy_io_error; } } else { pll_res->phy_base = ioremap(phy_base_reg->start, resource_size(phy_base_reg)); if (!pll_res->phy_base) { pr_err("Unable to remap pll phy base resources\n"); rc = -ENOMEM; goto phy_io_error; } } dynamic_pll_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dynamic_pll_base"); if (dynamic_pll_base_reg) { pll_res->dyn_pll_base = ioremap(dynamic_pll_base_reg->start, resource_size(dynamic_pll_base_reg)); if (!pll_res->dyn_pll_base) { pr_err("Unable to remap dynamic pll base resources\n"); rc = -ENOMEM; goto dyn_pll_io_error; } } gdsc_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gdsc_base"); if (!gdsc_base_reg) { pr_err("Unable to get the gdsc base resource\n"); rc = -ENOMEM; goto gdsc_io_error; } pll_res->gdsc_base = ioremap(gdsc_base_reg->start, resource_size(gdsc_base_reg)); if (!pll_res->gdsc_base) { pr_err("Unable to remap gdsc base resources\n"); rc = -ENOMEM; goto gdsc_io_error; } rc = mdss_pll_resource_init(pdev, pll_res); if (rc) { pr_err("Pll resource init failed rc=%d\n", rc); goto res_init_error; } rc = mdss_pll_clock_register(pdev, pll_res); if (rc) { pr_err("Pll clock register failed rc=%d\n", rc); goto clock_register_error; } return rc; clock_register_error: mdss_pll_resource_deinit(pdev, pll_res); res_init_error: if (pll_res->gdsc_base) iounmap(pll_res->gdsc_base); gdsc_io_error: if (pll_res->dyn_pll_base) iounmap(pll_res->dyn_pll_base); dyn_pll_io_error: if (pll_res->phy_base) iounmap(pll_res->phy_base); phy_io_error: if (pll_res->pll_1_base) iounmap(pll_res->pll_1_base); mdss_pll_resource_release(pdev, pll_res); res_parse_error: iounmap(pll_res->pll_base); io_error: devm_kfree(&pdev->dev, pll_res); error: return rc; }
static int mdss_pll_probe(struct platform_device *pdev) { int rc = 0; const char *label; struct resource *pll_base_reg; struct resource *phy_base_reg; struct mdss_pll_resources *pll_res; if (!pdev->dev.of_node) { pr_err("MDSS pll driver only supports device tree probe\n"); rc = -ENOTSUPP; goto error; } label = of_get_property(pdev->dev.of_node, "label", NULL); if (!label) pr_info("%d: MDSS pll label not specified\n", __LINE__); else pr_info("MDSS pll label = %s\n", label); pll_res = devm_kzalloc(&pdev->dev, sizeof(struct mdss_pll_resources), GFP_KERNEL); if (!pll_res) { pr_err("Failed to allocate the clock pll\n"); rc = -ENOMEM; goto error; } platform_set_drvdata(pdev, pll_res); pll_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_base"); if (!pll_base_reg) { pr_err("Unable to get the pll base resources\n"); rc = -ENOMEM; goto io_error; } pll_res->pll_base = ioremap(pll_base_reg->start, resource_size(pll_base_reg)); if (!pll_res->pll_base) { pr_err("Unable to remap pll base resources\n"); rc = -ENOMEM; goto io_error; } rc = mdss_pll_resource_parse(pdev, pll_res); if (rc) { pr_err("Pll resource parsing from dt failed rc=%d\n", rc); goto res_parse_error; } phy_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_base"); if (!phy_base_reg) { /* This resource is mandatory for HDMI pll */ if (pll_res->pll_interface_type == MDSS_HDMI_PLL) { pr_err("Unable to get the phy base resources\n"); rc = -ENOMEM; goto phy_io_error; } } else { pll_res->phy_base = ioremap(phy_base_reg->start, resource_size(phy_base_reg)); if (!pll_res->phy_base) { pr_err("Unable to remap pll phy base resources\n"); rc = -ENOMEM; goto phy_io_error; } } rc = mdss_pll_resource_init(pdev, pll_res); if (rc) { pr_err("Pll resource init failed rc=%d\n", rc); goto res_init_error; } rc = mdss_pll_clock_register(pdev, pll_res); if (rc) { pr_err("Pll clock register failed rc=%d\n", rc); goto clock_register_error; } return rc; clock_register_error: mdss_pll_resource_deinit(pdev, pll_res); res_init_error: if (pll_res->phy_base) iounmap(pll_res->phy_base); phy_io_error: mdss_pll_resource_release(pdev, pll_res); res_parse_error: iounmap(pll_res->pll_base); io_error: devm_kfree(&pdev->dev, pll_res); error: return rc; }