2 * Rockchip DP PHY driver
4 * Copyright (C) 2016 FuZhou Rockchip Co., Ltd.
5 * Author: Yakir Yang <ykk@@rock-chips.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License.
12 #include <linux/clk.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
16 #include <linux/phy/phy.h>
17 #include <linux/platform_device.h>
18 #include <linux/regmap.h>
20 #define GRF_SOC_CON12 0x0274
22 #define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK BIT(20)
23 #define GRF_EDP_REF_CLK_SEL_INTER BIT(4)
25 #define GRF_EDP_PHY_SIDDQ_HIWORD_MASK BIT(21)
26 #define GRF_EDP_PHY_SIDDQ_ON 0
27 #define GRF_EDP_PHY_SIDDQ_OFF BIT(5)
29 struct rockchip_dp_phy
{
35 static int rockchip_set_phy_state(struct phy
*phy
, bool enable
)
37 struct rockchip_dp_phy
*dp
= phy_get_drvdata(phy
);
41 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
,
42 GRF_EDP_PHY_SIDDQ_HIWORD_MASK
|
43 GRF_EDP_PHY_SIDDQ_ON
);
45 dev_err(dp
->dev
, "Can't enable PHY power %d\n", ret
);
49 ret
= clk_prepare_enable(dp
->phy_24m
);
51 clk_disable_unprepare(dp
->phy_24m
);
53 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
,
54 GRF_EDP_PHY_SIDDQ_HIWORD_MASK
|
55 GRF_EDP_PHY_SIDDQ_OFF
);
61 static int rockchip_dp_phy_power_on(struct phy
*phy
)
63 return rockchip_set_phy_state(phy
, true);
66 static int rockchip_dp_phy_power_off(struct phy
*phy
)
68 return rockchip_set_phy_state(phy
, false);
71 static const struct phy_ops rockchip_dp_phy_ops
= {
72 .power_on
= rockchip_dp_phy_power_on
,
73 .power_off
= rockchip_dp_phy_power_off
,
77 static int rockchip_dp_phy_probe(struct platform_device
*pdev
)
79 struct device
*dev
= &pdev
->dev
;
80 struct device_node
*np
= dev
->of_node
;
81 struct phy_provider
*phy_provider
;
82 struct rockchip_dp_phy
*dp
;
89 if (!dev
->parent
|| !dev
->parent
->of_node
)
92 dp
= devm_kzalloc(dev
, sizeof(*dp
), GFP_KERNEL
);
98 dp
->phy_24m
= devm_clk_get(dev
, "24m");
99 if (IS_ERR(dp
->phy_24m
)) {
100 dev_err(dev
, "cannot get clock 24m\n");
101 return PTR_ERR(dp
->phy_24m
);
104 ret
= clk_set_rate(dp
->phy_24m
, 24000000);
106 dev_err(dp
->dev
, "cannot set clock phy_24m %d\n", ret
);
110 dp
->grf
= syscon_node_to_regmap(dev
->parent
->of_node
);
111 if (IS_ERR(dp
->grf
)) {
112 dev_err(dev
, "rk3288-dp needs the General Register Files syscon\n");
113 return PTR_ERR(dp
->grf
);
116 ret
= regmap_write(dp
->grf
, GRF_SOC_CON12
, GRF_EDP_REF_CLK_SEL_INTER
|
117 GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK
);
119 dev_err(dp
->dev
, "Could not config GRF edp ref clk: %d\n", ret
);
123 phy
= devm_phy_create(dev
, np
, &rockchip_dp_phy_ops
);
125 dev_err(dev
, "failed to create phy\n");
128 phy_set_drvdata(phy
, dp
);
130 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
132 return PTR_ERR_OR_ZERO(phy_provider
);
135 static const struct of_device_id rockchip_dp_phy_dt_ids
[] = {
136 { .compatible
= "rockchip,rk3288-dp-phy" },
140 MODULE_DEVICE_TABLE(of
, rockchip_dp_phy_dt_ids
);
142 static struct platform_driver rockchip_dp_phy_driver
= {
143 .probe
= rockchip_dp_phy_probe
,
145 .name
= "rockchip-dp-phy",
146 .of_match_table
= rockchip_dp_phy_dt_ids
,
150 module_platform_driver(rockchip_dp_phy_driver
);
152 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
153 MODULE_DESCRIPTION("Rockchip DP PHY driver");
154 MODULE_LICENSE("GPL v2");