1 // SPDX-License-Identifier: GPL-2.0
3 * phy-uniphier-ahci.c - PHY driver for UniPhier AHCI controller
4 * Copyright 2016-2020, Socionext Inc.
5 * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
8 #include <linux/bitfield.h>
9 #include <linux/bitops.h>
10 #include <linux/clk.h>
11 #include <linux/iopoll.h>
12 #include <linux/module.h>
14 #include <linux/of_platform.h>
15 #include <linux/phy/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/reset.h>
19 struct uniphier_ahciphy_priv
{
22 struct clk
*clk
, *clk_parent
, *clk_parent_gio
;
23 struct reset_control
*rst
, *rst_parent
, *rst_parent_gio
;
24 struct reset_control
*rst_pm
, *rst_tx
, *rst_rx
;
25 const struct uniphier_ahciphy_soc_data
*data
;
28 struct uniphier_ahciphy_soc_data
{
29 int (*init
)(struct uniphier_ahciphy_priv
*priv
);
30 int (*power_on
)(struct uniphier_ahciphy_priv
*priv
);
31 int (*power_off
)(struct uniphier_ahciphy_priv
*priv
);
39 #define CKCTRL0_CK_OFF BIT(9)
40 #define CKCTRL0_NCY_MASK GENMASK(8, 4)
41 #define CKCTRL0_NCY5_MASK GENMASK(3, 2)
42 #define CKCTRL0_PRESCALE_MASK GENMASK(1, 0)
44 #define CKCTRL1_LOS_LVL_MASK GENMASK(20, 16)
45 #define CKCTRL1_TX_LVL_MASK GENMASK(12, 8)
47 #define RXTXCTRL_RX_EQ_VALL_MASK GENMASK(31, 29)
48 #define RXTXCTRL_RX_DPLL_MODE_MASK GENMASK(28, 26)
49 #define RXTXCTRL_TX_ATTEN_MASK GENMASK(14, 12)
50 #define RXTXCTRL_TX_BOOST_MASK GENMASK(11, 8)
51 #define RXTXCTRL_TX_EDGERATE_MASK GENMASK(3, 2)
52 #define RXTXCTRL_TX_CKO_EN BIT(0)
54 #define RSTPWR_RX_EN_VAL BIT(18)
58 #define CKCTRL_P0_READY BIT(15)
59 #define CKCTRL_P0_RESET BIT(10)
60 #define CKCTRL_REF_SSP_EN BIT(9)
62 #define TXCTRL0_AMP_G3_MASK GENMASK(22, 16)
63 #define TXCTRL0_AMP_G2_MASK GENMASK(14, 8)
64 #define TXCTRL0_AMP_G1_MASK GENMASK(6, 0)
66 #define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16)
67 #define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8)
68 #define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0)
70 #define RXCTRL_LOS_LVL_MASK GENMASK(20, 16)
71 #define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8)
72 #define RXCTRL_RX_EQ_MASK GENMASK(2, 0)
74 static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv
*priv
)
78 /* set phy MPLL parameters */
79 val
= readl(priv
->base
+ CKCTRL0
);
80 val
&= ~CKCTRL0_NCY_MASK
;
81 val
|= FIELD_PREP(CKCTRL0_NCY_MASK
, 0x6);
82 val
&= ~CKCTRL0_NCY5_MASK
;
83 val
|= FIELD_PREP(CKCTRL0_NCY5_MASK
, 0x2);
84 val
&= ~CKCTRL0_PRESCALE_MASK
;
85 val
|= FIELD_PREP(CKCTRL0_PRESCALE_MASK
, 0x1);
86 writel(val
, priv
->base
+ CKCTRL0
);
88 /* setup phy control parameters */
89 val
= readl(priv
->base
+ CKCTRL1
);
90 val
&= ~CKCTRL1_LOS_LVL_MASK
;
91 val
|= FIELD_PREP(CKCTRL1_LOS_LVL_MASK
, 0x10);
92 val
&= ~CKCTRL1_TX_LVL_MASK
;
93 val
|= FIELD_PREP(CKCTRL1_TX_LVL_MASK
, 0x06);
94 writel(val
, priv
->base
+ CKCTRL1
);
96 val
= readl(priv
->base
+ RXTXCTRL
);
97 val
&= ~RXTXCTRL_RX_EQ_VALL_MASK
;
98 val
|= FIELD_PREP(RXTXCTRL_RX_EQ_VALL_MASK
, 0x6);
99 val
&= ~RXTXCTRL_RX_DPLL_MODE_MASK
;
100 val
|= FIELD_PREP(RXTXCTRL_RX_DPLL_MODE_MASK
, 0x3);
101 val
&= ~RXTXCTRL_TX_ATTEN_MASK
;
102 val
|= FIELD_PREP(RXTXCTRL_TX_ATTEN_MASK
, 0x3);
103 val
&= ~RXTXCTRL_TX_BOOST_MASK
;
104 val
|= FIELD_PREP(RXTXCTRL_TX_BOOST_MASK
, 0x5);
105 val
&= ~RXTXCTRL_TX_EDGERATE_MASK
;
106 val
|= FIELD_PREP(RXTXCTRL_TX_EDGERATE_MASK
, 0x0);
107 writel(val
, priv
->base
+ RXTXCTRL
);
112 static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv
*priv
)
117 /* enable reference clock for phy */
118 val
= readl(priv
->base
+ CKCTRL0
);
119 val
&= ~CKCTRL0_CK_OFF
;
120 writel(val
, priv
->base
+ CKCTRL0
);
122 /* enable TX clock */
123 val
= readl(priv
->base
+ RXTXCTRL
);
124 val
|= RXTXCTRL_TX_CKO_EN
;
125 writel(val
, priv
->base
+ RXTXCTRL
);
127 /* wait until RX is ready */
128 ret
= readl_poll_timeout(priv
->base
+ RSTPWR
, val
,
129 !(val
& RSTPWR_RX_EN_VAL
), 200, 2000);
131 dev_err(priv
->dev
, "Failed to check whether Rx is ready\n");
132 goto out_disable_clock
;
135 /* release all reset */
136 ret
= reset_control_deassert(priv
->rst_pm
);
138 dev_err(priv
->dev
, "Failed to release PM reset\n");
139 goto out_disable_clock
;
142 ret
= reset_control_deassert(priv
->rst_tx
);
144 dev_err(priv
->dev
, "Failed to release Tx reset\n");
145 goto out_reset_pm_assert
;
148 ret
= reset_control_deassert(priv
->rst_rx
);
150 dev_err(priv
->dev
, "Failed to release Rx reset\n");
151 goto out_reset_tx_assert
;
157 reset_control_assert(priv
->rst_tx
);
159 reset_control_assert(priv
->rst_pm
);
162 /* disable TX clock */
163 val
= readl(priv
->base
+ RXTXCTRL
);
164 val
&= ~RXTXCTRL_TX_CKO_EN
;
165 writel(val
, priv
->base
+ RXTXCTRL
);
167 /* disable reference clock for phy */
168 val
= readl(priv
->base
+ CKCTRL0
);
169 val
|= CKCTRL0_CK_OFF
;
170 writel(val
, priv
->base
+ CKCTRL0
);
175 static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv
*priv
)
179 reset_control_assert(priv
->rst_rx
);
180 reset_control_assert(priv
->rst_tx
);
181 reset_control_assert(priv
->rst_pm
);
183 /* disable TX clock */
184 val
= readl(priv
->base
+ RXTXCTRL
);
185 val
&= ~RXTXCTRL_TX_CKO_EN
;
186 writel(val
, priv
->base
+ RXTXCTRL
);
188 /* disable reference clock for phy */
189 val
= readl(priv
->base
+ CKCTRL0
);
190 val
|= CKCTRL0_CK_OFF
;
191 writel(val
, priv
->base
+ CKCTRL0
);
196 static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv
*priv
,
201 val
= readl(priv
->base
+ CKCTRL
);
204 val
|= CKCTRL_REF_SSP_EN
;
205 writel(val
, priv
->base
+ CKCTRL
);
206 val
&= ~CKCTRL_P0_RESET
;
207 writel(val
, priv
->base
+ CKCTRL
);
209 val
|= CKCTRL_P0_RESET
;
210 writel(val
, priv
->base
+ CKCTRL
);
211 val
&= ~CKCTRL_REF_SSP_EN
;
212 writel(val
, priv
->base
+ CKCTRL
);
216 static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv
*priv
)
221 uniphier_ahciphy_pxs2_enable(priv
, true);
223 /* wait until PLL is ready */
224 if (priv
->data
->is_ready_high
)
225 ret
= readl_poll_timeout(priv
->base
+ CKCTRL
, val
,
226 (val
& CKCTRL_P0_READY
), 200, 400);
228 ret
= readl_poll_timeout(priv
->base
+ CKCTRL
, val
,
229 !(val
& CKCTRL_P0_READY
), 200, 400);
231 dev_err(priv
->dev
, "Failed to check whether PHY PLL is ready\n");
232 uniphier_ahciphy_pxs2_enable(priv
, false);
238 static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv
*priv
)
240 uniphier_ahciphy_pxs2_enable(priv
, false);
245 static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv
*priv
)
250 /* setup port parameter */
251 val
= readl(priv
->base
+ TXCTRL0
);
252 val
&= ~TXCTRL0_AMP_G3_MASK
;
253 val
|= FIELD_PREP(TXCTRL0_AMP_G3_MASK
, 0x73);
254 val
&= ~TXCTRL0_AMP_G2_MASK
;
255 val
|= FIELD_PREP(TXCTRL0_AMP_G2_MASK
, 0x46);
256 val
&= ~TXCTRL0_AMP_G1_MASK
;
257 val
|= FIELD_PREP(TXCTRL0_AMP_G1_MASK
, 0x42);
258 writel(val
, priv
->base
+ TXCTRL0
);
260 val
= readl(priv
->base
+ TXCTRL1
);
261 val
&= ~TXCTRL1_DEEMPH_G3_MASK
;
262 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK
, 0x23);
263 val
&= ~TXCTRL1_DEEMPH_G2_MASK
;
264 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK
, 0x05);
265 val
&= ~TXCTRL1_DEEMPH_G1_MASK
;
266 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK
, 0x05);
268 val
= readl(priv
->base
+ RXCTRL
);
269 val
&= ~RXCTRL_LOS_LVL_MASK
;
270 val
|= FIELD_PREP(RXCTRL_LOS_LVL_MASK
, 0x9);
271 val
&= ~RXCTRL_LOS_BIAS_MASK
;
272 val
|= FIELD_PREP(RXCTRL_LOS_BIAS_MASK
, 0x2);
273 val
&= ~RXCTRL_RX_EQ_MASK
;
274 val
|= FIELD_PREP(RXCTRL_RX_EQ_MASK
, 0x1);
276 /* dummy read 25 times to make a wait time for the phy to stabilize */
277 for (i
= 0; i
< 25; i
++)
278 readl(priv
->base
+ CKCTRL
);
283 static int uniphier_ahciphy_init(struct phy
*phy
)
285 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
288 ret
= clk_prepare_enable(priv
->clk_parent_gio
);
292 ret
= clk_prepare_enable(priv
->clk_parent
);
294 goto out_clk_gio_disable
;
296 ret
= reset_control_deassert(priv
->rst_parent_gio
);
298 goto out_clk_disable
;
300 ret
= reset_control_deassert(priv
->rst_parent
);
302 goto out_rst_gio_assert
;
304 if (priv
->data
->init
) {
305 ret
= priv
->data
->init(priv
);
313 reset_control_assert(priv
->rst_parent
);
315 reset_control_assert(priv
->rst_parent_gio
);
317 clk_disable_unprepare(priv
->clk_parent
);
319 clk_disable_unprepare(priv
->clk_parent_gio
);
324 static int uniphier_ahciphy_exit(struct phy
*phy
)
326 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
328 reset_control_assert(priv
->rst_parent
);
329 reset_control_assert(priv
->rst_parent_gio
);
330 clk_disable_unprepare(priv
->clk_parent
);
331 clk_disable_unprepare(priv
->clk_parent_gio
);
336 static int uniphier_ahciphy_power_on(struct phy
*phy
)
338 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
341 ret
= clk_prepare_enable(priv
->clk
);
345 ret
= reset_control_deassert(priv
->rst
);
347 goto out_clk_disable
;
349 if (priv
->data
->power_on
) {
350 ret
= priv
->data
->power_on(priv
);
352 goto out_reset_assert
;
358 reset_control_assert(priv
->rst
);
360 clk_disable_unprepare(priv
->clk
);
365 static int uniphier_ahciphy_power_off(struct phy
*phy
)
367 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
370 if (priv
->data
->power_off
)
371 ret
= priv
->data
->power_off(priv
);
373 reset_control_assert(priv
->rst
);
374 clk_disable_unprepare(priv
->clk
);
379 static const struct phy_ops uniphier_ahciphy_ops
= {
380 .init
= uniphier_ahciphy_init
,
381 .exit
= uniphier_ahciphy_exit
,
382 .power_on
= uniphier_ahciphy_power_on
,
383 .power_off
= uniphier_ahciphy_power_off
,
384 .owner
= THIS_MODULE
,
387 static int uniphier_ahciphy_probe(struct platform_device
*pdev
)
389 struct device
*dev
= &pdev
->dev
;
390 struct uniphier_ahciphy_priv
*priv
;
392 struct phy_provider
*phy_provider
;
394 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
399 priv
->data
= of_device_get_match_data(dev
);
400 if (WARN_ON(!priv
->data
))
403 priv
->base
= devm_platform_ioremap_resource(pdev
, 0);
404 if (IS_ERR(priv
->base
))
405 return PTR_ERR(priv
->base
);
407 priv
->clk_parent
= devm_clk_get(dev
, "link");
408 if (IS_ERR(priv
->clk_parent
))
409 return PTR_ERR(priv
->clk_parent
);
411 if (priv
->data
->is_phy_clk
) {
412 priv
->clk
= devm_clk_get(dev
, "phy");
413 if (IS_ERR(priv
->clk
))
414 return PTR_ERR(priv
->clk
);
417 priv
->rst_parent
= devm_reset_control_get_shared(dev
, "link");
418 if (IS_ERR(priv
->rst_parent
))
419 return PTR_ERR(priv
->rst_parent
);
421 priv
->rst
= devm_reset_control_get_shared(dev
, "phy");
422 if (IS_ERR(priv
->rst
))
423 return PTR_ERR(priv
->rst
);
425 if (priv
->data
->is_legacy
) {
426 priv
->clk_parent_gio
= devm_clk_get(dev
, "gio");
427 if (IS_ERR(priv
->clk_parent_gio
))
428 return PTR_ERR(priv
->clk_parent_gio
);
429 priv
->rst_parent_gio
=
430 devm_reset_control_get_shared(dev
, "gio");
431 if (IS_ERR(priv
->rst_parent_gio
))
432 return PTR_ERR(priv
->rst_parent_gio
);
434 priv
->rst_pm
= devm_reset_control_get_shared(dev
, "pm");
435 if (IS_ERR(priv
->rst_pm
))
436 return PTR_ERR(priv
->rst_pm
);
438 priv
->rst_tx
= devm_reset_control_get_shared(dev
, "tx");
439 if (IS_ERR(priv
->rst_tx
))
440 return PTR_ERR(priv
->rst_tx
);
442 priv
->rst_rx
= devm_reset_control_get_shared(dev
, "rx");
443 if (IS_ERR(priv
->rst_rx
))
444 return PTR_ERR(priv
->rst_rx
);
447 phy
= devm_phy_create(dev
, dev
->of_node
, &uniphier_ahciphy_ops
);
449 dev_err(dev
, "failed to create phy\n");
453 phy_set_drvdata(phy
, priv
);
454 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
455 if (IS_ERR(phy_provider
))
456 return PTR_ERR(phy_provider
);
461 static const struct uniphier_ahciphy_soc_data uniphier_pro4_data
= {
462 .init
= uniphier_ahciphy_pro4_init
,
463 .power_on
= uniphier_ahciphy_pro4_power_on
,
464 .power_off
= uniphier_ahciphy_pro4_power_off
,
469 static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data
= {
470 .power_on
= uniphier_ahciphy_pxs2_power_on
,
471 .power_off
= uniphier_ahciphy_pxs2_power_off
,
473 .is_ready_high
= false,
477 static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data
= {
478 .init
= uniphier_ahciphy_pxs3_init
,
479 .power_on
= uniphier_ahciphy_pxs2_power_on
,
480 .power_off
= uniphier_ahciphy_pxs2_power_off
,
482 .is_ready_high
= true,
486 static const struct of_device_id uniphier_ahciphy_match
[] = {
488 .compatible
= "socionext,uniphier-pro4-ahci-phy",
489 .data
= &uniphier_pro4_data
,
492 .compatible
= "socionext,uniphier-pxs2-ahci-phy",
493 .data
= &uniphier_pxs2_data
,
496 .compatible
= "socionext,uniphier-pxs3-ahci-phy",
497 .data
= &uniphier_pxs3_data
,
501 MODULE_DEVICE_TABLE(of
, uniphier_ahciphy_match
);
503 static struct platform_driver uniphier_ahciphy_driver
= {
504 .probe
= uniphier_ahciphy_probe
,
506 .name
= "uniphier-ahci-phy",
507 .of_match_table
= uniphier_ahciphy_match
,
510 module_platform_driver(uniphier_ahciphy_driver
);
512 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
513 MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller");
514 MODULE_LICENSE("GPL v2");