1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * phy-ti-pipe3 - PIPE3 PHY driver. |
4 | * |
5 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com |
6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> |
7 | */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/property.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/phy/phy.h> |
14 | #include <linux/of.h> |
15 | #include <linux/clk.h> |
16 | #include <linux/err.h> |
17 | #include <linux/io.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/delay.h> |
20 | #include <linux/phy/omap_control_phy.h> |
21 | #include <linux/of_platform.h> |
22 | #include <linux/mfd/syscon.h> |
23 | #include <linux/regmap.h> |
24 | |
25 | #define PLL_STATUS 0x00000004 |
26 | #define PLL_GO 0x00000008 |
27 | #define PLL_CONFIGURATION1 0x0000000C |
28 | #define PLL_CONFIGURATION2 0x00000010 |
29 | #define PLL_CONFIGURATION3 0x00000014 |
30 | #define PLL_CONFIGURATION4 0x00000020 |
31 | |
32 | #define PLL_REGM_MASK 0x001FFE00 |
33 | #define PLL_REGM_SHIFT 0x9 |
34 | #define PLL_REGM_F_MASK 0x0003FFFF |
35 | #define PLL_REGM_F_SHIFT 0x0 |
36 | #define PLL_REGN_MASK 0x000001FE |
37 | #define PLL_REGN_SHIFT 0x1 |
38 | #define PLL_SELFREQDCO_MASK 0x0000000E |
39 | #define PLL_SELFREQDCO_SHIFT 0x1 |
40 | #define PLL_SD_MASK 0x0003FC00 |
41 | #define PLL_SD_SHIFT 10 |
42 | #define SET_PLL_GO 0x1 |
43 | #define PLL_LDOPWDN BIT(15) |
44 | #define PLL_TICOPWDN BIT(16) |
45 | #define PLL_LOCK 0x2 |
46 | #define PLL_IDLE 0x1 |
47 | |
48 | #define SATA_PLL_SOFT_RESET BIT(18) |
49 | |
50 | #define PIPE3_PHY_PWRCTL_CLK_CMD_MASK GENMASK(21, 14) |
51 | #define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 14 |
52 | |
53 | #define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK GENMASK(31, 22) |
54 | #define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 22 |
55 | |
56 | #define PIPE3_PHY_RX_POWERON (0x1 << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT) |
57 | #define PIPE3_PHY_TX_POWERON (0x2 << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT) |
58 | |
59 | #define PCIE_PCS_MASK 0xFF0000 |
60 | #define PCIE_PCS_DELAY_COUNT_SHIFT 0x10 |
61 | |
62 | #define PIPE3_PHY_RX_ANA_PROGRAMMABILITY 0x0000000C |
63 | #define INTERFACE_MASK GENMASK(31, 27) |
64 | #define INTERFACE_SHIFT 27 |
65 | #define INTERFACE_MODE_USBSS BIT(4) |
66 | #define INTERFACE_MODE_SATA_1P5 BIT(3) |
67 | #define INTERFACE_MODE_SATA_3P0 BIT(2) |
68 | #define INTERFACE_MODE_PCIE BIT(0) |
69 | |
70 | #define LOSD_MASK GENMASK(17, 14) |
71 | #define LOSD_SHIFT 14 |
72 | #define MEM_PLLDIV GENMASK(6, 5) |
73 | |
74 | #define PIPE3_PHY_RX_TRIM 0x0000001C |
75 | #define MEM_DLL_TRIM_SEL_MASK GENMASK(31, 30) |
76 | #define MEM_DLL_TRIM_SHIFT 30 |
77 | |
78 | #define PIPE3_PHY_RX_DLL 0x00000024 |
79 | #define MEM_DLL_PHINT_RATE_MASK GENMASK(31, 30) |
80 | #define MEM_DLL_PHINT_RATE_SHIFT 30 |
81 | |
82 | #define PIPE3_PHY_RX_DIGITAL_MODES 0x00000028 |
83 | #define MEM_HS_RATE_MASK GENMASK(28, 27) |
84 | #define MEM_HS_RATE_SHIFT 27 |
85 | #define MEM_OVRD_HS_RATE BIT(26) |
86 | #define MEM_OVRD_HS_RATE_SHIFT 26 |
87 | #define MEM_CDR_FASTLOCK BIT(23) |
88 | #define MEM_CDR_FASTLOCK_SHIFT 23 |
89 | #define MEM_CDR_LBW_MASK GENMASK(22, 21) |
90 | #define MEM_CDR_LBW_SHIFT 21 |
91 | #define MEM_CDR_STEPCNT_MASK GENMASK(20, 19) |
92 | #define MEM_CDR_STEPCNT_SHIFT 19 |
93 | #define MEM_CDR_STL_MASK GENMASK(18, 16) |
94 | #define MEM_CDR_STL_SHIFT 16 |
95 | #define MEM_CDR_THR_MASK GENMASK(15, 13) |
96 | #define MEM_CDR_THR_SHIFT 13 |
97 | #define MEM_CDR_THR_MODE BIT(12) |
98 | #define MEM_CDR_THR_MODE_SHIFT 12 |
99 | #define MEM_CDR_2NDO_SDM_MODE BIT(11) |
100 | #define MEM_CDR_2NDO_SDM_MODE_SHIFT 11 |
101 | |
102 | #define PIPE3_PHY_RX_EQUALIZER 0x00000038 |
103 | #define MEM_EQLEV_MASK GENMASK(31, 16) |
104 | #define MEM_EQLEV_SHIFT 16 |
105 | #define MEM_EQFTC_MASK GENMASK(15, 11) |
106 | #define MEM_EQFTC_SHIFT 11 |
107 | #define MEM_EQCTL_MASK GENMASK(10, 7) |
108 | #define MEM_EQCTL_SHIFT 7 |
109 | #define MEM_OVRD_EQLEV BIT(2) |
110 | #define MEM_OVRD_EQLEV_SHIFT 2 |
111 | #define MEM_OVRD_EQFTC BIT(1) |
112 | #define MEM_OVRD_EQFTC_SHIFT 1 |
113 | |
114 | #define SATA_PHY_RX_IO_AND_A2D_OVERRIDES 0x44 |
115 | #define MEM_CDR_LOS_SOURCE_MASK GENMASK(10, 9) |
116 | #define MEM_CDR_LOS_SOURCE_SHIFT 9 |
117 | |
118 | /* |
119 | * This is an Empirical value that works, need to confirm the actual |
120 | * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status |
121 | * to be correctly reflected in the PIPE3PHY_PLL_STATUS register. |
122 | */ |
123 | #define PLL_IDLE_TIME 100 /* in milliseconds */ |
124 | #define PLL_LOCK_TIME 100 /* in milliseconds */ |
125 | |
126 | enum pipe3_mode { PIPE3_MODE_PCIE = 1, |
127 | PIPE3_MODE_SATA, |
128 | PIPE3_MODE_USBSS }; |
129 | |
130 | struct pipe3_dpll_params { |
131 | u16 m; |
132 | u8 n; |
133 | u8 freq:3; |
134 | u8 sd; |
135 | u32 mf; |
136 | }; |
137 | |
138 | struct pipe3_dpll_map { |
139 | unsigned long rate; |
140 | struct pipe3_dpll_params params; |
141 | }; |
142 | |
143 | struct pipe3_settings { |
144 | u8 ana_interface; |
145 | u8 ana_losd; |
146 | u8 dig_fastlock; |
147 | u8 dig_lbw; |
148 | u8 dig_stepcnt; |
149 | u8 dig_stl; |
150 | u8 dig_thr; |
151 | u8 dig_thr_mode; |
152 | u8 dig_2ndo_sdm_mode; |
153 | u8 dig_hs_rate; |
154 | u8 dig_ovrd_hs_rate; |
155 | u8 dll_trim_sel; |
156 | u8 dll_phint_rate; |
157 | u8 eq_lev; |
158 | u8 eq_ftc; |
159 | u8 eq_ctl; |
160 | u8 eq_ovrd_lev; |
161 | u8 eq_ovrd_ftc; |
162 | }; |
163 | |
164 | struct ti_pipe3 { |
165 | void __iomem *pll_ctrl_base; |
166 | void __iomem *phy_rx; |
167 | void __iomem *phy_tx; |
168 | struct device *dev; |
169 | struct device *control_dev; |
170 | struct clk *wkupclk; |
171 | struct clk *sys_clk; |
172 | struct clk *refclk; |
173 | struct clk *div_clk; |
174 | struct pipe3_dpll_map *dpll_map; |
175 | struct regmap *phy_power_syscon; /* ctrl. reg. acces */ |
176 | struct regmap *pcs_syscon; /* ctrl. reg. acces */ |
177 | struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */ |
178 | unsigned int dpll_reset_reg; /* reg. index within syscon */ |
179 | unsigned int power_reg; /* power reg. index within syscon */ |
180 | unsigned int pcie_pcs_reg; /* pcs reg. index in syscon */ |
181 | bool sata_refclk_enabled; |
182 | enum pipe3_mode mode; |
183 | struct pipe3_settings settings; |
184 | }; |
185 | |
186 | static struct pipe3_dpll_map dpll_map_usb[] = { |
187 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ |
188 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ |
189 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ |
190 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ |
191 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ |
192 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ |
193 | { }, /* Terminator */ |
194 | }; |
195 | |
196 | static struct pipe3_dpll_map dpll_map_sata[] = { |
197 | {12000000, {625, 4, 4, 6, 0} }, /* 12 MHz */ |
198 | {16800000, {625, 6, 4, 7, 0} }, /* 16.8 MHz */ |
199 | {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ |
200 | {20000000, {750, 9, 4, 6, 0} }, /* 20 MHz */ |
201 | {26000000, {750, 12, 4, 6, 0} }, /* 26 MHz */ |
202 | {38400000, {625, 15, 4, 6, 0} }, /* 38.4 MHz */ |
203 | { }, /* Terminator */ |
204 | }; |
205 | |
206 | struct pipe3_data { |
207 | enum pipe3_mode mode; |
208 | struct pipe3_dpll_map *dpll_map; |
209 | struct pipe3_settings settings; |
210 | }; |
211 | |
212 | static struct pipe3_data data_usb = { |
213 | .mode = PIPE3_MODE_USBSS, |
214 | .dpll_map = dpll_map_usb, |
215 | .settings = { |
216 | /* DRA75x TRM Table 26-17 Preferred USB3_PHY_RX SCP Register Settings */ |
217 | .ana_interface = INTERFACE_MODE_USBSS, |
218 | .ana_losd = 0xa, |
219 | .dig_fastlock = 1, |
220 | .dig_lbw = 3, |
221 | .dig_stepcnt = 0, |
222 | .dig_stl = 0x3, |
223 | .dig_thr = 1, |
224 | .dig_thr_mode = 1, |
225 | .dig_2ndo_sdm_mode = 0, |
226 | .dig_hs_rate = 0, |
227 | .dig_ovrd_hs_rate = 1, |
228 | .dll_trim_sel = 0x2, |
229 | .dll_phint_rate = 0x3, |
230 | .eq_lev = 0, |
231 | .eq_ftc = 0, |
232 | .eq_ctl = 0x9, |
233 | .eq_ovrd_lev = 0, |
234 | .eq_ovrd_ftc = 0, |
235 | }, |
236 | }; |
237 | |
238 | static struct pipe3_data data_sata = { |
239 | .mode = PIPE3_MODE_SATA, |
240 | .dpll_map = dpll_map_sata, |
241 | .settings = { |
242 | /* DRA75x TRM Table 26-9 Preferred SATA_PHY_RX SCP Register Settings */ |
243 | .ana_interface = INTERFACE_MODE_SATA_3P0, |
244 | .ana_losd = 0x5, |
245 | .dig_fastlock = 1, |
246 | .dig_lbw = 3, |
247 | .dig_stepcnt = 0, |
248 | .dig_stl = 0x3, |
249 | .dig_thr = 1, |
250 | .dig_thr_mode = 1, |
251 | .dig_2ndo_sdm_mode = 0, |
252 | .dig_hs_rate = 0, /* Not in TRM preferred settings */ |
253 | .dig_ovrd_hs_rate = 0, /* Not in TRM preferred settings */ |
254 | .dll_trim_sel = 0x1, |
255 | .dll_phint_rate = 0x2, /* for 1.5 GHz DPLL clock */ |
256 | .eq_lev = 0, |
257 | .eq_ftc = 0x1f, |
258 | .eq_ctl = 0, |
259 | .eq_ovrd_lev = 1, |
260 | .eq_ovrd_ftc = 1, |
261 | }, |
262 | }; |
263 | |
264 | static struct pipe3_data data_pcie = { |
265 | .mode = PIPE3_MODE_PCIE, |
266 | .settings = { |
267 | /* DRA75x TRM Table 26-62 Preferred PCIe_PHY_RX SCP Register Settings */ |
268 | .ana_interface = INTERFACE_MODE_PCIE, |
269 | .ana_losd = 0xa, |
270 | .dig_fastlock = 1, |
271 | .dig_lbw = 3, |
272 | .dig_stepcnt = 0, |
273 | .dig_stl = 0x3, |
274 | .dig_thr = 1, |
275 | .dig_thr_mode = 1, |
276 | .dig_2ndo_sdm_mode = 0, |
277 | .dig_hs_rate = 0, |
278 | .dig_ovrd_hs_rate = 0, |
279 | .dll_trim_sel = 0x2, |
280 | .dll_phint_rate = 0x3, |
281 | .eq_lev = 0, |
282 | .eq_ftc = 0x1f, |
283 | .eq_ctl = 1, |
284 | .eq_ovrd_lev = 0, |
285 | .eq_ovrd_ftc = 0, |
286 | }, |
287 | }; |
288 | |
289 | static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset) |
290 | { |
291 | return __raw_readl(addr: addr + offset); |
292 | } |
293 | |
294 | static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset, |
295 | u32 data) |
296 | { |
297 | __raw_writel(val: data, addr: addr + offset); |
298 | } |
299 | |
300 | static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy) |
301 | { |
302 | unsigned long rate; |
303 | struct pipe3_dpll_map *dpll_map = phy->dpll_map; |
304 | |
305 | rate = clk_get_rate(clk: phy->sys_clk); |
306 | |
307 | for (; dpll_map->rate; dpll_map++) { |
308 | if (rate == dpll_map->rate) |
309 | return &dpll_map->params; |
310 | } |
311 | |
312 | dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n" , rate); |
313 | |
314 | return NULL; |
315 | } |
316 | |
317 | static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy); |
318 | static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy); |
319 | |
320 | static int ti_pipe3_power_off(struct phy *x) |
321 | { |
322 | int ret; |
323 | struct ti_pipe3 *phy = phy_get_drvdata(phy: x); |
324 | |
325 | if (!phy->phy_power_syscon) { |
326 | omap_control_phy_power(dev: phy->control_dev, on: 0); |
327 | return 0; |
328 | } |
329 | |
330 | ret = regmap_update_bits(map: phy->phy_power_syscon, reg: phy->power_reg, |
331 | PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val: 0); |
332 | return ret; |
333 | } |
334 | |
335 | static void ti_pipe3_calibrate(struct ti_pipe3 *phy); |
336 | |
337 | static int ti_pipe3_power_on(struct phy *x) |
338 | { |
339 | u32 val; |
340 | u32 mask; |
341 | unsigned long rate; |
342 | struct ti_pipe3 *phy = phy_get_drvdata(phy: x); |
343 | bool rx_pending = false; |
344 | |
345 | if (!phy->phy_power_syscon) { |
346 | omap_control_phy_power(dev: phy->control_dev, on: 1); |
347 | return 0; |
348 | } |
349 | |
350 | rate = clk_get_rate(clk: phy->sys_clk); |
351 | if (!rate) { |
352 | dev_err(phy->dev, "Invalid clock rate\n" ); |
353 | return -EINVAL; |
354 | } |
355 | rate = rate / 1000000; |
356 | mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK; |
357 | val = rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT; |
358 | regmap_update_bits(map: phy->phy_power_syscon, reg: phy->power_reg, |
359 | mask, val); |
360 | /* |
361 | * For PCIe, TX and RX must be powered on simultaneously. |
362 | * For USB and SATA, TX must be powered on before RX |
363 | */ |
364 | mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK; |
365 | if (phy->mode == PIPE3_MODE_SATA || phy->mode == PIPE3_MODE_USBSS) { |
366 | val = PIPE3_PHY_TX_POWERON; |
367 | rx_pending = true; |
368 | } else { |
369 | val = PIPE3_PHY_TX_POWERON | PIPE3_PHY_RX_POWERON; |
370 | } |
371 | |
372 | regmap_update_bits(map: phy->phy_power_syscon, reg: phy->power_reg, |
373 | mask, val); |
374 | |
375 | if (rx_pending) { |
376 | val = PIPE3_PHY_TX_POWERON | PIPE3_PHY_RX_POWERON; |
377 | regmap_update_bits(map: phy->phy_power_syscon, reg: phy->power_reg, |
378 | mask, val); |
379 | } |
380 | |
381 | if (phy->mode == PIPE3_MODE_PCIE) |
382 | ti_pipe3_calibrate(phy); |
383 | |
384 | return 0; |
385 | } |
386 | |
387 | static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy) |
388 | { |
389 | u32 val; |
390 | unsigned long timeout; |
391 | |
392 | timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME); |
393 | do { |
394 | cpu_relax(); |
395 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_STATUS); |
396 | if (val & PLL_LOCK) |
397 | return 0; |
398 | } while (!time_after(jiffies, timeout)); |
399 | |
400 | dev_err(phy->dev, "DPLL failed to lock\n" ); |
401 | return -EBUSY; |
402 | } |
403 | |
404 | static int ti_pipe3_dpll_program(struct ti_pipe3 *phy) |
405 | { |
406 | u32 val; |
407 | struct pipe3_dpll_params *dpll_params; |
408 | |
409 | dpll_params = ti_pipe3_get_dpll_params(phy); |
410 | if (!dpll_params) |
411 | return -EINVAL; |
412 | |
413 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION1); |
414 | val &= ~PLL_REGN_MASK; |
415 | val |= dpll_params->n << PLL_REGN_SHIFT; |
416 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION1, data: val); |
417 | |
418 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2); |
419 | val &= ~PLL_SELFREQDCO_MASK; |
420 | val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; |
421 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2, data: val); |
422 | |
423 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION1); |
424 | val &= ~PLL_REGM_MASK; |
425 | val |= dpll_params->m << PLL_REGM_SHIFT; |
426 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION1, data: val); |
427 | |
428 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION4); |
429 | val &= ~PLL_REGM_F_MASK; |
430 | val |= dpll_params->mf << PLL_REGM_F_SHIFT; |
431 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION4, data: val); |
432 | |
433 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION3); |
434 | val &= ~PLL_SD_MASK; |
435 | val |= dpll_params->sd << PLL_SD_SHIFT; |
436 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION3, data: val); |
437 | |
438 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); |
439 | |
440 | return ti_pipe3_dpll_wait_lock(phy); |
441 | } |
442 | |
443 | static void ti_pipe3_calibrate(struct ti_pipe3 *phy) |
444 | { |
445 | u32 val; |
446 | struct pipe3_settings *s = &phy->settings; |
447 | |
448 | val = ti_pipe3_readl(addr: phy->phy_rx, PIPE3_PHY_RX_ANA_PROGRAMMABILITY); |
449 | val &= ~(INTERFACE_MASK | LOSD_MASK | MEM_PLLDIV); |
450 | val |= (s->ana_interface << INTERFACE_SHIFT | s->ana_losd << LOSD_SHIFT); |
451 | ti_pipe3_writel(addr: phy->phy_rx, PIPE3_PHY_RX_ANA_PROGRAMMABILITY, data: val); |
452 | |
453 | val = ti_pipe3_readl(addr: phy->phy_rx, PIPE3_PHY_RX_DIGITAL_MODES); |
454 | val &= ~(MEM_HS_RATE_MASK | MEM_OVRD_HS_RATE | MEM_CDR_FASTLOCK | |
455 | MEM_CDR_LBW_MASK | MEM_CDR_STEPCNT_MASK | MEM_CDR_STL_MASK | |
456 | MEM_CDR_THR_MASK | MEM_CDR_THR_MODE | MEM_CDR_2NDO_SDM_MODE); |
457 | val |= s->dig_hs_rate << MEM_HS_RATE_SHIFT | |
458 | s->dig_ovrd_hs_rate << MEM_OVRD_HS_RATE_SHIFT | |
459 | s->dig_fastlock << MEM_CDR_FASTLOCK_SHIFT | |
460 | s->dig_lbw << MEM_CDR_LBW_SHIFT | |
461 | s->dig_stepcnt << MEM_CDR_STEPCNT_SHIFT | |
462 | s->dig_stl << MEM_CDR_STL_SHIFT | |
463 | s->dig_thr << MEM_CDR_THR_SHIFT | |
464 | s->dig_thr_mode << MEM_CDR_THR_MODE_SHIFT | |
465 | s->dig_2ndo_sdm_mode << MEM_CDR_2NDO_SDM_MODE_SHIFT; |
466 | ti_pipe3_writel(addr: phy->phy_rx, PIPE3_PHY_RX_DIGITAL_MODES, data: val); |
467 | |
468 | val = ti_pipe3_readl(addr: phy->phy_rx, PIPE3_PHY_RX_TRIM); |
469 | val &= ~MEM_DLL_TRIM_SEL_MASK; |
470 | val |= s->dll_trim_sel << MEM_DLL_TRIM_SHIFT; |
471 | ti_pipe3_writel(addr: phy->phy_rx, PIPE3_PHY_RX_TRIM, data: val); |
472 | |
473 | val = ti_pipe3_readl(addr: phy->phy_rx, PIPE3_PHY_RX_DLL); |
474 | val &= ~MEM_DLL_PHINT_RATE_MASK; |
475 | val |= s->dll_phint_rate << MEM_DLL_PHINT_RATE_SHIFT; |
476 | ti_pipe3_writel(addr: phy->phy_rx, PIPE3_PHY_RX_DLL, data: val); |
477 | |
478 | val = ti_pipe3_readl(addr: phy->phy_rx, PIPE3_PHY_RX_EQUALIZER); |
479 | val &= ~(MEM_EQLEV_MASK | MEM_EQFTC_MASK | MEM_EQCTL_MASK | |
480 | MEM_OVRD_EQLEV | MEM_OVRD_EQFTC); |
481 | val |= s->eq_lev << MEM_EQLEV_SHIFT | |
482 | s->eq_ftc << MEM_EQFTC_SHIFT | |
483 | s->eq_ctl << MEM_EQCTL_SHIFT | |
484 | s->eq_ovrd_lev << MEM_OVRD_EQLEV_SHIFT | |
485 | s->eq_ovrd_ftc << MEM_OVRD_EQFTC_SHIFT; |
486 | ti_pipe3_writel(addr: phy->phy_rx, PIPE3_PHY_RX_EQUALIZER, data: val); |
487 | |
488 | if (phy->mode == PIPE3_MODE_SATA) { |
489 | val = ti_pipe3_readl(addr: phy->phy_rx, |
490 | SATA_PHY_RX_IO_AND_A2D_OVERRIDES); |
491 | val &= ~MEM_CDR_LOS_SOURCE_MASK; |
492 | ti_pipe3_writel(addr: phy->phy_rx, SATA_PHY_RX_IO_AND_A2D_OVERRIDES, |
493 | data: val); |
494 | } |
495 | } |
496 | |
497 | static int ti_pipe3_init(struct phy *x) |
498 | { |
499 | struct ti_pipe3 *phy = phy_get_drvdata(phy: x); |
500 | u32 val; |
501 | int ret = 0; |
502 | |
503 | ti_pipe3_enable_clocks(phy); |
504 | /* |
505 | * Set pcie_pcs register to 0x96 for proper functioning of phy |
506 | * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table |
507 | * 18-1804. |
508 | */ |
509 | if (phy->mode == PIPE3_MODE_PCIE) { |
510 | if (!phy->pcs_syscon) { |
511 | omap_control_pcie_pcs(dev: phy->control_dev, delay: 0x96); |
512 | return 0; |
513 | } |
514 | |
515 | val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT; |
516 | ret = regmap_update_bits(map: phy->pcs_syscon, reg: phy->pcie_pcs_reg, |
517 | PCIE_PCS_MASK, val); |
518 | return ret; |
519 | } |
520 | |
521 | /* Bring it out of IDLE if it is IDLE */ |
522 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2); |
523 | if (val & PLL_IDLE) { |
524 | val &= ~PLL_IDLE; |
525 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2, data: val); |
526 | ret = ti_pipe3_dpll_wait_lock(phy); |
527 | } |
528 | |
529 | /* SATA has issues if re-programmed when locked */ |
530 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_STATUS); |
531 | if ((val & PLL_LOCK) && phy->mode == PIPE3_MODE_SATA) |
532 | return ret; |
533 | |
534 | /* Program the DPLL */ |
535 | ret = ti_pipe3_dpll_program(phy); |
536 | if (ret) { |
537 | ti_pipe3_disable_clocks(phy); |
538 | return -EINVAL; |
539 | } |
540 | |
541 | ti_pipe3_calibrate(phy); |
542 | |
543 | return ret; |
544 | } |
545 | |
546 | static int ti_pipe3_exit(struct phy *x) |
547 | { |
548 | struct ti_pipe3 *phy = phy_get_drvdata(phy: x); |
549 | u32 val; |
550 | unsigned long timeout; |
551 | |
552 | /* If dpll_reset_syscon is not present we wont power down SATA DPLL |
553 | * due to Errata i783 |
554 | */ |
555 | if (phy->mode == PIPE3_MODE_SATA && !phy->dpll_reset_syscon) |
556 | return 0; |
557 | |
558 | /* PCIe doesn't have internal DPLL */ |
559 | if (phy->mode != PIPE3_MODE_PCIE) { |
560 | /* Put DPLL in IDLE mode */ |
561 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2); |
562 | val |= PLL_IDLE; |
563 | ti_pipe3_writel(addr: phy->pll_ctrl_base, PLL_CONFIGURATION2, data: val); |
564 | |
565 | /* wait for LDO and Oscillator to power down */ |
566 | timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); |
567 | do { |
568 | cpu_relax(); |
569 | val = ti_pipe3_readl(addr: phy->pll_ctrl_base, PLL_STATUS); |
570 | if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) |
571 | break; |
572 | } while (!time_after(jiffies, timeout)); |
573 | |
574 | if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { |
575 | dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n" , |
576 | val); |
577 | return -EBUSY; |
578 | } |
579 | } |
580 | |
581 | /* i783: SATA needs control bit toggle after PLL unlock */ |
582 | if (phy->mode == PIPE3_MODE_SATA) { |
583 | regmap_update_bits(map: phy->dpll_reset_syscon, reg: phy->dpll_reset_reg, |
584 | SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET); |
585 | regmap_update_bits(map: phy->dpll_reset_syscon, reg: phy->dpll_reset_reg, |
586 | SATA_PLL_SOFT_RESET, val: 0); |
587 | } |
588 | |
589 | ti_pipe3_disable_clocks(phy); |
590 | |
591 | return 0; |
592 | } |
593 | static const struct phy_ops ops = { |
594 | .init = ti_pipe3_init, |
595 | .exit = ti_pipe3_exit, |
596 | .power_on = ti_pipe3_power_on, |
597 | .power_off = ti_pipe3_power_off, |
598 | .owner = THIS_MODULE, |
599 | }; |
600 | |
601 | static const struct of_device_id ti_pipe3_id_table[]; |
602 | |
603 | static int ti_pipe3_get_clk(struct ti_pipe3 *phy) |
604 | { |
605 | struct clk *clk; |
606 | struct device *dev = phy->dev; |
607 | |
608 | phy->refclk = devm_clk_get(dev, id: "refclk" ); |
609 | if (IS_ERR(ptr: phy->refclk)) { |
610 | dev_err(dev, "unable to get refclk\n" ); |
611 | /* older DTBs have missing refclk in SATA PHY |
612 | * so don't bail out in case of SATA PHY. |
613 | */ |
614 | if (phy->mode != PIPE3_MODE_SATA) |
615 | return PTR_ERR(ptr: phy->refclk); |
616 | } |
617 | |
618 | if (phy->mode != PIPE3_MODE_SATA) { |
619 | phy->wkupclk = devm_clk_get(dev, id: "wkupclk" ); |
620 | if (IS_ERR(ptr: phy->wkupclk)) { |
621 | dev_err(dev, "unable to get wkupclk\n" ); |
622 | return PTR_ERR(ptr: phy->wkupclk); |
623 | } |
624 | } else { |
625 | phy->wkupclk = ERR_PTR(error: -ENODEV); |
626 | } |
627 | |
628 | if (phy->mode != PIPE3_MODE_PCIE || phy->phy_power_syscon) { |
629 | phy->sys_clk = devm_clk_get(dev, id: "sysclk" ); |
630 | if (IS_ERR(ptr: phy->sys_clk)) { |
631 | dev_err(dev, "unable to get sysclk\n" ); |
632 | return -EINVAL; |
633 | } |
634 | } |
635 | |
636 | if (phy->mode == PIPE3_MODE_PCIE) { |
637 | clk = devm_clk_get(dev, id: "dpll_ref" ); |
638 | if (IS_ERR(ptr: clk)) { |
639 | dev_err(dev, "unable to get dpll ref clk\n" ); |
640 | return PTR_ERR(ptr: clk); |
641 | } |
642 | clk_set_rate(clk, rate: 1500000000); |
643 | |
644 | clk = devm_clk_get(dev, id: "dpll_ref_m2" ); |
645 | if (IS_ERR(ptr: clk)) { |
646 | dev_err(dev, "unable to get dpll ref m2 clk\n" ); |
647 | return PTR_ERR(ptr: clk); |
648 | } |
649 | clk_set_rate(clk, rate: 100000000); |
650 | |
651 | clk = devm_clk_get(dev, id: "phy-div" ); |
652 | if (IS_ERR(ptr: clk)) { |
653 | dev_err(dev, "unable to get phy-div clk\n" ); |
654 | return PTR_ERR(ptr: clk); |
655 | } |
656 | clk_set_rate(clk, rate: 100000000); |
657 | |
658 | phy->div_clk = devm_clk_get(dev, id: "div-clk" ); |
659 | if (IS_ERR(ptr: phy->div_clk)) { |
660 | dev_err(dev, "unable to get div-clk\n" ); |
661 | return PTR_ERR(ptr: phy->div_clk); |
662 | } |
663 | } else { |
664 | phy->div_clk = ERR_PTR(error: -ENODEV); |
665 | } |
666 | |
667 | return 0; |
668 | } |
669 | |
670 | static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) |
671 | { |
672 | struct device *dev = phy->dev; |
673 | struct device_node *node = dev->of_node; |
674 | struct device_node *control_node; |
675 | struct platform_device *control_pdev; |
676 | |
677 | phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(np: node, |
678 | property: "syscon-phy-power" ); |
679 | if (IS_ERR(ptr: phy->phy_power_syscon)) { |
680 | dev_dbg(dev, |
681 | "can't get syscon-phy-power, using control device\n" ); |
682 | phy->phy_power_syscon = NULL; |
683 | } else { |
684 | if (of_property_read_u32_index(np: node, |
685 | propname: "syscon-phy-power" , index: 1, |
686 | out_value: &phy->power_reg)) { |
687 | dev_err(dev, "couldn't get power reg. offset\n" ); |
688 | return -EINVAL; |
689 | } |
690 | } |
691 | |
692 | if (!phy->phy_power_syscon) { |
693 | control_node = of_parse_phandle(np: node, phandle_name: "ctrl-module" , index: 0); |
694 | if (!control_node) { |
695 | dev_err(dev, "Failed to get control device phandle\n" ); |
696 | return -EINVAL; |
697 | } |
698 | |
699 | control_pdev = of_find_device_by_node(np: control_node); |
700 | of_node_put(node: control_node); |
701 | if (!control_pdev) { |
702 | dev_err(dev, "Failed to get control device\n" ); |
703 | return -EINVAL; |
704 | } |
705 | |
706 | phy->control_dev = &control_pdev->dev; |
707 | } |
708 | |
709 | if (phy->mode == PIPE3_MODE_PCIE) { |
710 | phy->pcs_syscon = syscon_regmap_lookup_by_phandle(np: node, |
711 | property: "syscon-pcs" ); |
712 | if (IS_ERR(ptr: phy->pcs_syscon)) { |
713 | dev_dbg(dev, |
714 | "can't get syscon-pcs, using omap control\n" ); |
715 | phy->pcs_syscon = NULL; |
716 | } else { |
717 | if (of_property_read_u32_index(np: node, |
718 | propname: "syscon-pcs" , index: 1, |
719 | out_value: &phy->pcie_pcs_reg)) { |
720 | dev_err(dev, |
721 | "couldn't get pcie pcs reg. offset\n" ); |
722 | return -EINVAL; |
723 | } |
724 | } |
725 | } |
726 | |
727 | if (phy->mode == PIPE3_MODE_SATA) { |
728 | phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(np: node, |
729 | property: "syscon-pllreset" ); |
730 | if (IS_ERR(ptr: phy->dpll_reset_syscon)) { |
731 | dev_info(dev, |
732 | "can't get syscon-pllreset, sata dpll won't idle\n" ); |
733 | phy->dpll_reset_syscon = NULL; |
734 | } else { |
735 | if (of_property_read_u32_index(np: node, |
736 | propname: "syscon-pllreset" , index: 1, |
737 | out_value: &phy->dpll_reset_reg)) { |
738 | dev_err(dev, |
739 | "couldn't get pllreset reg. offset\n" ); |
740 | return -EINVAL; |
741 | } |
742 | } |
743 | } |
744 | |
745 | return 0; |
746 | } |
747 | |
748 | static int ti_pipe3_get_tx_rx_base(struct ti_pipe3 *phy) |
749 | { |
750 | struct device *dev = phy->dev; |
751 | struct platform_device *pdev = to_platform_device(dev); |
752 | |
753 | phy->phy_rx = devm_platform_ioremap_resource_byname(pdev, name: "phy_rx" ); |
754 | if (IS_ERR(ptr: phy->phy_rx)) |
755 | return PTR_ERR(ptr: phy->phy_rx); |
756 | |
757 | phy->phy_tx = devm_platform_ioremap_resource_byname(pdev, name: "phy_tx" ); |
758 | |
759 | return PTR_ERR_OR_ZERO(ptr: phy->phy_tx); |
760 | } |
761 | |
762 | static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy) |
763 | { |
764 | struct device *dev = phy->dev; |
765 | struct platform_device *pdev = to_platform_device(dev); |
766 | |
767 | if (phy->mode == PIPE3_MODE_PCIE) |
768 | return 0; |
769 | |
770 | phy->pll_ctrl_base = |
771 | devm_platform_ioremap_resource_byname(pdev, name: "pll_ctrl" ); |
772 | return PTR_ERR_OR_ZERO(ptr: phy->pll_ctrl_base); |
773 | } |
774 | |
775 | static int ti_pipe3_probe(struct platform_device *pdev) |
776 | { |
777 | struct ti_pipe3 *phy; |
778 | struct phy *generic_phy; |
779 | struct phy_provider *phy_provider; |
780 | struct device *dev = &pdev->dev; |
781 | int ret; |
782 | const struct pipe3_data *data; |
783 | |
784 | phy = devm_kzalloc(dev, size: sizeof(*phy), GFP_KERNEL); |
785 | if (!phy) |
786 | return -ENOMEM; |
787 | |
788 | data = device_get_match_data(dev); |
789 | if (!data) |
790 | return -EINVAL; |
791 | |
792 | phy->dev = dev; |
793 | phy->mode = data->mode; |
794 | phy->dpll_map = data->dpll_map; |
795 | phy->settings = data->settings; |
796 | |
797 | ret = ti_pipe3_get_pll_base(phy); |
798 | if (ret) |
799 | return ret; |
800 | |
801 | ret = ti_pipe3_get_tx_rx_base(phy); |
802 | if (ret) |
803 | return ret; |
804 | |
805 | ret = ti_pipe3_get_sysctrl(phy); |
806 | if (ret) |
807 | return ret; |
808 | |
809 | ret = ti_pipe3_get_clk(phy); |
810 | if (ret) |
811 | return ret; |
812 | |
813 | platform_set_drvdata(pdev, data: phy); |
814 | pm_runtime_enable(dev); |
815 | |
816 | /* |
817 | * Prevent auto-disable of refclk for SATA PHY due to Errata i783 |
818 | */ |
819 | if (phy->mode == PIPE3_MODE_SATA) { |
820 | if (!IS_ERR(ptr: phy->refclk)) { |
821 | clk_prepare_enable(clk: phy->refclk); |
822 | phy->sata_refclk_enabled = true; |
823 | } |
824 | } |
825 | |
826 | generic_phy = devm_phy_create(dev, NULL, ops: &ops); |
827 | if (IS_ERR(ptr: generic_phy)) |
828 | return PTR_ERR(ptr: generic_phy); |
829 | |
830 | phy_set_drvdata(phy: generic_phy, data: phy); |
831 | |
832 | ti_pipe3_power_off(x: generic_phy); |
833 | |
834 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
835 | return PTR_ERR_OR_ZERO(ptr: phy_provider); |
836 | } |
837 | |
838 | static void ti_pipe3_remove(struct platform_device *pdev) |
839 | { |
840 | struct ti_pipe3 *phy = platform_get_drvdata(pdev); |
841 | |
842 | if (phy->mode == PIPE3_MODE_SATA) { |
843 | clk_disable_unprepare(clk: phy->refclk); |
844 | phy->sata_refclk_enabled = false; |
845 | } |
846 | pm_runtime_disable(dev: &pdev->dev); |
847 | } |
848 | |
849 | static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) |
850 | { |
851 | int ret = 0; |
852 | |
853 | if (!IS_ERR(ptr: phy->refclk)) { |
854 | ret = clk_prepare_enable(clk: phy->refclk); |
855 | if (ret) { |
856 | dev_err(phy->dev, "Failed to enable refclk %d\n" , ret); |
857 | return ret; |
858 | } |
859 | } |
860 | |
861 | if (!IS_ERR(ptr: phy->wkupclk)) { |
862 | ret = clk_prepare_enable(clk: phy->wkupclk); |
863 | if (ret) { |
864 | dev_err(phy->dev, "Failed to enable wkupclk %d\n" , ret); |
865 | goto disable_refclk; |
866 | } |
867 | } |
868 | |
869 | if (!IS_ERR(ptr: phy->div_clk)) { |
870 | ret = clk_prepare_enable(clk: phy->div_clk); |
871 | if (ret) { |
872 | dev_err(phy->dev, "Failed to enable div_clk %d\n" , ret); |
873 | goto disable_wkupclk; |
874 | } |
875 | } |
876 | |
877 | return 0; |
878 | |
879 | disable_wkupclk: |
880 | if (!IS_ERR(ptr: phy->wkupclk)) |
881 | clk_disable_unprepare(clk: phy->wkupclk); |
882 | |
883 | disable_refclk: |
884 | if (!IS_ERR(ptr: phy->refclk)) |
885 | clk_disable_unprepare(clk: phy->refclk); |
886 | |
887 | return ret; |
888 | } |
889 | |
890 | static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy) |
891 | { |
892 | if (!IS_ERR(ptr: phy->wkupclk)) |
893 | clk_disable_unprepare(clk: phy->wkupclk); |
894 | if (!IS_ERR(ptr: phy->refclk)) |
895 | clk_disable_unprepare(clk: phy->refclk); |
896 | if (!IS_ERR(ptr: phy->div_clk)) |
897 | clk_disable_unprepare(clk: phy->div_clk); |
898 | } |
899 | |
900 | static const struct of_device_id ti_pipe3_id_table[] = { |
901 | { |
902 | .compatible = "ti,phy-usb3" , |
903 | .data = &data_usb, |
904 | }, |
905 | { |
906 | .compatible = "ti,omap-usb3" , |
907 | .data = &data_usb, |
908 | }, |
909 | { |
910 | .compatible = "ti,phy-pipe3-sata" , |
911 | .data = &data_sata, |
912 | }, |
913 | { |
914 | .compatible = "ti,phy-pipe3-pcie" , |
915 | .data = &data_pcie, |
916 | }, |
917 | {} |
918 | }; |
919 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); |
920 | |
921 | static struct platform_driver ti_pipe3_driver = { |
922 | .probe = ti_pipe3_probe, |
923 | .remove_new = ti_pipe3_remove, |
924 | .driver = { |
925 | .name = "ti-pipe3" , |
926 | .of_match_table = ti_pipe3_id_table, |
927 | }, |
928 | }; |
929 | |
930 | module_platform_driver(ti_pipe3_driver); |
931 | |
932 | MODULE_ALIAS("platform:ti_pipe3" ); |
933 | MODULE_AUTHOR("Texas Instruments Inc." ); |
934 | MODULE_DESCRIPTION("TI PIPE3 phy driver" ); |
935 | MODULE_LICENSE("GPL v2" ); |
936 | |