1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe SERDES driver for AM654x SoC
5 * Copyright (C) 2018 - 2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
9 #include <dt-bindings/phy/phy.h>
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/delay.h>
13 #include <linux/module.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/mux/consumer.h>
16 #include <linux/of_address.h>
17 #include <linux/phy/phy.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/regmap.h>
24 #define COMLANE_R138 0xb38
27 #define COMLANE_R190 0xb90
29 #define COMLANE_R194 0xb94
31 #define SERDES_CTRL 0x1fd0
33 #define WIZ_LANEXCTL_STS 0x1fe0
34 #define TX0_DISABLE_STATE 0x4
35 #define TX0_SLEEP_STATE 0x5
36 #define TX0_SNOOZE_STATE 0x6
37 #define TX0_ENABLE_STATE 0x7
39 #define RX0_DISABLE_STATE 0x4
40 #define RX0_SLEEP_STATE 0x5
41 #define RX0_SNOOZE_STATE 0x6
42 #define RX0_ENABLE_STATE 0x7
44 #define WIZ_PLL_CTRL 0x1ff4
45 #define PLL_DISABLE_STATE 0x4
46 #define PLL_SLEEP_STATE 0x5
47 #define PLL_SNOOZE_STATE 0x6
48 #define PLL_ENABLE_STATE 0x7
50 #define PLL_LOCK_TIME 100000 /* in microseconds */
51 #define SLEEP_TIME 100 /* in microseconds */
54 #define LANE_PCIE0_LANE0 0x1
56 #define LANE_PCIE1_LANE0 0x0
57 #define LANE_PCIE0_LANE1 0x1
59 #define SERDES_NUM_CLOCKS 3
61 #define AM654_SERDES_CTRL_CLKSEL_MASK GENMASK(7, 4)
62 #define AM654_SERDES_CTRL_CLKSEL_SHIFT 4
64 struct serdes_am654_clk_mux
{
66 struct regmap
*regmap
;
69 struct clk_init_data clk_data
;
72 #define to_serdes_am654_clk_mux(_hw) \
73 container_of(_hw, struct serdes_am654_clk_mux, hw)
75 static struct regmap_config serdes_am654_regmap_config
= {
82 static const struct reg_field cmu_master_cdn_o
= REG_FIELD(CMU_R07C
, 24, 24);
83 static const struct reg_field config_version
= REG_FIELD(COMLANE_R138
, 16, 23);
84 static const struct reg_field l1_master_cdn_o
= REG_FIELD(COMLANE_R190
, 9, 9);
85 static const struct reg_field cmu_ok_i_0
= REG_FIELD(COMLANE_R194
, 19, 19);
86 static const struct reg_field por_en
= REG_FIELD(SERDES_CTRL
, 29, 29);
87 static const struct reg_field tx0_enable
= REG_FIELD(WIZ_LANEXCTL_STS
, 29, 31);
88 static const struct reg_field rx0_enable
= REG_FIELD(WIZ_LANEXCTL_STS
, 13, 15);
89 static const struct reg_field pll_enable
= REG_FIELD(WIZ_PLL_CTRL
, 29, 31);
90 static const struct reg_field pll_ok
= REG_FIELD(WIZ_PLL_CTRL
, 28, 28);
93 struct regmap
*regmap
;
94 struct regmap_field
*cmu_master_cdn_o
;
95 struct regmap_field
*config_version
;
96 struct regmap_field
*l1_master_cdn_o
;
97 struct regmap_field
*cmu_ok_i_0
;
98 struct regmap_field
*por_en
;
99 struct regmap_field
*tx0_enable
;
100 struct regmap_field
*rx0_enable
;
101 struct regmap_field
*pll_enable
;
102 struct regmap_field
*pll_ok
;
105 struct mux_control
*control
;
108 struct device_node
*of_node
;
109 struct clk_onecell_data clk_data
;
110 struct clk
*clks
[SERDES_NUM_CLOCKS
];
113 static int serdes_am654_enable_pll(struct serdes_am654
*phy
)
118 ret
= regmap_field_write(phy
->pll_enable
, PLL_ENABLE_STATE
);
122 return regmap_field_read_poll_timeout(phy
->pll_ok
, val
, val
, 1000,
126 static void serdes_am654_disable_pll(struct serdes_am654
*phy
)
128 struct device
*dev
= phy
->dev
;
131 ret
= regmap_field_write(phy
->pll_enable
, PLL_DISABLE_STATE
);
133 dev_err(dev
, "Failed to disable PLL\n");
136 static int serdes_am654_enable_txrx(struct serdes_am654
*phy
)
141 ret
= regmap_field_write(phy
->tx0_enable
, TX0_ENABLE_STATE
);
146 ret
= regmap_field_write(phy
->rx0_enable
, RX0_ENABLE_STATE
);
153 static int serdes_am654_disable_txrx(struct serdes_am654
*phy
)
158 ret
= regmap_field_write(phy
->tx0_enable
, TX0_DISABLE_STATE
);
163 ret
= regmap_field_write(phy
->rx0_enable
, RX0_DISABLE_STATE
);
170 static int serdes_am654_power_on(struct phy
*x
)
172 struct serdes_am654
*phy
= phy_get_drvdata(x
);
173 struct device
*dev
= phy
->dev
;
177 ret
= serdes_am654_enable_pll(phy
);
179 dev_err(dev
, "Failed to enable PLL\n");
183 ret
= serdes_am654_enable_txrx(phy
);
185 dev_err(dev
, "Failed to enable TX RX\n");
189 return regmap_field_read_poll_timeout(phy
->cmu_ok_i_0
, val
, val
,
190 SLEEP_TIME
, PLL_LOCK_TIME
);
193 static int serdes_am654_power_off(struct phy
*x
)
195 struct serdes_am654
*phy
= phy_get_drvdata(x
);
197 serdes_am654_disable_txrx(phy
);
198 serdes_am654_disable_pll(phy
);
203 static int serdes_am654_init(struct phy
*x
)
205 struct serdes_am654
*phy
= phy_get_drvdata(x
);
208 ret
= regmap_field_write(phy
->config_version
, VERSION
);
212 ret
= regmap_field_write(phy
->cmu_master_cdn_o
, 0x1);
216 ret
= regmap_field_write(phy
->l1_master_cdn_o
, 0x1);
223 static int serdes_am654_reset(struct phy
*x
)
225 struct serdes_am654
*phy
= phy_get_drvdata(x
);
228 ret
= regmap_field_write(phy
->por_en
, 0x1);
234 ret
= regmap_field_write(phy
->por_en
, 0x0);
241 static void serdes_am654_release(struct phy
*x
)
243 struct serdes_am654
*phy
= phy_get_drvdata(x
);
245 phy
->type
= PHY_NONE
;
247 mux_control_deselect(phy
->control
);
250 static struct phy
*serdes_am654_xlate(struct device
*dev
,
251 struct of_phandle_args
*args
)
253 struct serdes_am654
*am654_phy
;
257 phy
= of_phy_simple_xlate(dev
, args
);
261 am654_phy
= phy_get_drvdata(phy
);
263 return ERR_PTR(-EBUSY
);
265 ret
= mux_control_select(am654_phy
->control
, args
->args
[1]);
267 dev_err(dev
, "Failed to select SERDES Lane Function\n");
271 am654_phy
->busy
= true;
272 am654_phy
->type
= args
->args
[0];
277 static const struct phy_ops ops
= {
278 .reset
= serdes_am654_reset
,
279 .init
= serdes_am654_init
,
280 .power_on
= serdes_am654_power_on
,
281 .power_off
= serdes_am654_power_off
,
282 .release
= serdes_am654_release
,
283 .owner
= THIS_MODULE
,
286 #define SERDES_NUM_MUX_COMBINATIONS 16
293 serdes_am654_mux_table
[SERDES_NUM_MUX_COMBINATIONS
][SERDES_NUM_CLOCKS
] = {
295 * Each combination maps to one of
296 * "Figure 12-1986. SerDes Reference Clock Distribution"
299 /* Parent of CMU refclk, Left output, Right output
300 * either of EXT_REFCLK, LICLK, RICLK
302 { EXT_REFCLK
, EXT_REFCLK
, EXT_REFCLK
}, /* 0000 */
303 { RICLK
, EXT_REFCLK
, EXT_REFCLK
}, /* 0001 */
304 { EXT_REFCLK
, RICLK
, LICLK
}, /* 0010 */
305 { RICLK
, RICLK
, EXT_REFCLK
}, /* 0011 */
306 { LICLK
, EXT_REFCLK
, EXT_REFCLK
}, /* 0100 */
307 { EXT_REFCLK
, EXT_REFCLK
, EXT_REFCLK
}, /* 0101 */
308 { LICLK
, RICLK
, LICLK
}, /* 0110 */
309 { EXT_REFCLK
, RICLK
, LICLK
}, /* 0111 */
310 { EXT_REFCLK
, EXT_REFCLK
, LICLK
}, /* 1000 */
311 { RICLK
, EXT_REFCLK
, LICLK
}, /* 1001 */
312 { EXT_REFCLK
, RICLK
, EXT_REFCLK
}, /* 1010 */
313 { RICLK
, RICLK
, EXT_REFCLK
}, /* 1011 */
314 { LICLK
, EXT_REFCLK
, LICLK
}, /* 1100 */
315 { EXT_REFCLK
, EXT_REFCLK
, LICLK
}, /* 1101 */
316 { LICLK
, RICLK
, EXT_REFCLK
}, /* 1110 */
317 { EXT_REFCLK
, RICLK
, EXT_REFCLK
}, /* 1111 */
320 static u8
serdes_am654_clk_mux_get_parent(struct clk_hw
*hw
)
322 struct serdes_am654_clk_mux
*mux
= to_serdes_am654_clk_mux(hw
);
323 struct regmap
*regmap
= mux
->regmap
;
324 unsigned int reg
= mux
->reg
;
327 regmap_read(regmap
, reg
, &val
);
328 val
&= AM654_SERDES_CTRL_CLKSEL_MASK
;
329 val
>>= AM654_SERDES_CTRL_CLKSEL_SHIFT
;
331 return serdes_am654_mux_table
[val
][mux
->clk_id
];
334 static int serdes_am654_clk_mux_set_parent(struct clk_hw
*hw
, u8 index
)
336 struct serdes_am654_clk_mux
*mux
= to_serdes_am654_clk_mux(hw
);
337 struct regmap
*regmap
= mux
->regmap
;
338 const char *name
= clk_hw_get_name(hw
);
339 unsigned int reg
= mux
->reg
;
340 int clk_id
= mux
->clk_id
;
341 int parents
[SERDES_NUM_CLOCKS
];
347 /* get existing setting */
348 regmap_read(regmap
, reg
, &val
);
349 val
&= AM654_SERDES_CTRL_CLKSEL_MASK
;
350 val
>>= AM654_SERDES_CTRL_CLKSEL_SHIFT
;
352 for (i
= 0; i
< SERDES_NUM_CLOCKS
; i
++)
353 parents
[i
] = serdes_am654_mux_table
[val
][i
];
355 /* change parent of this clock. others left intact */
356 parents
[clk_id
] = index
;
359 for (val
= 0; val
< SERDES_NUM_MUX_COMBINATIONS
; val
++) {
360 p
= serdes_am654_mux_table
[val
];
362 for (i
= 0; i
< SERDES_NUM_CLOCKS
; i
++) {
363 if (parents
[i
] != p
[i
]) {
375 * This can never happen, unless we missed
376 * a valid combination in serdes_am654_mux_table.
378 WARN(1, "Failed to find the parent of %s clock\n", name
);
382 val
<<= AM654_SERDES_CTRL_CLKSEL_SHIFT
;
383 ret
= regmap_update_bits(regmap
, reg
, AM654_SERDES_CTRL_CLKSEL_MASK
,
389 static const struct clk_ops serdes_am654_clk_mux_ops
= {
390 .set_parent
= serdes_am654_clk_mux_set_parent
,
391 .get_parent
= serdes_am654_clk_mux_get_parent
,
394 static int serdes_am654_clk_register(struct serdes_am654
*am654_phy
,
395 const char *clock_name
, int clock_num
)
397 struct device_node
*node
= am654_phy
->of_node
;
398 struct device
*dev
= am654_phy
->dev
;
399 struct serdes_am654_clk_mux
*mux
;
400 struct device_node
*regmap_node
;
401 const char **parent_names
;
402 struct clk_init_data
*init
;
403 unsigned int num_parents
;
404 struct regmap
*regmap
;
410 mux
= devm_kzalloc(dev
, sizeof(*mux
), GFP_KERNEL
);
414 init
= &mux
->clk_data
;
416 regmap_node
= of_parse_phandle(node
, "ti,serdes-clk", 0);
418 dev_err(dev
, "Fail to get serdes-clk node\n");
423 regmap
= syscon_node_to_regmap(regmap_node
->parent
);
424 if (IS_ERR(regmap
)) {
425 dev_err(dev
, "Fail to get Syscon regmap\n");
426 ret
= PTR_ERR(regmap
);
430 num_parents
= of_clk_get_parent_count(node
);
431 if (num_parents
< 2) {
432 dev_err(dev
, "SERDES clock must have parents\n");
437 parent_names
= devm_kzalloc(dev
, (sizeof(char *) * num_parents
),
444 of_clk_parent_fill(node
, parent_names
, num_parents
);
446 addr
= of_get_address(regmap_node
, 0, NULL
, NULL
);
452 reg
= be32_to_cpu(*addr
);
454 init
->ops
= &serdes_am654_clk_mux_ops
;
455 init
->flags
= CLK_SET_RATE_NO_REPARENT
;
456 init
->parent_names
= parent_names
;
457 init
->num_parents
= num_parents
;
458 init
->name
= clock_name
;
460 mux
->regmap
= regmap
;
462 mux
->clk_id
= clock_num
;
465 clk
= devm_clk_register(dev
, &mux
->hw
);
471 am654_phy
->clks
[clock_num
] = clk
;
474 of_node_put(regmap_node
);
478 static const struct of_device_id serdes_am654_id_table
[] = {
480 .compatible
= "ti,phy-am654-serdes",
484 MODULE_DEVICE_TABLE(of
, serdes_am654_id_table
);
486 static int serdes_am654_regfield_init(struct serdes_am654
*am654_phy
)
488 struct regmap
*regmap
= am654_phy
->regmap
;
489 struct device
*dev
= am654_phy
->dev
;
491 am654_phy
->cmu_master_cdn_o
= devm_regmap_field_alloc(dev
, regmap
,
493 if (IS_ERR(am654_phy
->cmu_master_cdn_o
)) {
494 dev_err(dev
, "CMU_MASTER_CDN_O reg field init failed\n");
495 return PTR_ERR(am654_phy
->cmu_master_cdn_o
);
498 am654_phy
->config_version
= devm_regmap_field_alloc(dev
, regmap
,
500 if (IS_ERR(am654_phy
->config_version
)) {
501 dev_err(dev
, "CONFIG_VERSION reg field init failed\n");
502 return PTR_ERR(am654_phy
->config_version
);
505 am654_phy
->l1_master_cdn_o
= devm_regmap_field_alloc(dev
, regmap
,
507 if (IS_ERR(am654_phy
->l1_master_cdn_o
)) {
508 dev_err(dev
, "L1_MASTER_CDN_O reg field init failed\n");
509 return PTR_ERR(am654_phy
->l1_master_cdn_o
);
512 am654_phy
->cmu_ok_i_0
= devm_regmap_field_alloc(dev
, regmap
,
514 if (IS_ERR(am654_phy
->cmu_ok_i_0
)) {
515 dev_err(dev
, "CMU_OK_I_0 reg field init failed\n");
516 return PTR_ERR(am654_phy
->cmu_ok_i_0
);
519 am654_phy
->por_en
= devm_regmap_field_alloc(dev
, regmap
, por_en
);
520 if (IS_ERR(am654_phy
->por_en
)) {
521 dev_err(dev
, "POR_EN reg field init failed\n");
522 return PTR_ERR(am654_phy
->por_en
);
525 am654_phy
->tx0_enable
= devm_regmap_field_alloc(dev
, regmap
,
527 if (IS_ERR(am654_phy
->tx0_enable
)) {
528 dev_err(dev
, "TX0_ENABLE reg field init failed\n");
529 return PTR_ERR(am654_phy
->tx0_enable
);
532 am654_phy
->rx0_enable
= devm_regmap_field_alloc(dev
, regmap
,
534 if (IS_ERR(am654_phy
->rx0_enable
)) {
535 dev_err(dev
, "RX0_ENABLE reg field init failed\n");
536 return PTR_ERR(am654_phy
->rx0_enable
);
539 am654_phy
->pll_enable
= devm_regmap_field_alloc(dev
, regmap
,
541 if (IS_ERR(am654_phy
->pll_enable
)) {
542 dev_err(dev
, "PLL_ENABLE reg field init failed\n");
543 return PTR_ERR(am654_phy
->pll_enable
);
546 am654_phy
->pll_ok
= devm_regmap_field_alloc(dev
, regmap
, pll_ok
);
547 if (IS_ERR(am654_phy
->pll_ok
)) {
548 dev_err(dev
, "PLL_OK reg field init failed\n");
549 return PTR_ERR(am654_phy
->pll_ok
);
555 static int serdes_am654_probe(struct platform_device
*pdev
)
557 struct phy_provider
*phy_provider
;
558 struct device
*dev
= &pdev
->dev
;
559 struct device_node
*node
= dev
->of_node
;
560 struct clk_onecell_data
*clk_data
;
561 struct serdes_am654
*am654_phy
;
562 struct mux_control
*control
;
563 const char *clock_name
;
564 struct regmap
*regmap
;
570 am654_phy
= devm_kzalloc(dev
, sizeof(*am654_phy
), GFP_KERNEL
);
574 base
= devm_platform_ioremap_resource(pdev
, 0);
576 return PTR_ERR(base
);
578 regmap
= devm_regmap_init_mmio(dev
, base
, &serdes_am654_regmap_config
);
579 if (IS_ERR(regmap
)) {
580 dev_err(dev
, "Failed to initialize regmap\n");
581 return PTR_ERR(regmap
);
584 control
= devm_mux_control_get(dev
, NULL
);
586 return PTR_ERR(control
);
588 am654_phy
->dev
= dev
;
589 am654_phy
->of_node
= node
;
590 am654_phy
->regmap
= regmap
;
591 am654_phy
->control
= control
;
592 am654_phy
->type
= PHY_NONE
;
594 ret
= serdes_am654_regfield_init(am654_phy
);
596 dev_err(dev
, "Failed to initialize regfields\n");
600 platform_set_drvdata(pdev
, am654_phy
);
602 for (i
= 0; i
< SERDES_NUM_CLOCKS
; i
++) {
603 ret
= of_property_read_string_index(node
, "clock-output-names",
606 dev_err(dev
, "Failed to get clock name\n");
610 ret
= serdes_am654_clk_register(am654_phy
, clock_name
, i
);
612 dev_err(dev
, "Failed to initialize clock %s\n",
618 clk_data
= &am654_phy
->clk_data
;
619 clk_data
->clks
= am654_phy
->clks
;
620 clk_data
->clk_num
= SERDES_NUM_CLOCKS
;
621 ret
= of_clk_add_provider(node
, of_clk_src_onecell_get
, clk_data
);
625 pm_runtime_enable(dev
);
627 phy
= devm_phy_create(dev
, NULL
, &ops
);
631 phy_set_drvdata(phy
, am654_phy
);
632 phy_provider
= devm_of_phy_provider_register(dev
, serdes_am654_xlate
);
633 if (IS_ERR(phy_provider
)) {
634 ret
= PTR_ERR(phy_provider
);
641 of_clk_del_provider(node
);
646 static int serdes_am654_remove(struct platform_device
*pdev
)
648 struct serdes_am654
*am654_phy
= platform_get_drvdata(pdev
);
649 struct device_node
*node
= am654_phy
->of_node
;
651 pm_runtime_disable(&pdev
->dev
);
652 of_clk_del_provider(node
);
657 static struct platform_driver serdes_am654_driver
= {
658 .probe
= serdes_am654_probe
,
659 .remove
= serdes_am654_remove
,
662 .of_match_table
= serdes_am654_id_table
,
665 module_platform_driver(serdes_am654_driver
);
667 MODULE_AUTHOR("Texas Instruments Inc.");
668 MODULE_DESCRIPTION("TI AM654x SERDES driver");
669 MODULE_LICENSE("GPL v2");