diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c index a252b07a696a..7acf8fd7c62c 100644 --- a/drivers/soc/rockchip/grf.c +++ b/drivers/soc/rockchip/grf.c @@ -5,6 +5,7 @@ * Copyright (c) 2016 Heiko Stuebner */ +#include #include #include #include @@ -12,6 +13,97 @@ #include #include +struct rockchip_grf; + +struct rockchip_grf_funcs { + int (*reset)(struct rockchip_grf *grf); +}; + +struct rockchip_grf { + struct regmap *regmap; + const struct rockchip_grf_funcs *funcs; +}; + +static int rockchip_edp_phy_grf_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rockchip_grf *grf; + int ret; + + grf = devm_kzalloc(dev, sizeof(*grf), GFP_KERNEL); + if (!grf) + return -ENOMEM; + + grf->funcs = of_device_get_match_data(dev); + if (!grf->funcs) + return -ENODEV; + + grf->regmap = syscon_node_to_regmap(dev->of_node); + if (IS_ERR(grf->regmap)) { + ret = PTR_ERR(grf->regmap); + dev_err(dev, "failed to get grf: %d\n", ret); + return ret; + } + + ret = grf->funcs->reset(grf); + if (ret) + return ret; + + platform_set_drvdata(pdev, grf); + + return 0; +} + +static int __maybe_unused rockchip_edp_phy_grf_resume(struct device *dev) +{ + struct rockchip_grf *grf = dev_get_drvdata(dev); + + return grf->funcs->reset(grf); +} + +static const struct dev_pm_ops rockchip_edp_phy_grf_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rockchip_edp_phy_grf_resume) +}; + +static int rk3568_edp_phy_grf_reset(struct rockchip_grf *grf) +{ + u32 status; + int ret; + + ret = regmap_read(grf->regmap, 0x0030, &status); + if (ret < 0) + return ret; + + if (!FIELD_GET(0x1, status)) { + regmap_write(grf->regmap, 0x0028, 0x00070007); + regmap_write(grf->regmap, 0x0000, 0x0ff10ff1); + } + + return 0; +} + +static const struct rockchip_grf_funcs rk3568_edp_phy_grf_funcs = { + .reset = rk3568_edp_phy_grf_reset, +}; + +static const struct of_device_id rockchip_edp_phy_grf_match[] = { + { + .compatible = "rockchip,rk3568-edp-phy-grf", + .data = &rk3568_edp_phy_grf_funcs, + }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_edp_phy_grf_match); + +static struct platform_driver rockchip_edp_phy_grf_driver = { + .driver = { + .name = "rockchip-edp-phy-grf", + .of_match_table = rockchip_edp_phy_grf_match, + .pm = &rockchip_edp_phy_grf_pm_ops, + }, + .probe = rockchip_edp_phy_grf_probe, +}; + #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) @@ -204,6 +296,10 @@ static int __init rockchip_grf_init(void) struct regmap *grf; int ret, i; + ret = platform_driver_register(&rockchip_edp_phy_grf_driver); + if (ret) + return ret; + np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match, &match); if (!np)