1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip DP PHY driver
5 * Copyright (C) 2016 FuZhou Rockchip Co., Ltd.
6 * Author: Yakir Yang <ykk@@rock-chips.com>
10 #include <linux/mfd/syscon.h>
11 #include <linux/module.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
17 #define GRF_SOC_CON12 0x0274
19 #define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK BIT(20)
20 #define GRF_EDP_REF_CLK_SEL_INTER BIT(4)
22 #define GRF_EDP_PHY_SIDDQ_HIWORD_MASK BIT(21)
23 #define GRF_EDP_PHY_SIDDQ_ON 0
24 #define GRF_EDP_PHY_SIDDQ_OFF BIT(5)
26 struct rockchip_dp_phy
{
32 static int rockchip_set_phy_state(struct phy
*phy
, bool enable
)
34 struct rockchip_dp_phy
*dp
= phy_get_drvdata(phy
);
38 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
,
39 GRF_EDP_PHY_SIDDQ_HIWORD_MASK
|
40 GRF_EDP_PHY_SIDDQ_ON
);
42 dev_err(dp
->dev
, "Can't enable PHY power %d\n", ret
);
46 ret
= clk_prepare_enable(dp
->phy_24m
);
48 clk_disable_unprepare(dp
->phy_24m
);
50 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
,
51 GRF_EDP_PHY_SIDDQ_HIWORD_MASK
|
52 GRF_EDP_PHY_SIDDQ_OFF
);
58 static int rockchip_dp_phy_power_on(struct phy
*phy
)
60 return rockchip_set_phy_state(phy
, true);
63 static int rockchip_dp_phy_power_off(struct phy
*phy
)
65 return rockchip_set_phy_state(phy
, false);
68 static const struct phy_ops rockchip_dp_phy_ops
= {
69 .power_on
= rockchip_dp_phy_power_on
,
70 .power_off
= rockchip_dp_phy_power_off
,
74 static int rockchip_dp_phy_probe(struct platform_device
*pdev
)
76 struct device
*dev
= &pdev
->dev
;
77 struct device_node
*np
= dev
->of_node
;
78 struct phy_provider
*phy_provider
;
79 struct rockchip_dp_phy
*dp
;
86 if (!dev
->parent
|| !dev
->parent
->of_node
)
89 dp
= devm_kzalloc(dev
, sizeof(*dp
), GFP_KERNEL
);
95 dp
->phy_24m
= devm_clk_get(dev
, "24m");
96 if (IS_ERR(dp
->phy_24m
)) {
97 dev_err(dev
, "cannot get clock 24m\n");
98 return PTR_ERR(dp
->phy_24m
);
101 ret
= clk_set_rate(dp
->phy_24m
, 24000000);
103 dev_err(dp
->dev
, "cannot set clock phy_24m %d\n", ret
);
107 dp
->grf
= syscon_node_to_regmap(dev
->parent
->of_node
);
108 if (IS_ERR(dp
->grf
)) {
109 dev_err(dev
, "rk3288-dp needs the General Register Files syscon\n");
110 return PTR_ERR(dp
->grf
);
113 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
, GRF_EDP_REF_CLK_SEL_INTER
|
114 GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK
);
116 dev_err(dp
->dev
, "Could not config GRF edp ref clk: %d\n", ret
);
120 phy
= devm_phy_create(dev
, np
, &rockchip_dp_phy_ops
);
122 dev_err(dev
, "failed to create phy\n");
125 phy_set_drvdata(phy
, dp
);
127 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
129 return PTR_ERR_OR_ZERO(phy_provider
);
132 static const struct of_device_id rockchip_dp_phy_dt_ids
[] = {
133 { .compatible
= "rockchip,rk3288-dp-phy" },
137 MODULE_DEVICE_TABLE(of
, rockchip_dp_phy_dt_ids
);
139 static struct platform_driver rockchip_dp_phy_driver
= {
140 .probe
= rockchip_dp_phy_probe
,
142 .name
= "rockchip-dp-phy",
143 .of_match_table
= rockchip_dp_phy_dt_ids
,
147 module_platform_driver(rockchip_dp_phy_driver
);
149 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
150 MODULE_DESCRIPTION("Rockchip DP PHY driver");
151 MODULE_LICENSE("GPL v2");