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
;
23 struct reset_control
*rst
, *rst_parent
;
24 const struct uniphier_ahciphy_soc_data
*data
;
27 struct uniphier_ahciphy_soc_data
{
28 int (*init
)(struct uniphier_ahciphy_priv
*priv
);
29 int (*power_on
)(struct uniphier_ahciphy_priv
*priv
);
30 int (*power_off
)(struct uniphier_ahciphy_priv
*priv
);
37 #define CKCTRL_P0_READY BIT(15)
38 #define CKCTRL_P0_RESET BIT(10)
39 #define CKCTRL_REF_SSP_EN BIT(9)
41 #define TXCTRL0_AMP_G3_MASK GENMASK(22, 16)
42 #define TXCTRL0_AMP_G2_MASK GENMASK(14, 8)
43 #define TXCTRL0_AMP_G1_MASK GENMASK(6, 0)
45 #define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16)
46 #define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8)
47 #define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0)
49 #define RXCTRL_LOS_LVL_MASK GENMASK(20, 16)
50 #define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8)
51 #define RXCTRL_RX_EQ_MASK GENMASK(2, 0)
53 static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv
*priv
,
58 val
= readl(priv
->base
+ CKCTRL
);
61 val
|= CKCTRL_REF_SSP_EN
;
62 writel(val
, priv
->base
+ CKCTRL
);
63 val
&= ~CKCTRL_P0_RESET
;
64 writel(val
, priv
->base
+ CKCTRL
);
66 val
|= CKCTRL_P0_RESET
;
67 writel(val
, priv
->base
+ CKCTRL
);
68 val
&= ~CKCTRL_REF_SSP_EN
;
69 writel(val
, priv
->base
+ CKCTRL
);
73 static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv
*priv
)
78 uniphier_ahciphy_pxs2_enable(priv
, true);
80 /* wait until PLL is ready */
81 if (priv
->data
->is_ready_high
)
82 ret
= readl_poll_timeout(priv
->base
+ CKCTRL
, val
,
83 (val
& CKCTRL_P0_READY
), 200, 400);
85 ret
= readl_poll_timeout(priv
->base
+ CKCTRL
, val
,
86 !(val
& CKCTRL_P0_READY
), 200, 400);
88 dev_err(priv
->dev
, "Failed to check whether PHY PLL is ready\n");
89 uniphier_ahciphy_pxs2_enable(priv
, false);
95 static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv
*priv
)
97 uniphier_ahciphy_pxs2_enable(priv
, false);
102 static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv
*priv
)
107 /* setup port parameter */
108 val
= readl(priv
->base
+ TXCTRL0
);
109 val
&= ~TXCTRL0_AMP_G3_MASK
;
110 val
|= FIELD_PREP(TXCTRL0_AMP_G3_MASK
, 0x73);
111 val
&= ~TXCTRL0_AMP_G2_MASK
;
112 val
|= FIELD_PREP(TXCTRL0_AMP_G2_MASK
, 0x46);
113 val
&= ~TXCTRL0_AMP_G1_MASK
;
114 val
|= FIELD_PREP(TXCTRL0_AMP_G1_MASK
, 0x42);
115 writel(val
, priv
->base
+ TXCTRL0
);
117 val
= readl(priv
->base
+ TXCTRL1
);
118 val
&= ~TXCTRL1_DEEMPH_G3_MASK
;
119 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK
, 0x23);
120 val
&= ~TXCTRL1_DEEMPH_G2_MASK
;
121 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK
, 0x05);
122 val
&= ~TXCTRL1_DEEMPH_G1_MASK
;
123 val
|= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK
, 0x05);
125 val
= readl(priv
->base
+ RXCTRL
);
126 val
&= ~RXCTRL_LOS_LVL_MASK
;
127 val
|= FIELD_PREP(RXCTRL_LOS_LVL_MASK
, 0x9);
128 val
&= ~RXCTRL_LOS_BIAS_MASK
;
129 val
|= FIELD_PREP(RXCTRL_LOS_BIAS_MASK
, 0x2);
130 val
&= ~RXCTRL_RX_EQ_MASK
;
131 val
|= FIELD_PREP(RXCTRL_RX_EQ_MASK
, 0x1);
133 /* dummy read 25 times to make a wait time for the phy to stabilize */
134 for (i
= 0; i
< 25; i
++)
135 readl(priv
->base
+ CKCTRL
);
140 static int uniphier_ahciphy_init(struct phy
*phy
)
142 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
145 ret
= clk_prepare_enable(priv
->clk_parent
);
149 ret
= reset_control_deassert(priv
->rst_parent
);
151 goto out_clk_disable
;
153 if (priv
->data
->init
) {
154 ret
= priv
->data
->init(priv
);
162 reset_control_assert(priv
->rst_parent
);
164 clk_disable_unprepare(priv
->clk_parent
);
169 static int uniphier_ahciphy_exit(struct phy
*phy
)
171 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
173 reset_control_assert(priv
->rst_parent
);
174 clk_disable_unprepare(priv
->clk_parent
);
179 static int uniphier_ahciphy_power_on(struct phy
*phy
)
181 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
184 ret
= clk_prepare_enable(priv
->clk
);
188 ret
= reset_control_deassert(priv
->rst
);
190 goto out_clk_disable
;
192 if (priv
->data
->power_on
) {
193 ret
= priv
->data
->power_on(priv
);
195 goto out_reset_assert
;
201 reset_control_assert(priv
->rst
);
203 clk_disable_unprepare(priv
->clk
);
208 static int uniphier_ahciphy_power_off(struct phy
*phy
)
210 struct uniphier_ahciphy_priv
*priv
= phy_get_drvdata(phy
);
213 if (priv
->data
->power_off
)
214 ret
= priv
->data
->power_off(priv
);
216 reset_control_assert(priv
->rst
);
217 clk_disable_unprepare(priv
->clk
);
222 static const struct phy_ops uniphier_ahciphy_ops
= {
223 .init
= uniphier_ahciphy_init
,
224 .exit
= uniphier_ahciphy_exit
,
225 .power_on
= uniphier_ahciphy_power_on
,
226 .power_off
= uniphier_ahciphy_power_off
,
227 .owner
= THIS_MODULE
,
230 static int uniphier_ahciphy_probe(struct platform_device
*pdev
)
232 struct device
*dev
= &pdev
->dev
;
233 struct uniphier_ahciphy_priv
*priv
;
235 struct phy_provider
*phy_provider
;
237 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
242 priv
->data
= of_device_get_match_data(dev
);
243 if (WARN_ON(!priv
->data
))
246 priv
->base
= devm_platform_ioremap_resource(pdev
, 0);
247 if (IS_ERR(priv
->base
))
248 return PTR_ERR(priv
->base
);
250 priv
->clk_parent
= devm_clk_get(dev
, "link");
251 if (IS_ERR(priv
->clk_parent
))
252 return PTR_ERR(priv
->clk_parent
);
254 if (priv
->data
->is_phy_clk
) {
255 priv
->clk
= devm_clk_get(dev
, "phy");
256 if (IS_ERR(priv
->clk
))
257 return PTR_ERR(priv
->clk
);
260 priv
->rst_parent
= devm_reset_control_get_shared(dev
, "link");
261 if (IS_ERR(priv
->rst_parent
))
262 return PTR_ERR(priv
->rst_parent
);
264 priv
->rst
= devm_reset_control_get_shared(dev
, "phy");
265 if (IS_ERR(priv
->rst
))
266 return PTR_ERR(priv
->rst
);
268 phy
= devm_phy_create(dev
, dev
->of_node
, &uniphier_ahciphy_ops
);
270 dev_err(dev
, "failed to create phy\n");
274 phy_set_drvdata(phy
, priv
);
275 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
276 if (IS_ERR(phy_provider
))
277 return PTR_ERR(phy_provider
);
282 static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data
= {
283 .power_on
= uniphier_ahciphy_pxs2_power_on
,
284 .power_off
= uniphier_ahciphy_pxs2_power_off
,
285 .is_ready_high
= false,
289 static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data
= {
290 .init
= uniphier_ahciphy_pxs3_init
,
291 .power_on
= uniphier_ahciphy_pxs2_power_on
,
292 .power_off
= uniphier_ahciphy_pxs2_power_off
,
293 .is_ready_high
= true,
297 static const struct of_device_id uniphier_ahciphy_match
[] = {
299 .compatible
= "socionext,uniphier-pxs2-ahci-phy",
300 .data
= &uniphier_pxs2_data
,
303 .compatible
= "socionext,uniphier-pxs3-ahci-phy",
304 .data
= &uniphier_pxs3_data
,
308 MODULE_DEVICE_TABLE(of
, uniphier_ahciphy_match
);
310 static struct platform_driver uniphier_ahciphy_driver
= {
311 .probe
= uniphier_ahciphy_probe
,
313 .name
= "uniphier-ahci-phy",
314 .of_match_table
= uniphier_ahciphy_match
,
317 module_platform_driver(uniphier_ahciphy_driver
);
319 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
320 MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller");
321 MODULE_LICENSE("GPL v2");