1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * MediaTek DisplayPort PHY driver |
4 | * |
5 | * Copyright (c) 2022, BayLibre Inc. |
6 | * Copyright (c) 2022, MediaTek Inc. |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/io.h> |
11 | #include <linux/mfd/syscon.h> |
12 | #include <linux/of.h> |
13 | #include <linux/phy/phy.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regmap.h> |
16 | |
17 | #define PHY_OFFSET 0x1000 |
18 | |
19 | #define MTK_DP_PHY_DIG_PLL_CTL_1 (PHY_OFFSET + 0x14) |
20 | #define TPLL_SSC_EN BIT(3) |
21 | |
22 | #define MTK_DP_PHY_DIG_BIT_RATE (PHY_OFFSET + 0x3C) |
23 | #define BIT_RATE_RBR 0 |
24 | #define BIT_RATE_HBR 1 |
25 | #define BIT_RATE_HBR2 2 |
26 | #define BIT_RATE_HBR3 3 |
27 | |
28 | #define MTK_DP_PHY_DIG_SW_RST (PHY_OFFSET + 0x38) |
29 | #define DP_GLB_SW_RST_PHYD BIT(0) |
30 | |
31 | #define MTK_DP_LANE0_DRIVING_PARAM_3 (PHY_OFFSET + 0x138) |
32 | #define MTK_DP_LANE1_DRIVING_PARAM_3 (PHY_OFFSET + 0x238) |
33 | #define MTK_DP_LANE2_DRIVING_PARAM_3 (PHY_OFFSET + 0x338) |
34 | #define MTK_DP_LANE3_DRIVING_PARAM_3 (PHY_OFFSET + 0x438) |
35 | #define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT BIT(4) |
36 | #define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT (BIT(10) | BIT(12)) |
37 | #define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT GENMASK(20, 19) |
38 | #define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT GENMASK(29, 29) |
39 | #define DRIVING_PARAM_3_DEFAULT (XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \ |
40 | XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \ |
41 | XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \ |
42 | XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT) |
43 | |
44 | #define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT GENMASK(4, 3) |
45 | #define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT GENMASK(12, 9) |
46 | #define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT (BIT(18) | BIT(21)) |
47 | #define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT GENMASK(29, 29) |
48 | #define DRIVING_PARAM_4_DEFAULT (XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \ |
49 | XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \ |
50 | XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \ |
51 | XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT) |
52 | |
53 | #define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT (BIT(3) | BIT(5)) |
54 | #define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT GENMASK(13, 12) |
55 | #define DRIVING_PARAM_5_DEFAULT (XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \ |
56 | XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT) |
57 | |
58 | #define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT 0 |
59 | #define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT GENMASK(10, 10) |
60 | #define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT GENMASK(19, 19) |
61 | #define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT GENMASK(28, 28) |
62 | #define DRIVING_PARAM_6_DEFAULT (XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \ |
63 | XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \ |
64 | XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \ |
65 | XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT) |
66 | |
67 | #define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT 0 |
68 | #define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT GENMASK(10, 9) |
69 | #define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT GENMASK(19, 18) |
70 | #define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT 0 |
71 | #define DRIVING_PARAM_7_DEFAULT (XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \ |
72 | XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \ |
73 | XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \ |
74 | XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT) |
75 | |
76 | #define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT GENMASK(3, 3) |
77 | #define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT 0 |
78 | #define DRIVING_PARAM_8_DEFAULT (XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \ |
79 | XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT) |
80 | |
81 | struct mtk_dp_phy { |
82 | struct regmap *regs; |
83 | }; |
84 | |
85 | static int mtk_dp_phy_init(struct phy *phy) |
86 | { |
87 | struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); |
88 | static const u32 driving_params[] = { |
89 | DRIVING_PARAM_3_DEFAULT, |
90 | DRIVING_PARAM_4_DEFAULT, |
91 | DRIVING_PARAM_5_DEFAULT, |
92 | DRIVING_PARAM_6_DEFAULT, |
93 | DRIVING_PARAM_7_DEFAULT, |
94 | DRIVING_PARAM_8_DEFAULT |
95 | }; |
96 | |
97 | regmap_bulk_write(map: dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3, |
98 | val: driving_params, ARRAY_SIZE(driving_params)); |
99 | regmap_bulk_write(map: dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3, |
100 | val: driving_params, ARRAY_SIZE(driving_params)); |
101 | regmap_bulk_write(map: dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3, |
102 | val: driving_params, ARRAY_SIZE(driving_params)); |
103 | regmap_bulk_write(map: dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3, |
104 | val: driving_params, ARRAY_SIZE(driving_params)); |
105 | |
106 | return 0; |
107 | } |
108 | |
109 | static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) |
110 | { |
111 | struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); |
112 | u32 val; |
113 | |
114 | if (opts->dp.set_rate) { |
115 | switch (opts->dp.link_rate) { |
116 | default: |
117 | dev_err(&phy->dev, |
118 | "Implementation error, unknown linkrate %x\n" , |
119 | opts->dp.link_rate); |
120 | return -EINVAL; |
121 | case 1620: |
122 | val = BIT_RATE_RBR; |
123 | break; |
124 | case 2700: |
125 | val = BIT_RATE_HBR; |
126 | break; |
127 | case 5400: |
128 | val = BIT_RATE_HBR2; |
129 | break; |
130 | case 8100: |
131 | val = BIT_RATE_HBR3; |
132 | break; |
133 | } |
134 | regmap_write(map: dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val); |
135 | } |
136 | |
137 | regmap_update_bits(map: dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1, |
138 | TPLL_SSC_EN, val: opts->dp.ssc ? TPLL_SSC_EN : 0); |
139 | |
140 | return 0; |
141 | } |
142 | |
143 | static int mtk_dp_phy_reset(struct phy *phy) |
144 | { |
145 | struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); |
146 | |
147 | regmap_update_bits(map: dp_phy->regs, MTK_DP_PHY_DIG_SW_RST, |
148 | DP_GLB_SW_RST_PHYD, val: 0); |
149 | usleep_range(min: 50, max: 200); |
150 | regmap_update_bits(map: dp_phy->regs, MTK_DP_PHY_DIG_SW_RST, |
151 | DP_GLB_SW_RST_PHYD, val: 1); |
152 | |
153 | return 0; |
154 | } |
155 | |
156 | static const struct phy_ops mtk_dp_phy_dev_ops = { |
157 | .init = mtk_dp_phy_init, |
158 | .configure = mtk_dp_phy_configure, |
159 | .reset = mtk_dp_phy_reset, |
160 | .owner = THIS_MODULE, |
161 | }; |
162 | |
163 | static int mtk_dp_phy_probe(struct platform_device *pdev) |
164 | { |
165 | struct device *dev = &pdev->dev; |
166 | struct mtk_dp_phy *dp_phy; |
167 | struct phy *phy; |
168 | struct regmap *regs; |
169 | |
170 | regs = *(struct regmap **)dev->platform_data; |
171 | if (!regs) |
172 | return dev_err_probe(dev, err: -EINVAL, |
173 | fmt: "No data passed, requires struct regmap**\n" ); |
174 | |
175 | dp_phy = devm_kzalloc(dev, size: sizeof(*dp_phy), GFP_KERNEL); |
176 | if (!dp_phy) |
177 | return -ENOMEM; |
178 | |
179 | dp_phy->regs = regs; |
180 | phy = devm_phy_create(dev, NULL, ops: &mtk_dp_phy_dev_ops); |
181 | if (IS_ERR(ptr: phy)) |
182 | return dev_err_probe(dev, err: PTR_ERR(ptr: phy), |
183 | fmt: "Failed to create DP PHY\n" ); |
184 | |
185 | phy_set_drvdata(phy, data: dp_phy); |
186 | if (!dev->of_node) |
187 | phy_create_lookup(phy, con_id: "dp" , dev_id: dev_name(dev)); |
188 | |
189 | return 0; |
190 | } |
191 | |
192 | static struct platform_driver mtk_dp_phy_driver = { |
193 | .probe = mtk_dp_phy_probe, |
194 | .driver = { |
195 | .name = "mediatek-dp-phy" , |
196 | }, |
197 | }; |
198 | module_platform_driver(mtk_dp_phy_driver); |
199 | |
200 | MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>" ); |
201 | MODULE_DESCRIPTION("MediaTek DP PHY Driver" ); |
202 | MODULE_LICENSE("GPL" ); |
203 | |