xref: /linux/drivers/phy/socionext/phy-uniphier-ahci.c (revision b1f9f4541e99a43e3d52bc65408d0b96a340c1df)
1a1bf1c60SKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0
2a1bf1c60SKunihiko Hayashi /*
3a1bf1c60SKunihiko Hayashi  * phy-uniphier-ahci.c - PHY driver for UniPhier AHCI controller
4a1bf1c60SKunihiko Hayashi  * Copyright 2016-2020, Socionext Inc.
5a1bf1c60SKunihiko Hayashi  * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
6a1bf1c60SKunihiko Hayashi  */
7a1bf1c60SKunihiko Hayashi 
8a1bf1c60SKunihiko Hayashi #include <linux/bitfield.h>
9a1bf1c60SKunihiko Hayashi #include <linux/bitops.h>
10a1bf1c60SKunihiko Hayashi #include <linux/clk.h>
11a1bf1c60SKunihiko Hayashi #include <linux/iopoll.h>
12a1bf1c60SKunihiko Hayashi #include <linux/module.h>
13a1bf1c60SKunihiko Hayashi #include <linux/of.h>
14a1bf1c60SKunihiko Hayashi #include <linux/of_platform.h>
15a1bf1c60SKunihiko Hayashi #include <linux/phy/phy.h>
16a1bf1c60SKunihiko Hayashi #include <linux/platform_device.h>
17a1bf1c60SKunihiko Hayashi #include <linux/reset.h>
18a1bf1c60SKunihiko Hayashi 
19a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv {
20a1bf1c60SKunihiko Hayashi 	struct device *dev;
21a1bf1c60SKunihiko Hayashi 	void __iomem  *base;
22*b1f9f454SKunihiko Hayashi 	struct clk *clk, *clk_parent, *clk_parent_gio;
23*b1f9f454SKunihiko Hayashi 	struct reset_control *rst, *rst_parent, *rst_parent_gio;
24*b1f9f454SKunihiko Hayashi 	struct reset_control *rst_pm, *rst_tx, *rst_rx;
25a1bf1c60SKunihiko Hayashi 	const struct uniphier_ahciphy_soc_data *data;
26a1bf1c60SKunihiko Hayashi };
27a1bf1c60SKunihiko Hayashi 
28a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_soc_data {
29a1bf1c60SKunihiko Hayashi 	int (*init)(struct uniphier_ahciphy_priv *priv);
30a1bf1c60SKunihiko Hayashi 	int (*power_on)(struct uniphier_ahciphy_priv *priv);
31a1bf1c60SKunihiko Hayashi 	int (*power_off)(struct uniphier_ahciphy_priv *priv);
32*b1f9f454SKunihiko Hayashi 	bool is_legacy;
33a1bf1c60SKunihiko Hayashi 	bool is_ready_high;
34a1bf1c60SKunihiko Hayashi 	bool is_phy_clk;
35a1bf1c60SKunihiko Hayashi };
36a1bf1c60SKunihiko Hayashi 
37*b1f9f454SKunihiko Hayashi /* for Pro4 */
38*b1f9f454SKunihiko Hayashi #define CKCTRL0				0x0
39*b1f9f454SKunihiko Hayashi #define CKCTRL0_CK_OFF			BIT(9)
40*b1f9f454SKunihiko Hayashi #define CKCTRL0_NCY_MASK		GENMASK(8, 4)
41*b1f9f454SKunihiko Hayashi #define CKCTRL0_NCY5_MASK		GENMASK(3, 2)
42*b1f9f454SKunihiko Hayashi #define CKCTRL0_PRESCALE_MASK		GENMASK(1, 0)
43*b1f9f454SKunihiko Hayashi #define CKCTRL1				0x4
44*b1f9f454SKunihiko Hayashi #define CKCTRL1_LOS_LVL_MASK		GENMASK(20, 16)
45*b1f9f454SKunihiko Hayashi #define CKCTRL1_TX_LVL_MASK		GENMASK(12, 8)
46*b1f9f454SKunihiko Hayashi #define RXTXCTRL			0x8
47*b1f9f454SKunihiko Hayashi #define RXTXCTRL_RX_EQ_VALL_MASK	GENMASK(31, 29)
48*b1f9f454SKunihiko Hayashi #define RXTXCTRL_RX_DPLL_MODE_MASK	GENMASK(28, 26)
49*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_ATTEN_MASK		GENMASK(14, 12)
50*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_BOOST_MASK		GENMASK(11, 8)
51*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_EDGERATE_MASK	GENMASK(3, 2)
52*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_CKO_EN		BIT(0)
53*b1f9f454SKunihiko Hayashi #define RSTPWR				0x30
54*b1f9f454SKunihiko Hayashi #define RSTPWR_RX_EN_VAL		BIT(18)
55*b1f9f454SKunihiko Hayashi 
56a1bf1c60SKunihiko Hayashi /* for PXs2/PXs3 */
57a1bf1c60SKunihiko Hayashi #define CKCTRL				0x0
58a1bf1c60SKunihiko Hayashi #define CKCTRL_P0_READY			BIT(15)
59a1bf1c60SKunihiko Hayashi #define CKCTRL_P0_RESET			BIT(10)
60a1bf1c60SKunihiko Hayashi #define CKCTRL_REF_SSP_EN		BIT(9)
61a1bf1c60SKunihiko Hayashi #define TXCTRL0				0x4
62a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G3_MASK		GENMASK(22, 16)
63a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G2_MASK		GENMASK(14, 8)
64a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G1_MASK		GENMASK(6, 0)
65a1bf1c60SKunihiko Hayashi #define TXCTRL1				0x8
66a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G3_MASK		GENMASK(21, 16)
67a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G2_MASK		GENMASK(13, 8)
68a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G1_MASK		GENMASK(5, 0)
69a1bf1c60SKunihiko Hayashi #define RXCTRL				0xc
70a1bf1c60SKunihiko Hayashi #define RXCTRL_LOS_LVL_MASK		GENMASK(20, 16)
71a1bf1c60SKunihiko Hayashi #define RXCTRL_LOS_BIAS_MASK		GENMASK(10, 8)
72a1bf1c60SKunihiko Hayashi #define RXCTRL_RX_EQ_MASK		GENMASK(2, 0)
73a1bf1c60SKunihiko Hayashi 
74*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv *priv)
75*b1f9f454SKunihiko Hayashi {
76*b1f9f454SKunihiko Hayashi 	u32 val;
77*b1f9f454SKunihiko Hayashi 
78*b1f9f454SKunihiko Hayashi 	/* set phy MPLL parameters */
79*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + CKCTRL0);
80*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL0_NCY_MASK;
81*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(CKCTRL0_NCY_MASK, 0x6);
82*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL0_NCY5_MASK;
83*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(CKCTRL0_NCY5_MASK, 0x2);
84*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL0_PRESCALE_MASK;
85*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(CKCTRL0_PRESCALE_MASK, 0x1);
86*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + CKCTRL0);
87*b1f9f454SKunihiko Hayashi 
88*b1f9f454SKunihiko Hayashi 	/* setup phy control parameters */
89*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + CKCTRL1);
90*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL1_LOS_LVL_MASK;
91*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(CKCTRL1_LOS_LVL_MASK, 0x10);
92*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL1_TX_LVL_MASK;
93*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(CKCTRL1_TX_LVL_MASK, 0x06);
94*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + CKCTRL1);
95*b1f9f454SKunihiko Hayashi 
96*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + RXTXCTRL);
97*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_RX_EQ_VALL_MASK;
98*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(RXTXCTRL_RX_EQ_VALL_MASK, 0x6);
99*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_RX_DPLL_MODE_MASK;
100*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(RXTXCTRL_RX_DPLL_MODE_MASK, 0x3);
101*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_TX_ATTEN_MASK;
102*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(RXTXCTRL_TX_ATTEN_MASK, 0x3);
103*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_TX_BOOST_MASK;
104*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(RXTXCTRL_TX_BOOST_MASK, 0x5);
105*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_TX_EDGERATE_MASK;
106*b1f9f454SKunihiko Hayashi 	val |= FIELD_PREP(RXTXCTRL_TX_EDGERATE_MASK, 0x0);
107*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + RXTXCTRL);
108*b1f9f454SKunihiko Hayashi 
109*b1f9f454SKunihiko Hayashi 	return 0;
110*b1f9f454SKunihiko Hayashi }
111*b1f9f454SKunihiko Hayashi 
112*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv *priv)
113*b1f9f454SKunihiko Hayashi {
114*b1f9f454SKunihiko Hayashi 	u32 val;
115*b1f9f454SKunihiko Hayashi 	int ret;
116*b1f9f454SKunihiko Hayashi 
117*b1f9f454SKunihiko Hayashi 	/* enable reference clock for phy */
118*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + CKCTRL0);
119*b1f9f454SKunihiko Hayashi 	val &= ~CKCTRL0_CK_OFF;
120*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + CKCTRL0);
121*b1f9f454SKunihiko Hayashi 
122*b1f9f454SKunihiko Hayashi 	/* enable TX clock */
123*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + RXTXCTRL);
124*b1f9f454SKunihiko Hayashi 	val |= RXTXCTRL_TX_CKO_EN;
125*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + RXTXCTRL);
126*b1f9f454SKunihiko Hayashi 
127*b1f9f454SKunihiko Hayashi 	/* wait until RX is ready */
128*b1f9f454SKunihiko Hayashi 	ret = readl_poll_timeout(priv->base + RSTPWR, val,
129*b1f9f454SKunihiko Hayashi 				 !(val & RSTPWR_RX_EN_VAL), 200, 2000);
130*b1f9f454SKunihiko Hayashi 	if (ret) {
131*b1f9f454SKunihiko Hayashi 		dev_err(priv->dev, "Failed to check whether Rx is ready\n");
132*b1f9f454SKunihiko Hayashi 		goto out_disable_clock;
133*b1f9f454SKunihiko Hayashi 	}
134*b1f9f454SKunihiko Hayashi 
135*b1f9f454SKunihiko Hayashi 	/* release all reset */
136*b1f9f454SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_pm);
137*b1f9f454SKunihiko Hayashi 	if (ret) {
138*b1f9f454SKunihiko Hayashi 		dev_err(priv->dev, "Failed to release PM reset\n");
139*b1f9f454SKunihiko Hayashi 		goto out_disable_clock;
140*b1f9f454SKunihiko Hayashi 	}
141*b1f9f454SKunihiko Hayashi 
142*b1f9f454SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_tx);
143*b1f9f454SKunihiko Hayashi 	if (ret) {
144*b1f9f454SKunihiko Hayashi 		dev_err(priv->dev, "Failed to release Tx reset\n");
145*b1f9f454SKunihiko Hayashi 		goto out_reset_pm_assert;
146*b1f9f454SKunihiko Hayashi 	}
147*b1f9f454SKunihiko Hayashi 
148*b1f9f454SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_rx);
149*b1f9f454SKunihiko Hayashi 	if (ret) {
150*b1f9f454SKunihiko Hayashi 		dev_err(priv->dev, "Failed to release Rx reset\n");
151*b1f9f454SKunihiko Hayashi 		goto out_reset_tx_assert;
152*b1f9f454SKunihiko Hayashi 	}
153*b1f9f454SKunihiko Hayashi 
154*b1f9f454SKunihiko Hayashi 	return 0;
155*b1f9f454SKunihiko Hayashi 
156*b1f9f454SKunihiko Hayashi out_reset_tx_assert:
157*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_tx);
158*b1f9f454SKunihiko Hayashi out_reset_pm_assert:
159*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_pm);
160*b1f9f454SKunihiko Hayashi 
161*b1f9f454SKunihiko Hayashi out_disable_clock:
162*b1f9f454SKunihiko Hayashi 	/* disable TX clock */
163*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + RXTXCTRL);
164*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_TX_CKO_EN;
165*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + RXTXCTRL);
166*b1f9f454SKunihiko Hayashi 
167*b1f9f454SKunihiko Hayashi 	/* disable reference clock for phy */
168*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + CKCTRL0);
169*b1f9f454SKunihiko Hayashi 	val |= CKCTRL0_CK_OFF;
170*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + CKCTRL0);
171*b1f9f454SKunihiko Hayashi 
172*b1f9f454SKunihiko Hayashi 	return ret;
173*b1f9f454SKunihiko Hayashi }
174*b1f9f454SKunihiko Hayashi 
175*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv *priv)
176*b1f9f454SKunihiko Hayashi {
177*b1f9f454SKunihiko Hayashi 	u32 val;
178*b1f9f454SKunihiko Hayashi 
179*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_rx);
180*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_tx);
181*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_pm);
182*b1f9f454SKunihiko Hayashi 
183*b1f9f454SKunihiko Hayashi 	/* disable TX clock */
184*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + RXTXCTRL);
185*b1f9f454SKunihiko Hayashi 	val &= ~RXTXCTRL_TX_CKO_EN;
186*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + RXTXCTRL);
187*b1f9f454SKunihiko Hayashi 
188*b1f9f454SKunihiko Hayashi 	/* disable reference clock for phy */
189*b1f9f454SKunihiko Hayashi 	val = readl(priv->base + CKCTRL0);
190*b1f9f454SKunihiko Hayashi 	val |= CKCTRL0_CK_OFF;
191*b1f9f454SKunihiko Hayashi 	writel(val, priv->base + CKCTRL0);
192*b1f9f454SKunihiko Hayashi 
193*b1f9f454SKunihiko Hayashi 	return 0;
194*b1f9f454SKunihiko Hayashi }
195*b1f9f454SKunihiko Hayashi 
196a1bf1c60SKunihiko Hayashi static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv,
197a1bf1c60SKunihiko Hayashi 					 bool enable)
198a1bf1c60SKunihiko Hayashi {
199a1bf1c60SKunihiko Hayashi 	u32 val;
200a1bf1c60SKunihiko Hayashi 
201a1bf1c60SKunihiko Hayashi 	val = readl(priv->base + CKCTRL);
202a1bf1c60SKunihiko Hayashi 
203a1bf1c60SKunihiko Hayashi 	if (enable) {
204a1bf1c60SKunihiko Hayashi 		val |= CKCTRL_REF_SSP_EN;
205a1bf1c60SKunihiko Hayashi 		writel(val, priv->base + CKCTRL);
206a1bf1c60SKunihiko Hayashi 		val &= ~CKCTRL_P0_RESET;
207a1bf1c60SKunihiko Hayashi 		writel(val, priv->base + CKCTRL);
208a1bf1c60SKunihiko Hayashi 	} else {
209a1bf1c60SKunihiko Hayashi 		val |= CKCTRL_P0_RESET;
210a1bf1c60SKunihiko Hayashi 		writel(val, priv->base + CKCTRL);
211a1bf1c60SKunihiko Hayashi 		val &= ~CKCTRL_REF_SSP_EN;
212a1bf1c60SKunihiko Hayashi 		writel(val, priv->base + CKCTRL);
213a1bf1c60SKunihiko Hayashi 	}
214a1bf1c60SKunihiko Hayashi }
215a1bf1c60SKunihiko Hayashi 
216a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv)
217a1bf1c60SKunihiko Hayashi {
218a1bf1c60SKunihiko Hayashi 	int ret;
219a1bf1c60SKunihiko Hayashi 	u32 val;
220a1bf1c60SKunihiko Hayashi 
221a1bf1c60SKunihiko Hayashi 	uniphier_ahciphy_pxs2_enable(priv, true);
222a1bf1c60SKunihiko Hayashi 
223a1bf1c60SKunihiko Hayashi 	/* wait until PLL is ready */
224a1bf1c60SKunihiko Hayashi 	if (priv->data->is_ready_high)
225a1bf1c60SKunihiko Hayashi 		ret = readl_poll_timeout(priv->base + CKCTRL, val,
226a1bf1c60SKunihiko Hayashi 					 (val & CKCTRL_P0_READY), 200, 400);
227a1bf1c60SKunihiko Hayashi 	else
228a1bf1c60SKunihiko Hayashi 		ret = readl_poll_timeout(priv->base + CKCTRL, val,
229a1bf1c60SKunihiko Hayashi 					 !(val & CKCTRL_P0_READY), 200, 400);
230a1bf1c60SKunihiko Hayashi 	if (ret) {
231a1bf1c60SKunihiko Hayashi 		dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n");
232a1bf1c60SKunihiko Hayashi 		uniphier_ahciphy_pxs2_enable(priv, false);
233a1bf1c60SKunihiko Hayashi 	}
234a1bf1c60SKunihiko Hayashi 
235a1bf1c60SKunihiko Hayashi 	return ret;
236a1bf1c60SKunihiko Hayashi }
237a1bf1c60SKunihiko Hayashi 
238a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv)
239a1bf1c60SKunihiko Hayashi {
240a1bf1c60SKunihiko Hayashi 	uniphier_ahciphy_pxs2_enable(priv, false);
241a1bf1c60SKunihiko Hayashi 
242a1bf1c60SKunihiko Hayashi 	return 0;
243a1bf1c60SKunihiko Hayashi }
244a1bf1c60SKunihiko Hayashi 
245a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv)
246a1bf1c60SKunihiko Hayashi {
247a1bf1c60SKunihiko Hayashi 	int i;
248a1bf1c60SKunihiko Hayashi 	u32 val;
249a1bf1c60SKunihiko Hayashi 
250a1bf1c60SKunihiko Hayashi 	/* setup port parameter */
251a1bf1c60SKunihiko Hayashi 	val = readl(priv->base + TXCTRL0);
252a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL0_AMP_G3_MASK;
253a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL0_AMP_G3_MASK, 0x73);
254a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL0_AMP_G2_MASK;
255a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL0_AMP_G2_MASK, 0x46);
256a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL0_AMP_G1_MASK;
257a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL0_AMP_G1_MASK, 0x42);
258a1bf1c60SKunihiko Hayashi 	writel(val, priv->base + TXCTRL0);
259a1bf1c60SKunihiko Hayashi 
260a1bf1c60SKunihiko Hayashi 	val = readl(priv->base + TXCTRL1);
261a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL1_DEEMPH_G3_MASK;
262a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK, 0x23);
263a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL1_DEEMPH_G2_MASK;
264a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK, 0x05);
265a1bf1c60SKunihiko Hayashi 	val &= ~TXCTRL1_DEEMPH_G1_MASK;
266a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK, 0x05);
267a1bf1c60SKunihiko Hayashi 
268a1bf1c60SKunihiko Hayashi 	val = readl(priv->base + RXCTRL);
269a1bf1c60SKunihiko Hayashi 	val &= ~RXCTRL_LOS_LVL_MASK;
270a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(RXCTRL_LOS_LVL_MASK, 0x9);
271a1bf1c60SKunihiko Hayashi 	val &= ~RXCTRL_LOS_BIAS_MASK;
272a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(RXCTRL_LOS_BIAS_MASK, 0x2);
273a1bf1c60SKunihiko Hayashi 	val &= ~RXCTRL_RX_EQ_MASK;
274a1bf1c60SKunihiko Hayashi 	val |= FIELD_PREP(RXCTRL_RX_EQ_MASK, 0x1);
275a1bf1c60SKunihiko Hayashi 
276a1bf1c60SKunihiko Hayashi 	/* dummy read 25 times to make a wait time for the phy to stabilize */
277a1bf1c60SKunihiko Hayashi 	for (i = 0; i < 25; i++)
278a1bf1c60SKunihiko Hayashi 		readl(priv->base + CKCTRL);
279a1bf1c60SKunihiko Hayashi 
280a1bf1c60SKunihiko Hayashi 	return 0;
281a1bf1c60SKunihiko Hayashi }
282a1bf1c60SKunihiko Hayashi 
283a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_init(struct phy *phy)
284a1bf1c60SKunihiko Hayashi {
285a1bf1c60SKunihiko Hayashi 	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
286a1bf1c60SKunihiko Hayashi 	int ret;
287a1bf1c60SKunihiko Hayashi 
288*b1f9f454SKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk_parent_gio);
289a1bf1c60SKunihiko Hayashi 	if (ret)
290a1bf1c60SKunihiko Hayashi 		return ret;
291a1bf1c60SKunihiko Hayashi 
292*b1f9f454SKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk_parent);
293*b1f9f454SKunihiko Hayashi 	if (ret)
294*b1f9f454SKunihiko Hayashi 		goto out_clk_gio_disable;
295*b1f9f454SKunihiko Hayashi 
296*b1f9f454SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_parent_gio);
297a1bf1c60SKunihiko Hayashi 	if (ret)
298a1bf1c60SKunihiko Hayashi 		goto out_clk_disable;
299a1bf1c60SKunihiko Hayashi 
300*b1f9f454SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_parent);
301*b1f9f454SKunihiko Hayashi 	if (ret)
302*b1f9f454SKunihiko Hayashi 		goto out_rst_gio_assert;
303*b1f9f454SKunihiko Hayashi 
304a1bf1c60SKunihiko Hayashi 	if (priv->data->init) {
305a1bf1c60SKunihiko Hayashi 		ret = priv->data->init(priv);
306a1bf1c60SKunihiko Hayashi 		if (ret)
307a1bf1c60SKunihiko Hayashi 			goto out_rst_assert;
308a1bf1c60SKunihiko Hayashi 	}
309a1bf1c60SKunihiko Hayashi 
310a1bf1c60SKunihiko Hayashi 	return 0;
311a1bf1c60SKunihiko Hayashi 
312a1bf1c60SKunihiko Hayashi out_rst_assert:
313a1bf1c60SKunihiko Hayashi 	reset_control_assert(priv->rst_parent);
314*b1f9f454SKunihiko Hayashi out_rst_gio_assert:
315*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_parent_gio);
316a1bf1c60SKunihiko Hayashi out_clk_disable:
317a1bf1c60SKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent);
318*b1f9f454SKunihiko Hayashi out_clk_gio_disable:
319*b1f9f454SKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent_gio);
320a1bf1c60SKunihiko Hayashi 
321a1bf1c60SKunihiko Hayashi 	return ret;
322a1bf1c60SKunihiko Hayashi }
323a1bf1c60SKunihiko Hayashi 
324a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_exit(struct phy *phy)
325a1bf1c60SKunihiko Hayashi {
326a1bf1c60SKunihiko Hayashi 	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
327a1bf1c60SKunihiko Hayashi 
328a1bf1c60SKunihiko Hayashi 	reset_control_assert(priv->rst_parent);
329*b1f9f454SKunihiko Hayashi 	reset_control_assert(priv->rst_parent_gio);
330a1bf1c60SKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent);
331*b1f9f454SKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent_gio);
332a1bf1c60SKunihiko Hayashi 
333a1bf1c60SKunihiko Hayashi 	return 0;
334a1bf1c60SKunihiko Hayashi }
335a1bf1c60SKunihiko Hayashi 
336a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_power_on(struct phy *phy)
337a1bf1c60SKunihiko Hayashi {
338a1bf1c60SKunihiko Hayashi 	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
339a1bf1c60SKunihiko Hayashi 	int ret = 0;
340a1bf1c60SKunihiko Hayashi 
341a1bf1c60SKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk);
342a1bf1c60SKunihiko Hayashi 	if (ret)
343a1bf1c60SKunihiko Hayashi 		return ret;
344a1bf1c60SKunihiko Hayashi 
345a1bf1c60SKunihiko Hayashi 	ret = reset_control_deassert(priv->rst);
346a1bf1c60SKunihiko Hayashi 	if (ret)
347a1bf1c60SKunihiko Hayashi 		goto out_clk_disable;
348a1bf1c60SKunihiko Hayashi 
349a1bf1c60SKunihiko Hayashi 	if (priv->data->power_on) {
350a1bf1c60SKunihiko Hayashi 		ret = priv->data->power_on(priv);
351a1bf1c60SKunihiko Hayashi 		if (ret)
352a1bf1c60SKunihiko Hayashi 			goto out_reset_assert;
353a1bf1c60SKunihiko Hayashi 	}
354a1bf1c60SKunihiko Hayashi 
355a1bf1c60SKunihiko Hayashi 	return 0;
356a1bf1c60SKunihiko Hayashi 
357a1bf1c60SKunihiko Hayashi out_reset_assert:
358a1bf1c60SKunihiko Hayashi 	reset_control_assert(priv->rst);
359a1bf1c60SKunihiko Hayashi out_clk_disable:
360a1bf1c60SKunihiko Hayashi 	clk_disable_unprepare(priv->clk);
361a1bf1c60SKunihiko Hayashi 
362a1bf1c60SKunihiko Hayashi 	return ret;
363a1bf1c60SKunihiko Hayashi }
364a1bf1c60SKunihiko Hayashi 
365a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_power_off(struct phy *phy)
366a1bf1c60SKunihiko Hayashi {
367a1bf1c60SKunihiko Hayashi 	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
368a1bf1c60SKunihiko Hayashi 	int ret = 0;
369a1bf1c60SKunihiko Hayashi 
370a1bf1c60SKunihiko Hayashi 	if (priv->data->power_off)
371a1bf1c60SKunihiko Hayashi 		ret = priv->data->power_off(priv);
372a1bf1c60SKunihiko Hayashi 
373a1bf1c60SKunihiko Hayashi 	reset_control_assert(priv->rst);
374a1bf1c60SKunihiko Hayashi 	clk_disable_unprepare(priv->clk);
375a1bf1c60SKunihiko Hayashi 
376a1bf1c60SKunihiko Hayashi 	return ret;
377a1bf1c60SKunihiko Hayashi }
378a1bf1c60SKunihiko Hayashi 
379a1bf1c60SKunihiko Hayashi static const struct phy_ops uniphier_ahciphy_ops = {
380a1bf1c60SKunihiko Hayashi 	.init  = uniphier_ahciphy_init,
381a1bf1c60SKunihiko Hayashi 	.exit  = uniphier_ahciphy_exit,
382a1bf1c60SKunihiko Hayashi 	.power_on  = uniphier_ahciphy_power_on,
383a1bf1c60SKunihiko Hayashi 	.power_off = uniphier_ahciphy_power_off,
384a1bf1c60SKunihiko Hayashi 	.owner = THIS_MODULE,
385a1bf1c60SKunihiko Hayashi };
386a1bf1c60SKunihiko Hayashi 
387a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_probe(struct platform_device *pdev)
388a1bf1c60SKunihiko Hayashi {
389a1bf1c60SKunihiko Hayashi 	struct device *dev = &pdev->dev;
390a1bf1c60SKunihiko Hayashi 	struct uniphier_ahciphy_priv *priv;
391a1bf1c60SKunihiko Hayashi 	struct phy *phy;
392a1bf1c60SKunihiko Hayashi 	struct phy_provider *phy_provider;
393a1bf1c60SKunihiko Hayashi 
394a1bf1c60SKunihiko Hayashi 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
395a1bf1c60SKunihiko Hayashi 	if (!priv)
396a1bf1c60SKunihiko Hayashi 		return -ENOMEM;
397a1bf1c60SKunihiko Hayashi 
398a1bf1c60SKunihiko Hayashi 	priv->dev = dev;
399a1bf1c60SKunihiko Hayashi 	priv->data = of_device_get_match_data(dev);
400a1bf1c60SKunihiko Hayashi 	if (WARN_ON(!priv->data))
401a1bf1c60SKunihiko Hayashi 		return -EINVAL;
402a1bf1c60SKunihiko Hayashi 
403a1bf1c60SKunihiko Hayashi 	priv->base = devm_platform_ioremap_resource(pdev, 0);
404a1bf1c60SKunihiko Hayashi 	if (IS_ERR(priv->base))
405a1bf1c60SKunihiko Hayashi 		return PTR_ERR(priv->base);
406a1bf1c60SKunihiko Hayashi 
407a1bf1c60SKunihiko Hayashi 	priv->clk_parent = devm_clk_get(dev, "link");
408a1bf1c60SKunihiko Hayashi 	if (IS_ERR(priv->clk_parent))
409a1bf1c60SKunihiko Hayashi 		return PTR_ERR(priv->clk_parent);
410a1bf1c60SKunihiko Hayashi 
411a1bf1c60SKunihiko Hayashi 	if (priv->data->is_phy_clk) {
412a1bf1c60SKunihiko Hayashi 		priv->clk = devm_clk_get(dev, "phy");
413a1bf1c60SKunihiko Hayashi 		if (IS_ERR(priv->clk))
414a1bf1c60SKunihiko Hayashi 			return PTR_ERR(priv->clk);
415a1bf1c60SKunihiko Hayashi 	}
416a1bf1c60SKunihiko Hayashi 
417a1bf1c60SKunihiko Hayashi 	priv->rst_parent = devm_reset_control_get_shared(dev, "link");
418a1bf1c60SKunihiko Hayashi 	if (IS_ERR(priv->rst_parent))
419a1bf1c60SKunihiko Hayashi 		return PTR_ERR(priv->rst_parent);
420a1bf1c60SKunihiko Hayashi 
421a1bf1c60SKunihiko Hayashi 	priv->rst = devm_reset_control_get_shared(dev, "phy");
422a1bf1c60SKunihiko Hayashi 	if (IS_ERR(priv->rst))
423a1bf1c60SKunihiko Hayashi 		return PTR_ERR(priv->rst);
424a1bf1c60SKunihiko Hayashi 
425*b1f9f454SKunihiko Hayashi 	if (priv->data->is_legacy) {
426*b1f9f454SKunihiko Hayashi 		priv->clk_parent_gio = devm_clk_get(dev, "gio");
427*b1f9f454SKunihiko Hayashi 		if (IS_ERR(priv->clk_parent_gio))
428*b1f9f454SKunihiko Hayashi 			return PTR_ERR(priv->clk_parent_gio);
429*b1f9f454SKunihiko Hayashi 		priv->rst_parent_gio =
430*b1f9f454SKunihiko Hayashi 			devm_reset_control_get_shared(dev, "gio");
431*b1f9f454SKunihiko Hayashi 		if (IS_ERR(priv->rst_parent_gio))
432*b1f9f454SKunihiko Hayashi 			return PTR_ERR(priv->rst_parent_gio);
433*b1f9f454SKunihiko Hayashi 
434*b1f9f454SKunihiko Hayashi 		priv->rst_pm = devm_reset_control_get_shared(dev, "pm");
435*b1f9f454SKunihiko Hayashi 		if (IS_ERR(priv->rst_pm))
436*b1f9f454SKunihiko Hayashi 			return PTR_ERR(priv->rst_pm);
437*b1f9f454SKunihiko Hayashi 
438*b1f9f454SKunihiko Hayashi 		priv->rst_tx = devm_reset_control_get_shared(dev, "tx");
439*b1f9f454SKunihiko Hayashi 		if (IS_ERR(priv->rst_tx))
440*b1f9f454SKunihiko Hayashi 			return PTR_ERR(priv->rst_tx);
441*b1f9f454SKunihiko Hayashi 
442*b1f9f454SKunihiko Hayashi 		priv->rst_rx = devm_reset_control_get_shared(dev, "rx");
443*b1f9f454SKunihiko Hayashi 		if (IS_ERR(priv->rst_rx))
444*b1f9f454SKunihiko Hayashi 			return PTR_ERR(priv->rst_rx);
445*b1f9f454SKunihiko Hayashi 	}
446*b1f9f454SKunihiko Hayashi 
447a1bf1c60SKunihiko Hayashi 	phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops);
448a1bf1c60SKunihiko Hayashi 	if (IS_ERR(phy)) {
449a1bf1c60SKunihiko Hayashi 		dev_err(dev, "failed to create phy\n");
450a1bf1c60SKunihiko Hayashi 		return PTR_ERR(phy);
451a1bf1c60SKunihiko Hayashi 	}
452a1bf1c60SKunihiko Hayashi 
453a1bf1c60SKunihiko Hayashi 	phy_set_drvdata(phy, priv);
454a1bf1c60SKunihiko Hayashi 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
455a1bf1c60SKunihiko Hayashi 	if (IS_ERR(phy_provider))
456a1bf1c60SKunihiko Hayashi 		return PTR_ERR(phy_provider);
457a1bf1c60SKunihiko Hayashi 
458a1bf1c60SKunihiko Hayashi 	return 0;
459a1bf1c60SKunihiko Hayashi }
460a1bf1c60SKunihiko Hayashi 
461*b1f9f454SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pro4_data = {
462*b1f9f454SKunihiko Hayashi 	.init = uniphier_ahciphy_pro4_init,
463*b1f9f454SKunihiko Hayashi 	.power_on  = uniphier_ahciphy_pro4_power_on,
464*b1f9f454SKunihiko Hayashi 	.power_off = uniphier_ahciphy_pro4_power_off,
465*b1f9f454SKunihiko Hayashi 	.is_legacy = true,
466*b1f9f454SKunihiko Hayashi 	.is_phy_clk = false,
467*b1f9f454SKunihiko Hayashi };
468*b1f9f454SKunihiko Hayashi 
469a1bf1c60SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data = {
470a1bf1c60SKunihiko Hayashi 	.power_on  = uniphier_ahciphy_pxs2_power_on,
471a1bf1c60SKunihiko Hayashi 	.power_off = uniphier_ahciphy_pxs2_power_off,
472*b1f9f454SKunihiko Hayashi 	.is_legacy = false,
473a1bf1c60SKunihiko Hayashi 	.is_ready_high = false,
474a1bf1c60SKunihiko Hayashi 	.is_phy_clk = false,
475a1bf1c60SKunihiko Hayashi };
476a1bf1c60SKunihiko Hayashi 
477a1bf1c60SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data = {
478a1bf1c60SKunihiko Hayashi 	.init      = uniphier_ahciphy_pxs3_init,
479a1bf1c60SKunihiko Hayashi 	.power_on  = uniphier_ahciphy_pxs2_power_on,
480a1bf1c60SKunihiko Hayashi 	.power_off = uniphier_ahciphy_pxs2_power_off,
481*b1f9f454SKunihiko Hayashi 	.is_legacy = false,
482a1bf1c60SKunihiko Hayashi 	.is_ready_high = true,
483a1bf1c60SKunihiko Hayashi 	.is_phy_clk = true,
484a1bf1c60SKunihiko Hayashi };
485a1bf1c60SKunihiko Hayashi 
486a1bf1c60SKunihiko Hayashi static const struct of_device_id uniphier_ahciphy_match[] = {
487a1bf1c60SKunihiko Hayashi 	{
488*b1f9f454SKunihiko Hayashi 		.compatible = "socionext,uniphier-pro4-ahci-phy",
489*b1f9f454SKunihiko Hayashi 		.data = &uniphier_pro4_data,
490*b1f9f454SKunihiko Hayashi 	},
491*b1f9f454SKunihiko Hayashi 	{
492a1bf1c60SKunihiko Hayashi 		.compatible = "socionext,uniphier-pxs2-ahci-phy",
493a1bf1c60SKunihiko Hayashi 		.data = &uniphier_pxs2_data,
494a1bf1c60SKunihiko Hayashi 	},
495a1bf1c60SKunihiko Hayashi 	{
496a1bf1c60SKunihiko Hayashi 		.compatible = "socionext,uniphier-pxs3-ahci-phy",
497a1bf1c60SKunihiko Hayashi 		.data = &uniphier_pxs3_data,
498a1bf1c60SKunihiko Hayashi 	},
499a1bf1c60SKunihiko Hayashi 	{ /* Sentinel */ },
500a1bf1c60SKunihiko Hayashi };
501a1bf1c60SKunihiko Hayashi MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match);
502a1bf1c60SKunihiko Hayashi 
503a1bf1c60SKunihiko Hayashi static struct platform_driver uniphier_ahciphy_driver = {
504a1bf1c60SKunihiko Hayashi 	.probe = uniphier_ahciphy_probe,
505a1bf1c60SKunihiko Hayashi 	.driver = {
506a1bf1c60SKunihiko Hayashi 		.name = "uniphier-ahci-phy",
507a1bf1c60SKunihiko Hayashi 		.of_match_table = uniphier_ahciphy_match,
508a1bf1c60SKunihiko Hayashi 	},
509a1bf1c60SKunihiko Hayashi };
510a1bf1c60SKunihiko Hayashi module_platform_driver(uniphier_ahciphy_driver);
511a1bf1c60SKunihiko Hayashi 
512a1bf1c60SKunihiko Hayashi MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
513a1bf1c60SKunihiko Hayashi MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller");
514a1bf1c60SKunihiko Hayashi MODULE_LICENSE("GPL v2");
515