Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Intel Combo-PHY driver
  4 *
  5 * Copyright (C) 2019-2020 Intel Corporation.
  6 */
  7
  8#include <linux/bitfield.h>
  9#include <linux/clk.h>
 10#include <linux/iopoll.h>
 11#include <linux/mfd/syscon.h>
 12#include <linux/module.h>
 13#include <linux/mutex.h>
 14#include <linux/of.h>
 15#include <linux/phy/phy.h>
 16#include <linux/platform_device.h>
 17#include <linux/regmap.h>
 18#include <linux/reset.h>
 19
 20#include <dt-bindings/phy/phy.h>
 21
 22#define PCIE_PHY_GEN_CTRL	0x00
 23#define PCIE_PHY_CLK_PAD	BIT(17)
 24
 25#define PAD_DIS_CFG		0x174
 26
 27#define PCS_XF_ATE_OVRD_IN_2	0x3008
 28#define ADAPT_REQ_MSK		GENMASK(5, 4)
 29
 30#define PCS_XF_RX_ADAPT_ACK	0x3010
 31#define RX_ADAPT_ACK_BIT	BIT(0)
 32
 33#define CR_ADDR(addr, lane)	(((addr) + (lane) * 0x100) << 2)
 34#define REG_COMBO_MODE(x)	((x) * 0x200)
 35#define REG_CLK_DISABLE(x)	((x) * 0x200 + 0x124)
 36
 37#define COMBO_PHY_ID(x)		((x)->parent->id)
 38#define PHY_ID(x)		((x)->id)
 39
 40#define CLK_100MHZ		100000000
 41#define CLK_156_25MHZ		156250000
 42
 43static const unsigned long intel_iphy_clk_rates[] = {
 44	CLK_100MHZ, CLK_156_25MHZ, CLK_100MHZ,
 45};
 46
 47enum {
 48	PHY_0,
 49	PHY_1,
 50	PHY_MAX_NUM
 51};
 52
 53/*
 54 * Clock Register bit fields to enable clocks
 55 * for ComboPhy according to the mode.
 56 */
 57enum intel_phy_mode {
 58	PHY_PCIE_MODE = 0,
 59	PHY_XPCS_MODE,
 60	PHY_SATA_MODE,
 61};
 62
 63/* ComboPhy mode Register values */
 64enum intel_combo_mode {
 65	PCIE0_PCIE1_MODE = 0,
 66	PCIE_DL_MODE,
 67	RXAUI_MODE,
 68	XPCS0_XPCS1_MODE,
 69	SATA0_SATA1_MODE,
 70};
 71
 72enum aggregated_mode {
 73	PHY_SL_MODE,
 74	PHY_DL_MODE,
 75};
 76
 77struct intel_combo_phy;
 78
 79struct intel_cbphy_iphy {
 80	struct phy		*phy;
 81	struct intel_combo_phy	*parent;
 82	struct reset_control	*app_rst;
 83	u32			id;
 84};
 85
 86struct intel_combo_phy {
 87	struct device		*dev;
 88	struct clk		*core_clk;
 89	unsigned long		clk_rate;
 90	void __iomem		*app_base;
 91	void __iomem		*cr_base;
 92	struct regmap		*syscfg;
 93	struct regmap		*hsiocfg;
 94	u32			id;
 95	u32			bid;
 96	struct reset_control	*phy_rst;
 97	struct reset_control	*core_rst;
 98	struct intel_cbphy_iphy	iphy[PHY_MAX_NUM];
 99	enum intel_phy_mode	phy_mode;
100	enum aggregated_mode	aggr_mode;
101	u32			init_cnt;
102	struct mutex		lock;
103};
104
105static int intel_cbphy_iphy_enable(struct intel_cbphy_iphy *iphy, bool set)
106{
107	struct intel_combo_phy *cbphy = iphy->parent;
108	u32 mask = BIT(cbphy->phy_mode * 2 + iphy->id);
109	u32 val;
110
111	/* Register: 0 is enable, 1 is disable */
112	val = set ? 0 : mask;
113
114	return regmap_update_bits(cbphy->hsiocfg, REG_CLK_DISABLE(cbphy->bid),
115				  mask, val);
116}
117
118static int intel_cbphy_pcie_refclk_cfg(struct intel_cbphy_iphy *iphy, bool set)
119{
120	struct intel_combo_phy *cbphy = iphy->parent;
121	u32 mask = BIT(cbphy->id * 2 + iphy->id);
122	u32 val;
123
124	/* Register: 0 is enable, 1 is disable */
125	val = set ? 0 : mask;
126
127	return regmap_update_bits(cbphy->syscfg, PAD_DIS_CFG, mask, val);
128}
129
130static inline void combo_phy_w32_off_mask(void __iomem *base, unsigned int reg,
131					  u32 mask, u32 val)
132{
133	u32 reg_val;
134
135	reg_val = readl(base + reg);
136	reg_val &= ~mask;
137	reg_val |= val;
138	writel(reg_val, base + reg);
139}
140
141static int intel_cbphy_iphy_cfg(struct intel_cbphy_iphy *iphy,
142				int (*phy_cfg)(struct intel_cbphy_iphy *))
143{
144	struct intel_combo_phy *cbphy = iphy->parent;
145	int ret;
146
147	ret = phy_cfg(iphy);
148	if (ret)
149		return ret;
150
151	if (cbphy->aggr_mode != PHY_DL_MODE)
152		return 0;
153
154	return phy_cfg(&cbphy->iphy[PHY_1]);
155}
156
157static int intel_cbphy_pcie_en_pad_refclk(struct intel_cbphy_iphy *iphy)
158{
159	struct intel_combo_phy *cbphy = iphy->parent;
160	int ret;
161
162	ret = intel_cbphy_pcie_refclk_cfg(iphy, true);
163	if (ret) {
164		dev_err(cbphy->dev, "Failed to enable PCIe pad refclk\n");
165		return ret;
166	}
167
168	if (cbphy->init_cnt)
169		return 0;
170
171	combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
172			       PCIE_PHY_CLK_PAD, FIELD_PREP(PCIE_PHY_CLK_PAD, 0));
173
174	/* Delay for stable clock PLL */
175	usleep_range(50, 100);
176
177	return 0;
178}
179
180static int intel_cbphy_pcie_dis_pad_refclk(struct intel_cbphy_iphy *iphy)
181{
182	struct intel_combo_phy *cbphy = iphy->parent;
183	int ret;
184
185	ret = intel_cbphy_pcie_refclk_cfg(iphy, false);
186	if (ret) {
187		dev_err(cbphy->dev, "Failed to disable PCIe pad refclk\n");
188		return ret;
189	}
190
191	if (cbphy->init_cnt)
192		return 0;
193
194	combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
195			       PCIE_PHY_CLK_PAD, FIELD_PREP(PCIE_PHY_CLK_PAD, 1));
196
197	return 0;
198}
199
200static int intel_cbphy_set_mode(struct intel_combo_phy *cbphy)
201{
202	enum intel_combo_mode cb_mode;
203	enum aggregated_mode aggr = cbphy->aggr_mode;
204	struct device *dev = cbphy->dev;
205	enum intel_phy_mode mode;
206	int ret;
207
208	mode = cbphy->phy_mode;
209
210	switch (mode) {
211	case PHY_PCIE_MODE:
212		cb_mode = (aggr == PHY_DL_MODE) ? PCIE_DL_MODE : PCIE0_PCIE1_MODE;
213		break;
214
215	case PHY_XPCS_MODE:
216		cb_mode = (aggr == PHY_DL_MODE) ? RXAUI_MODE : XPCS0_XPCS1_MODE;
217		break;
218
219	case PHY_SATA_MODE:
220		if (aggr == PHY_DL_MODE) {
221			dev_err(dev, "Mode:%u not support dual lane!\n", mode);
222			return -EINVAL;
223		}
224
225		cb_mode = SATA0_SATA1_MODE;
226		break;
227	default:
228		return -EINVAL;
229	}
230
231	ret = regmap_write(cbphy->hsiocfg, REG_COMBO_MODE(cbphy->bid), cb_mode);
232	if (ret)
233		dev_err(dev, "Failed to set ComboPhy mode: %d\n", ret);
234
235	return ret;
236}
237
238static void intel_cbphy_rst_assert(struct intel_combo_phy *cbphy)
239{
240	reset_control_assert(cbphy->core_rst);
241	reset_control_assert(cbphy->phy_rst);
242}
243
244static void intel_cbphy_rst_deassert(struct intel_combo_phy *cbphy)
245{
246	reset_control_deassert(cbphy->core_rst);
247	reset_control_deassert(cbphy->phy_rst);
248	/* Delay to ensure reset process is done */
249	usleep_range(10, 20);
250}
251
252static int intel_cbphy_iphy_power_on(struct intel_cbphy_iphy *iphy)
253{
254	struct intel_combo_phy *cbphy = iphy->parent;
255	int ret;
256
257	if (!cbphy->init_cnt) {
258		ret = clk_prepare_enable(cbphy->core_clk);
259		if (ret) {
260			dev_err(cbphy->dev, "Clock enable failed!\n");
261			return ret;
262		}
263
264		ret = clk_set_rate(cbphy->core_clk, cbphy->clk_rate);
265		if (ret) {
266			dev_err(cbphy->dev, "Clock freq set to %lu failed!\n",
267				cbphy->clk_rate);
268			goto clk_err;
269		}
270
271		intel_cbphy_rst_assert(cbphy);
272		intel_cbphy_rst_deassert(cbphy);
273		ret = intel_cbphy_set_mode(cbphy);
274		if (ret)
275			goto clk_err;
276	}
277
278	ret = intel_cbphy_iphy_enable(iphy, true);
279	if (ret) {
280		dev_err(cbphy->dev, "Failed enabling PHY core\n");
281		goto clk_err;
282	}
283
284	ret = reset_control_deassert(iphy->app_rst);
285	if (ret) {
286		dev_err(cbphy->dev, "PHY(%u:%u) reset deassert failed!\n",
287			COMBO_PHY_ID(iphy), PHY_ID(iphy));
288		goto clk_err;
289	}
290
291	/* Delay to ensure reset process is done */
292	udelay(1);
293
294	return 0;
295
296clk_err:
297	clk_disable_unprepare(cbphy->core_clk);
298
299	return ret;
300}
301
302static int intel_cbphy_iphy_power_off(struct intel_cbphy_iphy *iphy)
303{
304	struct intel_combo_phy *cbphy = iphy->parent;
305	int ret;
306
307	ret = reset_control_assert(iphy->app_rst);
308	if (ret) {
309		dev_err(cbphy->dev, "PHY(%u:%u) reset assert failed!\n",
310			COMBO_PHY_ID(iphy), PHY_ID(iphy));
311		return ret;
312	}
313
314	ret = intel_cbphy_iphy_enable(iphy, false);
315	if (ret) {
316		dev_err(cbphy->dev, "Failed disabling PHY core\n");
317		return ret;
318	}
319
320	if (cbphy->init_cnt)
321		return 0;
322
323	clk_disable_unprepare(cbphy->core_clk);
324	intel_cbphy_rst_assert(cbphy);
325
326	return 0;
327}
328
329static int intel_cbphy_init(struct phy *phy)
330{
331	struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
332	struct intel_combo_phy *cbphy = iphy->parent;
333	int ret;
334
335	mutex_lock(&cbphy->lock);
336	ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_iphy_power_on);
337	if (ret)
338		goto err;
339
340	if (cbphy->phy_mode == PHY_PCIE_MODE) {
341		ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_pcie_en_pad_refclk);
342		if (ret)
343			goto err;
344	}
345
346	cbphy->init_cnt++;
347
348err:
349	mutex_unlock(&cbphy->lock);
350
351	return ret;
352}
353
354static int intel_cbphy_exit(struct phy *phy)
355{
356	struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
357	struct intel_combo_phy *cbphy = iphy->parent;
358	int ret;
359
360	mutex_lock(&cbphy->lock);
361	cbphy->init_cnt--;
362	if (cbphy->phy_mode == PHY_PCIE_MODE) {
363		ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_pcie_dis_pad_refclk);
364		if (ret)
365			goto err;
366	}
367
368	ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_iphy_power_off);
369
370err:
371	mutex_unlock(&cbphy->lock);
372
373	return ret;
374}
375
376static int intel_cbphy_calibrate(struct phy *phy)
377{
378	struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
379	struct intel_combo_phy *cbphy = iphy->parent;
380	void __iomem *cr_base = cbphy->cr_base;
381	int val, ret, id;
382
383	if (cbphy->phy_mode != PHY_XPCS_MODE)
384		return 0;
385
386	id = PHY_ID(iphy);
387
388	/* trigger auto RX adaptation */
389	combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
390			       ADAPT_REQ_MSK, FIELD_PREP(ADAPT_REQ_MSK, 3));
391	/* Wait RX adaptation to finish */
392	ret = readl_poll_timeout(cr_base + CR_ADDR(PCS_XF_RX_ADAPT_ACK, id),
393				 val, val & RX_ADAPT_ACK_BIT, 10, 5000);
394	if (ret)
395		dev_err(cbphy->dev, "RX Adaptation failed!\n");
396	else
397		dev_dbg(cbphy->dev, "RX Adaptation success!\n");
398
399	/* Stop RX adaptation */
400	combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
401			       ADAPT_REQ_MSK, FIELD_PREP(ADAPT_REQ_MSK, 0));
402
403	return ret;
404}
405
406static int intel_cbphy_fwnode_parse(struct intel_combo_phy *cbphy)
407{
408	struct device *dev = cbphy->dev;
409	struct platform_device *pdev = to_platform_device(dev);
410	struct fwnode_handle *fwnode = dev_fwnode(dev);
411	struct fwnode_reference_args ref;
412	int ret;
413	u32 val;
414
415	cbphy->core_clk = devm_clk_get(dev, NULL);
416	if (IS_ERR(cbphy->core_clk)) {
417		ret = PTR_ERR(cbphy->core_clk);
418		if (ret != -EPROBE_DEFER)
419			dev_err(dev, "Get clk failed:%d!\n", ret);
420		return ret;
421	}
422
423	cbphy->core_rst = devm_reset_control_get_optional(dev, "core");
424	if (IS_ERR(cbphy->core_rst)) {
425		ret = PTR_ERR(cbphy->core_rst);
426		if (ret != -EPROBE_DEFER)
427			dev_err(dev, "Get core reset control err: %d!\n", ret);
428		return ret;
429	}
430
431	cbphy->phy_rst = devm_reset_control_get_optional(dev, "phy");
432	if (IS_ERR(cbphy->phy_rst)) {
433		ret = PTR_ERR(cbphy->phy_rst);
434		if (ret != -EPROBE_DEFER)
435			dev_err(dev, "Get PHY reset control err: %d!\n", ret);
436		return ret;
437	}
438
439	cbphy->iphy[0].app_rst = devm_reset_control_get_optional(dev, "iphy0");
440	if (IS_ERR(cbphy->iphy[0].app_rst)) {
441		ret = PTR_ERR(cbphy->iphy[0].app_rst);
442		if (ret != -EPROBE_DEFER)
443			dev_err(dev, "Get phy0 reset control err: %d!\n", ret);
444		return ret;
445	}
446
447	cbphy->iphy[1].app_rst = devm_reset_control_get_optional(dev, "iphy1");
448	if (IS_ERR(cbphy->iphy[1].app_rst)) {
449		ret = PTR_ERR(cbphy->iphy[1].app_rst);
450		if (ret != -EPROBE_DEFER)
451			dev_err(dev, "Get phy1 reset control err: %d!\n", ret);
452		return ret;
453	}
454
455	cbphy->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
456	if (IS_ERR(cbphy->app_base))
457		return PTR_ERR(cbphy->app_base);
458
459	cbphy->cr_base = devm_platform_ioremap_resource_byname(pdev, "core");
460	if (IS_ERR(cbphy->cr_base))
461		return PTR_ERR(cbphy->cr_base);
462
463	/*
464	 * syscfg and hsiocfg variables stores the handle of the registers set
465	 * in which ComboPhy subsytem specific registers are subset. Using
466	 * Register map framework to access the registers set.
467	 */
468	ret = fwnode_property_get_reference_args(fwnode, "intel,syscfg", NULL,
469						 1, 0, &ref);
470	if (ret < 0)
471		return ret;
472
473	cbphy->id = ref.args[0];
474	cbphy->syscfg = device_node_to_regmap(to_of_node(ref.fwnode));
475	fwnode_handle_put(ref.fwnode);
476
477	ret = fwnode_property_get_reference_args(fwnode, "intel,hsio", NULL, 1,
478						 0, &ref);
479	if (ret < 0)
480		return ret;
481
482	cbphy->bid = ref.args[0];
483	cbphy->hsiocfg = device_node_to_regmap(to_of_node(ref.fwnode));
484	fwnode_handle_put(ref.fwnode);
485
486	ret = fwnode_property_read_u32_array(fwnode, "intel,phy-mode", &val, 1);
487	if (ret)
488		return ret;
489
490	switch (val) {
491	case PHY_TYPE_PCIE:
492		cbphy->phy_mode = PHY_PCIE_MODE;
493		break;
494
495	case PHY_TYPE_SATA:
496		cbphy->phy_mode = PHY_SATA_MODE;
497		break;
498
499	case PHY_TYPE_XPCS:
500		cbphy->phy_mode = PHY_XPCS_MODE;
501		break;
502
503	default:
504		dev_err(dev, "Invalid PHY mode: %u\n", val);
505		return -EINVAL;
506	}
507
508	cbphy->clk_rate = intel_iphy_clk_rates[cbphy->phy_mode];
509
510	if (fwnode_property_present(fwnode, "intel,aggregation"))
511		cbphy->aggr_mode = PHY_DL_MODE;
512	else
513		cbphy->aggr_mode = PHY_SL_MODE;
514
515	return 0;
516}
517
518static const struct phy_ops intel_cbphy_ops = {
519	.init		= intel_cbphy_init,
520	.exit		= intel_cbphy_exit,
521	.calibrate	= intel_cbphy_calibrate,
522	.owner		= THIS_MODULE,
523};
524
525static struct phy *intel_cbphy_xlate(struct device *dev,
526				     struct of_phandle_args *args)
527{
528	struct intel_combo_phy *cbphy = dev_get_drvdata(dev);
529	u32 iphy_id;
530
531	if (args->args_count < 1) {
532		dev_err(dev, "Invalid number of arguments\n");
533		return ERR_PTR(-EINVAL);
534	}
535
536	iphy_id = args->args[0];
537	if (iphy_id >= PHY_MAX_NUM) {
538		dev_err(dev, "Invalid phy instance %d\n", iphy_id);
539		return ERR_PTR(-EINVAL);
540	}
541
542	if (cbphy->aggr_mode == PHY_DL_MODE && iphy_id == PHY_1) {
543		dev_err(dev, "Invalid. ComboPhy is in Dual lane mode %d\n", iphy_id);
544		return ERR_PTR(-EINVAL);
545	}
546
547	return cbphy->iphy[iphy_id].phy;
548}
549
550static int intel_cbphy_create(struct intel_combo_phy *cbphy)
551{
552	struct phy_provider *phy_provider;
553	struct device *dev = cbphy->dev;
554	struct intel_cbphy_iphy *iphy;
555	int i;
556
557	for (i = 0; i < PHY_MAX_NUM; i++) {
558		iphy = &cbphy->iphy[i];
559		iphy->parent = cbphy;
560		iphy->id = i;
561
562		/* In dual lane mode skip phy creation for the second phy */
563		if (cbphy->aggr_mode == PHY_DL_MODE && iphy->id == PHY_1)
564			continue;
565
566		iphy->phy = devm_phy_create(dev, NULL, &intel_cbphy_ops);
567		if (IS_ERR(iphy->phy)) {
568			dev_err(dev, "PHY[%u:%u]: create PHY instance failed!\n",
569				COMBO_PHY_ID(iphy), PHY_ID(iphy));
570
571			return PTR_ERR(iphy->phy);
572		}
573
574		phy_set_drvdata(iphy->phy, iphy);
575	}
576
577	dev_set_drvdata(dev, cbphy);
578	phy_provider = devm_of_phy_provider_register(dev, intel_cbphy_xlate);
579	if (IS_ERR(phy_provider))
580		dev_err(dev, "Register PHY provider failed!\n");
581
582	return PTR_ERR_OR_ZERO(phy_provider);
583}
584
585static int intel_cbphy_probe(struct platform_device *pdev)
586{
587	struct device *dev = &pdev->dev;
588	struct intel_combo_phy *cbphy;
589	int ret;
590
591	cbphy = devm_kzalloc(dev, sizeof(*cbphy), GFP_KERNEL);
592	if (!cbphy)
593		return -ENOMEM;
594
595	cbphy->dev = dev;
596	cbphy->init_cnt = 0;
597	mutex_init(&cbphy->lock);
598	ret = intel_cbphy_fwnode_parse(cbphy);
599	if (ret)
600		return ret;
601
602	platform_set_drvdata(pdev, cbphy);
603
604	return intel_cbphy_create(cbphy);
605}
606
607static int intel_cbphy_remove(struct platform_device *pdev)
608{
609	struct intel_combo_phy *cbphy = platform_get_drvdata(pdev);
610
611	intel_cbphy_rst_assert(cbphy);
612	clk_disable_unprepare(cbphy->core_clk);
613	return 0;
614}
615
616static const struct of_device_id of_intel_cbphy_match[] = {
617	{ .compatible = "intel,combo-phy" },
618	{ .compatible = "intel,combophy-lgm" },
619	{}
620};
621
622static struct platform_driver intel_cbphy_driver = {
623	.probe = intel_cbphy_probe,
624	.remove = intel_cbphy_remove,
625	.driver = {
626		.name = "intel-combo-phy",
627		.of_match_table = of_intel_cbphy_match,
628	}
629};
630
631module_platform_driver(intel_cbphy_driver);
632
633MODULE_DESCRIPTION("Intel Combo-phy driver");
634MODULE_LICENSE("GPL v2");