Make it possible to decouple the registration of the DisplayPort PHY driver from the DisplayPort IP driver by adding a devicetree match to probe the PHY, registering an OF PHY provider and this device's own MMIO regmap - if, and only if, this PHY driver was registered with an OF match.
In order to retain compatibility with older devicetrees that are not declaring the DisplayPort PHY as a separate node, the legacy code was moved in a `mtk_dp_phy_legacy_probe()` function, which gets called if the driver was registered by the DisplayPort one. Signed-off-by: AngeloGioacchino Del Regno <[email protected]> --- drivers/phy/mediatek/phy-mtk-dp.c | 70 ++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c index bf7b3a95e72d..98e05fe05ce3 100644 --- a/drivers/phy/mediatek/phy-mtk-dp.c +++ b/drivers/phy/mediatek/phy-mtk-dp.c @@ -79,6 +79,7 @@ XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT) struct mtk_dp_phy { + struct device *dev; struct regmap *regmap; }; @@ -160,43 +161,92 @@ static const struct phy_ops mtk_dp_phy_dev_ops = { .owner = THIS_MODULE, }; +static int mtk_dp_phy_legacy_probe(struct platform_device *pdev, struct mtk_dp_phy *dp_phy) +{ + struct device *dev = &pdev->dev; + struct phy *phy; + + dp_phy->regmap = *(struct regmap **)dev->platform_data; + if (!dp_phy->regmap) + return dev_err_probe(dev, -EINVAL, "No platform data available\n"); + + phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops); + if (IS_ERR(phy)) + return dev_err_probe(dev, PTR_ERR(phy), + "Failed to create DP PHY\n"); + + phy_set_drvdata(phy, dp_phy); + phy_create_lookup(phy, "dp", dev_name(dev)); + + return 0; +} + +static const struct regmap_config mtk_dp_phy_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .disable_locking = true, +}; + static int mtk_dp_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct phy_provider *provider; struct mtk_dp_phy *dp_phy; + void __iomem *base; struct phy *phy; - struct regmap *regs; - - regs = *(struct regmap **)dev->platform_data; - if (!regs) - return dev_err_probe(dev, -EINVAL, - "No data passed, requires struct regmap**\n"); dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL); if (!dp_phy) return -ENOMEM; - dp_phy->regmap = regs; + dp_phy->dev = dev; + + /* If there's no devicetree, go for legacy pdev probe */ + if (!dev->of_node) + return mtk_dp_phy_legacy_probe(pdev, dp_phy); + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + dp_phy->regmap = devm_regmap_init_mmio(dev, base, &mtk_dp_phy_regmap_cfg); + if (IS_ERR(dp_phy->regmap)) + return PTR_ERR(dp_phy->regmap); + phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops); if (IS_ERR(phy)) return dev_err_probe(dev, PTR_ERR(phy), "Failed to create DP PHY\n"); phy_set_drvdata(phy, dp_phy); - if (!dev->of_node) - phy_create_lookup(phy, "dp", dev_name(dev)); + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(provider)) + return PTR_ERR(provider); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); return 0; } +static const struct of_device_id mtk_dp_phy_of_match[] = { + { .compatible = "mediatek,mt8195-dp-phy" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mtk_dp_phy_of_match); + static struct platform_driver mtk_dp_phy_driver = { .probe = mtk_dp_phy_probe, .driver = { .name = "mediatek-dp-phy", + .of_match_table = mtk_dp_phy_of_match, }, }; module_platform_driver(mtk_dp_phy_driver); +MODULE_AUTHOR("AngeloGioacchino Del Regno <[email protected]>"); MODULE_AUTHOR("Markus Schneider-Pargmann <[email protected]>"); -MODULE_DESCRIPTION("MediaTek DP PHY Driver"); +MODULE_DESCRIPTION("MediaTek DisplayPort PHY Driver"); MODULE_LICENSE("GPL"); -- 2.54.0
