blob: 6c199400fa5b4a184d82d681bcc53919060a2ead [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 Jakhadeafa4ba02020-02-06 07:11:01 +01009#include <dt-bindings/phy/phy.h>
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010010#include <linux/clk.h>
Scott Telfordc8b427e2018-08-09 11:30:30 +010011#include <linux/delay.h>
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/iopoll.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/of_device.h>
20#include <linux/phy/phy.h>
21#include <linux/platform_device.h>
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +010022#include <linux/reset.h>
Swapnil Jakhade69d114a2020-02-06 07:10:58 +010023#include <linux/regmap.h>
Scott Telfordc8b427e2018-08-09 11:30:30 +010024
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +010025#define REF_CLK_19_2MHz 19200000
26#define REF_CLK_25MHz 25000000
27
Scott Telfordc8b427e2018-08-09 11:30:30 +010028#define MAX_NUM_LANES 4
29#define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */
30
Swapnil Jakhade21c79142020-02-06 07:10:55 +010031#define POLL_TIMEOUT_US 5000
Swapnil Jakhade69d114a2020-02-06 07:10:58 +010032
33#define TORRENT_COMMON_CDB_OFFSET 0x0
34
35#define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \
36 ((0x4000 << (block_offset)) + \
37 (((ln) << 9) << (reg_offset)))
38
39#define TORRENT_RX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \
40 ((0x8000 << (block_offset)) + \
41 (((ln) << 9) << (reg_offset)))
42
43#define TORRENT_PHY_PCS_COMMON_OFFSET(block_offset) \
44 (0xC000 << (block_offset))
45
46#define TORRENT_PHY_PMA_COMMON_OFFSET(block_offset) \
47 (0xE000 << (block_offset))
Scott Telfordc8b427e2018-08-09 11:30:30 +010048
Swapnil Jakhadecba472e2020-02-06 07:10:59 +010049#define TORRENT_DPTX_PHY_OFFSET 0x0
50
Scott Telfordc8b427e2018-08-09 11:30:30 +010051/*
52 * register offsets from DPTX PHY register block base (i.e MHDP
53 * register base + 0x30a00)
54 */
Scott Telfordc8b427e2018-08-09 11:30:30 +010055#define PHY_AUX_CTRL 0x04
56#define PHY_RESET 0x20
Swapnil Jakhade572d6592020-02-06 07:10:57 +010057#define PMA_TX_ELEC_IDLE_MASK 0xF0U
58#define PMA_TX_ELEC_IDLE_SHIFT 4
59#define PHY_L00_RESET_N_MASK 0x01U
Scott Telfordc8b427e2018-08-09 11:30:30 +010060#define PHY_PMA_XCVR_PLLCLK_EN 0x24
61#define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28
62#define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c
63#define PHY_POWER_STATE_LN_0 0x0000
64#define PHY_POWER_STATE_LN_1 0x0008
65#define PHY_POWER_STATE_LN_2 0x0010
66#define PHY_POWER_STATE_LN_3 0x0018
Swapnil Jakhade21c79142020-02-06 07:10:55 +010067#define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU
Scott Telfordc8b427e2018-08-09 11:30:30 +010068#define PHY_PMA_XCVR_POWER_STATE_ACK 0x30
69#define PHY_PMA_CMN_READY 0x34
Scott Telfordc8b427e2018-08-09 11:30:30 +010070
71/*
72 * register offsets from SD0801 PHY register block base (i.e MHDP
73 * register base + 0x500000)
74 */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +010075#define CMN_SSM_BANDGAP_TMR 0x0021U
76#define CMN_SSM_BIAS_TMR 0x0022U
77#define CMN_PLLSM0_PLLPRE_TMR 0x002AU
78#define CMN_PLLSM0_PLLLOCK_TMR 0x002CU
79#define CMN_PLLSM1_PLLPRE_TMR 0x0032U
80#define CMN_PLLSM1_PLLLOCK_TMR 0x0034U
81#define CMN_BGCAL_INIT_TMR 0x0064U
82#define CMN_BGCAL_ITER_TMR 0x0065U
83#define CMN_IBCAL_INIT_TMR 0x0074U
84#define CMN_PLL0_VCOCAL_TCTRL 0x0082U
85#define CMN_PLL0_VCOCAL_INIT_TMR 0x0084U
86#define CMN_PLL0_VCOCAL_ITER_TMR 0x0085U
87#define CMN_PLL0_VCOCAL_REFTIM_START 0x0086U
88#define CMN_PLL0_VCOCAL_PLLCNT_START 0x0088U
89#define CMN_PLL0_INTDIV_M0 0x0090U
90#define CMN_PLL0_FRACDIVL_M0 0x0091U
91#define CMN_PLL0_FRACDIVH_M0 0x0092U
92#define CMN_PLL0_HIGH_THR_M0 0x0093U
93#define CMN_PLL0_DSM_DIAG_M0 0x0094U
94#define CMN_PLL0_SS_CTRL1_M0 0x0098U
95#define CMN_PLL0_SS_CTRL2_M0 0x0099U
96#define CMN_PLL0_SS_CTRL3_M0 0x009AU
97#define CMN_PLL0_SS_CTRL4_M0 0x009BU
98#define CMN_PLL0_LOCK_REFCNT_START 0x009CU
99#define CMN_PLL0_LOCK_PLLCNT_START 0x009EU
100#define CMN_PLL0_LOCK_PLLCNT_THR 0x009FU
101#define CMN_PLL1_VCOCAL_TCTRL 0x00C2U
102#define CMN_PLL1_VCOCAL_INIT_TMR 0x00C4U
103#define CMN_PLL1_VCOCAL_ITER_TMR 0x00C5U
104#define CMN_PLL1_VCOCAL_REFTIM_START 0x00C6U
105#define CMN_PLL1_VCOCAL_PLLCNT_START 0x00C8U
106#define CMN_PLL1_INTDIV_M0 0x00D0U
107#define CMN_PLL1_FRACDIVL_M0 0x00D1U
108#define CMN_PLL1_FRACDIVH_M0 0x00D2U
109#define CMN_PLL1_HIGH_THR_M0 0x00D3U
110#define CMN_PLL1_DSM_DIAG_M0 0x00D4U
111#define CMN_PLL1_SS_CTRL1_M0 0x00D8U
112#define CMN_PLL1_SS_CTRL2_M0 0x00D9U
113#define CMN_PLL1_SS_CTRL3_M0 0x00DAU
114#define CMN_PLL1_SS_CTRL4_M0 0x00DBU
115#define CMN_PLL1_LOCK_REFCNT_START 0x00DCU
116#define CMN_PLL1_LOCK_PLLCNT_START 0x00DEU
117#define CMN_PLL1_LOCK_PLLCNT_THR 0x00DFU
118#define CMN_TXPUCAL_INIT_TMR 0x0104U
119#define CMN_TXPUCAL_ITER_TMR 0x0105U
120#define CMN_TXPDCAL_INIT_TMR 0x010CU
121#define CMN_TXPDCAL_ITER_TMR 0x010DU
122#define CMN_RXCAL_INIT_TMR 0x0114U
123#define CMN_RXCAL_ITER_TMR 0x0115U
124#define CMN_SD_CAL_INIT_TMR 0x0124U
125#define CMN_SD_CAL_ITER_TMR 0x0125U
126#define CMN_SD_CAL_REFTIM_START 0x0126U
127#define CMN_SD_CAL_PLLCNT_START 0x0128U
128#define CMN_PDIAG_PLL0_CTRL_M0 0x01A0U
129#define CMN_PDIAG_PLL0_CLK_SEL_M0 0x01A1U
130#define CMN_PDIAG_PLL0_CP_PADJ_M0 0x01A4U
131#define CMN_PDIAG_PLL0_CP_IADJ_M0 0x01A5U
132#define CMN_PDIAG_PLL0_FILT_PADJ_M0 0x01A6U
133#define CMN_PDIAG_PLL0_CP_PADJ_M1 0x01B4U
134#define CMN_PDIAG_PLL0_CP_IADJ_M1 0x01B5U
135#define CMN_PDIAG_PLL1_CTRL_M0 0x01C0U
136#define CMN_PDIAG_PLL1_CLK_SEL_M0 0x01C1U
137#define CMN_PDIAG_PLL1_CP_PADJ_M0 0x01C4U
138#define CMN_PDIAG_PLL1_CP_IADJ_M0 0x01C5U
139#define CMN_PDIAG_PLL1_FILT_PADJ_M0 0x01C6U
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100140
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100141/* PMA TX Lane registers */
142#define TX_TXCC_CTRL 0x0040U
143#define TX_TXCC_CPOST_MULT_00 0x004CU
144#define TX_TXCC_MGNFS_MULT_000 0x0050U
145#define DRV_DIAG_TX_DRV 0x00C6U
146#define XCVR_DIAG_PLLDRC_CTRL 0x00E5U
147#define XCVR_DIAG_HSCLK_SEL 0x00E6U
148#define XCVR_DIAG_HSCLK_DIV 0x00E7U
149#define XCVR_DIAG_BIDI_CTRL 0x00EAU
150#define TX_PSC_A0 0x0100U
151#define TX_PSC_A2 0x0102U
152#define TX_PSC_A3 0x0103U
153#define TX_RCVDET_ST_TMR 0x0123U
154#define TX_DIAG_ACYA 0x01E7U
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100155#define TX_DIAG_ACYA_HBDC_MASK 0x0001U
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100156
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100157/* PMA RX Lane registers */
158#define RX_PSC_A0 0x0000U
159#define RX_PSC_A2 0x0002U
160#define RX_PSC_A3 0x0003U
161#define RX_PSC_CAL 0x0006U
162#define RX_REE_GCSM1_CTRL 0x0108U
163#define RX_REE_GCSM2_CTRL 0x0110U
164#define RX_REE_PERGCSM_CTRL 0x0118U
Scott Telfordc8b427e2018-08-09 11:30:30 +0100165
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100166/* PHY PCS common registers */
167#define PHY_PLL_CFG 0x000EU
168
169/* PHY PMA common registers */
170#define PHY_PMA_CMN_CTRL2 0x0001U
171#define PHY_PMA_PLL_RAW_CTRL 0x0003U
172
173static const struct reg_field phy_pll_cfg =
174 REG_FIELD(PHY_PLL_CFG, 0, 1);
175
176static const struct reg_field phy_pma_cmn_ctrl_2 =
177 REG_FIELD(PHY_PMA_CMN_CTRL2, 0, 7);
178
179static const struct reg_field phy_pma_pll_raw_ctrl =
180 REG_FIELD(PHY_PMA_PLL_RAW_CTRL, 0, 1);
181
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100182static const struct reg_field phy_reset_ctrl =
183 REG_FIELD(PHY_RESET, 8, 8);
184
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100185struct cdns_torrent_inst {
186 struct phy *phy;
187 u32 mlane;
188 u32 phy_type;
189 u32 num_lanes;
190 struct reset_control *lnk_rst;
191};
192
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100193struct cdns_torrent_phy {
Scott Telfordc8b427e2018-08-09 11:30:30 +0100194 void __iomem *base; /* DPTX registers base */
195 void __iomem *sd_base; /* SD0801 registers base */
Scott Telfordc8b427e2018-08-09 11:30:30 +0100196 u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100197 struct reset_control *phy_rst;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100198 struct device *dev;
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100199 struct clk *clk;
200 unsigned long ref_clk_rate;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100201 struct cdns_torrent_inst phys[MAX_NUM_LANES];
202 int nsubnodes;
Swapnil Jakhade29d1fd22020-09-16 20:28:25 +0200203 const struct cdns_torrent_data *init_data;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100204 struct regmap *regmap;
205 struct regmap *regmap_common_cdb;
206 struct regmap *regmap_phy_pcs_common_cdb;
207 struct regmap *regmap_phy_pma_common_cdb;
208 struct regmap *regmap_tx_lane_cdb[MAX_NUM_LANES];
209 struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES];
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100210 struct regmap *regmap_dptx_phy_reg;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100211 struct regmap_field *phy_pll_cfg;
212 struct regmap_field *phy_pma_cmn_ctrl_2;
213 struct regmap_field *phy_pma_pll_raw_ctrl;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100214 struct regmap_field *phy_reset_ctrl;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100215};
216
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100217enum phy_powerstate {
218 POWERSTATE_A0 = 0,
219 /* Powerstate A1 is unused */
220 POWERSTATE_A2 = 2,
221 POWERSTATE_A3 = 3,
222};
223
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100224static int cdns_torrent_dp_init(struct phy *phy);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100225static int cdns_torrent_dp_exit(struct phy *phy);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100226static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
227 u32 num_lanes);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100228static
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100229int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy);
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100230static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy,
231 struct cdns_torrent_inst *inst);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100232static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100233void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy);
234static
235void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
236 u32 rate, bool ssc);
237static
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100238void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100239static
240void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
241 u32 rate, bool ssc);
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100242static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
Scott Telfordc8b427e2018-08-09 11:30:30 +0100243 unsigned int lane);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100244static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
245 u32 rate, u32 num_lanes);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100246static int cdns_torrent_dp_configure(struct phy *phy,
247 union phy_configure_opts *opts);
248static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
249 u32 num_lanes,
250 enum phy_powerstate powerstate);
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100251static int cdns_torrent_phy_on(struct phy *phy);
252static int cdns_torrent_phy_off(struct phy *phy);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100253
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100254static const struct phy_ops cdns_torrent_phy_ops = {
255 .init = cdns_torrent_dp_init,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100256 .exit = cdns_torrent_dp_exit,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100257 .configure = cdns_torrent_dp_configure,
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100258 .power_on = cdns_torrent_phy_on,
259 .power_off = cdns_torrent_phy_off,
Scott Telfordc8b427e2018-08-09 11:30:30 +0100260 .owner = THIS_MODULE,
261};
262
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100263struct cdns_torrent_data {
264 u8 block_offset_shift;
265 u8 reg_offset_shift;
266};
267
268struct cdns_regmap_cdb_context {
269 struct device *dev;
270 void __iomem *base;
271 u8 reg_offset_shift;
272};
273
274static int cdns_regmap_write(void *context, unsigned int reg, unsigned int val)
275{
276 struct cdns_regmap_cdb_context *ctx = context;
277 u32 offset = reg << ctx->reg_offset_shift;
278
279 writew(val, ctx->base + offset);
280
281 return 0;
282}
283
284static int cdns_regmap_read(void *context, unsigned int reg, unsigned int *val)
285{
286 struct cdns_regmap_cdb_context *ctx = context;
287 u32 offset = reg << ctx->reg_offset_shift;
288
289 *val = readw(ctx->base + offset);
290 return 0;
291}
292
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100293static int cdns_regmap_dptx_write(void *context, unsigned int reg,
294 unsigned int val)
295{
296 struct cdns_regmap_cdb_context *ctx = context;
297 u32 offset = reg;
298
299 writel(val, ctx->base + offset);
300
301 return 0;
302}
303
304static int cdns_regmap_dptx_read(void *context, unsigned int reg,
305 unsigned int *val)
306{
307 struct cdns_regmap_cdb_context *ctx = context;
308 u32 offset = reg;
309
310 *val = readl(ctx->base + offset);
311 return 0;
312}
313
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100314#define TORRENT_TX_LANE_CDB_REGMAP_CONF(n) \
315{ \
316 .name = "torrent_tx_lane" n "_cdb", \
317 .reg_stride = 1, \
318 .fast_io = true, \
319 .reg_write = cdns_regmap_write, \
320 .reg_read = cdns_regmap_read, \
321}
322
323#define TORRENT_RX_LANE_CDB_REGMAP_CONF(n) \
324{ \
325 .name = "torrent_rx_lane" n "_cdb", \
326 .reg_stride = 1, \
327 .fast_io = true, \
328 .reg_write = cdns_regmap_write, \
329 .reg_read = cdns_regmap_read, \
330}
331
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200332static const struct regmap_config cdns_torrent_tx_lane_cdb_config[] = {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100333 TORRENT_TX_LANE_CDB_REGMAP_CONF("0"),
334 TORRENT_TX_LANE_CDB_REGMAP_CONF("1"),
335 TORRENT_TX_LANE_CDB_REGMAP_CONF("2"),
336 TORRENT_TX_LANE_CDB_REGMAP_CONF("3"),
337};
338
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200339static const struct regmap_config cdns_torrent_rx_lane_cdb_config[] = {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100340 TORRENT_RX_LANE_CDB_REGMAP_CONF("0"),
341 TORRENT_RX_LANE_CDB_REGMAP_CONF("1"),
342 TORRENT_RX_LANE_CDB_REGMAP_CONF("2"),
343 TORRENT_RX_LANE_CDB_REGMAP_CONF("3"),
344};
345
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200346static const struct regmap_config cdns_torrent_common_cdb_config = {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100347 .name = "torrent_common_cdb",
348 .reg_stride = 1,
349 .fast_io = true,
350 .reg_write = cdns_regmap_write,
351 .reg_read = cdns_regmap_read,
352};
353
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200354static const struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100355 .name = "torrent_phy_pcs_cmn_cdb",
356 .reg_stride = 1,
357 .fast_io = true,
358 .reg_write = cdns_regmap_write,
359 .reg_read = cdns_regmap_read,
360};
361
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200362static const struct regmap_config cdns_torrent_phy_pma_cmn_cdb_config = {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100363 .name = "torrent_phy_pma_cmn_cdb",
364 .reg_stride = 1,
365 .fast_io = true,
366 .reg_write = cdns_regmap_write,
367 .reg_read = cdns_regmap_read,
368};
369
Rikard Falkeborn57d39c72020-09-12 22:46:39 +0200370static const struct regmap_config cdns_torrent_dptx_phy_config = {
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100371 .name = "torrent_dptx_phy",
372 .reg_stride = 1,
373 .fast_io = true,
374 .reg_write = cdns_regmap_dptx_write,
375 .reg_read = cdns_regmap_dptx_read,
376};
377
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +0100378/* PHY mmr access functions */
379
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100380static void cdns_torrent_phy_write(struct regmap *regmap, u32 offset, u32 val)
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +0100381{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100382 regmap_write(regmap, offset, val);
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +0100383}
384
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100385static u32 cdns_torrent_phy_read(struct regmap *regmap, u32 offset)
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100386{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100387 unsigned int val;
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100388
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100389 regmap_read(regmap, offset, &val);
390 return val;
391}
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100392
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100393/* DPTX mmr access functions */
394
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100395static void cdns_torrent_dp_write(struct regmap *regmap, u32 offset, u32 val)
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100396{
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100397 regmap_write(regmap, offset, val);
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100398}
399
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100400static u32 cdns_torrent_dp_read(struct regmap *regmap, u32 offset)
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100401{
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100402 u32 val;
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100403
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100404 regmap_read(regmap, offset, &val);
405 return val;
406}
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100407
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100408/*
409 * Structure used to store values of PHY registers for voltage-related
410 * coefficients, for particular voltage swing and pre-emphasis level. Values
411 * are shared across all physical lanes.
412 */
413struct coefficients {
414 /* Value of DRV_DIAG_TX_DRV register to use */
415 u16 diag_tx_drv;
416 /* Value of TX_TXCC_MGNFS_MULT_000 register to use */
417 u16 mgnfs_mult;
418 /* Value of TX_TXCC_CPOST_MULT_00 register to use */
419 u16 cpost_mult;
420};
421
422/*
423 * Array consists of values of voltage-related registers for sd0801 PHY. A value
424 * of 0xFFFF is a placeholder for invalid combination, and will never be used.
425 */
426static const struct coefficients vltg_coeff[4][4] = {
427 /* voltage swing 0, pre-emphasis 0->3 */
428 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x002A,
429 .cpost_mult = 0x0000},
430 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x001F,
431 .cpost_mult = 0x0014},
432 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0012,
433 .cpost_mult = 0x0020},
434 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
435 .cpost_mult = 0x002A}
436 },
437
438 /* voltage swing 1, pre-emphasis 0->3 */
439 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x001F,
440 .cpost_mult = 0x0000},
441 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0013,
442 .cpost_mult = 0x0012},
443 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
444 .cpost_mult = 0x001F},
445 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
446 .cpost_mult = 0xFFFF}
447 },
448
449 /* voltage swing 2, pre-emphasis 0->3 */
450 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0013,
451 .cpost_mult = 0x0000},
452 {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
453 .cpost_mult = 0x0013},
454 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
455 .cpost_mult = 0xFFFF},
456 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
457 .cpost_mult = 0xFFFF}
458 },
459
460 /* voltage swing 3, pre-emphasis 0->3 */
461 { {.diag_tx_drv = 0x0003, .mgnfs_mult = 0x0000,
462 .cpost_mult = 0x0000},
463 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
464 .cpost_mult = 0xFFFF},
465 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
466 .cpost_mult = 0xFFFF},
467 {.diag_tx_drv = 0xFFFF, .mgnfs_mult = 0xFFFF,
468 .cpost_mult = 0xFFFF}
469 }
470};
471
472/*
473 * Enable or disable PLL for selected lanes.
474 */
475static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
476 struct phy_configure_opts_dp *dp,
477 bool enable)
478{
479 u32 rd_val;
480 u32 ret;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100481 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
482
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100483 /*
484 * Used to determine, which bits to check for or enable in
485 * PHY_PMA_XCVR_PLLCLK_EN register.
486 */
487 u32 pll_bits;
488 /* Used to enable or disable lanes. */
489 u32 pll_val;
490
491 /* Select values of registers and mask, depending on enabled lane
492 * count.
493 */
494 switch (dp->lanes) {
495 /* lane 0 */
496 case (1):
497 pll_bits = 0x00000001;
498 break;
499 /* lanes 0-1 */
500 case (2):
501 pll_bits = 0x00000003;
502 break;
503 /* lanes 0-3, all */
504 default:
505 pll_bits = 0x0000000F;
506 break;
507 }
508
509 if (enable)
510 pll_val = pll_bits;
511 else
512 pll_val = 0x00000000;
513
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100514 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100515
516 /* Wait for acknowledgment from PHY. */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100517 ret = regmap_read_poll_timeout(regmap,
518 PHY_PMA_XCVR_PLLCLK_EN_ACK,
519 rd_val,
520 (rd_val & pll_bits) == pll_val,
521 0, POLL_TIMEOUT_US);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100522 ndelay(100);
523 return ret;
524}
525
526/*
527 * Perform register operations related to setting link rate, once powerstate is
528 * set and PLL disable request was processed.
529 */
530static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
531 struct phy_configure_opts_dp *dp)
532{
533 u32 ret;
534 u32 read_val;
535
536 /* Disable the cmn_pll0_en before re-programming the new data rate. */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100537 regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100538
539 /*
540 * Wait for PLL ready de-assertion.
541 * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1
542 */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100543 ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
544 read_val,
545 ((read_val >> 2) & 0x01) != 0,
546 0, POLL_TIMEOUT_US);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100547 if (ret)
548 return ret;
549 ndelay(200);
550
551 /* DP Rate Change - VCO Output settings. */
552 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) {
553 /* PMA common configuration 19.2MHz */
554 cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate,
555 dp->ssc);
556 cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
557 } else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) {
558 /* PMA common configuration 25MHz */
559 cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate,
560 dp->ssc);
561 cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
562 }
563 cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
564
565 /* Enable the cmn_pll0_en. */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100566 regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100567
568 /*
569 * Wait for PLL ready assertion.
570 * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1
571 */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100572 ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
573 read_val,
574 (read_val & 0x01) != 0,
575 0, POLL_TIMEOUT_US);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100576 return ret;
577}
578
579/*
580 * Verify, that parameters to configure PHY with are correct.
581 */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100582static int cdns_torrent_dp_verify_config(struct cdns_torrent_inst *inst,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100583 struct phy_configure_opts_dp *dp)
584{
585 u8 i;
586
587 /* If changing link rate was required, verify it's supported. */
588 if (dp->set_rate) {
589 switch (dp->link_rate) {
590 case 1620:
591 case 2160:
592 case 2430:
593 case 2700:
594 case 3240:
595 case 4320:
596 case 5400:
597 case 8100:
598 /* valid bit rate */
599 break;
600 default:
601 return -EINVAL;
602 }
603 }
604
605 /* Verify lane count. */
606 switch (dp->lanes) {
607 case 1:
608 case 2:
609 case 4:
610 /* valid lane count. */
611 break;
612 default:
613 return -EINVAL;
614 }
615
616 /* Check against actual number of PHY's lanes. */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100617 if (dp->lanes > inst->num_lanes)
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100618 return -EINVAL;
619
620 /*
621 * If changing voltages is required, check swing and pre-emphasis
622 * levels, per-lane.
623 */
624 if (dp->set_voltages) {
625 /* Lane count verified previously. */
626 for (i = 0; i < dp->lanes; i++) {
627 if (dp->voltage[i] > 3 || dp->pre[i] > 3)
628 return -EINVAL;
629
630 /* Sum of voltage swing and pre-emphasis levels cannot
631 * exceed 3.
632 */
633 if (dp->voltage[i] + dp->pre[i] > 3)
634 return -EINVAL;
635 }
636 }
637
638 return 0;
639}
640
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100641/* Set power state A0 and PLL clock enable to 0 on enabled lanes. */
642static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
643 u32 num_lanes)
644{
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100645 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
646 u32 pwr_state = cdns_torrent_dp_read(regmap,
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100647 PHY_PMA_XCVR_POWER_STATE_REQ);
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100648 u32 pll_clk_en = cdns_torrent_dp_read(regmap,
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100649 PHY_PMA_XCVR_PLLCLK_EN);
650
651 /* Lane 0 is always enabled. */
652 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
653 PHY_POWER_STATE_LN_0);
654 pll_clk_en &= ~0x01U;
655
656 if (num_lanes > 1) {
657 /* lane 1 */
658 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
659 PHY_POWER_STATE_LN_1);
660 pll_clk_en &= ~(0x01U << 1);
661 }
662
663 if (num_lanes > 2) {
664 /* lanes 2 and 3 */
665 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
666 PHY_POWER_STATE_LN_2);
667 pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
668 PHY_POWER_STATE_LN_3);
669 pll_clk_en &= ~(0x01U << 2);
670 pll_clk_en &= ~(0x01U << 3);
671 }
672
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100673 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state);
674 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_clk_en);
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100675}
676
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100677/* Configure lane count as required. */
678static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
679 struct phy_configure_opts_dp *dp)
680{
681 u32 value;
682 u32 ret;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100683 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100684 u8 lane_mask = (1 << dp->lanes) - 1;
685
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100686 value = cdns_torrent_dp_read(regmap, PHY_RESET);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100687 /* clear pma_tx_elec_idle_ln_* bits. */
688 value &= ~PMA_TX_ELEC_IDLE_MASK;
689 /* Assert pma_tx_elec_idle_ln_* for disabled lanes. */
690 value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) &
691 PMA_TX_ELEC_IDLE_MASK;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100692 cdns_torrent_dp_write(regmap, PHY_RESET, value);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100693
694 /* reset the link by asserting phy_l00_reset_n low */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100695 cdns_torrent_dp_write(regmap, PHY_RESET,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100696 value & (~PHY_L00_RESET_N_MASK));
697
698 /*
699 * Assert lane reset on unused lanes and lane 0 so they remain in reset
700 * and powered down when re-enabling the link
701 */
702 value = (value & 0x0000FFF0) | (0x0000000E & lane_mask);
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100703 cdns_torrent_dp_write(regmap, PHY_RESET, value);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100704
705 cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes);
706
707 /* release phy_l0*_reset_n based on used laneCount */
708 value = (value & 0x0000FFF0) | (0x0000000F & lane_mask);
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100709 cdns_torrent_dp_write(regmap, PHY_RESET, value);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100710
711 /* Wait, until PHY gets ready after releasing PHY reset signal. */
712 ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
713 if (ret)
714 return ret;
715
716 ndelay(100);
717
718 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100719 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100720
721 ret = cdns_torrent_dp_run(cdns_phy, dp->lanes);
722
723 return ret;
724}
725
726/* Configure link rate as required. */
727static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
728 struct phy_configure_opts_dp *dp)
729{
730 u32 ret;
731
732 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
733 POWERSTATE_A3);
734 if (ret)
735 return ret;
736 ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false);
737 if (ret)
738 return ret;
739 ndelay(200);
740
741 ret = cdns_torrent_dp_configure_rate(cdns_phy, dp);
742 if (ret)
743 return ret;
744 ndelay(200);
745
746 ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true);
747 if (ret)
748 return ret;
749 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
750 POWERSTATE_A2);
751 if (ret)
752 return ret;
753 ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
754 POWERSTATE_A0);
755 if (ret)
756 return ret;
757 ndelay(900);
758
759 return ret;
760}
761
762/* Configure voltage swing and pre-emphasis for all enabled lanes. */
763static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy,
764 struct phy_configure_opts_dp *dp)
765{
766 u8 lane;
767 u16 val;
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100768
769 for (lane = 0; lane < dp->lanes; lane++) {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100770 val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
771 TX_DIAG_ACYA);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100772 /*
773 * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the
774 * current state of the analog TX driver.
775 */
776 val |= TX_DIAG_ACYA_HBDC_MASK;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100777 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
778 TX_DIAG_ACYA, val);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100779
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100780 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
781 TX_TXCC_CTRL, 0x08A4);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100782 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100783 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
784 DRV_DIAG_TX_DRV, val);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100785 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100786 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
787 TX_TXCC_MGNFS_MULT_000,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100788 val);
789 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100790 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
791 TX_TXCC_CPOST_MULT_00,
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100792 val);
793
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100794 val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
795 TX_DIAG_ACYA);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100796 /*
797 * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of
798 * analog TX driver to reflect the new programmed one.
799 */
800 val &= ~TX_DIAG_ACYA_HBDC_MASK;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100801 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
802 TX_DIAG_ACYA, val);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100803 }
804};
805
806static int cdns_torrent_dp_configure(struct phy *phy,
807 union phy_configure_opts *opts)
808{
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100809 struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
810 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100811 int ret;
812
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100813 ret = cdns_torrent_dp_verify_config(inst, &opts->dp);
Swapnil Jakhade572d6592020-02-06 07:10:57 +0100814 if (ret) {
815 dev_err(&phy->dev, "invalid params for phy configure\n");
816 return ret;
817 }
818
819 if (opts->dp.set_lanes) {
820 ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp);
821 if (ret) {
822 dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n");
823 return ret;
824 }
825 }
826
827 if (opts->dp.set_rate) {
828 ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp);
829 if (ret) {
830 dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n");
831 return ret;
832 }
833 }
834
835 if (opts->dp.set_voltages)
836 cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp);
837
838 return ret;
839}
840
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100841static int cdns_torrent_dp_init(struct phy *phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100842{
843 unsigned char lane_bits;
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100844 int ret;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100845 struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
846 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100847 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100848
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100849 ret = clk_prepare_enable(cdns_phy->clk);
850 if (ret) {
851 dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
852 return ret;
853 }
854
855 cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
856 if (!(cdns_phy->ref_clk_rate)) {
857 dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
858 clk_disable_unprepare(cdns_phy->clk);
859 return -EINVAL;
860 }
861
862 switch (cdns_phy->ref_clk_rate) {
863 case REF_CLK_19_2MHz:
864 case REF_CLK_25MHz:
865 /* Valid Ref Clock Rate */
866 break;
867 default:
868 dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
869 return -EINVAL;
870 }
871
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100872 cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
Scott Telfordc8b427e2018-08-09 11:30:30 +0100873
874 /* PHY PMA registers configuration function */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100875 cdns_torrent_dp_pma_cfg(cdns_phy, inst);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100876
877 /*
878 * Set lines power state to A0
879 * Set lines pll clk enable to 0
880 */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100881 cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100882
883 /*
884 * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
885 * used lanes
886 */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100887 lane_bits = (1 << inst->num_lanes) - 1;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100888 cdns_torrent_dp_write(regmap, PHY_RESET,
Swapnil Jakhadef61b3ae2020-02-06 07:10:54 +0100889 ((0xF & ~lane_bits) << 4) | (0xF & lane_bits));
Scott Telfordc8b427e2018-08-09 11:30:30 +0100890
891 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100892 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100893
894 /* PHY PMA registers configuration functions */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100895 /* Initialize PHY with max supported link rate, without SSC. */
896 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
897 cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy,
898 cdns_phy->max_bit_rate,
899 false);
900 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
901 cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy,
902 cdns_phy->max_bit_rate,
903 false);
904 cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100905 inst->num_lanes);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100906
907 /* take out of reset */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100908 regmap_field_write(cdns_phy->phy_reset_ctrl, 0x1);
909
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100910 cdns_torrent_phy_on(phy);
911
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100912 ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
913 if (ret)
914 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100915
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100916 ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes);
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100917
918 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100919}
920
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100921static int cdns_torrent_dp_exit(struct phy *phy)
922{
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100923 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100924
925 clk_disable_unprepare(cdns_phy->clk);
926 return 0;
927}
928
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100929static
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100930int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100931{
932 unsigned int reg;
933 int ret;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100934 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100935
Swapnil Jakhadecba472e2020-02-06 07:10:59 +0100936 ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg,
937 reg & 1, 0, POLL_TIMEOUT_US);
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100938 if (ret == -ETIMEDOUT) {
Scott Telfordc8b427e2018-08-09 11:30:30 +0100939 dev_err(cdns_phy->dev,
940 "timeout waiting for PMA common ready\n");
Swapnil Jakhade21c79142020-02-06 07:10:55 +0100941 return -ETIMEDOUT;
942 }
943
944 return 0;
Scott Telfordc8b427e2018-08-09 11:30:30 +0100945}
946
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100947static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy,
948 struct cdns_torrent_inst *inst)
Scott Telfordc8b427e2018-08-09 11:30:30 +0100949{
950 unsigned int i;
951
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100952 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
953 /* PMA common configuration 19.2MHz */
954 cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
955 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
956 /* PMA common configuration 25MHz */
957 cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100958
959 /* PMA lane configuration to deal with multi-link operation */
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +0100960 for (i = 0; i < inst->num_lanes; i++)
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100961 cdns_torrent_dp_pma_lane_cfg(cdns_phy, i);
Scott Telfordc8b427e2018-08-09 11:30:30 +0100962}
963
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +0100964static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100965void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy)
966{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100967 struct regmap *regmap = cdns_phy->regmap_common_cdb;
968
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100969 /* refclock registers - assumes 19.2 MHz refclock */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100970 cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0014);
971 cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0027);
972 cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00A1);
973 cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0027);
974 cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00A1);
975 cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x0060);
976 cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x0060);
977 cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0014);
978 cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x0018);
979 cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0005);
980 cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x0018);
981 cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0005);
982 cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x0240);
983 cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0005);
984 cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002);
985 cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002);
986 cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000B);
987 cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x0137);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +0100988
989 /* PLL registers */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +0100990 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
991 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
992 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
993 cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
994 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
995 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
996 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
997 cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
998 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00C0);
999 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
1000 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00C0);
1001 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
1002 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0260);
1003 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
1004 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0260);
1005 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001006}
1007
1008/*
1009 * Set registers responsible for enabling and configuring SSC, with second and
1010 * third register values provided by parameters.
1011 */
1012static
1013void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy,
1014 u32 ctrl2_val, u32 ctrl3_val)
1015{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001016 struct regmap *regmap = cdns_phy->regmap_common_cdb;
1017
1018 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
1019 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
1020 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl3_val);
1021 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
1022 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
1023 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
1024 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl3_val);
1025 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001026}
1027
1028static
1029void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
1030 u32 rate, bool ssc)
1031{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001032 struct regmap *regmap = cdns_phy->regmap_common_cdb;
1033
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001034 /* Assumes 19.2 MHz refclock */
1035 switch (rate) {
1036 /* Setting VCO for 10.8GHz */
1037 case 2700:
1038 case 5400:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001039 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001040 CMN_PLL0_INTDIV_M0, 0x0119);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001041 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001042 CMN_PLL0_FRACDIVL_M0, 0x4000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001043 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001044 CMN_PLL0_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001045 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001046 CMN_PLL0_HIGH_THR_M0, 0x00BC);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001047 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001048 CMN_PDIAG_PLL0_CTRL_M0, 0x0012);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001049 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001050 CMN_PLL1_INTDIV_M0, 0x0119);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001051 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001052 CMN_PLL1_FRACDIVL_M0, 0x4000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001053 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001054 CMN_PLL1_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001055 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001056 CMN_PLL1_HIGH_THR_M0, 0x00BC);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001057 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001058 CMN_PDIAG_PLL1_CTRL_M0, 0x0012);
1059 if (ssc)
1060 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A,
1061 0x006A);
1062 break;
1063 /* Setting VCO for 9.72GHz */
1064 case 1620:
1065 case 2430:
1066 case 3240:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001067 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001068 CMN_PLL0_INTDIV_M0, 0x01FA);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001069 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001070 CMN_PLL0_FRACDIVL_M0, 0x4000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001071 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001072 CMN_PLL0_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001073 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001074 CMN_PLL0_HIGH_THR_M0, 0x0152);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001075 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001076 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001077 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001078 CMN_PLL1_INTDIV_M0, 0x01FA);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001079 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001080 CMN_PLL1_FRACDIVL_M0, 0x4000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001081 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001082 CMN_PLL1_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001083 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001084 CMN_PLL1_HIGH_THR_M0, 0x0152);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001085 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001086 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
1087 if (ssc)
1088 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD,
1089 0x0069);
1090 break;
1091 /* Setting VCO for 8.64GHz */
1092 case 2160:
1093 case 4320:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001094 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001095 CMN_PLL0_INTDIV_M0, 0x01C2);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001096 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001097 CMN_PLL0_FRACDIVL_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001098 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001099 CMN_PLL0_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001100 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001101 CMN_PLL0_HIGH_THR_M0, 0x012C);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001102 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001103 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001104 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001105 CMN_PLL1_INTDIV_M0, 0x01C2);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001106 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001107 CMN_PLL1_FRACDIVL_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001108 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001109 CMN_PLL1_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001110 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001111 CMN_PLL1_HIGH_THR_M0, 0x012C);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001112 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001113 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
1114 if (ssc)
1115 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536,
1116 0x0069);
1117 break;
1118 /* Setting VCO for 8.1GHz */
1119 case 8100:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001120 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001121 CMN_PLL0_INTDIV_M0, 0x01A5);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001122 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001123 CMN_PLL0_FRACDIVL_M0, 0xE000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001124 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001125 CMN_PLL0_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001126 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001127 CMN_PLL0_HIGH_THR_M0, 0x011A);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001128 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001129 CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001130 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001131 CMN_PLL1_INTDIV_M0, 0x01A5);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001132 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001133 CMN_PLL1_FRACDIVL_M0, 0xE000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001134 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001135 CMN_PLL1_FRACDIVH_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001136 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001137 CMN_PLL1_HIGH_THR_M0, 0x011A);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001138 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001139 CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
1140 if (ssc)
1141 cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7,
1142 0x006A);
1143 break;
1144 }
1145
1146 if (ssc) {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001147 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001148 CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001149 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001150 CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001151 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001152 CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001153 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001154 CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
1155 } else {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001156 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001157 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001158 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001159 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260);
1160 /* Set reset register values to disable SSC */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001161 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001162 CMN_PLL0_SS_CTRL1_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001163 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001164 CMN_PLL0_SS_CTRL2_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001165 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001166 CMN_PLL0_SS_CTRL3_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001167 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001168 CMN_PLL0_SS_CTRL4_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001169 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001170 CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001171 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001172 CMN_PLL1_SS_CTRL1_M0, 0x0002);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001173 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001174 CMN_PLL1_SS_CTRL2_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001175 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001176 CMN_PLL1_SS_CTRL3_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001177 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001178 CMN_PLL1_SS_CTRL4_M0, 0x0000);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001179 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001180 CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
1181 }
1182
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001183 cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x0099);
1184 cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x0099);
1185 cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x0099);
1186 cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x0099);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001187}
1188
1189static
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001190void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001191{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001192 struct regmap *regmap = cdns_phy->regmap_common_cdb;
1193
Scott Telfordc8b427e2018-08-09 11:30:30 +01001194 /* refclock registers - assumes 25 MHz refclock */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001195 cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0019);
1196 cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0032);
1197 cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00D1);
1198 cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0032);
1199 cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00D1);
1200 cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x007D);
1201 cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x007D);
1202 cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0019);
1203 cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x001E);
1204 cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0006);
1205 cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x001E);
1206 cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0006);
1207 cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x02EE);
1208 cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0006);
1209 cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002);
1210 cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002);
1211 cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000E);
1212 cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x012B);
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001213
Scott Telfordc8b427e2018-08-09 11:30:30 +01001214 /* PLL registers */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001215 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
1216 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
1217 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
1218 cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
1219 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
1220 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
1221 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
1222 cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
1223 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00FA);
1224 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
1225 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00FA);
1226 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
1227 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0317);
1228 cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
1229 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0317);
1230 cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001231}
1232
1233/*
1234 * Set registers responsible for enabling and configuring SSC, with second
1235 * register value provided by a parameter.
1236 */
1237static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy,
1238 u32 ctrl2_val)
1239{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001240 struct regmap *regmap = cdns_phy->regmap_common_cdb;
1241
1242 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
1243 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
1244 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x007F);
1245 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
1246 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
1247 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
1248 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x007F);
1249 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001250}
1251
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001252static
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001253void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
1254 u32 rate, bool ssc)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001255{
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001256 struct regmap *regmap = cdns_phy->regmap_common_cdb;
1257
Scott Telfordc8b427e2018-08-09 11:30:30 +01001258 /* Assumes 25 MHz refclock */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001259 switch (rate) {
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001260 /* Setting VCO for 10.8GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001261 case 2700:
1262 case 5400:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001263 cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01B0);
1264 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
1265 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
1266 cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0120);
1267 cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01B0);
1268 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
1269 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
1270 cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0120);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001271 if (ssc)
1272 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001273 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001274 /* Setting VCO for 9.72GHz */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001275 case 1620:
Scott Telfordc8b427e2018-08-09 11:30:30 +01001276 case 2430:
1277 case 3240:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001278 cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0184);
1279 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xCCCD);
1280 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
1281 cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0104);
1282 cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0184);
1283 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xCCCD);
1284 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
1285 cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0104);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001286 if (ssc)
1287 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001288 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001289 /* Setting VCO for 8.64GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001290 case 2160:
1291 case 4320:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001292 cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0159);
1293 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x999A);
1294 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
1295 cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00E7);
1296 cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0159);
1297 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x999A);
1298 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
1299 cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00E7);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001300 if (ssc)
1301 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001302 break;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001303 /* Setting VCO for 8.1GHz */
Scott Telfordc8b427e2018-08-09 11:30:30 +01001304 case 8100:
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001305 cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0144);
1306 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
1307 cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
1308 cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00D8);
1309 cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0144);
1310 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
1311 cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
1312 cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00D8);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001313 if (ssc)
1314 cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001315 break;
1316 }
1317
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001318 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
1319 cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001320
1321 if (ssc) {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001322 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001323 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001324 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001325 CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001326 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001327 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001328 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001329 CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
1330 } else {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001331 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001332 CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001333 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001334 CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317);
1335 /* Set reset register values to disable SSC */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001336 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002);
1337 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000);
1338 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000);
1339 cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000);
1340 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001341 CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001342 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002);
1343 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000);
1344 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000);
1345 cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000);
1346 cdns_torrent_phy_write(regmap,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001347 CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
1348 }
1349
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001350 cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x00C7);
1351 cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7);
1352 cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x00C7);
1353 cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001354}
1355
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001356static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
1357 u32 rate, u32 num_lanes)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001358{
1359 unsigned int clk_sel_val = 0;
1360 unsigned int hsclk_div_val = 0;
1361 unsigned int i;
1362
1363 /* 16'h0000 for single DP link configuration */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001364 regmap_field_write(cdns_phy->phy_pll_cfg, 0x0);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001365
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001366 switch (rate) {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001367 case 1620:
1368 clk_sel_val = 0x0f01;
1369 hsclk_div_val = 2;
1370 break;
1371 case 2160:
1372 case 2430:
1373 case 2700:
1374 clk_sel_val = 0x0701;
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001375 hsclk_div_val = 1;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001376 break;
1377 case 3240:
1378 clk_sel_val = 0x0b00;
1379 hsclk_div_val = 2;
1380 break;
1381 case 4320:
1382 case 5400:
1383 clk_sel_val = 0x0301;
1384 hsclk_div_val = 0;
1385 break;
1386 case 8100:
1387 clk_sel_val = 0x0200;
1388 hsclk_div_val = 0;
1389 break;
1390 }
1391
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001392 cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
Swapnil Jakhadeccb1b892020-02-06 07:10:53 +01001393 CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001394 cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001395 CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001396
1397 /* PMA lane configuration to deal with multi-link operation */
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001398 for (i = 0; i < num_lanes; i++)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001399 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
1400 XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001401}
1402
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001403static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
1404 unsigned int lane)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001405{
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001406 /* Per lane, refclock-dependent receiver detection setting */
1407 if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001408 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1409 TX_RCVDET_ST_TMR, 0x0780);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001410 else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001411 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1412 TX_RCVDET_ST_TMR, 0x09C4);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001413
Scott Telfordc8b427e2018-08-09 11:30:30 +01001414 /* Writing Tx/Rx Power State Controllers registers */
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001415 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1416 TX_PSC_A0, 0x00FB);
1417 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1418 TX_PSC_A2, 0x04AA);
1419 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1420 TX_PSC_A3, 0x04AA);
1421 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1422 RX_PSC_A0, 0x0000);
1423 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1424 RX_PSC_A2, 0x0000);
1425 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1426 RX_PSC_A3, 0x0000);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001427
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001428 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1429 RX_PSC_CAL, 0x0000);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001430
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001431 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1432 RX_REE_GCSM1_CTRL, 0x0000);
1433 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1434 RX_REE_GCSM2_CTRL, 0x0000);
1435 cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
1436 RX_REE_PERGCSM_CTRL, 0x0000);
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001437
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001438 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1439 XCVR_DIAG_BIDI_CTRL, 0x000F);
1440 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1441 XCVR_DIAG_PLLDRC_CTRL, 0x0001);
1442 cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
1443 XCVR_DIAG_HSCLK_SEL, 0x0000);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001444}
1445
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001446static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
1447 u32 num_lanes,
1448 enum phy_powerstate powerstate)
1449{
1450 /* Register value for power state for a single byte. */
1451 u32 value_part;
1452 u32 value;
1453 u32 mask;
1454 u32 read_val;
1455 u32 ret;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001456 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001457
1458 switch (powerstate) {
1459 case (POWERSTATE_A0):
1460 value_part = 0x01U;
1461 break;
1462 case (POWERSTATE_A2):
1463 value_part = 0x04U;
1464 break;
1465 default:
1466 /* Powerstate A3 */
1467 value_part = 0x08U;
1468 break;
1469 }
1470
1471 /* Select values of registers and mask, depending on enabled
1472 * lane count.
1473 */
1474 switch (num_lanes) {
1475 /* lane 0 */
1476 case (1):
1477 value = value_part;
1478 mask = 0x0000003FU;
1479 break;
1480 /* lanes 0-1 */
1481 case (2):
1482 value = (value_part
1483 | (value_part << 8));
1484 mask = 0x00003F3FU;
1485 break;
1486 /* lanes 0-3, all */
1487 default:
1488 value = (value_part
1489 | (value_part << 8)
1490 | (value_part << 16)
1491 | (value_part << 24));
1492 mask = 0x3F3F3F3FU;
1493 break;
1494 }
1495
1496 /* Set power state A<n>. */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001497 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value);
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001498 /* Wait, until PHY acknowledges power state completion. */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001499 ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK,
1500 read_val, (read_val & mask) == value, 0,
1501 POLL_TIMEOUT_US);
1502 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001503 ndelay(100);
1504
1505 return ret;
1506}
1507
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001508static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001509{
1510 unsigned int read_val;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001511 int ret;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001512 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001513
1514 /*
1515 * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
1516 * master lane
1517 */
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001518 ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK,
1519 read_val, read_val & 1,
1520 0, POLL_TIMEOUT_US);
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001521 if (ret == -ETIMEDOUT) {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001522 dev_err(cdns_phy->dev,
1523 "timeout waiting for link PLL clock enable ack\n");
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001524 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001525 }
1526
Scott Telfordc8b427e2018-08-09 11:30:30 +01001527 ndelay(100);
1528
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001529 ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001530 POWERSTATE_A2);
1531 if (ret)
1532 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001533
Swapnil Jakhade572d6592020-02-06 07:10:57 +01001534 ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001535 POWERSTATE_A0);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001536
Swapnil Jakhade21c79142020-02-06 07:10:55 +01001537 return ret;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001538}
1539
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001540static int cdns_torrent_phy_on(struct phy *phy)
1541{
1542 struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
1543 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
1544 int ret;
1545
1546 /* Take the PHY out of reset */
1547 ret = reset_control_deassert(cdns_phy->phy_rst);
1548 if (ret)
1549 return ret;
1550
1551 /* Take the PHY lane group out of reset */
1552 return reset_control_deassert(inst->lnk_rst);
1553}
1554
1555static int cdns_torrent_phy_off(struct phy *phy)
1556{
1557 struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
1558 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
1559 int ret;
1560
1561 ret = reset_control_assert(cdns_phy->phy_rst);
1562 if (ret)
1563 return ret;
1564
1565 return reset_control_assert(inst->lnk_rst);
1566}
Scott Telfordc8b427e2018-08-09 11:30:30 +01001567
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001568static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base,
1569 u32 block_offset,
1570 u8 reg_offset_shift,
1571 const struct regmap_config *config)
1572{
1573 struct cdns_regmap_cdb_context *ctx;
1574
1575 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1576 if (!ctx)
1577 return ERR_PTR(-ENOMEM);
1578
1579 ctx->dev = dev;
1580 ctx->base = base + block_offset;
1581 ctx->reg_offset_shift = reg_offset_shift;
1582
1583 return devm_regmap_init(dev, NULL, ctx, config);
1584}
1585
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001586static int cdns_torrent_dp_regfield_init(struct cdns_torrent_phy *cdns_phy)
1587{
1588 struct device *dev = cdns_phy->dev;
1589 struct regmap_field *field;
1590 struct regmap *regmap;
1591
1592 regmap = cdns_phy->regmap_dptx_phy_reg;
1593 field = devm_regmap_field_alloc(dev, regmap, phy_reset_ctrl);
1594 if (IS_ERR(field)) {
1595 dev_err(dev, "PHY_RESET reg field init failed\n");
1596 return PTR_ERR(field);
1597 }
1598 cdns_phy->phy_reset_ctrl = field;
1599
1600 return 0;
1601}
1602
1603static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001604{
1605 struct device *dev = cdns_phy->dev;
1606 struct regmap_field *field;
1607 struct regmap *regmap;
1608
1609 regmap = cdns_phy->regmap_phy_pcs_common_cdb;
1610 field = devm_regmap_field_alloc(dev, regmap, phy_pll_cfg);
1611 if (IS_ERR(field)) {
1612 dev_err(dev, "PHY_PLL_CFG reg field init failed\n");
1613 return PTR_ERR(field);
1614 }
1615 cdns_phy->phy_pll_cfg = field;
1616
1617 regmap = cdns_phy->regmap_phy_pma_common_cdb;
1618 field = devm_regmap_field_alloc(dev, regmap, phy_pma_cmn_ctrl_2);
1619 if (IS_ERR(field)) {
1620 dev_err(dev, "PHY_PMA_CMN_CTRL2 reg field init failed\n");
1621 return PTR_ERR(field);
1622 }
1623 cdns_phy->phy_pma_cmn_ctrl_2 = field;
1624
1625 regmap = cdns_phy->regmap_phy_pma_common_cdb;
1626 field = devm_regmap_field_alloc(dev, regmap, phy_pma_pll_raw_ctrl);
1627 if (IS_ERR(field)) {
1628 dev_err(dev, "PHY_PMA_PLL_RAW_CTRL reg field init failed\n");
1629 return PTR_ERR(field);
1630 }
1631 cdns_phy->phy_pma_pll_raw_ctrl = field;
1632
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001633 return 0;
1634}
1635
1636static int cdns_torrent_dp_regmap_init(struct cdns_torrent_phy *cdns_phy)
1637{
1638 void __iomem *base = cdns_phy->base;
1639 struct device *dev = cdns_phy->dev;
1640 struct regmap *regmap;
1641 u8 reg_offset_shift;
1642 u32 block_offset;
1643
1644 reg_offset_shift = cdns_phy->init_data->reg_offset_shift;
1645
1646 block_offset = TORRENT_DPTX_PHY_OFFSET;
1647 regmap = cdns_regmap_init(dev, base, block_offset,
1648 reg_offset_shift,
1649 &cdns_torrent_dptx_phy_config);
1650 if (IS_ERR(regmap)) {
1651 dev_err(dev, "Failed to init DPTX PHY regmap\n");
1652 return PTR_ERR(regmap);
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001653 }
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001654 cdns_phy->regmap_dptx_phy_reg = regmap;
Swapnil Jakhadecba472e2020-02-06 07:10:59 +01001655
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001656 return 0;
1657}
1658
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001659static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001660{
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001661 void __iomem *sd_base = cdns_phy->sd_base;
1662 u8 block_offset_shift, reg_offset_shift;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001663 struct device *dev = cdns_phy->dev;
1664 struct regmap *regmap;
1665 u32 block_offset;
1666 int i;
1667
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001668 block_offset_shift = cdns_phy->init_data->block_offset_shift;
1669 reg_offset_shift = cdns_phy->init_data->reg_offset_shift;
1670
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001671 for (i = 0; i < MAX_NUM_LANES; i++) {
1672 block_offset = TORRENT_TX_LANE_CDB_OFFSET(i, block_offset_shift,
1673 reg_offset_shift);
1674 regmap = cdns_regmap_init(dev, sd_base, block_offset,
1675 reg_offset_shift,
1676 &cdns_torrent_tx_lane_cdb_config[i]);
1677 if (IS_ERR(regmap)) {
1678 dev_err(dev, "Failed to init tx lane CDB regmap\n");
1679 return PTR_ERR(regmap);
1680 }
1681 cdns_phy->regmap_tx_lane_cdb[i] = regmap;
1682
1683 block_offset = TORRENT_RX_LANE_CDB_OFFSET(i, block_offset_shift,
1684 reg_offset_shift);
1685 regmap = cdns_regmap_init(dev, sd_base, block_offset,
1686 reg_offset_shift,
1687 &cdns_torrent_rx_lane_cdb_config[i]);
1688 if (IS_ERR(regmap)) {
1689 dev_err(dev, "Failed to init rx lane CDB regmap\n");
1690 return PTR_ERR(regmap);
1691 }
1692 cdns_phy->regmap_rx_lane_cdb[i] = regmap;
1693 }
1694
1695 block_offset = TORRENT_COMMON_CDB_OFFSET;
1696 regmap = cdns_regmap_init(dev, sd_base, block_offset,
1697 reg_offset_shift,
1698 &cdns_torrent_common_cdb_config);
1699 if (IS_ERR(regmap)) {
1700 dev_err(dev, "Failed to init common CDB regmap\n");
1701 return PTR_ERR(regmap);
1702 }
1703 cdns_phy->regmap_common_cdb = regmap;
1704
1705 block_offset = TORRENT_PHY_PCS_COMMON_OFFSET(block_offset_shift);
1706 regmap = cdns_regmap_init(dev, sd_base, block_offset,
1707 reg_offset_shift,
1708 &cdns_torrent_phy_pcs_cmn_cdb_config);
1709 if (IS_ERR(regmap)) {
1710 dev_err(dev, "Failed to init PHY PCS common CDB regmap\n");
1711 return PTR_ERR(regmap);
1712 }
1713 cdns_phy->regmap_phy_pcs_common_cdb = regmap;
1714
1715 block_offset = TORRENT_PHY_PMA_COMMON_OFFSET(block_offset_shift);
1716 regmap = cdns_regmap_init(dev, sd_base, block_offset,
1717 reg_offset_shift,
1718 &cdns_torrent_phy_pma_cmn_cdb_config);
1719 if (IS_ERR(regmap)) {
1720 dev_err(dev, "Failed to init PHY PMA common CDB regmap\n");
1721 return PTR_ERR(regmap);
1722 }
1723 cdns_phy->regmap_phy_pma_common_cdb = regmap;
1724
1725 return 0;
1726}
1727
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001728static int cdns_torrent_phy_probe(struct platform_device *pdev)
Scott Telfordc8b427e2018-08-09 11:30:30 +01001729{
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001730 struct cdns_torrent_phy *cdns_phy;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001731 struct device *dev = &pdev->dev;
1732 struct phy_provider *phy_provider;
Swapnil Jakhade29d1fd22020-09-16 20:28:25 +02001733 const struct cdns_torrent_data *data;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001734 struct device_node *child;
1735 int ret, subnodes, node = 0, i;
Swapnil Jakhaded09945e2020-09-16 20:28:29 +02001736 u32 total_num_lanes = 0;
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001737 u8 init_dp_regmap = 0;
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001738
1739 /* Get init data for this PHY */
Swapnil Jakhade29d1fd22020-09-16 20:28:25 +02001740 data = of_device_get_match_data(dev);
1741 if (!data)
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001742 return -EINVAL;
1743
Scott Telfordc8b427e2018-08-09 11:30:30 +01001744 cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL);
1745 if (!cdns_phy)
1746 return -ENOMEM;
1747
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001748 dev_set_drvdata(dev, cdns_phy);
1749 cdns_phy->dev = dev;
Swapnil Jakhade29d1fd22020-09-16 20:28:25 +02001750 cdns_phy->init_data = data;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001751
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001752 cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0);
1753 if (IS_ERR(cdns_phy->phy_rst)) {
1754 dev_err(dev, "%s: failed to get reset\n",
1755 dev->of_node->full_name);
1756 return PTR_ERR(cdns_phy->phy_rst);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001757 }
1758
Swapnil Jakhadee4b496a2020-02-06 07:10:56 +01001759 cdns_phy->clk = devm_clk_get(dev, "refclk");
1760 if (IS_ERR(cdns_phy->clk)) {
1761 dev_err(dev, "phy ref clock not found\n");
1762 return PTR_ERR(cdns_phy->clk);
1763 }
1764
Swapnil Jakhade46d205a2020-09-16 20:28:26 +02001765 cdns_phy->sd_base = devm_platform_ioremap_resource(pdev, 0);
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001766 if (IS_ERR(cdns_phy->sd_base))
1767 return PTR_ERR(cdns_phy->sd_base);
1768
1769 subnodes = of_get_available_child_count(dev->of_node);
1770 if (subnodes == 0) {
1771 dev_err(dev, "No available link subnodes found\n");
1772 return -EINVAL;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001773 }
1774
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001775 ret = cdns_torrent_regmap_init(cdns_phy);
1776 if (ret)
1777 return ret;
1778
1779 ret = cdns_torrent_regfield_init(cdns_phy);
1780 if (ret)
1781 return ret;
1782
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001783 for_each_available_child_of_node(dev->of_node, child) {
1784 struct phy *gphy;
1785
1786 cdns_phy->phys[node].lnk_rst =
1787 of_reset_control_array_get_exclusive(child);
1788 if (IS_ERR(cdns_phy->phys[node].lnk_rst)) {
1789 dev_err(dev, "%s: failed to get reset\n",
1790 child->full_name);
1791 ret = PTR_ERR(cdns_phy->phys[node].lnk_rst);
1792 goto put_lnk_rst;
1793 }
1794
1795 if (of_property_read_u32(child, "reg",
1796 &cdns_phy->phys[node].mlane)) {
1797 dev_err(dev, "%s: No \"reg\"-property.\n",
1798 child->full_name);
1799 ret = -EINVAL;
1800 goto put_child;
1801 }
1802
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001803 if (of_property_read_u32(child, "cdns,phy-type",
1804 &cdns_phy->phys[node].phy_type)) {
1805 dev_err(dev, "%s: No \"cdns,phy-type\"-property.\n",
1806 child->full_name);
1807 ret = -EINVAL;
1808 goto put_child;
1809 }
1810
Swapnil Jakhaded09945e2020-09-16 20:28:29 +02001811 if (of_property_read_u32(child, "cdns,num-lanes",
1812 &cdns_phy->phys[node].num_lanes)) {
1813 dev_err(dev, "%s: No \"cdns,num-lanes\"-property.\n",
1814 child->full_name);
1815 ret = -EINVAL;
1816 goto put_child;
1817 }
1818
1819 total_num_lanes += cdns_phy->phys[node].num_lanes;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001820
1821 if (cdns_phy->phys[node].phy_type == PHY_TYPE_DP) {
1822 switch (cdns_phy->phys[node].num_lanes) {
1823 case 1:
1824 case 2:
1825 case 4:
1826 /* valid number of lanes */
1827 break;
1828 default:
1829 dev_err(dev, "unsupported number of lanes: %d\n",
1830 cdns_phy->phys[node].num_lanes);
1831 ret = -EINVAL;
1832 goto put_child;
1833 }
1834
1835 cdns_phy->max_bit_rate = DEFAULT_MAX_BIT_RATE;
1836 of_property_read_u32(child, "cdns,max-bit-rate",
1837 &cdns_phy->max_bit_rate);
1838
1839 switch (cdns_phy->max_bit_rate) {
1840 case 1620:
1841 case 2160:
1842 case 2430:
1843 case 2700:
1844 case 3240:
1845 case 4320:
1846 case 5400:
1847 case 8100:
1848 /* valid bit rate */
1849 break;
1850 default:
1851 dev_err(dev, "unsupported max bit rate: %dMbps\n",
1852 cdns_phy->max_bit_rate);
1853 ret = -EINVAL;
1854 goto put_child;
1855 }
1856
1857 /* DPTX registers */
Swapnil Jakhade46d205a2020-09-16 20:28:26 +02001858 cdns_phy->base = devm_platform_ioremap_resource(pdev, 1);
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001859 if (IS_ERR(cdns_phy->base)) {
1860 ret = PTR_ERR(cdns_phy->base);
1861 goto put_child;
1862 }
1863
1864 gphy = devm_phy_create(dev, child,
1865 &cdns_torrent_phy_ops);
1866 if (IS_ERR(gphy)) {
1867 ret = PTR_ERR(gphy);
1868 goto put_child;
1869 }
1870
Swapnil Jakhade2e70c842020-09-16 20:28:28 +02001871 if (!init_dp_regmap) {
1872 ret = cdns_torrent_dp_regmap_init(cdns_phy);
1873 if (ret)
1874 goto put_child;
1875
1876 ret = cdns_torrent_dp_regfield_init(cdns_phy);
1877 if (ret)
1878 goto put_child;
1879
1880 init_dp_regmap++;
1881 }
1882
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001883 dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n",
1884 cdns_phy->phys[node].num_lanes,
1885 cdns_phy->max_bit_rate / 1000,
1886 cdns_phy->max_bit_rate % 1000);
Swapnil Jakhade0ffcc372020-09-11 08:18:34 +02001887
1888 gphy->attrs.bus_width = cdns_phy->phys[node].num_lanes;
1889 gphy->attrs.max_link_rate = cdns_phy->max_bit_rate;
1890 gphy->attrs.mode = PHY_MODE_DP;
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001891 }
1892 cdns_phy->phys[node].phy = gphy;
1893 phy_set_drvdata(gphy, &cdns_phy->phys[node]);
1894
1895 node++;
1896 }
1897 cdns_phy->nsubnodes = node;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001898
Swapnil Jakhaded09945e2020-09-16 20:28:29 +02001899 if (total_num_lanes > MAX_NUM_LANES) {
1900 dev_err(dev, "Invalid lane configuration\n");
1901 goto put_lnk_rst;
1902 }
1903
Scott Telfordc8b427e2018-08-09 11:30:30 +01001904 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001905 if (IS_ERR(phy_provider)) {
1906 ret = PTR_ERR(phy_provider);
1907 goto put_lnk_rst;
1908 }
Scott Telfordc8b427e2018-08-09 11:30:30 +01001909
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001910 return 0;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001911
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001912put_child:
1913 node++;
1914put_lnk_rst:
1915 for (i = 0; i < node; i++)
1916 reset_control_put(cdns_phy->phys[i].lnk_rst);
1917 of_node_put(child);
1918 return ret;
1919}
1920
1921static int cdns_torrent_phy_remove(struct platform_device *pdev)
1922{
1923 struct cdns_torrent_phy *cdns_phy = platform_get_drvdata(pdev);
1924 int i;
1925
1926 reset_control_assert(cdns_phy->phy_rst);
1927 for (i = 0; i < cdns_phy->nsubnodes; i++) {
1928 reset_control_assert(cdns_phy->phys[i].lnk_rst);
1929 reset_control_put(cdns_phy->phys[i].lnk_rst);
1930 }
1931
1932 return 0;
Scott Telfordc8b427e2018-08-09 11:30:30 +01001933}
1934
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001935static const struct cdns_torrent_data cdns_map_torrent = {
1936 .block_offset_shift = 0x2,
1937 .reg_offset_shift = 0x2,
1938};
1939
Swapnil Jakhade597bf3f2020-02-06 07:11:00 +01001940static const struct cdns_torrent_data ti_j721e_map_torrent = {
1941 .block_offset_shift = 0x0,
1942 .reg_offset_shift = 0x1,
1943};
1944
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001945static const struct of_device_id cdns_torrent_phy_of_match[] = {
Scott Telfordc8b427e2018-08-09 11:30:30 +01001946 {
Swapnil Jakhade69d114a2020-02-06 07:10:58 +01001947 .compatible = "cdns,torrent-phy",
1948 .data = &cdns_map_torrent,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001949 },
Swapnil Jakhade597bf3f2020-02-06 07:11:00 +01001950 {
1951 .compatible = "ti,j721e-serdes-10g",
1952 .data = &ti_j721e_map_torrent,
1953 },
Scott Telfordc8b427e2018-08-09 11:30:30 +01001954 {}
1955};
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001956MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001957
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001958static struct platform_driver cdns_torrent_phy_driver = {
1959 .probe = cdns_torrent_phy_probe,
Swapnil Jakhadeafa4ba02020-02-06 07:11:01 +01001960 .remove = cdns_torrent_phy_remove,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001961 .driver = {
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001962 .name = "cdns-torrent-phy",
1963 .of_match_table = cdns_torrent_phy_of_match,
Scott Telfordc8b427e2018-08-09 11:30:30 +01001964 }
1965};
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001966module_platform_driver(cdns_torrent_phy_driver);
Scott Telfordc8b427e2018-08-09 11:30:30 +01001967
1968MODULE_AUTHOR("Cadence Design Systems, Inc.");
Swapnil Jakhade92e9ccc2020-02-06 07:10:52 +01001969MODULE_DESCRIPTION("Cadence Torrent PHY driver");
Scott Telfordc8b427e2018-08-09 11:30:30 +01001970MODULE_LICENSE("GPL v2");