1
2
3
4
5
6
7
8
9
10#include <common.h>
11#include <log.h>
12#include <malloc.h>
13#include <asm/io.h>
14#include <bitfield.h>
15#include <dm.h>
16#include <errno.h>
17#include <generic-phy.h>
18#include <regmap.h>
19#include <linux/delay.h>
20#include <power/regulator.h>
21#include <reset.h>
22#include <clk.h>
23#include <phy-mipi-dphy.h>
24
25#include <linux/bitops.h>
26#include <linux/compat.h>
27#include <linux/bitfield.h>
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#define MIPI_DSI_PHY_CTRL 0x0
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101#define MIPI_DSI_CHAN_CTRL 0x4
102
103
104
105
106
107
108
109
110
111
112
113#define MIPI_DSI_CHAN_STS 0x8
114
115
116
117
118
119
120#define MIPI_DSI_CLK_TIM 0xc
121
122
123
124
125
126
127#define MIPI_DSI_HS_TIM 0x10
128
129
130
131
132
133
134#define MIPI_DSI_LP_TIM 0x14
135
136
137#define MIPI_DSI_ANA_UP_TIM 0x18
138
139
140#define MIPI_DSI_INIT_TIM 0x1c
141
142
143#define MIPI_DSI_WAKEUP_TIM 0x20
144
145
146
147
148#define MIPI_DSI_LPOK_TIM 0x24
149
150
151#define MIPI_DSI_LP_WCHDOG 0x28
152
153
154
155
156#define MIPI_DSI_ANA_CTRL 0x2c
157
158
159
160
161#define MIPI_DSI_CLK_TIM1 0x30
162
163
164#define MIPI_DSI_TURN_WCHDOG 0x34
165
166
167
168
169#define MIPI_DSI_ULPS_CHECK 0x38
170#define MIPI_DSI_TEST_CTRL0 0x3c
171#define MIPI_DSI_TEST_CTRL1 0x40
172
173#define NSEC_PER_MSEC 1000000L
174
175struct phy_meson_axg_mipi_dphy_priv {
176 struct regmap *regmap;
177#if CONFIG_IS_ENABLED(CLK)
178 struct clk clk;
179#endif
180 struct reset_ctl reset;
181 struct phy analog;
182 struct phy_configure_opts_mipi_dphy config;
183};
184
185static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, void *params)
186{
187 struct udevice *dev = phy->dev;
188 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
189 struct phy_configure_opts_mipi_dphy *config = params;
190 int ret;
191
192 ret = phy_mipi_dphy_config_validate(config);
193 if (ret)
194 return ret;
195
196 ret = generic_phy_configure(&priv->analog, config);
197 if (ret)
198 return ret;
199
200 memcpy(&priv->config, config, sizeof(priv->config));
201
202 return 0;
203}
204
205static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
206{
207 struct udevice *dev = phy->dev;
208 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
209 unsigned long temp;
210 int ret;
211
212 ret = generic_phy_power_on(&priv->analog);
213 if (ret)
214 return ret;
215
216
217 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, 0x1);
218 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
219 BIT(0) |
220 BIT(7) |
221 BIT(8));
222
223
224 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));
225
226
227 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
228 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
229 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);
230
231
232 temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
233 temp = temp * 8 * 10;
234
235 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
236 DIV_ROUND_UP(priv->config.clk_trail, temp) |
237 (DIV_ROUND_UP(priv->config.clk_post +
238 priv->config.hs_trail, temp) << 8) |
239 (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
240 (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
241 regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
242 DIV_ROUND_UP(priv->config.clk_pre, temp));
243
244 regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
245 DIV_ROUND_UP(priv->config.hs_exit, temp) |
246 (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) |
247 (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) |
248 (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24));
249
250 regmap_write(priv->regmap, MIPI_DSI_LP_TIM,
251 DIV_ROUND_UP(priv->config.lpx, temp) |
252 (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) |
253 (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) |
254 (DIV_ROUND_UP(priv->config.ta_get, temp) << 24));
255
256 regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100);
257 regmap_write(priv->regmap, MIPI_DSI_INIT_TIM,
258 DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp));
259 regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM,
260 DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp));
261 regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C);
262 regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C);
263 regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000);
264 regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000);
265
266
267 switch (priv->config.lanes) {
268 case 1:
269 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe);
270 break;
271 case 2:
272 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc);
273 break;
274 case 3:
275 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8);
276 break;
277 case 4:
278 default:
279 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0);
280 break;
281 }
282
283
284 regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1));
285
286 return 0;
287}
288
289static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy)
290{
291 struct udevice *dev = phy->dev;
292 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
293
294 regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf);
295 regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31));
296
297 return generic_phy_power_off(&priv->analog);
298}
299
300static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
301{
302 struct udevice *dev = phy->dev;
303 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
304 int ret;
305
306 ret = generic_phy_init(&priv->analog);
307 if (ret)
308 return ret;
309
310 ret = reset_assert(&priv->reset);
311 udelay(1);
312 ret |= reset_deassert(&priv->reset);
313 if (ret)
314 return ret;
315
316 return 0;
317}
318
319static int phy_meson_axg_mipi_dphy_exit(struct phy *phy)
320{
321 struct udevice *dev = phy->dev;
322 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
323 int ret;
324
325 ret = generic_phy_exit(&priv->analog);
326 if (ret)
327 return ret;
328
329 return reset_assert(&priv->reset);
330}
331
332struct phy_ops meson_axg_mipi_dphy_ops = {
333 .init = phy_meson_axg_mipi_dphy_init,
334 .exit = phy_meson_axg_mipi_dphy_exit,
335 .power_on = phy_meson_axg_mipi_dphy_power_on,
336 .power_off = phy_meson_axg_mipi_dphy_power_off,
337 .configure = phy_meson_axg_mipi_dphy_configure,
338};
339
340int meson_axg_mipi_dphy_probe(struct udevice *dev)
341{
342 struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
343 int ret;
344
345 ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
346 if (ret)
347 return ret;
348
349 ret = generic_phy_get_by_index(dev, 0, &priv->analog);
350 if (ret)
351 return ret;
352
353 ret = reset_get_by_index(dev, 0, &priv->reset);
354 if (ret == -ENOTSUPP)
355 return 0;
356 else if (ret)
357 return ret;
358
359 ret = reset_deassert(&priv->reset);
360 if (ret) {
361 reset_release_all(&priv->reset, 1);
362 return ret;
363 }
364
365#if CONFIG_IS_ENABLED(CLK)
366 ret = clk_get_by_index(dev, 0, &priv->clk);
367 if (ret < 0)
368 return ret;
369
370 ret = clk_enable(&priv->clk);
371 if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
372 pr_err("failed to enable PHY clock\n");
373 clk_free(&priv->clk);
374 return ret;
375 }
376#endif
377
378 return 0;
379}
380
381static const struct udevice_id meson_axg_mipi_dphy_ids[] = {
382 { .compatible = "amlogic,axg-mipi-dphy" },
383 { }
384};
385
386U_BOOT_DRIVER(meson_axg_mipi_dphy) = {
387 .name = "meson_axg_mipi_dphy",
388 .id = UCLASS_PHY,
389 .of_match = meson_axg_mipi_dphy_ids,
390 .probe = meson_axg_mipi_dphy_probe,
391 .ops = &meson_axg_mipi_dphy_ops,
392 .priv_auto = sizeof(struct phy_meson_axg_mipi_dphy_priv),
393};
394