1// SPDX-License-Identifier: GPL-2.0
2/*
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>
6 */
7
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>
13#include <linux/of.h>
14#include <linux/of_platform.h>
15#include <linux/phy/phy.h>
16#include <linux/platform_device.h>
17#include <linux/reset.h>
18
19struct uniphier_ahciphy_priv {
20	struct device *dev;
21	void __iomem  *base;
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;
26};
27
28struct 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);
32	bool is_legacy;
33	bool is_ready_high;
34	bool is_phy_clk;
35};
36
37/* for Pro4 */
38#define CKCTRL0				0x0
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)
43#define CKCTRL1				0x4
44#define CKCTRL1_LOS_LVL_MASK		GENMASK(20, 16)
45#define CKCTRL1_TX_LVL_MASK		GENMASK(12, 8)
46#define RXTXCTRL			0x8
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)
53#define RSTPWR				0x30
54#define RSTPWR_RX_EN_VAL		BIT(18)
55
56/* for PXs2/PXs3 */
57#define CKCTRL				0x0
58#define CKCTRL_P0_READY			BIT(15)
59#define CKCTRL_P0_RESET			BIT(10)
60#define CKCTRL_REF_SSP_EN		BIT(9)
61#define TXCTRL0				0x4
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)
65#define TXCTRL1				0x8
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)
69#define RXCTRL				0xc
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)
73
74static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv *priv)
75{
76	u32 val;
77
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);
87
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);
95
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);
108
109	return 0;
110}
111
112static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv *priv)
113{
114	u32 val;
115	int ret;
116
117	/* enable reference clock for phy */
118	val = readl(priv->base + CKCTRL0);
119	val &= ~CKCTRL0_CK_OFF;
120	writel(val, priv->base + CKCTRL0);
121
122	/* enable TX clock */
123	val = readl(priv->base + RXTXCTRL);
124	val |= RXTXCTRL_TX_CKO_EN;
125	writel(val, priv->base + RXTXCTRL);
126
127	/* wait until RX is ready */
128	ret = readl_poll_timeout(priv->base + RSTPWR, val,
129				 !(val & RSTPWR_RX_EN_VAL), 200, 2000);
130	if (ret) {
131		dev_err(priv->dev, "Failed to check whether Rx is ready\n");
132		goto out_disable_clock;
133	}
134
135	/* release all reset */
136	ret = reset_control_deassert(priv->rst_pm);
137	if (ret) {
138		dev_err(priv->dev, "Failed to release PM reset\n");
139		goto out_disable_clock;
140	}
141
142	ret = reset_control_deassert(priv->rst_tx);
143	if (ret) {
144		dev_err(priv->dev, "Failed to release Tx reset\n");
145		goto out_reset_pm_assert;
146	}
147
148	ret = reset_control_deassert(priv->rst_rx);
149	if (ret) {
150		dev_err(priv->dev, "Failed to release Rx reset\n");
151		goto out_reset_tx_assert;
152	}
153
154	return 0;
155
156out_reset_tx_assert:
157	reset_control_assert(priv->rst_tx);
158out_reset_pm_assert:
159	reset_control_assert(priv->rst_pm);
160
161out_disable_clock:
162	/* disable TX clock */
163	val = readl(priv->base + RXTXCTRL);
164	val &= ~RXTXCTRL_TX_CKO_EN;
165	writel(val, priv->base + RXTXCTRL);
166
167	/* disable reference clock for phy */
168	val = readl(priv->base + CKCTRL0);
169	val |= CKCTRL0_CK_OFF;
170	writel(val, priv->base + CKCTRL0);
171
172	return ret;
173}
174
175static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv *priv)
176{
177	u32 val;
178
179	reset_control_assert(priv->rst_rx);
180	reset_control_assert(priv->rst_tx);
181	reset_control_assert(priv->rst_pm);
182
183	/* disable TX clock */
184	val = readl(priv->base + RXTXCTRL);
185	val &= ~RXTXCTRL_TX_CKO_EN;
186	writel(val, priv->base + RXTXCTRL);
187
188	/* disable reference clock for phy */
189	val = readl(priv->base + CKCTRL0);
190	val |= CKCTRL0_CK_OFF;
191	writel(val, priv->base + CKCTRL0);
192
193	return 0;
194}
195
196static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv,
197					 bool enable)
198{
199	u32 val;
200
201	val = readl(priv->base + CKCTRL);
202
203	if (enable) {
204		val |= CKCTRL_REF_SSP_EN;
205		writel(val, priv->base + CKCTRL);
206		val &= ~CKCTRL_P0_RESET;
207		writel(val, priv->base + CKCTRL);
208	} else {
209		val |= CKCTRL_P0_RESET;
210		writel(val, priv->base + CKCTRL);
211		val &= ~CKCTRL_REF_SSP_EN;
212		writel(val, priv->base + CKCTRL);
213	}
214}
215
216static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv)
217{
218	int ret;
219	u32 val;
220
221	uniphier_ahciphy_pxs2_enable(priv, true);
222
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);
227	else
228		ret = readl_poll_timeout(priv->base + CKCTRL, val,
229					 !(val & CKCTRL_P0_READY), 200, 400);
230	if (ret) {
231		dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n");
232		uniphier_ahciphy_pxs2_enable(priv, false);
233	}
234
235	return ret;
236}
237
238static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv)
239{
240	uniphier_ahciphy_pxs2_enable(priv, false);
241
242	return 0;
243}
244
245static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv)
246{
247	int i;
248	u32 val;
249
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);
259
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);
267
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);
275
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);
279
280	return 0;
281}
282
283static int uniphier_ahciphy_init(struct phy *phy)
284{
285	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
286	int ret;
287
288	ret = clk_prepare_enable(priv->clk_parent_gio);
289	if (ret)
290		return ret;
291
292	ret = clk_prepare_enable(priv->clk_parent);
293	if (ret)
294		goto out_clk_gio_disable;
295
296	ret = reset_control_deassert(priv->rst_parent_gio);
297	if (ret)
298		goto out_clk_disable;
299
300	ret = reset_control_deassert(priv->rst_parent);
301	if (ret)
302		goto out_rst_gio_assert;
303
304	if (priv->data->init) {
305		ret = priv->data->init(priv);
306		if (ret)
307			goto out_rst_assert;
308	}
309
310	return 0;
311
312out_rst_assert:
313	reset_control_assert(priv->rst_parent);
314out_rst_gio_assert:
315	reset_control_assert(priv->rst_parent_gio);
316out_clk_disable:
317	clk_disable_unprepare(priv->clk_parent);
318out_clk_gio_disable:
319	clk_disable_unprepare(priv->clk_parent_gio);
320
321	return ret;
322}
323
324static int uniphier_ahciphy_exit(struct phy *phy)
325{
326	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
327
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);
332
333	return 0;
334}
335
336static int uniphier_ahciphy_power_on(struct phy *phy)
337{
338	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
339	int ret = 0;
340
341	ret = clk_prepare_enable(priv->clk);
342	if (ret)
343		return ret;
344
345	ret = reset_control_deassert(priv->rst);
346	if (ret)
347		goto out_clk_disable;
348
349	if (priv->data->power_on) {
350		ret = priv->data->power_on(priv);
351		if (ret)
352			goto out_reset_assert;
353	}
354
355	return 0;
356
357out_reset_assert:
358	reset_control_assert(priv->rst);
359out_clk_disable:
360	clk_disable_unprepare(priv->clk);
361
362	return ret;
363}
364
365static int uniphier_ahciphy_power_off(struct phy *phy)
366{
367	struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
368	int ret = 0;
369
370	if (priv->data->power_off)
371		ret = priv->data->power_off(priv);
372
373	reset_control_assert(priv->rst);
374	clk_disable_unprepare(priv->clk);
375
376	return ret;
377}
378
379static 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,
385};
386
387static int uniphier_ahciphy_probe(struct platform_device *pdev)
388{
389	struct device *dev = &pdev->dev;
390	struct uniphier_ahciphy_priv *priv;
391	struct phy *phy;
392	struct phy_provider *phy_provider;
393
394	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
395	if (!priv)
396		return -ENOMEM;
397
398	priv->dev = dev;
399	priv->data = of_device_get_match_data(dev);
400	if (WARN_ON(!priv->data))
401		return -EINVAL;
402
403	priv->base = devm_platform_ioremap_resource(pdev, 0);
404	if (IS_ERR(priv->base))
405		return PTR_ERR(priv->base);
406
407	priv->clk_parent = devm_clk_get(dev, "link");
408	if (IS_ERR(priv->clk_parent))
409		return PTR_ERR(priv->clk_parent);
410
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);
415	}
416
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);
420
421	priv->rst = devm_reset_control_get_shared(dev, "phy");
422	if (IS_ERR(priv->rst))
423		return PTR_ERR(priv->rst);
424
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);
433
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);
437
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);
441
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);
445	}
446
447	phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops);
448	if (IS_ERR(phy)) {
449		dev_err(dev, "failed to create phy\n");
450		return PTR_ERR(phy);
451	}
452
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);
457
458	return 0;
459}
460
461static 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,
465	.is_legacy = true,
466	.is_phy_clk = false,
467};
468
469static 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,
472	.is_legacy = false,
473	.is_ready_high = false,
474	.is_phy_clk = false,
475};
476
477static 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,
481	.is_legacy = false,
482	.is_ready_high = true,
483	.is_phy_clk = true,
484};
485
486static const struct of_device_id uniphier_ahciphy_match[] = {
487	{
488		.compatible = "socionext,uniphier-pro4-ahci-phy",
489		.data = &uniphier_pro4_data,
490	},
491	{
492		.compatible = "socionext,uniphier-pxs2-ahci-phy",
493		.data = &uniphier_pxs2_data,
494	},
495	{
496		.compatible = "socionext,uniphier-pxs3-ahci-phy",
497		.data = &uniphier_pxs3_data,
498	},
499	{ /* Sentinel */ },
500};
501MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match);
502
503static struct platform_driver uniphier_ahciphy_driver = {
504	.probe = uniphier_ahciphy_probe,
505	.driver = {
506		.name = "uniphier-ahci-phy",
507		.of_match_table = uniphier_ahciphy_match,
508	},
509};
510module_platform_driver(uniphier_ahciphy_driver);
511
512MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
513MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller");
514MODULE_LICENSE("GPL v2");
515