From 36156156ae01f7f1f3509dd1c477e28b940fb2f0 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 13 Dec 2019 11:06:20 +0800 Subject: [PATCH] phy/rockchip: dp: Add support for RK3368 Add eDP PHY support for RK3368 SoC. RK3368 eDP PHY is similar to the RK3288. Change-Id: Ic2134ba719dadba121dc2fcc944662ef06b2ecfa Signed-off-by: Wyon Bi --- .../bindings/phy/rockchip-dp-phy.txt | 5 + drivers/phy/rockchip/phy-rockchip-dp.c | 102 +++++++++++------- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt index e3b4809fbe82..49bc6946a40c 100644 --- a/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt +++ b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt @@ -4,12 +4,17 @@ Rockchip specific extensions to the Analogix Display Port PHY Required properties: - compatible : should be one of the following supported values: - "rockchip.rk3288-dp-phy" + - "rockchip.rk3368-dp-phy" - clocks: from common clock binding: handle to dp clock. of memory mapped region. - clock-names: from common clock binding: Required elements: "24m" - #phy-cells : from the generic PHY bindings, must be 0; +Optional properties: +- resets : phandle to the reset of eDP 24m clock domain. +- reset-names : should be "edp_24m". + Example: grf: syscon@ff770000 { diff --git a/drivers/phy/rockchip/phy-rockchip-dp.c b/drivers/phy/rockchip/phy-rockchip-dp.c index 8b267a746576..f1c59f81670d 100644 --- a/drivers/phy/rockchip/phy-rockchip-dp.c +++ b/drivers/phy/rockchip/phy-rockchip-dp.c @@ -13,59 +13,57 @@ #include #include #include +#include #include #include #include +#include -#define GRF_SOC_CON12 0x0274 - -#define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK BIT(20) -#define GRF_EDP_REF_CLK_SEL_INTER BIT(4) - -#define GRF_EDP_PHY_SIDDQ_HIWORD_MASK BIT(21) -#define GRF_EDP_PHY_SIDDQ_ON 0 -#define GRF_EDP_PHY_SIDDQ_OFF BIT(5) +struct rockchip_dp_phy_data { + u32 grf_reg_offset; + u8 ref_clk_sel_shift; + u8 iddq_shift; +}; struct rockchip_dp_phy { struct device *dev; struct regmap *grf; struct clk *phy_24m; + struct reset_control *rst; + const struct rockchip_dp_phy_data *data; }; -static int rockchip_set_phy_state(struct phy *phy, bool enable) -{ - struct rockchip_dp_phy *dp = phy_get_drvdata(phy); - int ret; - - if (enable) { - ret = regmap_write(dp->grf, GRF_SOC_CON12, - GRF_EDP_PHY_SIDDQ_HIWORD_MASK | - GRF_EDP_PHY_SIDDQ_ON); - if (ret < 0) { - dev_err(dp->dev, "Can't enable PHY power %d\n", ret); - return ret; - } - - ret = clk_prepare_enable(dp->phy_24m); - } else { - clk_disable_unprepare(dp->phy_24m); - - ret = regmap_write(dp->grf, GRF_SOC_CON12, - GRF_EDP_PHY_SIDDQ_HIWORD_MASK | - GRF_EDP_PHY_SIDDQ_OFF); - } - - return ret; -} - static int rockchip_dp_phy_power_on(struct phy *phy) { - return rockchip_set_phy_state(phy, true); + struct rockchip_dp_phy *dp = phy_get_drvdata(phy); + const struct rockchip_dp_phy_data *data = dp->data; + + clk_prepare_enable(dp->phy_24m); + + if (dp->rst) { + /* EDP 24m clock domain software reset */ + reset_control_assert(dp->rst); + usleep_range(20, 40); + reset_control_deassert(dp->rst); + } + + regmap_write(dp->grf, data->grf_reg_offset, + 0 | BIT(16 + data->iddq_shift)); + + return 0; } static int rockchip_dp_phy_power_off(struct phy *phy) { - return rockchip_set_phy_state(phy, false); + struct rockchip_dp_phy *dp = phy_get_drvdata(phy); + const struct rockchip_dp_phy_data *data = dp->data; + + regmap_write(dp->grf, data->grf_reg_offset, + BIT(data->iddq_shift) | BIT(16 + data->iddq_shift)); + + clk_disable_unprepare(dp->phy_24m); + + return 0; } static const struct phy_ops rockchip_dp_phy_ops = { @@ -80,6 +78,7 @@ static int rockchip_dp_phy_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct phy_provider *phy_provider; struct rockchip_dp_phy *dp; + const struct rockchip_dp_phy_data *data = of_device_get_match_data(dev); struct phy *phy; int ret; @@ -94,6 +93,7 @@ static int rockchip_dp_phy_probe(struct platform_device *pdev) return -ENOMEM; dp->dev = dev; + dp->data = data; dp->phy_24m = devm_clk_get(dev, "24m"); if (IS_ERR(dp->phy_24m)) { @@ -107,15 +107,24 @@ static int rockchip_dp_phy_probe(struct platform_device *pdev) return ret; } + dp->rst = devm_reset_control_get_optional(dev, "edp_24m"); + if (IS_ERR(dp->rst)) { + ret = PTR_ERR(dp->rst); + dev_err(dev, "failed to get reset control: %d\n", ret); + return ret; + } + dp->grf = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(dp->grf)) { dev_err(dev, "rk3288-dp needs the General Register Files syscon\n"); return PTR_ERR(dp->grf); } - ret = regmap_write(dp->grf, GRF_SOC_CON12, GRF_EDP_REF_CLK_SEL_INTER | - GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK); - if (ret != 0) { + /* eDP PHY reference clock source from internal clock */ + ret = regmap_write(dp->grf, data->grf_reg_offset, + BIT(data->ref_clk_sel_shift) | + BIT(16 + data->ref_clk_sel_shift)); + if (ret) { dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret); return ret; } @@ -132,8 +141,21 @@ static int rockchip_dp_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } +static const struct rockchip_dp_phy_data rk3288_dp_phy_data = { + .grf_reg_offset = 0x274, + .ref_clk_sel_shift = 4, + .iddq_shift = 5, +}; + +static const struct rockchip_dp_phy_data rk3368_dp_phy_data = { + .grf_reg_offset = 0x410, + .ref_clk_sel_shift = 0, + .iddq_shift = 1, +}; + static const struct of_device_id rockchip_dp_phy_dt_ids[] = { - { .compatible = "rockchip,rk3288-dp-phy" }, + { .compatible = "rockchip,rk3288-dp-phy", .data = &rk3288_dp_phy_data }, + { .compatible = "rockchip,rk3368-dp-phy", .data = &rk3368_dp_phy_data }, {} };