blob: e3b33569285f0e27f78bbb618dd15b9a84d8f5f9 [file] [log] [blame]
Scott Telfordc8b427e2018-08-09 11:30:30 +01001// SPDX-License-Identifier: GPL-2.0-only
2/*
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01003 * Cadence Torrent SD0801 PHY driver.
Scott Telfordc8b427e2018-08-09 11:30:30 +01004 *
5 * Copyright 2018 Cadence Design Systems, Inc.
6 *
7 */
8
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01009#include <linux/clk.h>
Scott Telfordc8b427e2018-08-09 11:30:30 +010010#include <linux/delay.h>
11#include <linux/err.h>
12#include <linux/io.h>
13#include <linux/iopoll.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/of_device.h>
19#include <linux/phy/phy.h>
20#include <linux/platform_device.h>
21
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010022#define REF_CLK_19_2MHz 19200000
23#define REF_CLK_25MHz 25000000
24
25#define DEFAULT_NUM_LANES 4
Scott Telfordc8b427e2018-08-09 11:30:30 +010026#define MAX_NUM_LANES 4
27#define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */
28
Swapnil Jakhade21c79142020-02-06 07:10:55 +010029#define POLL_TIMEOUT_US 5000
Scott Telfordc8b427e2018-08-09 11:30:30 +010030#define LANE_MASK 0x7
31
32/*
33 * register offsets from DPTX PHY register block base (i.e MHDP
34 * register base + 0x30a00)
35 */
36#define PHY_AUX_CONFIG 0x00
37#define PHY_AUX_CTRL 0x04
38#define PHY_RESET 0x20
Swapnil Jakhade572d6592020-02-06 07:10:57 +010039#define PMA_TX_ELEC_IDLE_MASK 0xF0U
40#define PMA_TX_ELEC_IDLE_SHIFT 4
41#define PHY_L00_RESET_N_MASK 0x01U
Scott Telfordc8b427e2018-08-09 11:30:30 +010042#define PHY_PMA_XCVR_PLLCLK_EN 0x24
43#define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28
44#define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c
45#define PHY_POWER_STATE_LN_0 0x0000
46#define PHY_POWER_STATE_LN_1 0x0008
47#define PHY_POWER_STATE_LN_2 0x0010
48#define PHY_POWER_STATE_LN_3 0x0018
Swapnil Jakhade21c79142020-02-06 07:10:55 +010049#define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU
Scott Telfordc8b427e2018-08-09 11:30:30 +010050#define PHY_PMA_XCVR_POWER_STATE_ACK 0x30
51#define PHY_PMA_CMN_READY 0x34
52#define PHY_PMA_XCVR_TX_VMARGIN 0x38
53#define PHY_PMA_XCVR_TX_DEEMPH 0x3c
54
55/*
56 * register offsets from SD0801 PHY register block base (i.e MHDP
57 * register base + 0x500000)
58 */
59#define CMN_SSM_BANDGAP_TMR 0x00084
60#define CMN_SSM_BIAS_TMR 0x00088
61#define CMN_PLLSM0_PLLPRE_TMR 0x000a8
62#define CMN_PLLSM0_PLLLOCK_TMR 0x000b0
63#define CMN_PLLSM1_PLLPRE_TMR 0x000c8
64#define CMN_PLLSM1_PLLLOCK_TMR 0x000d0
65#define CMN_BGCAL_INIT_TMR 0x00190
66#define CMN_BGCAL_ITER_TMR 0x00194
67#define CMN_IBCAL_INIT_TMR 0x001d0
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010068#define CMN_PLL0_VCOCAL_TCTRL 0x00208
Scott Telfordc8b427e2018-08-09 11:30:30 +010069#define CMN_PLL0_VCOCAL_INIT_TMR 0x00210
70#define CMN_PLL0_VCOCAL_ITER_TMR 0x00214
71#define CMN_PLL0_VCOCAL_REFTIM_START 0x00218
72#define CMN_PLL0_VCOCAL_PLLCNT_START 0x00220
73#define CMN_PLL0_INTDIV_M0 0x00240
74#define CMN_PLL0_FRACDIVL_M0 0x00244
75#define CMN_PLL0_FRACDIVH_M0 0x00248
76#define CMN_PLL0_HIGH_THR_M0 0x0024c
77#define CMN_PLL0_DSM_DIAG_M0 0x00250
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010078#define CMN_PLL0_SS_CTRL1_M0 0x00260
79#define CMN_PLL0_SS_CTRL2_M0 0x00264
80#define CMN_PLL0_SS_CTRL3_M0 0x00268
81#define CMN_PLL0_SS_CTRL4_M0 0x0026C
82#define CMN_PLL0_LOCK_REFCNT_START 0x00270
Scott Telfordc8b427e2018-08-09 11:30:30 +010083#define CMN_PLL0_LOCK_PLLCNT_START 0x00278
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010084#define CMN_PLL0_LOCK_PLLCNT_THR 0x0027C
85#define CMN_PLL1_VCOCAL_TCTRL 0x00308
Scott Telfordc8b427e2018-08-09 11:30:30 +010086#define CMN_PLL1_VCOCAL_INIT_TMR 0x00310
87#define CMN_PLL1_VCOCAL_ITER_TMR 0x00314
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010088#define CMN_PLL1_VCOCAL_REFTIM_START 0x00318
89#define CMN_PLL1_VCOCAL_PLLCNT_START 0x00320
90#define CMN_PLL1_INTDIV_M0 0x00340
91#define CMN_PLL1_FRACDIVL_M0 0x00344
92#define CMN_PLL1_FRACDIVH_M0 0x00348
93#define CMN_PLL1_HIGH_THR_M0 0x0034c
Scott Telfordc8b427e2018-08-09 11:30:30 +010094#define CMN_PLL1_DSM_DIAG_M0 0x00350
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010095#define CMN_PLL1_SS_CTRL1_M0 0x00360
96#define CMN_PLL1_SS_CTRL2_M0 0x00364
97#define CMN_PLL1_SS_CTRL3_M0 0x00368
98#define CMN_PLL1_SS_CTRL4_M0 0x0036C
99#define CMN_PLL1_LOCK_REFCNT_START 0x00370
100#define CMN_PLL1_LOCK_PLLCNT_START 0x00378
101#define CMN_PLL1_LOCK_PLLCNT_THR 0x0037C
Scott Telfordc8b427e2018-08-09 11:30:30 +0100102#define CMN_TXPUCAL_INIT_TMR 0x00410
103#define CMN_TXPUCAL_ITER_TMR 0x00414
104#define CMN_TXPDCAL_INIT_TMR 0x00430
105#define CMN_TXPDCAL_ITER_TMR 0x00434
106#define CMN_RXCAL_INIT_TMR 0x00450
107#define CMN_RXCAL_ITER_TMR 0x00454
108#define CMN_SD_CAL_INIT_TMR 0x00490
109#define CMN_SD_CAL_ITER_TMR 0x00494
110#define CMN_SD_CAL_REFTIM_START 0x00498
111#define CMN_SD_CAL_PLLCNT_START 0x004a0
112#define CMN_PDIAG_PLL0_CTRL_M0 0x00680
113#define CMN_PDIAG_PLL0_CLK_SEL_M0 0x00684
114#define CMN_PDIAG_PLL0_CP_PADJ_M0 0x00690
115#define CMN_PDIAG_PLL0_CP_IADJ_M0 0x00694
116#define CMN_PDIAG_PLL0_FILT_PADJ_M0 0x00698
117#define CMN_PDIAG_PLL0_CP_PADJ_M1 0x006d0
118#define CMN_PDIAG_PLL0_CP_IADJ_M1 0x006d4
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100119#define CMN_PDIAG_PLL1_CTRL_M0 0x00700
Scott Telfordc8b427e2018-08-09 11:30:30 +0100120#define CMN_PDIAG_PLL1_CLK_SEL_M0 0x00704
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100121#define CMN_PDIAG_PLL1_CP_PADJ_M0 0x00710
122#define CMN_PDIAG_PLL1_CP_IADJ_M0 0x00714
123#define CMN_PDIAG_PLL1_FILT_PADJ_M0 0x00718
124
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100125#define TX_TXCC_CTRL 0x10100
126#define TX_TXCC_CPOST_MULT_00 0x10130
127#define TX_TXCC_MGNFS_MULT_000 0x10140
128#define DRV_DIAG_TX_DRV 0x10318
Scott Telfordc8b427e2018-08-09 11:30:30 +0100129#define XCVR_DIAG_PLLDRC_CTRL 0x10394
130#define XCVR_DIAG_HSCLK_SEL 0x10398
131#define XCVR_DIAG_HSCLK_DIV 0x1039c
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100132#define XCVR_DIAG_BIDI_CTRL 0x103a8
Scott Telfordc8b427e2018-08-09 11:30:30 +0100133#define TX_PSC_A0 0x10400
134#define TX_PSC_A1 0x10404
135#define TX_PSC_A2 0x10408
136#define TX_PSC_A3 0x1040c
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100137#define TX_RCVDET_ST_TMR 0x1048c
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100138#define TX_DIAG_ACYA 0x1079c
139#define TX_DIAG_ACYA_HBDC_MASK 0x0001U
Scott Telfordc8b427e2018-08-09 11:30:30 +0100140#define RX_PSC_A0 0x20000
141#define RX_PSC_A1 0x20004
142#define RX_PSC_A2 0x20008
143#define RX_PSC_A3 0x2000c
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100144#define RX_PSC_CAL 0x20018
145#define RX_REE_GCSM1_CTRL 0x20420
146#define RX_REE_GCSM2_CTRL 0x20440
147#define RX_REE_PERGCSM_CTRL 0x20460
148
Scott Telfordc8b427e2018-08-09 11:30:30 +0100149#define PHY_PLL_CFG 0x30038
150
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100151#define PHY_PMA_CMN_CTRL2 0x38004
152#define PHY_PMA_PLL_RAW_CTRL 0x3800c
153
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100154struct cdns_torrent_phy {
Scott Telfordc8b427e2018-08-09 11:30:30 +0100155 void __iomem *base; /* DPTX registers base */
156 void __iomem *sd_base; /* SD0801 registers base */
157 u32 num_lanes; /* Number of lanes to use */
158 u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
159 struct device *dev;
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100160 struct clk *clk;
161 unsigned long ref_clk_rate;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100162};
163
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100164enum phy_powerstate {
165 POWERSTATE_A0 = 0,
166 /* Powerstate A1 is unused */
167 POWERSTATE_A2 = 2,
168 POWERSTATE_A3 = 3,
169};
170
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100171static int cdns_torrent_dp_init(struct phy *phy);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100172static int cdns_torrent_dp_exit(struct phy *phy);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100173static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
174 u32 num_lanes);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100175static
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100176int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100177static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy);
178static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100179void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy);
180static
181void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
182 u32 rate, bool ssc);
183static
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100184void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100185static
186void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
187 u32 rate, bool ssc);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100188static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
Scott Telfordc8b427e2018-08-09 11:30:30 +0100189 unsigned int lane);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100190static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
191 u32 rate, u32 num_lanes);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100192static void cdns_dp_phy_write_field(struct cdns_torrent_phy *cdns_phy,
193 unsigned int offset,
194 unsigned char start_bit,
195 unsigned char num_bits,
196 unsigned int val);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100197
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100198static int cdns_torrent_dp_configure(struct phy *phy,
199 union phy_configure_opts *opts);
200static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
201 u32 num_lanes,
202 enum phy_powerstate powerstate);
203
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100204static const struct phy_ops cdns_torrent_phy_ops = {
205 .init = cdns_torrent_dp_init,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100206 .exit = cdns_torrent_dp_exit,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100207 .configure = cdns_torrent_dp_configure,
Scott Telfordc8b427e2018-08-09 11:30:30 +0100208 .owner = THIS_MODULE,
209};
210
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +0100211/* PHY mmr access functions */
212
213static void cdns_torrent_phy_write(struct cdns_torrent_phy *cdns_phy,
214 u32 offset, u32 val)
215{
216 writel(val, cdns_phy->sd_base + offset);
217}
218
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100219static u32 cdns_torrent_phy_read(struct cdns_torrent_phy *cdns_phy, u32 offset)
220{
221 return readl(cdns_phy->sd_base + offset);
222}
223
224#define cdns_torrent_phy_read_poll_timeout(cdns_phy, offset, val, cond, \
225 delay_us, timeout_us) \
226 readl_poll_timeout((cdns_phy)->sd_base + (offset), \
227 val, cond, delay_us, timeout_us)
228
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100229/* DPTX mmr access functions */
230
231static void cdns_torrent_dp_write(struct cdns_torrent_phy *cdns_phy,
232 u32 offset, u32 val)
233{
234 writel(val, cdns_phy->base + offset);
235}
236
237static u32 cdns_torrent_dp_read(struct cdns_torrent_phy *cdns_phy, u32 offset)
238{
239 return readl(cdns_phy->base + offset);
240}
241
242#define cdns_torrent_dp_read_poll_timeout(cdns_phy, offset, val, cond, \
243 delay_us, timeout_us) \
244 readl_poll_timeout((cdns_phy)->base + (offset), \
245 val, cond, delay_us, timeout_us)
246
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100247/*
248 * Structure used to store values of PHY registers for voltage-related
249 * coefficients, for particular voltage swing and pre-emphasis level. Values
250 * are shared across all physical lanes.
251 */
252struct coefficients {
253 /* Value of DRV_DIAG_TX_DRV register to use */
254 u16 diag_tx_drv;
255 /* Value of TX_TXCC_MGNFS_MULT_000 register to use */
256 u16 mgnfs_mult;
257 /* Value of TX_TXCC_CPOST_MULT_00 register to use */
258 u16 cpost_mult;
259};
260
261/*
262 * Array consists of values of voltage-related registers for sd0801 PHY. A value
263 * of 0xFFFF is a placeholder for invalid combination, and will never be used.
264 */
265static const struct coefficients vltg_coeff[4][4] = {
266 /* voltage swing 0, pre-emphasis 0->3 */
267 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x002A,
268 .cpost_mult = 0x0000},
269 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x001F,
270 .cpost_mult = 0x0014},
271 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0012,
272 .cpost_mult = 0x0020},
273 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
274 .cpost_mult = 0x002A}
275 },
276
277 /* voltage swing 1, pre-emphasis 0->3 */
278 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x001F,
279 .cpost_mult = 0x0000},
280 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0013,
281 .cpost_mult = 0x0012},
282 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
283 .cpost_mult = 0x001F},
284 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
285 .cpost_mult = 0xFFFF}
286 },
287
288 /* voltage swing 2, pre-emphasis 0->3 */
289 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0013,
290 .cpost_mult = 0x0000},
291 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
292 .cpost_mult = 0x0013},
293 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
294 .cpost_mult = 0xFFFF},
295 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
296 .cpost_mult = 0xFFFF}
297 },
298
299 /* voltage swing 3, pre-emphasis 0->3 */
300 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
301 .cpost_mult = 0x0000},
302 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
303 .cpost_mult = 0xFFFF},
304 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
305 .cpost_mult = 0xFFFF},
306 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
307 .cpost_mult = 0xFFFF}
308 }
309};
310
311/*
312 * Enable or disable PLL for selected lanes.
313 */
314static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
315 struct phy_configure_opts_dp *dp,
316 bool enable)
317{
318 u32 rd_val;
319 u32 ret;
320 /*
321 * Used to determine, which bits to check for or enable in
322 * PHY_PMA_XCVR_PLLCLK_EN register.
323 */
324 u32 pll_bits;
325 /* Used to enable or disable lanes. */
326 u32 pll_val;
327
328 /* Select values of registers and mask, depending on enabled lane
329 * count.
330 */
331 switch (dp->lanes) {
332 /* lane 0 */
333 case (1):
334 pll_bits = 0x00000001;
335 break;
336 /* lanes 0-1 */
337 case (2):
338 pll_bits = 0x00000003;
339 break;
340 /* lanes 0-3, all */
341 default:
342 pll_bits = 0x0000000F;
343 break;
344 }
345
346 if (enable)
347 pll_val = pll_bits;
348 else
349 pll_val = 0x00000000;
350
351 cdns_torrent_dp_write(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN, pll_val);
352
353 /* Wait for acknowledgment from PHY. */
354 ret = cdns_torrent_dp_read_poll_timeout(cdns_phy,
355 PHY_PMA_XCVR_PLLCLK_EN_ACK,
356 rd_val,
357 (rd_val & pll_bits) == pll_val,
358 0, POLL_TIMEOUT_US);
359 ndelay(100);
360 return ret;
361}
362
363/*
364 * Perform register operations related to setting link rate, once powerstate is
365 * set and PLL disable request was processed.
366 */
367static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
368 struct phy_configure_opts_dp *dp)
369{
370 u32 ret;
371 u32 read_val;
372
373 /* Disable the cmn_pll0_en before re-programming the new data rate. */
374 cdns_torrent_phy_write(cdns_phy, PHY_PMA_PLL_RAW_CTRL, 0);
375
376 /*
377 * Wait for PLL ready de-assertion.
378 * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1
379 */
380 ret = cdns_torrent_phy_read_poll_timeout(cdns_phy, PHY_PMA_CMN_CTRL2,
381 read_val,
382 ((read_val >> 2) & 0x01) != 0,
383 0, POLL_TIMEOUT_US);
384 if (ret)
385 return ret;
386 ndelay(200);
387
388 /* DP Rate Change - VCO Output settings. */
389 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) {
390 /* PMA common configuration 19.2MHz */
391 cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate,
392 dp->ssc);
393 cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
394 } else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) {
395 /* PMA common configuration 25MHz */
396 cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate,
397 dp->ssc);
398 cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
399 }
400 cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
401
402 /* Enable the cmn_pll0_en. */
403 cdns_torrent_phy_write(cdns_phy, PHY_PMA_PLL_RAW_CTRL, 0x3);
404
405 /*
406 * Wait for PLL ready assertion.
407 * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1
408 */
409 ret = cdns_torrent_phy_read_poll_timeout(cdns_phy, PHY_PMA_CMN_CTRL2,
410 read_val,
411 (read_val & 0x01) != 0,
412 0, POLL_TIMEOUT_US);
413 return ret;
414}
415
416/*
417 * Verify, that parameters to configure PHY with are correct.
418 */
419static int cdns_torrent_dp_verify_config(struct cdns_torrent_phy *cdns_phy,
420 struct phy_configure_opts_dp *dp)
421{
422 u8 i;
423
424 /* If changing link rate was required, verify it's supported. */
425 if (dp->set_rate) {
426 switch (dp->link_rate) {
427 case 1620:
428 case 2160:
429 case 2430:
430 case 2700:
431 case 3240:
432 case 4320:
433 case 5400:
434 case 8100:
435 /* valid bit rate */
436 break;
437 default:
438 return -EINVAL;
439 }
440 }
441
442 /* Verify lane count. */
443 switch (dp->lanes) {
444 case 1:
445 case 2:
446 case 4:
447 /* valid lane count. */
448 break;
449 default:
450 return -EINVAL;
451 }
452
453 /* Check against actual number of PHY's lanes. */
454 if (dp->lanes > cdns_phy->num_lanes)
455 return -EINVAL;
456
457 /*
458 * If changing voltages is required, check swing and pre-emphasis
459 * levels, per-lane.
460 */
461 if (dp->set_voltages) {
462 /* Lane count verified previously. */
463 for (i = 0; i < dp->lanes; i++) {
464 if (dp->voltage[i] > 3 || dp->pre[i] > 3)
465 return -EINVAL;
466
467 /* Sum of voltage swing and pre-emphasis levels cannot
468 * exceed 3.
469 */
470 if (dp->voltage[i] + dp->pre[i] > 3)
471 return -EINVAL;
472 }
473 }
474
475 return 0;
476}
477
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100478/* Set power state A0 and PLL clock enable to 0 on enabled lanes. */
479static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
480 u32 num_lanes)
481{
482 u32 pwr_state = cdns_torrent_dp_read(cdns_phy,
483 PHY_PMA_XCVR_POWER_STATE_REQ);
484 u32 pll_clk_en = cdns_torrent_dp_read(cdns_phy,
485 PHY_PMA_XCVR_PLLCLK_EN);
486
487 /* Lane 0 is always enabled. */
488 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
489 PHY_POWER_STATE_LN_0);
490 pll_clk_en &= ~0x01U;
491
492 if (num_lanes > 1) {
493 /* lane 1 */
494 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
495 PHY_POWER_STATE_LN_1);
496 pll_clk_en &= ~(0x01U << 1);
497 }
498
499 if (num_lanes > 2) {
500 /* lanes 2 and 3 */
501 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
502 PHY_POWER_STATE_LN_2);
503 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
504 PHY_POWER_STATE_LN_3);
505 pll_clk_en &= ~(0x01U << 2);
506 pll_clk_en &= ~(0x01U << 3);
507 }
508
509 cdns_torrent_dp_write(cdns_phy,
510 PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state);
511 cdns_torrent_dp_write(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN, pll_clk_en);
512}
513
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100514/* Configure lane count as required. */
515static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
516 struct phy_configure_opts_dp *dp)
517{
518 u32 value;
519 u32 ret;
520 u8 lane_mask = (1 << dp->lanes) - 1;
521
522 value = cdns_torrent_dp_read(cdns_phy, PHY_RESET);
523 /* clear pma_tx_elec_idle_ln_* bits. */
524 value &= ~PMA_TX_ELEC_IDLE_MASK;
525 /* Assert pma_tx_elec_idle_ln_* for disabled lanes. */
526 value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) &
527 PMA_TX_ELEC_IDLE_MASK;
528 cdns_torrent_dp_write(cdns_phy, PHY_RESET, value);
529
530 /* reset the link by asserting phy_l00_reset_n low */
531 cdns_torrent_dp_write(cdns_phy, PHY_RESET,
532 value & (~PHY_L00_RESET_N_MASK));
533
534 /*
535 * Assert lane reset on unused lanes and lane 0 so they remain in reset
536 * and powered down when re-enabling the link
537 */
538 value = (value & 0x0000FFF0) | (0x0000000E & lane_mask);
539 cdns_torrent_dp_write(cdns_phy, PHY_RESET, value);
540
541 cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes);
542
543 /* release phy_l0*_reset_n based on used laneCount */
544 value = (value & 0x0000FFF0) | (0x0000000F & lane_mask);
545 cdns_torrent_dp_write(cdns_phy, PHY_RESET, value);
546
547 /* Wait, until PHY gets ready after releasing PHY reset signal. */
548 ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
549 if (ret)
550 return ret;
551
552 ndelay(100);
553
554 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
555 cdns_torrent_dp_write(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
556
557 ret = cdns_torrent_dp_run(cdns_phy, dp->lanes);
558
559 return ret;
560}
561
562/* Configure link rate as required. */
563static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
564 struct phy_configure_opts_dp *dp)
565{
566 u32 ret;
567
568 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
569 POWERSTATE_A3);
570 if (ret)
571 return ret;
572 ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false);
573 if (ret)
574 return ret;
575 ndelay(200);
576
577 ret = cdns_torrent_dp_configure_rate(cdns_phy, dp);
578 if (ret)
579 return ret;
580 ndelay(200);
581
582 ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true);
583 if (ret)
584 return ret;
585 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
586 POWERSTATE_A2);
587 if (ret)
588 return ret;
589 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
590 POWERSTATE_A0);
591 if (ret)
592 return ret;
593 ndelay(900);
594
595 return ret;
596}
597
598/* Configure voltage swing and pre-emphasis for all enabled lanes. */
599static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy,
600 struct phy_configure_opts_dp *dp)
601{
602 u8 lane;
603 u16 val;
604 unsigned int lane_bits;
605
606 for (lane = 0; lane < dp->lanes; lane++) {
607 lane_bits = (lane & LANE_MASK) << 11;
608
609 val = cdns_torrent_phy_read(cdns_phy,
610 (TX_DIAG_ACYA | lane_bits));
611 /*
612 * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the
613 * current state of the analog TX driver.
614 */
615 val |= TX_DIAG_ACYA_HBDC_MASK;
616 cdns_torrent_phy_write(cdns_phy,
617 (TX_DIAG_ACYA | lane_bits), val);
618
619 cdns_torrent_phy_write(cdns_phy,
620 (TX_TXCC_CTRL | lane_bits), 0x08A4);
621 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv;
622 cdns_torrent_phy_write(cdns_phy,
623 (DRV_DIAG_TX_DRV | lane_bits), val);
624 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult;
625 cdns_torrent_phy_write(cdns_phy,
626 (TX_TXCC_MGNFS_MULT_000 | lane_bits),
627 val);
628 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult;
629 cdns_torrent_phy_write(cdns_phy,
630 (TX_TXCC_CPOST_MULT_00 | lane_bits),
631 val);
632
633 val = cdns_torrent_phy_read(cdns_phy,
634 (TX_DIAG_ACYA | lane_bits));
635 /*
636 * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of
637 * analog TX driver to reflect the new programmed one.
638 */
639 val &= ~TX_DIAG_ACYA_HBDC_MASK;
640 cdns_torrent_phy_write(cdns_phy,
641 (TX_DIAG_ACYA | lane_bits), val);
642 }
643};
644
645static int cdns_torrent_dp_configure(struct phy *phy,
646 union phy_configure_opts *opts)
647{
648 struct cdns_torrent_phy *cdns_phy = phy_get_drvdata(phy);
649 int ret;
650
651 ret = cdns_torrent_dp_verify_config(cdns_phy, &opts->dp);
652 if (ret) {
653 dev_err(&phy->dev, "invalid params for phy configure\n");
654 return ret;
655 }
656
657 if (opts->dp.set_lanes) {
658 ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp);
659 if (ret) {
660 dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n");
661 return ret;
662 }
663 }
664
665 if (opts->dp.set_rate) {
666 ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp);
667 if (ret) {
668 dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n");
669 return ret;
670 }
671 }
672
673 if (opts->dp.set_voltages)
674 cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp);
675
676 return ret;
677}
678
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100679static int cdns_torrent_dp_init(struct phy *phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100680{
681 unsigned char lane_bits;
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100682 int ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100683
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100684 struct cdns_torrent_phy *cdns_phy = phy_get_drvdata(phy);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100685
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100686 ret = clk_prepare_enable(cdns_phy->clk);
687 if (ret) {
688 dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
689 return ret;
690 }
691
692 cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
693 if (!(cdns_phy->ref_clk_rate)) {
694 dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
695 clk_disable_unprepare(cdns_phy->clk);
696 return -EINVAL;
697 }
698
699 switch (cdns_phy->ref_clk_rate) {
700 case REF_CLK_19_2MHz:
701 case REF_CLK_25MHz:
702 /* Valid Ref Clock Rate */
703 break;
704 default:
705 dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
706 return -EINVAL;
707 }
708
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100709 cdns_torrent_dp_write(cdns_phy, PHY_AUX_CTRL, 0x0003); /* enable AUX */
Scott Telfordc8b427e2018-08-09 11:30:30 +0100710
711 /* PHY PMA registers configuration function */
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100712 cdns_torrent_dp_pma_cfg(cdns_phy);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100713
714 /*
715 * Set lines power state to A0
716 * Set lines pll clk enable to 0
717 */
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100718 cdns_torrent_dp_set_a0_pll(cdns_phy, cdns_phy->num_lanes);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100719
720 /*
721 * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
722 * used lanes
723 */
724 lane_bits = (1 << cdns_phy->num_lanes) - 1;
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100725 cdns_torrent_dp_write(cdns_phy, PHY_RESET,
726 ((0xF & ~lane_bits) << 4) | (0xF & lane_bits));
Scott Telfordc8b427e2018-08-09 11:30:30 +0100727
728 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100729 cdns_torrent_dp_write(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100730
731 /* PHY PMA registers configuration functions */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100732 /* Initialize PHY with max supported link rate, without SSC. */
733 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
734 cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy,
735 cdns_phy->max_bit_rate,
736 false);
737 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
738 cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy,
739 cdns_phy->max_bit_rate,
740 false);
741 cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
742 cdns_phy->num_lanes);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100743
744 /* take out of reset */
745 cdns_dp_phy_write_field(cdns_phy, PHY_RESET, 8, 1, 1);
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100746 ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
747 if (ret)
748 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100749
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100750 ret = cdns_torrent_dp_run(cdns_phy, cdns_phy->num_lanes);
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100751
752 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100753}
754
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100755static int cdns_torrent_dp_exit(struct phy *phy)
756{
757 struct cdns_torrent_phy *cdns_phy = phy_get_drvdata(phy);
758
759 clk_disable_unprepare(cdns_phy->clk);
760 return 0;
761}
762
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100763static
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100764int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100765{
766 unsigned int reg;
767 int ret;
768
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100769 ret = cdns_torrent_dp_read_poll_timeout(cdns_phy, PHY_PMA_CMN_READY,
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100770 reg, reg & 1, 0,
771 POLL_TIMEOUT_US);
772 if (ret == -ETIMEDOUT) {
Scott Telfordc8b427e2018-08-09 11:30:30 +0100773 dev_err(cdns_phy->dev,
774 "timeout waiting for PMA common ready\n");
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100775 return -ETIMEDOUT;
776 }
777
778 return 0;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100779}
780
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100781static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100782{
783 unsigned int i;
784
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100785 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
786 /* PMA common configuration 19.2MHz */
787 cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
788 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
789 /* PMA common configuration 25MHz */
790 cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100791
792 /* PMA lane configuration to deal with multi-link operation */
793 for (i = 0; i < cdns_phy->num_lanes; i++)
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100794 cdns_torrent_dp_pma_lane_cfg(cdns_phy, i);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100795}
796
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100797static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100798void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy)
799{
800 /* refclock registers - assumes 19.2 MHz refclock */
801 cdns_torrent_phy_write(cdns_phy, CMN_SSM_BIAS_TMR, 0x0014);
802 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM0_PLLPRE_TMR, 0x0027);
803 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM0_PLLLOCK_TMR, 0x00A1);
804 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM1_PLLPRE_TMR, 0x0027);
805 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM1_PLLLOCK_TMR, 0x00A1);
806 cdns_torrent_phy_write(cdns_phy, CMN_BGCAL_INIT_TMR, 0x0060);
807 cdns_torrent_phy_write(cdns_phy, CMN_BGCAL_ITER_TMR, 0x0060);
808 cdns_torrent_phy_write(cdns_phy, CMN_IBCAL_INIT_TMR, 0x0014);
809 cdns_torrent_phy_write(cdns_phy, CMN_TXPUCAL_INIT_TMR, 0x0018);
810 cdns_torrent_phy_write(cdns_phy, CMN_TXPUCAL_ITER_TMR, 0x0005);
811 cdns_torrent_phy_write(cdns_phy, CMN_TXPDCAL_INIT_TMR, 0x0018);
812 cdns_torrent_phy_write(cdns_phy, CMN_TXPDCAL_ITER_TMR, 0x0005);
813 cdns_torrent_phy_write(cdns_phy, CMN_RXCAL_INIT_TMR, 0x0240);
814 cdns_torrent_phy_write(cdns_phy, CMN_RXCAL_ITER_TMR, 0x0005);
815 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_INIT_TMR, 0x0002);
816 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_ITER_TMR, 0x0002);
817 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_REFTIM_START, 0x000B);
818 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_PLLCNT_START, 0x0137);
819
820 /* PLL registers */
821 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
822 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
823 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
824 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_DSM_DIAG_M0, 0x0004);
825 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
826 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
827 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
828 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_DSM_DIAG_M0, 0x0004);
829 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_INIT_TMR, 0x00C0);
830 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
831 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_INIT_TMR, 0x00C0);
832 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
833 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_REFTIM_START, 0x0260);
834 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
835 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_REFTIM_START, 0x0260);
836 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
837}
838
839/*
840 * Set registers responsible for enabling and configuring SSC, with second and
841 * third register values provided by parameters.
842 */
843static
844void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy,
845 u32 ctrl2_val, u32 ctrl3_val)
846{
847 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, 0x0001);
848 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
849 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, ctrl3_val);
850 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL4_M0, 0x0003);
851 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, 0x0001);
852 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
853 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, ctrl3_val);
854 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL4_M0, 0x0003);
855}
856
857static
858void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
859 u32 rate, bool ssc)
860{
861 /* Assumes 19.2 MHz refclock */
862 switch (rate) {
863 /* Setting VCO for 10.8GHz */
864 case 2700:
865 case 5400:
866 cdns_torrent_phy_write(cdns_phy,
867 CMN_PLL0_INTDIV_M0, 0x0119);
868 cdns_torrent_phy_write(cdns_phy,
869 CMN_PLL0_FRACDIVL_M0, 0x4000);
870 cdns_torrent_phy_write(cdns_phy,
871 CMN_PLL0_FRACDIVH_M0, 0x0002);
872 cdns_torrent_phy_write(cdns_phy,
873 CMN_PLL0_HIGH_THR_M0, 0x00BC);
874 cdns_torrent_phy_write(cdns_phy,
875 CMN_PDIAG_PLL0_CTRL_M0, 0x0012);
876 cdns_torrent_phy_write(cdns_phy,
877 CMN_PLL1_INTDIV_M0, 0x0119);
878 cdns_torrent_phy_write(cdns_phy,
879 CMN_PLL1_FRACDIVL_M0, 0x4000);
880 cdns_torrent_phy_write(cdns_phy,
881 CMN_PLL1_FRACDIVH_M0, 0x0002);
882 cdns_torrent_phy_write(cdns_phy,
883 CMN_PLL1_HIGH_THR_M0, 0x00BC);
884 cdns_torrent_phy_write(cdns_phy,
885 CMN_PDIAG_PLL1_CTRL_M0, 0x0012);
886 if (ssc)
887 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A,
888 0x006A);
889 break;
890 /* Setting VCO for 9.72GHz */
891 case 1620:
892 case 2430:
893 case 3240:
894 cdns_torrent_phy_write(cdns_phy,
895 CMN_PLL0_INTDIV_M0, 0x01FA);
896 cdns_torrent_phy_write(cdns_phy,
897 CMN_PLL0_FRACDIVL_M0, 0x4000);
898 cdns_torrent_phy_write(cdns_phy,
899 CMN_PLL0_FRACDIVH_M0, 0x0002);
900 cdns_torrent_phy_write(cdns_phy,
901 CMN_PLL0_HIGH_THR_M0, 0x0152);
902 cdns_torrent_phy_write(cdns_phy,
903 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
904 cdns_torrent_phy_write(cdns_phy,
905 CMN_PLL1_INTDIV_M0, 0x01FA);
906 cdns_torrent_phy_write(cdns_phy,
907 CMN_PLL1_FRACDIVL_M0, 0x4000);
908 cdns_torrent_phy_write(cdns_phy,
909 CMN_PLL1_FRACDIVH_M0, 0x0002);
910 cdns_torrent_phy_write(cdns_phy,
911 CMN_PLL1_HIGH_THR_M0, 0x0152);
912 cdns_torrent_phy_write(cdns_phy,
913 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
914 if (ssc)
915 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD,
916 0x0069);
917 break;
918 /* Setting VCO for 8.64GHz */
919 case 2160:
920 case 4320:
921 cdns_torrent_phy_write(cdns_phy,
922 CMN_PLL0_INTDIV_M0, 0x01C2);
923 cdns_torrent_phy_write(cdns_phy,
924 CMN_PLL0_FRACDIVL_M0, 0x0000);
925 cdns_torrent_phy_write(cdns_phy,
926 CMN_PLL0_FRACDIVH_M0, 0x0002);
927 cdns_torrent_phy_write(cdns_phy,
928 CMN_PLL0_HIGH_THR_M0, 0x012C);
929 cdns_torrent_phy_write(cdns_phy,
930 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
931 cdns_torrent_phy_write(cdns_phy,
932 CMN_PLL1_INTDIV_M0, 0x01C2);
933 cdns_torrent_phy_write(cdns_phy,
934 CMN_PLL1_FRACDIVL_M0, 0x0000);
935 cdns_torrent_phy_write(cdns_phy,
936 CMN_PLL1_FRACDIVH_M0, 0x0002);
937 cdns_torrent_phy_write(cdns_phy,
938 CMN_PLL1_HIGH_THR_M0, 0x012C);
939 cdns_torrent_phy_write(cdns_phy,
940 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
941 if (ssc)
942 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536,
943 0x0069);
944 break;
945 /* Setting VCO for 8.1GHz */
946 case 8100:
947 cdns_torrent_phy_write(cdns_phy,
948 CMN_PLL0_INTDIV_M0, 0x01A5);
949 cdns_torrent_phy_write(cdns_phy,
950 CMN_PLL0_FRACDIVL_M0, 0xE000);
951 cdns_torrent_phy_write(cdns_phy,
952 CMN_PLL0_FRACDIVH_M0, 0x0002);
953 cdns_torrent_phy_write(cdns_phy,
954 CMN_PLL0_HIGH_THR_M0, 0x011A);
955 cdns_torrent_phy_write(cdns_phy,
956 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
957 cdns_torrent_phy_write(cdns_phy,
958 CMN_PLL1_INTDIV_M0, 0x01A5);
959 cdns_torrent_phy_write(cdns_phy,
960 CMN_PLL1_FRACDIVL_M0, 0xE000);
961 cdns_torrent_phy_write(cdns_phy,
962 CMN_PLL1_FRACDIVH_M0, 0x0002);
963 cdns_torrent_phy_write(cdns_phy,
964 CMN_PLL1_HIGH_THR_M0, 0x011A);
965 cdns_torrent_phy_write(cdns_phy,
966 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
967 if (ssc)
968 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7,
969 0x006A);
970 break;
971 }
972
973 if (ssc) {
974 cdns_torrent_phy_write(cdns_phy,
975 CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E);
976 cdns_torrent_phy_write(cdns_phy,
977 CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
978 cdns_torrent_phy_write(cdns_phy,
979 CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E);
980 cdns_torrent_phy_write(cdns_phy,
981 CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
982 } else {
983 cdns_torrent_phy_write(cdns_phy,
984 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260);
985 cdns_torrent_phy_write(cdns_phy,
986 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260);
987 /* Set reset register values to disable SSC */
988 cdns_torrent_phy_write(cdns_phy,
989 CMN_PLL0_SS_CTRL1_M0, 0x0002);
990 cdns_torrent_phy_write(cdns_phy,
991 CMN_PLL0_SS_CTRL2_M0, 0x0000);
992 cdns_torrent_phy_write(cdns_phy,
993 CMN_PLL0_SS_CTRL3_M0, 0x0000);
994 cdns_torrent_phy_write(cdns_phy,
995 CMN_PLL0_SS_CTRL4_M0, 0x0000);
996 cdns_torrent_phy_write(cdns_phy,
997 CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
998 cdns_torrent_phy_write(cdns_phy,
999 CMN_PLL1_SS_CTRL1_M0, 0x0002);
1000 cdns_torrent_phy_write(cdns_phy,
1001 CMN_PLL1_SS_CTRL2_M0, 0x0000);
1002 cdns_torrent_phy_write(cdns_phy,
1003 CMN_PLL1_SS_CTRL3_M0, 0x0000);
1004 cdns_torrent_phy_write(cdns_phy,
1005 CMN_PLL1_SS_CTRL4_M0, 0x0000);
1006 cdns_torrent_phy_write(cdns_phy,
1007 CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
1008 }
1009
1010 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_LOCK_REFCNT_START, 0x0099);
1011 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_LOCK_PLLCNT_START, 0x0099);
1012 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_LOCK_REFCNT_START, 0x0099);
1013 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_LOCK_PLLCNT_START, 0x0099);
1014}
1015
1016static
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001017void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001018{
1019 /* refclock registers - assumes 25 MHz refclock */
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001020 cdns_torrent_phy_write(cdns_phy, CMN_SSM_BIAS_TMR, 0x0019);
1021 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM0_PLLPRE_TMR, 0x0032);
1022 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM0_PLLLOCK_TMR, 0x00D1);
1023 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM1_PLLPRE_TMR, 0x0032);
1024 cdns_torrent_phy_write(cdns_phy, CMN_PLLSM1_PLLLOCK_TMR, 0x00D1);
1025 cdns_torrent_phy_write(cdns_phy, CMN_BGCAL_INIT_TMR, 0x007D);
1026 cdns_torrent_phy_write(cdns_phy, CMN_BGCAL_ITER_TMR, 0x007D);
1027 cdns_torrent_phy_write(cdns_phy, CMN_IBCAL_INIT_TMR, 0x0019);
1028 cdns_torrent_phy_write(cdns_phy, CMN_TXPUCAL_INIT_TMR, 0x001E);
1029 cdns_torrent_phy_write(cdns_phy, CMN_TXPUCAL_ITER_TMR, 0x0006);
1030 cdns_torrent_phy_write(cdns_phy, CMN_TXPDCAL_INIT_TMR, 0x001E);
1031 cdns_torrent_phy_write(cdns_phy, CMN_TXPDCAL_ITER_TMR, 0x0006);
1032 cdns_torrent_phy_write(cdns_phy, CMN_RXCAL_INIT_TMR, 0x02EE);
1033 cdns_torrent_phy_write(cdns_phy, CMN_RXCAL_ITER_TMR, 0x0006);
1034 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_INIT_TMR, 0x0002);
1035 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_ITER_TMR, 0x0002);
1036 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_REFTIM_START, 0x000E);
1037 cdns_torrent_phy_write(cdns_phy, CMN_SD_CAL_PLLCNT_START, 0x012B);
1038
Scott Telfordc8b427e2018-08-09 11:30:30 +01001039 /* PLL registers */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001040 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
1041 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001042 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
1043 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_DSM_DIAG_M0, 0x0004);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001044 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
1045 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
1046 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
1047 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_DSM_DIAG_M0, 0x0004);
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001048 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_INIT_TMR, 0x00FA);
1049 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
1050 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_INIT_TMR, 0x00FA);
1051 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001052 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_REFTIM_START, 0x0317);
1053 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
1054 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_REFTIM_START, 0x0317);
1055 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
1056}
1057
1058/*
1059 * Set registers responsible for enabling and configuring SSC, with second
1060 * register value provided by a parameter.
1061 */
1062static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy,
1063 u32 ctrl2_val)
1064{
1065 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, 0x0001);
1066 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
1067 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, 0x007F);
1068 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL4_M0, 0x0003);
1069 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, 0x0001);
1070 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
1071 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, 0x007F);
1072 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL4_M0, 0x0003);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001073}
1074
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001075static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001076void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
1077 u32 rate, bool ssc)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001078{
1079 /* Assumes 25 MHz refclock */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001080 switch (rate) {
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001081 /* Setting VCO for 10.8GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001082 case 2700:
1083 case 5400:
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001084 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_INTDIV_M0, 0x01B0);
1085 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVL_M0, 0x0000);
1086 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVH_M0, 0x0002);
1087 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_HIGH_THR_M0, 0x0120);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001088 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_INTDIV_M0, 0x01B0);
1089 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVL_M0, 0x0000);
1090 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVH_M0, 0x0002);
1091 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_HIGH_THR_M0, 0x0120);
1092 if (ssc)
1093 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001094 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001095 /* Setting VCO for 9.72GHz */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001096 case 1620:
Scott Telfordc8b427e2018-08-09 11:30:30 +01001097 case 2430:
1098 case 3240:
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001099 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_INTDIV_M0, 0x0184);
1100 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVL_M0, 0xCCCD);
1101 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVH_M0, 0x0002);
1102 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_HIGH_THR_M0, 0x0104);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001103 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_INTDIV_M0, 0x0184);
1104 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVL_M0, 0xCCCD);
1105 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVH_M0, 0x0002);
1106 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_HIGH_THR_M0, 0x0104);
1107 if (ssc)
1108 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001109 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001110 /* Setting VCO for 8.64GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001111 case 2160:
1112 case 4320:
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001113 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_INTDIV_M0, 0x0159);
1114 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVL_M0, 0x999A);
1115 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVH_M0, 0x0002);
1116 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_HIGH_THR_M0, 0x00E7);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001117 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_INTDIV_M0, 0x0159);
1118 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVL_M0, 0x999A);
1119 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVH_M0, 0x0002);
1120 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_HIGH_THR_M0, 0x00E7);
1121 if (ssc)
1122 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001123 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001124 /* Setting VCO for 8.1GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001125 case 8100:
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001126 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_INTDIV_M0, 0x0144);
1127 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVL_M0, 0x0000);
1128 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_FRACDIVH_M0, 0x0002);
1129 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_HIGH_THR_M0, 0x00D8);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001130 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_INTDIV_M0, 0x0144);
1131 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVL_M0, 0x0000);
1132 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_FRACDIVH_M0, 0x0002);
1133 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_HIGH_THR_M0, 0x00D8);
1134 if (ssc)
1135 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001136 break;
1137 }
1138
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001139 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001140 cdns_torrent_phy_write(cdns_phy, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
1141
1142 if (ssc) {
1143 cdns_torrent_phy_write(cdns_phy,
1144 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315);
1145 cdns_torrent_phy_write(cdns_phy,
1146 CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
1147 cdns_torrent_phy_write(cdns_phy,
1148 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315);
1149 cdns_torrent_phy_write(cdns_phy,
1150 CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
1151 } else {
1152 cdns_torrent_phy_write(cdns_phy,
1153 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317);
1154 cdns_torrent_phy_write(cdns_phy,
1155 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317);
1156 /* Set reset register values to disable SSC */
1157 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL1_M0, 0x0002);
1158 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL2_M0, 0x0000);
1159 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL3_M0, 0x0000);
1160 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_SS_CTRL4_M0, 0x0000);
1161 cdns_torrent_phy_write(cdns_phy,
1162 CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
1163 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL1_M0, 0x0002);
1164 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL2_M0, 0x0000);
1165 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL3_M0, 0x0000);
1166 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_SS_CTRL4_M0, 0x0000);
1167 cdns_torrent_phy_write(cdns_phy,
1168 CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
1169 }
1170
1171 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_LOCK_REFCNT_START, 0x00C7);
1172 cdns_torrent_phy_write(cdns_phy, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7);
1173 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_LOCK_REFCNT_START, 0x00C7);
1174 cdns_torrent_phy_write(cdns_phy, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001175}
1176
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001177static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
1178 u32 rate, u32 num_lanes)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001179{
1180 unsigned int clk_sel_val = 0;
1181 unsigned int hsclk_div_val = 0;
1182 unsigned int i;
1183
1184 /* 16'h0000 for single DP link configuration */
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001185 cdns_torrent_phy_write(cdns_phy, PHY_PLL_CFG, 0x0000);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001186
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001187 switch (rate) {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001188 case 1620:
1189 clk_sel_val = 0x0f01;
1190 hsclk_div_val = 2;
1191 break;
1192 case 2160:
1193 case 2430:
1194 case 2700:
1195 clk_sel_val = 0x0701;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001196 hsclk_div_val = 1;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001197 break;
1198 case 3240:
1199 clk_sel_val = 0x0b00;
1200 hsclk_div_val = 2;
1201 break;
1202 case 4320:
1203 case 5400:
1204 clk_sel_val = 0x0301;
1205 hsclk_div_val = 0;
1206 break;
1207 case 8100:
1208 clk_sel_val = 0x0200;
1209 hsclk_div_val = 0;
1210 break;
1211 }
1212
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001213 cdns_torrent_phy_write(cdns_phy,
1214 CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001215 cdns_torrent_phy_write(cdns_phy,
1216 CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001217
1218 /* PMA lane configuration to deal with multi-link operation */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001219 for (i = 0; i < num_lanes; i++)
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001220 cdns_torrent_phy_write(cdns_phy,
1221 (XCVR_DIAG_HSCLK_DIV | (i << 11)),
1222 hsclk_div_val);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001223}
1224
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001225static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
1226 unsigned int lane)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001227{
1228 unsigned int lane_bits = (lane & LANE_MASK) << 11;
1229
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001230 /* Per lane, refclock-dependent receiver detection setting */
1231 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
1232 cdns_torrent_phy_write(cdns_phy,
1233 (TX_RCVDET_ST_TMR | lane_bits), 0x0780);
1234 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
1235 cdns_torrent_phy_write(cdns_phy,
1236 (TX_RCVDET_ST_TMR | lane_bits), 0x09C4);
1237
Scott Telfordc8b427e2018-08-09 11:30:30 +01001238 /* Writing Tx/Rx Power State Controllers registers */
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001239 cdns_torrent_phy_write(cdns_phy, (TX_PSC_A0 | lane_bits), 0x00FB);
1240 cdns_torrent_phy_write(cdns_phy, (TX_PSC_A2 | lane_bits), 0x04AA);
1241 cdns_torrent_phy_write(cdns_phy, (TX_PSC_A3 | lane_bits), 0x04AA);
1242 cdns_torrent_phy_write(cdns_phy, (RX_PSC_A0 | lane_bits), 0x0000);
1243 cdns_torrent_phy_write(cdns_phy, (RX_PSC_A2 | lane_bits), 0x0000);
1244 cdns_torrent_phy_write(cdns_phy, (RX_PSC_A3 | lane_bits), 0x0000);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001245
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001246 cdns_torrent_phy_write(cdns_phy, (RX_PSC_CAL | lane_bits), 0x0000);
1247
1248 cdns_torrent_phy_write(cdns_phy,
1249 (RX_REE_GCSM1_CTRL | lane_bits), 0x0000);
1250 cdns_torrent_phy_write(cdns_phy,
1251 (RX_REE_GCSM2_CTRL | lane_bits), 0x0000);
1252 cdns_torrent_phy_write(cdns_phy,
1253 (RX_REE_PERGCSM_CTRL | lane_bits), 0x0000);
1254
1255 cdns_torrent_phy_write(cdns_phy,
1256 (XCVR_DIAG_BIDI_CTRL | lane_bits), 0x000F);
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001257 cdns_torrent_phy_write(cdns_phy,
1258 (XCVR_DIAG_PLLDRC_CTRL | lane_bits), 0x0001);
1259 cdns_torrent_phy_write(cdns_phy,
1260 (XCVR_DIAG_HSCLK_SEL | lane_bits), 0x0000);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001261}
1262
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001263static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
1264 u32 num_lanes,
1265 enum phy_powerstate powerstate)
1266{
1267 /* Register value for power state for a single byte. */
1268 u32 value_part;
1269 u32 value;
1270 u32 mask;
1271 u32 read_val;
1272 u32 ret;
1273
1274 switch (powerstate) {
1275 case (POWERSTATE_A0):
1276 value_part = 0x01U;
1277 break;
1278 case (POWERSTATE_A2):
1279 value_part = 0x04U;
1280 break;
1281 default:
1282 /* Powerstate A3 */
1283 value_part = 0x08U;
1284 break;
1285 }
1286
1287 /* Select values of registers and mask, depending on enabled
1288 * lane count.
1289 */
1290 switch (num_lanes) {
1291 /* lane 0 */
1292 case (1):
1293 value = value_part;
1294 mask = 0x0000003FU;
1295 break;
1296 /* lanes 0-1 */
1297 case (2):
1298 value = (value_part
1299 | (value_part << 8));
1300 mask = 0x00003F3FU;
1301 break;
1302 /* lanes 0-3, all */
1303 default:
1304 value = (value_part
1305 | (value_part << 8)
1306 | (value_part << 16)
1307 | (value_part << 24));
1308 mask = 0x3F3F3F3FU;
1309 break;
1310 }
1311
1312 /* Set power state A<n>. */
1313 cdns_torrent_dp_write(cdns_phy, PHY_PMA_XCVR_POWER_STATE_REQ, value);
1314 /* Wait, until PHY acknowledges power state completion. */
1315 ret = cdns_torrent_dp_read_poll_timeout(cdns_phy,
1316 PHY_PMA_XCVR_POWER_STATE_ACK,
1317 read_val,
1318 (read_val & mask) == value, 0,
1319 POLL_TIMEOUT_US);
1320 cdns_torrent_dp_write(cdns_phy,
1321 PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
1322 ndelay(100);
1323
1324 return ret;
1325}
1326
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001327static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001328{
1329 unsigned int read_val;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001330 int ret;
1331
1332 /*
1333 * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
1334 * master lane
1335 */
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +01001336 ret = cdns_torrent_dp_read_poll_timeout(cdns_phy,
1337 PHY_PMA_XCVR_PLLCLK_EN_ACK,
1338 read_val, read_val & 1, 0,
1339 POLL_TIMEOUT_US);
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001340 if (ret == -ETIMEDOUT) {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001341 dev_err(cdns_phy->dev,
1342 "timeout waiting for link PLL clock enable ack\n");
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001343 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001344 }
1345
Scott Telfordc8b427e2018-08-09 11:30:30 +01001346 ndelay(100);
1347
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001348 ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001349 POWERSTATE_A2);
1350 if (ret)
1351 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001352
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001353 ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001354 POWERSTATE_A0);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001355
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001356 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001357}
1358
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001359static void cdns_dp_phy_write_field(struct cdns_torrent_phy *cdns_phy,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001360 unsigned int offset,
1361 unsigned char start_bit,
1362 unsigned char num_bits,
1363 unsigned int val)
1364{
1365 unsigned int read_val;
1366
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +01001367 read_val = cdns_torrent_dp_read(cdns_phy, offset);
1368 cdns_torrent_dp_write(cdns_phy, offset,
1369 ((val << start_bit) |
1370 (read_val & ~(((1 << num_bits) - 1) <<
1371 start_bit))));
Scott Telfordc8b427e2018-08-09 11:30:30 +01001372}
1373
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001374static int cdns_torrent_phy_probe(struct platform_device *pdev)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001375{
1376 struct resource *regs;
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001377 struct cdns_torrent_phy *cdns_phy;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001378 struct device *dev = &pdev->dev;
1379 struct phy_provider *phy_provider;
1380 struct phy *phy;
1381 int err;
1382
1383 cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL);
1384 if (!cdns_phy)
1385 return -ENOMEM;
1386
1387 cdns_phy->dev = &pdev->dev;
1388
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001389 phy = devm_phy_create(dev, NULL, &cdns_torrent_phy_ops);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001390 if (IS_ERR(phy)) {
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001391 dev_err(dev, "failed to create Torrent PHY\n");
Scott Telfordc8b427e2018-08-09 11:30:30 +01001392 return PTR_ERR(phy);
1393 }
1394
1395 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1396 cdns_phy->base = devm_ioremap_resource(&pdev->dev, regs);
1397 if (IS_ERR(cdns_phy->base))
1398 return PTR_ERR(cdns_phy->base);
1399
1400 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1401 cdns_phy->sd_base = devm_ioremap_resource(&pdev->dev, regs);
1402 if (IS_ERR(cdns_phy->sd_base))
1403 return PTR_ERR(cdns_phy->sd_base);
1404
1405 err = device_property_read_u32(dev, "num_lanes",
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001406 &cdns_phy->num_lanes);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001407 if (err)
1408 cdns_phy->num_lanes = DEFAULT_NUM_LANES;
1409
1410 switch (cdns_phy->num_lanes) {
1411 case 1:
1412 case 2:
1413 case 4:
1414 /* valid number of lanes */
1415 break;
1416 default:
1417 dev_err(dev, "unsupported number of lanes: %d\n",
1418 cdns_phy->num_lanes);
1419 return -EINVAL;
1420 }
1421
1422 err = device_property_read_u32(dev, "max_bit_rate",
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001423 &cdns_phy->max_bit_rate);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001424 if (err)
1425 cdns_phy->max_bit_rate = DEFAULT_MAX_BIT_RATE;
1426
1427 switch (cdns_phy->max_bit_rate) {
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001428 case 1620:
Scott Telfordc8b427e2018-08-09 11:30:30 +01001429 case 2160:
1430 case 2430:
1431 case 2700:
1432 case 3240:
1433 case 4320:
1434 case 5400:
1435 case 8100:
1436 /* valid bit rate */
1437 break;
1438 default:
1439 dev_err(dev, "unsupported max bit rate: %dMbps\n",
1440 cdns_phy->max_bit_rate);
1441 return -EINVAL;
1442 }
1443
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001444 cdns_phy->clk = devm_clk_get(dev, "refclk");
1445 if (IS_ERR(cdns_phy->clk)) {
1446 dev_err(dev, "phy ref clock not found\n");
1447 return PTR_ERR(cdns_phy->clk);
1448 }
1449
Scott Telfordc8b427e2018-08-09 11:30:30 +01001450 phy_set_drvdata(phy, cdns_phy);
1451
1452 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1453
1454 dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n",
1455 cdns_phy->num_lanes,
1456 cdns_phy->max_bit_rate / 1000,
1457 cdns_phy->max_bit_rate % 1000);
1458
1459 return PTR_ERR_OR_ZERO(phy_provider);
1460}
1461
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001462static const struct of_device_id cdns_torrent_phy_of_match[] = {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001463 {
Yuti Amonkarc589e7012020-02-06 07:10:51 +01001464 .compatible = "cdns,torrent-phy"
Scott Telfordc8b427e2018-08-09 11:30:30 +01001465 },
1466 {}
1467};
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001468MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001469
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001470static struct platform_driver cdns_torrent_phy_driver = {
1471 .probe = cdns_torrent_phy_probe,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001472 .driver = {
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001473 .name = "cdns-torrent-phy",
1474 .of_match_table = cdns_torrent_phy_of_match,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001475 }
1476};
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001477module_platform_driver(cdns_torrent_phy_driver);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001478
1479MODULE_AUTHOR("Cadence Design Systems, Inc.");
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001480MODULE_DESCRIPTION("Cadence Torrent PHY driver");
Scott Telfordc8b427e2018-08-09 11:30:30 +01001481MODULE_LICENSE("GPL v2");