1 // SPDX-License-Identifier: GPL-2.0
3 * Cadence Sierra PHY Driver
5 * Copyright (c) 2018 Cadence Design Systems
6 * Author: Alan Douglas <adouglas@cadence.com>
10 #include <linux/delay.h>
11 #include <linux/err.h>
13 #include <linux/module.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
18 #include <linux/reset.h>
19 #include <linux/slab.h>
21 #include <linux/of_platform.h>
22 #include <dt-bindings/phy/phy.h>
24 /* PHY register offsets */
25 #define SIERRA_COMMON_CDB_OFFSET 0x0
26 #define SIERRA_MACRO_ID_REG 0x0
27 #define SIERRA_CMN_PLLLC_MODE_PREG 0x48
28 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG 0x49
29 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG 0x4A
30 #define SIERRA_CMN_PLLLC_LOCK_CNTSTART_PREG 0x4B
31 #define SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG 0x4F
32 #define SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG 0x50
33 #define SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG 0x62
35 #define SIERRA_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \
36 ((0x4000 << (block_offset)) + \
37 (((ln) << 9) << (reg_offset)))
39 #define SIERRA_DET_STANDEC_A_PREG 0x000
40 #define SIERRA_DET_STANDEC_B_PREG 0x001
41 #define SIERRA_DET_STANDEC_C_PREG 0x002
42 #define SIERRA_DET_STANDEC_D_PREG 0x003
43 #define SIERRA_DET_STANDEC_E_PREG 0x004
44 #define SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG 0x008
45 #define SIERRA_PSM_A0IN_TMR_PREG 0x009
46 #define SIERRA_PSM_DIAG_PREG 0x015
47 #define SIERRA_PSC_TX_A0_PREG 0x028
48 #define SIERRA_PSC_TX_A1_PREG 0x029
49 #define SIERRA_PSC_TX_A2_PREG 0x02A
50 #define SIERRA_PSC_TX_A3_PREG 0x02B
51 #define SIERRA_PSC_RX_A0_PREG 0x030
52 #define SIERRA_PSC_RX_A1_PREG 0x031
53 #define SIERRA_PSC_RX_A2_PREG 0x032
54 #define SIERRA_PSC_RX_A3_PREG 0x033
55 #define SIERRA_PLLCTRL_SUBRATE_PREG 0x03A
56 #define SIERRA_PLLCTRL_GEN_D_PREG 0x03E
57 #define SIERRA_PLLCTRL_CPGAIN_MODE_PREG 0x03F
58 #define SIERRA_PLLCTRL_STATUS_PREG 0x044
59 #define SIERRA_CLKPATH_BIASTRIM_PREG 0x04B
60 #define SIERRA_DFE_BIASTRIM_PREG 0x04C
61 #define SIERRA_DRVCTRL_ATTEN_PREG 0x06A
62 #define SIERRA_CLKPATHCTRL_TMR_PREG 0x081
63 #define SIERRA_RX_CREQ_FLTR_A_MODE3_PREG 0x085
64 #define SIERRA_RX_CREQ_FLTR_A_MODE2_PREG 0x086
65 #define SIERRA_RX_CREQ_FLTR_A_MODE1_PREG 0x087
66 #define SIERRA_RX_CREQ_FLTR_A_MODE0_PREG 0x088
67 #define SIERRA_CREQ_CCLKDET_MODE01_PREG 0x08E
68 #define SIERRA_RX_CTLE_MAINTENANCE_PREG 0x091
69 #define SIERRA_CREQ_FSMCLK_SEL_PREG 0x092
70 #define SIERRA_CREQ_EQ_CTRL_PREG 0x093
71 #define SIERRA_CREQ_SPARE_PREG 0x096
72 #define SIERRA_CREQ_EQ_OPEN_EYE_THRESH_PREG 0x097
73 #define SIERRA_CTLELUT_CTRL_PREG 0x098
74 #define SIERRA_DFE_ECMP_RATESEL_PREG 0x0C0
75 #define SIERRA_DFE_SMP_RATESEL_PREG 0x0C1
76 #define SIERRA_DEQ_PHALIGN_CTRL 0x0C4
77 #define SIERRA_DEQ_CONCUR_CTRL1_PREG 0x0C8
78 #define SIERRA_DEQ_CONCUR_CTRL2_PREG 0x0C9
79 #define SIERRA_DEQ_EPIPWR_CTRL2_PREG 0x0CD
80 #define SIERRA_DEQ_FAST_MAINT_CYCLES_PREG 0x0CE
81 #define SIERRA_DEQ_ERRCMP_CTRL_PREG 0x0D0
82 #define SIERRA_DEQ_OFFSET_CTRL_PREG 0x0D8
83 #define SIERRA_DEQ_GAIN_CTRL_PREG 0x0E0
84 #define SIERRA_DEQ_VGATUNE_CTRL_PREG 0x0E1
85 #define SIERRA_DEQ_GLUT0 0x0E8
86 #define SIERRA_DEQ_GLUT1 0x0E9
87 #define SIERRA_DEQ_GLUT2 0x0EA
88 #define SIERRA_DEQ_GLUT3 0x0EB
89 #define SIERRA_DEQ_GLUT4 0x0EC
90 #define SIERRA_DEQ_GLUT5 0x0ED
91 #define SIERRA_DEQ_GLUT6 0x0EE
92 #define SIERRA_DEQ_GLUT7 0x0EF
93 #define SIERRA_DEQ_GLUT8 0x0F0
94 #define SIERRA_DEQ_GLUT9 0x0F1
95 #define SIERRA_DEQ_GLUT10 0x0F2
96 #define SIERRA_DEQ_GLUT11 0x0F3
97 #define SIERRA_DEQ_GLUT12 0x0F4
98 #define SIERRA_DEQ_GLUT13 0x0F5
99 #define SIERRA_DEQ_GLUT14 0x0F6
100 #define SIERRA_DEQ_GLUT15 0x0F7
101 #define SIERRA_DEQ_GLUT16 0x0F8
102 #define SIERRA_DEQ_ALUT0 0x108
103 #define SIERRA_DEQ_ALUT1 0x109
104 #define SIERRA_DEQ_ALUT2 0x10A
105 #define SIERRA_DEQ_ALUT3 0x10B
106 #define SIERRA_DEQ_ALUT4 0x10C
107 #define SIERRA_DEQ_ALUT5 0x10D
108 #define SIERRA_DEQ_ALUT6 0x10E
109 #define SIERRA_DEQ_ALUT7 0x10F
110 #define SIERRA_DEQ_ALUT8 0x110
111 #define SIERRA_DEQ_ALUT9 0x111
112 #define SIERRA_DEQ_ALUT10 0x112
113 #define SIERRA_DEQ_ALUT11 0x113
114 #define SIERRA_DEQ_ALUT12 0x114
115 #define SIERRA_DEQ_ALUT13 0x115
116 #define SIERRA_DEQ_DFETAP_CTRL_PREG 0x128
117 #define SIERRA_DFE_EN_1010_IGNORE_PREG 0x134
118 #define SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG 0x150
119 #define SIERRA_DEQ_TAU_CTRL2_PREG 0x151
120 #define SIERRA_DEQ_PICTRL_PREG 0x161
121 #define SIERRA_CPICAL_TMRVAL_MODE1_PREG 0x170
122 #define SIERRA_CPICAL_TMRVAL_MODE0_PREG 0x171
123 #define SIERRA_CPICAL_PICNT_MODE1_PREG 0x174
124 #define SIERRA_CPI_OUTBUF_RATESEL_PREG 0x17C
125 #define SIERRA_CPICAL_RES_STARTCODE_MODE23_PREG 0x183
126 #define SIERRA_LFPSDET_SUPPORT_PREG 0x188
127 #define SIERRA_LFPSFILT_NS_PREG 0x18A
128 #define SIERRA_LFPSFILT_RD_PREG 0x18B
129 #define SIERRA_LFPSFILT_MP_PREG 0x18C
130 #define SIERRA_SIGDET_SUPPORT_PREG 0x190
131 #define SIERRA_SDFILT_H2L_A_PREG 0x191
132 #define SIERRA_SDFILT_L2H_PREG 0x193
133 #define SIERRA_RXBUFFER_CTLECTRL_PREG 0x19E
134 #define SIERRA_RXBUFFER_RCDFECTRL_PREG 0x19F
135 #define SIERRA_RXBUFFER_DFECTRL_PREG 0x1A0
136 #define SIERRA_DEQ_TAU_CTRL1_FAST_MAINT_PREG 0x14F
137 #define SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG 0x150
139 #define SIERRA_PHY_CONFIG_CTRL_OFFSET(block_offset) \
140 (0xc000 << (block_offset))
141 #define SIERRA_PHY_PLL_CFG 0xe
143 #define SIERRA_MACRO_ID 0x00007364
144 #define SIERRA_MAX_LANES 16
145 #define PLL_LOCK_TIME 100000
147 static const struct reg_field macro_id_type
=
148 REG_FIELD(SIERRA_MACRO_ID_REG
, 0, 15);
149 static const struct reg_field phy_pll_cfg_1
=
150 REG_FIELD(SIERRA_PHY_PLL_CFG
, 1, 1);
151 static const struct reg_field pllctrl_lock
=
152 REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG
, 0, 0);
154 struct cdns_sierra_inst
{
159 struct reset_control
*lnk_rst
;
162 struct cdns_reg_pairs
{
167 struct cdns_sierra_data
{
169 u8 block_offset_shift
;
175 const struct cdns_reg_pairs
*pcie_cmn_vals
;
176 const struct cdns_reg_pairs
*pcie_ln_vals
;
177 const struct cdns_reg_pairs
*usb_cmn_vals
;
178 const struct cdns_reg_pairs
*usb_ln_vals
;
181 struct cdns_regmap_cdb_context
{
187 struct cdns_sierra_phy
{
189 struct regmap
*regmap
;
190 struct cdns_sierra_data
*init_data
;
191 struct cdns_sierra_inst phys
[SIERRA_MAX_LANES
];
192 struct reset_control
*phy_rst
;
193 struct reset_control
*apb_rst
;
194 struct regmap
*regmap_lane_cdb
[SIERRA_MAX_LANES
];
195 struct regmap
*regmap_phy_config_ctrl
;
196 struct regmap
*regmap_common_cdb
;
197 struct regmap_field
*macro_id_type
;
198 struct regmap_field
*phy_pll_cfg_1
;
199 struct regmap_field
*pllctrl_lock
[SIERRA_MAX_LANES
];
201 struct clk
*cmn_refclk_dig_div
;
202 struct clk
*cmn_refclk1_dig_div
;
208 static int cdns_regmap_write(void *context
, unsigned int reg
, unsigned int val
)
210 struct cdns_regmap_cdb_context
*ctx
= context
;
211 u32 offset
= reg
<< ctx
->reg_offset_shift
;
213 writew(val
, ctx
->base
+ offset
);
218 static int cdns_regmap_read(void *context
, unsigned int reg
, unsigned int *val
)
220 struct cdns_regmap_cdb_context
*ctx
= context
;
221 u32 offset
= reg
<< ctx
->reg_offset_shift
;
223 *val
= readw(ctx
->base
+ offset
);
227 #define SIERRA_LANE_CDB_REGMAP_CONF(n) \
229 .name = "sierra_lane" n "_cdb", \
232 .reg_write = cdns_regmap_write, \
233 .reg_read = cdns_regmap_read, \
236 static const struct regmap_config cdns_sierra_lane_cdb_config
[] = {
237 SIERRA_LANE_CDB_REGMAP_CONF("0"),
238 SIERRA_LANE_CDB_REGMAP_CONF("1"),
239 SIERRA_LANE_CDB_REGMAP_CONF("2"),
240 SIERRA_LANE_CDB_REGMAP_CONF("3"),
241 SIERRA_LANE_CDB_REGMAP_CONF("4"),
242 SIERRA_LANE_CDB_REGMAP_CONF("5"),
243 SIERRA_LANE_CDB_REGMAP_CONF("6"),
244 SIERRA_LANE_CDB_REGMAP_CONF("7"),
245 SIERRA_LANE_CDB_REGMAP_CONF("8"),
246 SIERRA_LANE_CDB_REGMAP_CONF("9"),
247 SIERRA_LANE_CDB_REGMAP_CONF("10"),
248 SIERRA_LANE_CDB_REGMAP_CONF("11"),
249 SIERRA_LANE_CDB_REGMAP_CONF("12"),
250 SIERRA_LANE_CDB_REGMAP_CONF("13"),
251 SIERRA_LANE_CDB_REGMAP_CONF("14"),
252 SIERRA_LANE_CDB_REGMAP_CONF("15"),
255 static const struct regmap_config cdns_sierra_common_cdb_config
= {
256 .name
= "sierra_common_cdb",
259 .reg_write
= cdns_regmap_write
,
260 .reg_read
= cdns_regmap_read
,
263 static const struct regmap_config cdns_sierra_phy_config_ctrl_config
= {
264 .name
= "sierra_phy_config_ctrl",
267 .reg_write
= cdns_regmap_write
,
268 .reg_read
= cdns_regmap_read
,
271 static int cdns_sierra_phy_init(struct phy
*gphy
)
273 struct cdns_sierra_inst
*ins
= phy_get_drvdata(gphy
);
274 struct cdns_sierra_phy
*phy
= dev_get_drvdata(gphy
->dev
.parent
);
275 struct regmap
*regmap
;
277 const struct cdns_reg_pairs
*cmn_vals
, *ln_vals
;
278 u32 num_cmn_regs
, num_ln_regs
;
280 /* Initialise the PHY registers, unless auto configured */
284 clk_set_rate(phy
->cmn_refclk_dig_div
, 25000000);
285 clk_set_rate(phy
->cmn_refclk1_dig_div
, 25000000);
286 if (ins
->phy_type
== PHY_TYPE_PCIE
) {
287 num_cmn_regs
= phy
->init_data
->pcie_cmn_regs
;
288 num_ln_regs
= phy
->init_data
->pcie_ln_regs
;
289 cmn_vals
= phy
->init_data
->pcie_cmn_vals
;
290 ln_vals
= phy
->init_data
->pcie_ln_vals
;
291 } else if (ins
->phy_type
== PHY_TYPE_USB3
) {
292 num_cmn_regs
= phy
->init_data
->usb_cmn_regs
;
293 num_ln_regs
= phy
->init_data
->usb_ln_regs
;
294 cmn_vals
= phy
->init_data
->usb_cmn_vals
;
295 ln_vals
= phy
->init_data
->usb_ln_vals
;
300 regmap
= phy
->regmap_common_cdb
;
301 for (j
= 0; j
< num_cmn_regs
; j
++)
302 regmap_write(regmap
, cmn_vals
[j
].off
, cmn_vals
[j
].val
);
304 for (i
= 0; i
< ins
->num_lanes
; i
++) {
305 for (j
= 0; j
< num_ln_regs
; j
++) {
306 regmap
= phy
->regmap_lane_cdb
[i
+ ins
->mlane
];
307 regmap_write(regmap
, ln_vals
[j
].off
, ln_vals
[j
].val
);
314 static int cdns_sierra_phy_on(struct phy
*gphy
)
316 struct cdns_sierra_phy
*sp
= dev_get_drvdata(gphy
->dev
.parent
);
317 struct cdns_sierra_inst
*ins
= phy_get_drvdata(gphy
);
318 struct device
*dev
= sp
->dev
;
322 /* Take the PHY lane group out of reset */
323 ret
= reset_control_deassert(ins
->lnk_rst
);
325 dev_err(dev
, "Failed to take the PHY lane out of reset\n");
329 ret
= regmap_field_read_poll_timeout(sp
->pllctrl_lock
[ins
->mlane
],
330 val
, val
, 1000, PLL_LOCK_TIME
);
332 dev_err(dev
, "PLL lock of lane failed\n");
337 static int cdns_sierra_phy_off(struct phy
*gphy
)
339 struct cdns_sierra_inst
*ins
= phy_get_drvdata(gphy
);
341 return reset_control_assert(ins
->lnk_rst
);
344 static int cdns_sierra_phy_reset(struct phy
*gphy
)
346 struct cdns_sierra_phy
*sp
= dev_get_drvdata(gphy
->dev
.parent
);
348 reset_control_assert(sp
->phy_rst
);
349 reset_control_deassert(sp
->phy_rst
);
353 static const struct phy_ops ops
= {
354 .init
= cdns_sierra_phy_init
,
355 .power_on
= cdns_sierra_phy_on
,
356 .power_off
= cdns_sierra_phy_off
,
357 .reset
= cdns_sierra_phy_reset
,
358 .owner
= THIS_MODULE
,
361 static int cdns_sierra_get_optional(struct cdns_sierra_inst
*inst
,
362 struct device_node
*child
)
364 if (of_property_read_u32(child
, "reg", &inst
->mlane
))
367 if (of_property_read_u32(child
, "cdns,num-lanes", &inst
->num_lanes
))
370 if (of_property_read_u32(child
, "cdns,phy-type", &inst
->phy_type
))
376 static const struct of_device_id cdns_sierra_id_table
[];
378 static struct regmap
*cdns_regmap_init(struct device
*dev
, void __iomem
*base
,
379 u32 block_offset
, u8 reg_offset_shift
,
380 const struct regmap_config
*config
)
382 struct cdns_regmap_cdb_context
*ctx
;
384 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
386 return ERR_PTR(-ENOMEM
);
389 ctx
->base
= base
+ block_offset
;
390 ctx
->reg_offset_shift
= reg_offset_shift
;
392 return devm_regmap_init(dev
, NULL
, ctx
, config
);
395 static int cdns_regfield_init(struct cdns_sierra_phy
*sp
)
397 struct device
*dev
= sp
->dev
;
398 struct regmap_field
*field
;
399 struct regmap
*regmap
;
402 regmap
= sp
->regmap_common_cdb
;
403 field
= devm_regmap_field_alloc(dev
, regmap
, macro_id_type
);
405 dev_err(dev
, "MACRO_ID_TYPE reg field init failed\n");
406 return PTR_ERR(field
);
408 sp
->macro_id_type
= field
;
410 regmap
= sp
->regmap_phy_config_ctrl
;
411 field
= devm_regmap_field_alloc(dev
, regmap
, phy_pll_cfg_1
);
413 dev_err(dev
, "PHY_PLL_CFG_1 reg field init failed\n");
414 return PTR_ERR(field
);
416 sp
->phy_pll_cfg_1
= field
;
418 for (i
= 0; i
< SIERRA_MAX_LANES
; i
++) {
419 regmap
= sp
->regmap_lane_cdb
[i
];
420 field
= devm_regmap_field_alloc(dev
, regmap
, pllctrl_lock
);
422 dev_err(dev
, "P%d_ENABLE reg field init failed\n", i
);
423 return PTR_ERR(field
);
425 sp
->pllctrl_lock
[i
] = field
;
431 static int cdns_regmap_init_blocks(struct cdns_sierra_phy
*sp
,
432 void __iomem
*base
, u8 block_offset_shift
,
435 struct device
*dev
= sp
->dev
;
436 struct regmap
*regmap
;
440 for (i
= 0; i
< SIERRA_MAX_LANES
; i
++) {
441 block_offset
= SIERRA_LANE_CDB_OFFSET(i
, block_offset_shift
,
443 regmap
= cdns_regmap_init(dev
, base
, block_offset
,
445 &cdns_sierra_lane_cdb_config
[i
]);
446 if (IS_ERR(regmap
)) {
447 dev_err(dev
, "Failed to init lane CDB regmap\n");
448 return PTR_ERR(regmap
);
450 sp
->regmap_lane_cdb
[i
] = regmap
;
453 regmap
= cdns_regmap_init(dev
, base
, SIERRA_COMMON_CDB_OFFSET
,
455 &cdns_sierra_common_cdb_config
);
456 if (IS_ERR(regmap
)) {
457 dev_err(dev
, "Failed to init common CDB regmap\n");
458 return PTR_ERR(regmap
);
460 sp
->regmap_common_cdb
= regmap
;
462 block_offset
= SIERRA_PHY_CONFIG_CTRL_OFFSET(block_offset_shift
);
463 regmap
= cdns_regmap_init(dev
, base
, block_offset
, reg_offset_shift
,
464 &cdns_sierra_phy_config_ctrl_config
);
465 if (IS_ERR(regmap
)) {
466 dev_err(dev
, "Failed to init PHY config and control regmap\n");
467 return PTR_ERR(regmap
);
469 sp
->regmap_phy_config_ctrl
= regmap
;
474 static int cdns_sierra_phy_probe(struct platform_device
*pdev
)
476 struct cdns_sierra_phy
*sp
;
477 struct phy_provider
*phy_provider
;
478 struct device
*dev
= &pdev
->dev
;
479 const struct of_device_id
*match
;
480 struct cdns_sierra_data
*data
;
481 unsigned int id_value
;
482 int i
, ret
, node
= 0;
485 struct device_node
*dn
= dev
->of_node
, *child
;
487 if (of_get_child_count(dn
) == 0)
490 /* Get init data for this PHY */
491 match
= of_match_device(cdns_sierra_id_table
, dev
);
495 data
= (struct cdns_sierra_data
*)match
->data
;
497 sp
= devm_kzalloc(dev
, sizeof(*sp
), GFP_KERNEL
);
500 dev_set_drvdata(dev
, sp
);
502 sp
->init_data
= data
;
504 base
= devm_platform_ioremap_resource(pdev
, 0);
506 dev_err(dev
, "missing \"reg\"\n");
507 return PTR_ERR(base
);
510 ret
= cdns_regmap_init_blocks(sp
, base
, data
->block_offset_shift
,
511 data
->reg_offset_shift
);
515 ret
= cdns_regfield_init(sp
);
519 platform_set_drvdata(pdev
, sp
);
521 sp
->clk
= devm_clk_get_optional(dev
, "phy_clk");
522 if (IS_ERR(sp
->clk
)) {
523 dev_err(dev
, "failed to get clock phy_clk\n");
524 return PTR_ERR(sp
->clk
);
527 sp
->phy_rst
= devm_reset_control_get(dev
, "sierra_reset");
528 if (IS_ERR(sp
->phy_rst
)) {
529 dev_err(dev
, "failed to get reset\n");
530 return PTR_ERR(sp
->phy_rst
);
533 sp
->apb_rst
= devm_reset_control_get_optional(dev
, "sierra_apb");
534 if (IS_ERR(sp
->apb_rst
)) {
535 dev_err(dev
, "failed to get apb reset\n");
536 return PTR_ERR(sp
->apb_rst
);
539 clk
= devm_clk_get_optional(dev
, "cmn_refclk_dig_div");
541 dev_err(dev
, "cmn_refclk_dig_div clock not found\n");
545 sp
->cmn_refclk_dig_div
= clk
;
547 clk
= devm_clk_get_optional(dev
, "cmn_refclk1_dig_div");
549 dev_err(dev
, "cmn_refclk1_dig_div clock not found\n");
553 sp
->cmn_refclk1_dig_div
= clk
;
555 ret
= clk_prepare_enable(sp
->clk
);
560 reset_control_deassert(sp
->apb_rst
);
562 /* Check that PHY is present */
563 regmap_field_read(sp
->macro_id_type
, &id_value
);
564 if (sp
->init_data
->id_value
!= id_value
) {
569 sp
->autoconf
= of_property_read_bool(dn
, "cdns,autoconf");
571 for_each_available_child_of_node(dn
, child
) {
574 sp
->phys
[node
].lnk_rst
=
575 of_reset_control_array_get_exclusive(child
);
577 if (IS_ERR(sp
->phys
[node
].lnk_rst
)) {
578 dev_err(dev
, "failed to get reset %s\n",
580 ret
= PTR_ERR(sp
->phys
[node
].lnk_rst
);
585 ret
= cdns_sierra_get_optional(&sp
->phys
[node
], child
);
587 dev_err(dev
, "missing property in node %s\n",
593 sp
->num_lanes
+= sp
->phys
[node
].num_lanes
;
595 gphy
= devm_phy_create(dev
, child
, &ops
);
601 sp
->phys
[node
].phy
= gphy
;
602 phy_set_drvdata(gphy
, &sp
->phys
[node
]);
606 sp
->nsubnodes
= node
;
608 if (sp
->num_lanes
> SIERRA_MAX_LANES
) {
609 dev_err(dev
, "Invalid lane configuration\n");
613 /* If more than one subnode, configure the PHY as multilink */
614 if (!sp
->autoconf
&& sp
->nsubnodes
> 1)
615 regmap_field_write(sp
->phy_pll_cfg_1
, 0x1);
617 pm_runtime_enable(dev
);
618 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
619 reset_control_deassert(sp
->phy_rst
);
620 return PTR_ERR_OR_ZERO(phy_provider
);
625 for (i
= 0; i
< node
; i
++)
626 reset_control_put(sp
->phys
[i
].lnk_rst
);
629 clk_disable_unprepare(sp
->clk
);
630 reset_control_assert(sp
->apb_rst
);
634 static int cdns_sierra_phy_remove(struct platform_device
*pdev
)
636 struct cdns_sierra_phy
*phy
= platform_get_drvdata(pdev
);
639 reset_control_assert(phy
->phy_rst
);
640 reset_control_assert(phy
->apb_rst
);
641 pm_runtime_disable(&pdev
->dev
);
644 * The device level resets will be put automatically.
645 * Need to put the subnode resets here though.
647 for (i
= 0; i
< phy
->nsubnodes
; i
++) {
648 reset_control_assert(phy
->phys
[i
].lnk_rst
);
649 reset_control_put(phy
->phys
[i
].lnk_rst
);
654 /* refclk100MHz_32b_PCIe_cmn_pll_ext_ssc */
655 static const struct cdns_reg_pairs cdns_pcie_cmn_regs_ext_ssc
[] = {
656 {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG
},
657 {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG
},
658 {0x8A06, SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG
},
659 {0x8A06, SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG
},
660 {0x1B1B, SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG
}
663 /* refclk100MHz_32b_PCIe_ln_ext_ssc */
664 static const struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc
[] = {
665 {0x813E, SIERRA_CLKPATHCTRL_TMR_PREG
},
666 {0x8047, SIERRA_RX_CREQ_FLTR_A_MODE3_PREG
},
667 {0x808F, SIERRA_RX_CREQ_FLTR_A_MODE2_PREG
},
668 {0x808F, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG
},
669 {0x808F, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG
},
670 {0x033C, SIERRA_RX_CTLE_MAINTENANCE_PREG
},
671 {0x44CC, SIERRA_CREQ_EQ_OPEN_EYE_THRESH_PREG
}
674 /* refclk100MHz_20b_USB_cmn_pll_ext_ssc */
675 static const struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc
[] = {
676 {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG
},
677 {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG
},
678 {0x0000, SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG
},
679 {0x0000, SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG
}
682 /* refclk100MHz_20b_USB_ln_ext_ssc */
683 static const struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc
[] = {
684 {0xFE0A, SIERRA_DET_STANDEC_A_PREG
},
685 {0x000F, SIERRA_DET_STANDEC_B_PREG
},
686 {0x55A5, SIERRA_DET_STANDEC_C_PREG
},
687 {0x69ad, SIERRA_DET_STANDEC_D_PREG
},
688 {0x0241, SIERRA_DET_STANDEC_E_PREG
},
689 {0x0110, SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG
},
690 {0x0014, SIERRA_PSM_A0IN_TMR_PREG
},
691 {0xCF00, SIERRA_PSM_DIAG_PREG
},
692 {0x001F, SIERRA_PSC_TX_A0_PREG
},
693 {0x0007, SIERRA_PSC_TX_A1_PREG
},
694 {0x0003, SIERRA_PSC_TX_A2_PREG
},
695 {0x0003, SIERRA_PSC_TX_A3_PREG
},
696 {0x0FFF, SIERRA_PSC_RX_A0_PREG
},
697 {0x0003, SIERRA_PSC_RX_A1_PREG
},
698 {0x0003, SIERRA_PSC_RX_A2_PREG
},
699 {0x0001, SIERRA_PSC_RX_A3_PREG
},
700 {0x0001, SIERRA_PLLCTRL_SUBRATE_PREG
},
701 {0x0406, SIERRA_PLLCTRL_GEN_D_PREG
},
702 {0x5233, SIERRA_PLLCTRL_CPGAIN_MODE_PREG
},
703 {0x00CA, SIERRA_CLKPATH_BIASTRIM_PREG
},
704 {0x2512, SIERRA_DFE_BIASTRIM_PREG
},
705 {0x0000, SIERRA_DRVCTRL_ATTEN_PREG
},
706 {0x823E, SIERRA_CLKPATHCTRL_TMR_PREG
},
707 {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG
},
708 {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG
},
709 {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01_PREG
},
710 {0x023C, SIERRA_RX_CTLE_MAINTENANCE_PREG
},
711 {0x3232, SIERRA_CREQ_FSMCLK_SEL_PREG
},
712 {0x0000, SIERRA_CREQ_EQ_CTRL_PREG
},
713 {0x0000, SIERRA_CREQ_SPARE_PREG
},
714 {0xCC44, SIERRA_CREQ_EQ_OPEN_EYE_THRESH_PREG
},
715 {0x8452, SIERRA_CTLELUT_CTRL_PREG
},
716 {0x4121, SIERRA_DFE_ECMP_RATESEL_PREG
},
717 {0x4121, SIERRA_DFE_SMP_RATESEL_PREG
},
718 {0x0003, SIERRA_DEQ_PHALIGN_CTRL
},
719 {0x3200, SIERRA_DEQ_CONCUR_CTRL1_PREG
},
720 {0x5064, SIERRA_DEQ_CONCUR_CTRL2_PREG
},
721 {0x0030, SIERRA_DEQ_EPIPWR_CTRL2_PREG
},
722 {0x0048, SIERRA_DEQ_FAST_MAINT_CYCLES_PREG
},
723 {0x5A5A, SIERRA_DEQ_ERRCMP_CTRL_PREG
},
724 {0x02F5, SIERRA_DEQ_OFFSET_CTRL_PREG
},
725 {0x02F5, SIERRA_DEQ_GAIN_CTRL_PREG
},
726 {0x9999, SIERRA_DEQ_VGATUNE_CTRL_PREG
},
727 {0x0014, SIERRA_DEQ_GLUT0
},
728 {0x0014, SIERRA_DEQ_GLUT1
},
729 {0x0014, SIERRA_DEQ_GLUT2
},
730 {0x0014, SIERRA_DEQ_GLUT3
},
731 {0x0014, SIERRA_DEQ_GLUT4
},
732 {0x0014, SIERRA_DEQ_GLUT5
},
733 {0x0014, SIERRA_DEQ_GLUT6
},
734 {0x0014, SIERRA_DEQ_GLUT7
},
735 {0x0014, SIERRA_DEQ_GLUT8
},
736 {0x0014, SIERRA_DEQ_GLUT9
},
737 {0x0014, SIERRA_DEQ_GLUT10
},
738 {0x0014, SIERRA_DEQ_GLUT11
},
739 {0x0014, SIERRA_DEQ_GLUT12
},
740 {0x0014, SIERRA_DEQ_GLUT13
},
741 {0x0014, SIERRA_DEQ_GLUT14
},
742 {0x0014, SIERRA_DEQ_GLUT15
},
743 {0x0014, SIERRA_DEQ_GLUT16
},
744 {0x0BAE, SIERRA_DEQ_ALUT0
},
745 {0x0AEB, SIERRA_DEQ_ALUT1
},
746 {0x0A28, SIERRA_DEQ_ALUT2
},
747 {0x0965, SIERRA_DEQ_ALUT3
},
748 {0x08A2, SIERRA_DEQ_ALUT4
},
749 {0x07DF, SIERRA_DEQ_ALUT5
},
750 {0x071C, SIERRA_DEQ_ALUT6
},
751 {0x0659, SIERRA_DEQ_ALUT7
},
752 {0x0596, SIERRA_DEQ_ALUT8
},
753 {0x0514, SIERRA_DEQ_ALUT9
},
754 {0x0492, SIERRA_DEQ_ALUT10
},
755 {0x0410, SIERRA_DEQ_ALUT11
},
756 {0x038E, SIERRA_DEQ_ALUT12
},
757 {0x030C, SIERRA_DEQ_ALUT13
},
758 {0x03F4, SIERRA_DEQ_DFETAP_CTRL_PREG
},
759 {0x0001, SIERRA_DFE_EN_1010_IGNORE_PREG
},
760 {0x3C01, SIERRA_DEQ_TAU_CTRL1_FAST_MAINT_PREG
},
761 {0x3C40, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG
},
762 {0x1C08, SIERRA_DEQ_TAU_CTRL2_PREG
},
763 {0x0033, SIERRA_DEQ_PICTRL_PREG
},
764 {0x0400, SIERRA_CPICAL_TMRVAL_MODE1_PREG
},
765 {0x0330, SIERRA_CPICAL_TMRVAL_MODE0_PREG
},
766 {0x01FF, SIERRA_CPICAL_PICNT_MODE1_PREG
},
767 {0x0009, SIERRA_CPI_OUTBUF_RATESEL_PREG
},
768 {0x3232, SIERRA_CPICAL_RES_STARTCODE_MODE23_PREG
},
769 {0x0005, SIERRA_LFPSDET_SUPPORT_PREG
},
770 {0x000F, SIERRA_LFPSFILT_NS_PREG
},
771 {0x0009, SIERRA_LFPSFILT_RD_PREG
},
772 {0x0001, SIERRA_LFPSFILT_MP_PREG
},
773 {0x6013, SIERRA_SIGDET_SUPPORT_PREG
},
774 {0x8013, SIERRA_SDFILT_H2L_A_PREG
},
775 {0x8009, SIERRA_SDFILT_L2H_PREG
},
776 {0x0024, SIERRA_RXBUFFER_CTLECTRL_PREG
},
777 {0x0020, SIERRA_RXBUFFER_RCDFECTRL_PREG
},
778 {0x4243, SIERRA_RXBUFFER_DFECTRL_PREG
}
781 static const struct cdns_sierra_data cdns_map_sierra
= {
785 ARRAY_SIZE(cdns_pcie_cmn_regs_ext_ssc
),
786 ARRAY_SIZE(cdns_pcie_ln_regs_ext_ssc
),
787 ARRAY_SIZE(cdns_usb_cmn_regs_ext_ssc
),
788 ARRAY_SIZE(cdns_usb_ln_regs_ext_ssc
),
789 cdns_pcie_cmn_regs_ext_ssc
,
790 cdns_pcie_ln_regs_ext_ssc
,
791 cdns_usb_cmn_regs_ext_ssc
,
792 cdns_usb_ln_regs_ext_ssc
,
795 static const struct cdns_sierra_data cdns_ti_map_sierra
= {
799 ARRAY_SIZE(cdns_pcie_cmn_regs_ext_ssc
),
800 ARRAY_SIZE(cdns_pcie_ln_regs_ext_ssc
),
801 ARRAY_SIZE(cdns_usb_cmn_regs_ext_ssc
),
802 ARRAY_SIZE(cdns_usb_ln_regs_ext_ssc
),
803 cdns_pcie_cmn_regs_ext_ssc
,
804 cdns_pcie_ln_regs_ext_ssc
,
805 cdns_usb_cmn_regs_ext_ssc
,
806 cdns_usb_ln_regs_ext_ssc
,
809 static const struct of_device_id cdns_sierra_id_table
[] = {
811 .compatible
= "cdns,sierra-phy-t0",
812 .data
= &cdns_map_sierra
,
815 .compatible
= "ti,sierra-phy-t0",
816 .data
= &cdns_ti_map_sierra
,
820 MODULE_DEVICE_TABLE(of
, cdns_sierra_id_table
);
822 static struct platform_driver cdns_sierra_driver
= {
823 .probe
= cdns_sierra_phy_probe
,
824 .remove
= cdns_sierra_phy_remove
,
826 .name
= "cdns-sierra-phy",
827 .of_match_table
= cdns_sierra_id_table
,
830 module_platform_driver(cdns_sierra_driver
);
832 MODULE_ALIAS("platform:cdns_sierra");
833 MODULE_AUTHOR("Cadence Design Systems");
834 MODULE_DESCRIPTION("CDNS sierra phy driver");
835 MODULE_LICENSE("GPL v2");