brintos

brintos / linux-shallow public Read only

0
0
Text · 32.9 KiB · 43cef89 Raw
1256 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2014 STMicroelectronics4 *5 * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).6 *7 * Author: Alexandre Torgue <alexandre.torgue@st.com>8 */9 10#include <linux/platform_device.h>11#include <linux/io.h>12#include <linux/iopoll.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/of_platform.h>17#include <linux/of_address.h>18#include <linux/clk.h>19#include <linux/phy/phy.h>20#include <linux/delay.h>21#include <linux/mfd/syscon.h>22#include <linux/regmap.h>23#include <linux/reset.h>24 25#include <dt-bindings/phy/phy.h>26 27/* MiPHY registers */28#define MIPHY_CONF_RESET		0x0029#define RST_APPLI_SW		BIT(0)30#define RST_CONF_SW		BIT(1)31#define RST_MACRO_SW		BIT(2)32 33#define MIPHY_RESET			0x0134#define RST_PLL_SW		BIT(0)35#define RST_COMP_SW		BIT(2)36 37#define MIPHY_STATUS_1			0x0238#define PHY_RDY			BIT(0)39#define HFC_RDY			BIT(1)40#define HFC_PLL			BIT(2)41 42#define MIPHY_CONTROL			0x0443#define TERM_EN_SW		BIT(2)44#define DIS_LINK_RST		BIT(3)45#define AUTO_RST_RX		BIT(4)46#define PX_RX_POL		BIT(5)47 48#define MIPHY_BOUNDARY_SEL		0x0a49#define TX_SEL			BIT(6)50#define SSC_SEL			BIT(4)51#define GENSEL_SEL		BIT(0)52 53#define MIPHY_BOUNDARY_1		0x0b54#define MIPHY_BOUNDARY_2		0x0c55#define SSC_EN_SW		BIT(2)56 57#define MIPHY_PLL_CLKREF_FREQ		0x0d58#define MIPHY_SPEED			0x0e59#define TX_SPDSEL_80DEC		060#define TX_SPDSEL_40DEC		161#define TX_SPDSEL_20DEC		262#define RX_SPDSEL_80DEC		063#define RX_SPDSEL_40DEC		(1 << 2)64#define RX_SPDSEL_20DEC		(2 << 2)65 66#define MIPHY_CONF			0x0f67#define MIPHY_CTRL_TEST_SEL		0x2068#define MIPHY_CTRL_TEST_1		0x2169#define MIPHY_CTRL_TEST_2		0x2270#define MIPHY_CTRL_TEST_3		0x2371#define MIPHY_CTRL_TEST_4		0x2472#define MIPHY_FEEDBACK_TEST		0x2573#define MIPHY_DEBUG_BUS			0x2674#define MIPHY_DEBUG_STATUS_MSB		0x2775#define MIPHY_DEBUG_STATUS_LSB		0x2876#define MIPHY_PWR_RAIL_1		0x2977#define MIPHY_PWR_RAIL_2		0x2a78#define MIPHY_SYNCHAR_CONTROL		0x3079 80#define MIPHY_COMP_FSM_1		0x3a81#define COMP_START		BIT(6)82 83#define MIPHY_COMP_FSM_6		0x3f84#define COMP_DONE		BIT(7)85 86#define MIPHY_COMP_POSTP		0x4287#define MIPHY_TX_CTRL_1			0x4988#define TX_REG_STEP_0V		089#define TX_REG_STEP_P_25MV	190#define TX_REG_STEP_P_50MV	291#define TX_REG_STEP_N_25MV	792#define TX_REG_STEP_N_50MV	693#define TX_REG_STEP_N_75MV	594 95#define MIPHY_TX_CTRL_2			0x4a96#define TX_SLEW_SW_40_PS	097#define TX_SLEW_SW_80_PS	198#define TX_SLEW_SW_120_PS	299 100#define MIPHY_TX_CTRL_3			0x4b101#define MIPHY_TX_CAL_MAN		0x4e102#define TX_SLEW_CAL_MAN_EN	BIT(0)103 104#define MIPHY_TST_BIAS_BOOST_2		0x62105#define MIPHY_BIAS_BOOST_1		0x63106#define MIPHY_BIAS_BOOST_2		0x64107#define MIPHY_RX_DESBUFF_FDB_2		0x67108#define MIPHY_RX_DESBUFF_FDB_3		0x68109#define MIPHY_SIGDET_COMPENS1		0x69110#define MIPHY_SIGDET_COMPENS2		0x6a111#define MIPHY_JITTER_PERIOD		0x6b112#define MIPHY_JITTER_AMPLITUDE_1	0x6c113#define MIPHY_JITTER_AMPLITUDE_2	0x6d114#define MIPHY_JITTER_AMPLITUDE_3	0x6e115#define MIPHY_RX_K_GAIN			0x78116#define MIPHY_RX_BUFFER_CTRL		0x7a117#define VGA_GAIN		BIT(0)118#define EQ_DC_GAIN		BIT(2)119#define EQ_BOOST_GAIN		BIT(3)120 121#define MIPHY_RX_VGA_GAIN		0x7b122#define MIPHY_RX_EQU_GAIN_1		0x7f123#define MIPHY_RX_EQU_GAIN_2		0x80124#define MIPHY_RX_EQU_GAIN_3		0x81125#define MIPHY_RX_CAL_CTRL_1		0x97126#define MIPHY_RX_CAL_CTRL_2		0x98127 128#define MIPHY_RX_CAL_OFFSET_CTRL	0x99129#define CAL_OFFSET_VGA_64	(0x03 << 0)130#define CAL_OFFSET_THRESHOLD_64	(0x03 << 2)131#define VGA_OFFSET_POLARITY	BIT(4)132#define OFFSET_COMPENSATION_EN	BIT(6)133 134#define MIPHY_RX_CAL_VGA_STEP		0x9a135#define MIPHY_RX_CAL_EYE_MIN		0x9d136#define MIPHY_RX_CAL_OPT_LENGTH		0x9f137#define MIPHY_RX_LOCK_CTRL_1		0xc1138#define MIPHY_RX_LOCK_SETTINGS_OPT	0xc2139#define MIPHY_RX_LOCK_STEP		0xc4140 141#define MIPHY_RX_SIGDET_SLEEP_OA	0xc9142#define MIPHY_RX_SIGDET_SLEEP_SEL	0xca143#define MIPHY_RX_SIGDET_WAIT_SEL	0xcb144#define MIPHY_RX_SIGDET_DATA_SEL	0xcc145#define EN_ULTRA_LOW_POWER	BIT(0)146#define EN_FIRST_HALF		BIT(1)147#define EN_SECOND_HALF		BIT(2)148#define EN_DIGIT_SIGNAL_CHECK	BIT(3)149 150#define MIPHY_RX_POWER_CTRL_1		0xcd151#define MIPHY_RX_POWER_CTRL_2		0xce152#define MIPHY_PLL_CALSET_CTRL		0xd3153#define MIPHY_PLL_CALSET_1		0xd4154#define MIPHY_PLL_CALSET_2		0xd5155#define MIPHY_PLL_CALSET_3		0xd6156#define MIPHY_PLL_CALSET_4		0xd7157#define MIPHY_PLL_SBR_1			0xe3158#define SET_NEW_CHANGE		BIT(1)159 160#define MIPHY_PLL_SBR_2			0xe4161#define MIPHY_PLL_SBR_3			0xe5162#define MIPHY_PLL_SBR_4			0xe6163#define MIPHY_PLL_COMMON_MISC_2		0xe9164#define START_ACT_FILT		BIT(6)165 166#define MIPHY_PLL_SPAREIN		0xeb167 168/*169 * On STiH407 the glue logic can be different among MiPHY devices; for example:170 * MiPHY0: OSC_FORCE_EXT means:171 *  0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1172 * MiPHY1: OSC_FORCE_EXT means:173 *  1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1174 * Some devices have not the possibility to check if the osc is ready.175 */176#define MIPHY_OSC_FORCE_EXT	BIT(3)177#define MIPHY_OSC_RDY		BIT(5)178 179#define MIPHY_CTRL_MASK		0x0f180#define MIPHY_CTRL_DEFAULT	0181#define MIPHY_CTRL_SYNC_D_EN	BIT(2)182 183/* SATA / PCIe defines */184#define SATA_CTRL_MASK		0x07185#define PCIE_CTRL_MASK		0xff186#define SATA_CTRL_SELECT_SATA	1187#define SATA_CTRL_SELECT_PCIE	0188#define SYSCFG_PCIE_PCIE_VAL	0x80189#define SATA_SPDMODE		1190 191#define MIPHY_SATA_BANK_NB	3192#define MIPHY_PCIE_BANK_NB	2193 194enum {195	SYSCFG_CTRL,196	SYSCFG_STATUS,197	SYSCFG_PCI,198	SYSCFG_SATA,199	SYSCFG_REG_MAX,200};201 202struct miphy28lp_phy {203	struct phy *phy;204	struct miphy28lp_dev *phydev;205	void __iomem *base;206	void __iomem *pipebase;207 208	bool osc_force_ext;209	bool osc_rdy;210	bool px_rx_pol_inv;211	bool ssc;212	bool tx_impedance;213 214	struct reset_control *miphy_rst;215 216	u32 sata_gen;217 218	/* Sysconfig registers offsets needed to configure the device */219	u32 syscfg_reg[SYSCFG_REG_MAX];220	u8 type;221};222 223struct miphy28lp_dev {224	struct device *dev;225	struct regmap *regmap;226	struct mutex miphy_mutex;227	struct miphy28lp_phy **phys;228	int nphys;229};230 231enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };232 233static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };234 235struct pll_ratio {236	int clk_ref;237	int calset_1;238	int calset_2;239	int calset_3;240	int calset_4;241	int cal_ctrl;242};243 244static struct pll_ratio sata_pll_ratio = {245	.clk_ref = 0x1e,246	.calset_1 = 0xc8,247	.calset_2 = 0x00,248	.calset_3 = 0x00,249	.calset_4 = 0x00,250	.cal_ctrl = 0x00,251};252 253static struct pll_ratio pcie_pll_ratio = {254	.clk_ref = 0x1e,255	.calset_1 = 0xa6,256	.calset_2 = 0xaa,257	.calset_3 = 0xaa,258	.calset_4 = 0x00,259	.cal_ctrl = 0x00,260};261 262static struct pll_ratio usb3_pll_ratio = {263	.clk_ref = 0x1e,264	.calset_1 = 0xa6,265	.calset_2 = 0xaa,266	.calset_3 = 0xaa,267	.calset_4 = 0x04,268	.cal_ctrl = 0x00,269};270 271struct miphy28lp_pll_gen {272	int bank;273	int speed;274	int bias_boost_1;275	int bias_boost_2;276	int tx_ctrl_1;277	int tx_ctrl_2;278	int tx_ctrl_3;279	int rx_k_gain;280	int rx_vga_gain;281	int rx_equ_gain_1;282	int rx_equ_gain_2;283	int rx_equ_gain_3;284	int rx_buff_ctrl;285};286 287static struct miphy28lp_pll_gen sata_pll_gen[] = {288	{289		.bank		= 0x00,290		.speed		= TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,291		.bias_boost_1	= 0x00,292		.bias_boost_2	= 0xae,293		.tx_ctrl_2	= 0x53,294		.tx_ctrl_3	= 0x00,295		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,296		.rx_vga_gain	= 0x00,297		.rx_equ_gain_1	= 0x7d,298		.rx_equ_gain_2	= 0x56,299		.rx_equ_gain_3	= 0x00,300	},301	{302		.bank		= 0x01,303		.speed		= TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,304		.bias_boost_1	= 0x00,305		.bias_boost_2	= 0xae,306		.tx_ctrl_2	= 0x72,307		.tx_ctrl_3	= 0x20,308		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,309		.rx_vga_gain	= 0x00,310		.rx_equ_gain_1	= 0x7d,311		.rx_equ_gain_2	= 0x56,312		.rx_equ_gain_3	= 0x00,313	},314	{315		.bank		= 0x02,316		.speed		= TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,317		.bias_boost_1	= 0x00,318		.bias_boost_2	= 0xae,319		.tx_ctrl_2	= 0xc0,320		.tx_ctrl_3	= 0x20,321		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,322		.rx_vga_gain	= 0x00,323		.rx_equ_gain_1	= 0x7d,324		.rx_equ_gain_2	= 0x56,325		.rx_equ_gain_3	= 0x00,326	},327};328 329static struct miphy28lp_pll_gen pcie_pll_gen[] = {330	{331		.bank		= 0x00,332		.speed		= TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,333		.bias_boost_1	= 0x00,334		.bias_boost_2	= 0xa5,335		.tx_ctrl_1	= TX_REG_STEP_N_25MV,336		.tx_ctrl_2	= 0x71,337		.tx_ctrl_3	= 0x60,338		.rx_k_gain	= 0x98,339		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,340		.rx_vga_gain	= 0x00,341		.rx_equ_gain_1	= 0x79,342		.rx_equ_gain_2	= 0x56,343	},344	{345		.bank		= 0x01,346		.speed		= TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,347		.bias_boost_1	= 0x00,348		.bias_boost_2	= 0xa5,349		.tx_ctrl_1	= TX_REG_STEP_N_25MV,350		.tx_ctrl_2	= 0x70,351		.tx_ctrl_3	= 0x60,352		.rx_k_gain	= 0xcc,353		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,354		.rx_vga_gain	= 0x00,355		.rx_equ_gain_1	= 0x78,356		.rx_equ_gain_2	= 0x07,357	},358};359 360static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)361{362	void __iomem *base = miphy_phy->base;363	u8 val;364 365	/* Putting Macro in reset */366	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);367 368	val = RST_APPLI_SW | RST_CONF_SW;369	writeb_relaxed(val, base + MIPHY_CONF_RESET);370 371	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);372 373	/* Bringing the MIPHY-CPU registers out of reset */374	if (miphy_phy->type == PHY_TYPE_PCIE) {375		val = AUTO_RST_RX | TERM_EN_SW;376		writeb_relaxed(val, base + MIPHY_CONTROL);377	} else {378		val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;379		writeb_relaxed(val, base + MIPHY_CONTROL);380	}381}382 383static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,384		struct pll_ratio *pll_ratio)385{386	void __iomem *base = miphy_phy->base;387	u8 val;388 389	/* Applying PLL Settings */390	writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);391	writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);392 393	/* PLL Ratio */394	writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);395	writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);396	writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);397	writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);398	writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);399 400	writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);401 402	val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;403	writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);404 405	val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;406 407	if (miphy_phy->type != PHY_TYPE_SATA)408		val |= OFFSET_COMPENSATION_EN;409 410	writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);411 412	if (miphy_phy->type == PHY_TYPE_USB3) {413		writeb_relaxed(0x00, base + MIPHY_CONF);414		writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);415		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);416		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);417		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);418 419		val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;420		writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);421	}422 423}424 425static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)426{427	void __iomem *base = miphy_phy->base;428	int i;429 430	for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {431		struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];432 433		/* Banked settings */434		writeb_relaxed(gen->bank, base + MIPHY_CONF);435		writeb_relaxed(gen->speed, base + MIPHY_SPEED);436		writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);437		writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);438 439		/* TX buffer Settings */440		writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);441		writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);442 443		/* RX Buffer Settings */444		writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);445		writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);446		writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);447		writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);448		writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);449	}450}451 452static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)453{454	void __iomem *base = miphy_phy->base;455	int i;456 457	for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {458		struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];459 460		/* Banked settings */461		writeb_relaxed(gen->bank, base + MIPHY_CONF);462		writeb_relaxed(gen->speed, base + MIPHY_SPEED);463		writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);464		writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);465 466		/* TX buffer Settings */467		writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);468		writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);469		writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);470 471		writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);472 473		/* RX Buffer Settings */474		writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);475		writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);476		writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);477		writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);478	}479}480 481static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)482{483	u8 val;484 485	/* Waiting for Compensation to complete */486	return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6,487					  val, val & COMP_DONE, 1, 5 * USEC_PER_SEC);488}489 490 491static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,492		struct pll_ratio *pll_ratio)493{494	void __iomem *base = miphy_phy->base;495 496	/* Poll for HFC ready after reset release */497	/* Compensation measurement */498	writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);499 500	writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);501	writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);502	writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);503 504	if (miphy_phy->type == PHY_TYPE_PCIE)505		writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);506 507	writeb_relaxed(0x00, base + MIPHY_RESET);508	writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);509	writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);510 511	/* TX compensation offset to re-center TX impedance */512	writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);513 514	if (miphy_phy->type == PHY_TYPE_PCIE)515		return miphy28lp_wait_compensation(miphy_phy);516 517	return 0;518}519 520static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)521{522	void __iomem *base = miphy_phy->base;523	u8 val;524 525	/* MIPHY Reset */526	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);527	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);528	writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);529 530	val = RST_COMP_SW | RST_PLL_SW;531	writeb_relaxed(val, base + MIPHY_RESET);532 533	writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);534	writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);535	writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);536	writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);537	writeb_relaxed(0x00, base + MIPHY_RESET);538	writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);539	writeb_relaxed(0x00, base + MIPHY_CONF);540	writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);541	writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);542	writeb_relaxed(0x00, base + MIPHY_CONF);543	writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);544	writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);545	writeb_relaxed(0x00, base + MIPHY_CONF);546}547 548static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)549{550	void __iomem *base = miphy_phy->base;551	u8 val;552 553	/* Compensate Tx impedance to avoid out of range values */554	/*555	 * Enable the SSC on PLL for all banks556	 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp557	 */558	val = readb_relaxed(base + MIPHY_BOUNDARY_2);559	val |= SSC_EN_SW;560	writeb_relaxed(val, base + MIPHY_BOUNDARY_2);561 562	val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);563	val |= SSC_SEL;564	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);565 566	for (val = 0; val < MIPHY_SATA_BANK_NB; val++) {567		writeb_relaxed(val, base + MIPHY_CONF);568 569		/* Add value to each reference clock cycle  */570		/* and define the period length of the SSC */571		writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);572		writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3);573		writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4);574 575		/* Clear any previous request */576		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);577 578		/* requests the PLL to take in account new parameters */579		writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);580 581		/* To be sure there is no other pending requests */582		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);583	}584}585 586static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)587{588	void __iomem *base = miphy_phy->base;589	u8 val;590 591	/* Compensate Tx impedance to avoid out of range values */592	/*593	 * Enable the SSC on PLL for all banks594	 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp595	 */596	val = readb_relaxed(base + MIPHY_BOUNDARY_2);597	val |= SSC_EN_SW;598	writeb_relaxed(val, base + MIPHY_BOUNDARY_2);599 600	val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);601	val |= SSC_SEL;602	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);603 604	for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) {605		writeb_relaxed(val, base + MIPHY_CONF);606 607		/* Validate Step component */608		writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3);609		writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);610 611		/* Validate Period component */612		writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);613		writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);614 615		/* Clear any previous request */616		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);617 618		/* requests the PLL to take in account new parameters */619		writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);620 621		/* To be sure there is no other pending requests */622		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);623	}624}625 626static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy)627{628	/* Compensate Tx impedance to avoid out of range values */629	writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP);630}631 632static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)633{634	void __iomem *base = miphy_phy->base;635	int err;636	u8 val;637 638	/* Putting Macro in reset */639	miphy28lp_set_reset(miphy_phy);640 641	/* PLL calibration */642	miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);643 644	/* Banked settings Gen1/Gen2/Gen3 */645	miphy28lp_sata_config_gen(miphy_phy);646 647	/* Power control */648	/* Input bridge enable, manual input bridge control */649	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);650 651	/* Macro out of reset */652	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);653 654	/* Poll for HFC ready after reset release */655	/* Compensation measurement */656	err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);657	if (err)658		return err;659 660	if (miphy_phy->px_rx_pol_inv) {661		/* Invert Rx polarity */662		val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);663		val |= PX_RX_POL;664		writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);665	}666 667	if (miphy_phy->ssc)668		miphy_sata_tune_ssc(miphy_phy);669 670	if (miphy_phy->tx_impedance)671		miphy_tune_tx_impedance(miphy_phy);672 673	return 0;674}675 676static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)677{678	void __iomem *base = miphy_phy->base;679	int err;680 681	/* Putting Macro in reset */682	miphy28lp_set_reset(miphy_phy);683 684	/* PLL calibration */685	miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);686 687	/* Banked settings Gen1/Gen2 */688	miphy28lp_pcie_config_gen(miphy_phy);689 690	/* Power control */691	/* Input bridge enable, manual input bridge control */692	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);693 694	/* Macro out of reset */695	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);696 697	/* Poll for HFC ready after reset release */698	/* Compensation measurement */699	err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);700	if (err)701		return err;702 703	if (miphy_phy->ssc)704		miphy_pcie_tune_ssc(miphy_phy);705 706	if (miphy_phy->tx_impedance)707		miphy_tune_tx_impedance(miphy_phy);708 709	return 0;710}711 712 713static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)714{715	void __iomem *base = miphy_phy->base;716	u8 val;717 718	/* Putting Macro in reset */719	miphy28lp_set_reset(miphy_phy);720 721	/* PLL calibration */722	miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);723 724	/* Writing The Speed Rate */725	writeb_relaxed(0x00, base + MIPHY_CONF);726 727	val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;728	writeb_relaxed(val, base + MIPHY_SPEED);729 730	/* RX Channel compensation and calibration */731	writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);732	writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);733	writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);734 735	val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |736	      CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;737	writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);738	writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);739	writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);740 741	val = EQ_DC_GAIN | VGA_GAIN;742	writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);743	writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);744	writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);745 746	/* TX compensation offset to re-center TX impedance */747	writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);748 749	/* Enable GENSEL_SEL and SSC */750	/* TX_SEL=0 swing preemp forced by pipe registres */751	val = SSC_SEL | GENSEL_SEL;752	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);753 754	/* MIPHY Bias boost */755	writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);756	writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);757 758	/* SSC modulation */759	writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);760 761	/* MIPHY TX control */762	writeb_relaxed(0x00, base + MIPHY_CONF);763 764	/* Validate Step component */765	writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);766	writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);767 768	/* Validate Period component */769	writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);770	writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);771 772	/* Clear any previous request */773	writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);774 775	/* requests the PLL to take in account new parameters */776	writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);777 778	/* To be sure there is no other pending requests */779	writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);780 781	/* Rx PI controller settings */782	writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);783 784	/* MIPHY RX input bridge control */785	/* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */786	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);787	writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);788	writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);789 790	/* MIPHY Reset for usb3 */791	miphy28_usb3_miphy_reset(miphy_phy);792}793 794static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)795{796	u8 mask = HFC_PLL | HFC_RDY;797	u8 val;798 799	/*800	 * For PCIe and USB3 check only that PLL and HFC are ready801	 * For SATA check also that phy is ready!802	 */803	if (miphy_phy->type == PHY_TYPE_SATA)804		mask |= PHY_RDY;805 806	return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1,807					  val, (val & mask) == mask, 1,808					  5 * USEC_PER_SEC);809}810 811static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)812{813	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;814	u32 val;815 816	if (!miphy_phy->osc_rdy)817		return 0;818 819	if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])820		return -EINVAL;821 822	return regmap_read_poll_timeout(miphy_dev->regmap,823					miphy_phy->syscfg_reg[SYSCFG_STATUS],824					val, val & MIPHY_OSC_RDY, 1,825					5 * USEC_PER_SEC);826}827 828static int miphy28lp_get_resource_byname(struct device_node *child,829					  char *rname, struct resource *res)830{831	int index;832 833	index = of_property_match_string(child, "reg-names", rname);834	if (index < 0)835		return -ENODEV;836 837	return of_address_to_resource(child, index, res);838}839 840static int miphy28lp_get_one_addr(struct device *dev,841				  struct device_node *child, char *rname,842				  void __iomem **base)843{844	struct resource res;845	int ret;846 847	ret = miphy28lp_get_resource_byname(child, rname, &res);848	if (!ret) {849		*base = devm_ioremap(dev, res.start, resource_size(&res));850		if (!*base) {851			dev_err(dev, "failed to ioremap %s address region\n"852					, rname);853			return -ENOENT;854		}855	}856 857	return 0;858}859 860/* MiPHY reset and sysconf setup */861static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)862{863	int err;864	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;865 866	if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])867		return -EINVAL;868 869	err = reset_control_assert(miphy_phy->miphy_rst);870	if (err) {871		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");872		return err;873	}874 875	if (miphy_phy->osc_force_ext)876		miphy_val |= MIPHY_OSC_FORCE_EXT;877 878	regmap_update_bits(miphy_dev->regmap,879			   miphy_phy->syscfg_reg[SYSCFG_CTRL],880			   MIPHY_CTRL_MASK, miphy_val);881 882	err = reset_control_deassert(miphy_phy->miphy_rst);883	if (err) {884		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");885		return err;886	}887 888	return miphy_osc_is_ready(miphy_phy);889}890 891static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)892{893	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;894	int err, sata_conf = SATA_CTRL_SELECT_SATA;895 896	if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||897			(!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||898			(!miphy_phy->base))899		return -EINVAL;900 901	dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);902 903	/* Configure the glue-logic */904	sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);905 906	regmap_update_bits(miphy_dev->regmap,907			   miphy_phy->syscfg_reg[SYSCFG_SATA],908			   SATA_CTRL_MASK, sata_conf);909 910	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],911			   PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);912 913	/* MiPHY path and clocking init */914	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);915 916	if (err) {917		dev_err(miphy_dev->dev, "SATA phy setup failed\n");918		return err;919	}920 921	/* initialize miphy */922	miphy28lp_configure_sata(miphy_phy);923 924	return miphy_is_ready(miphy_phy);925}926 927static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)928{929	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;930	int err;931 932	if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||933			(!miphy_phy->syscfg_reg[SYSCFG_PCI])934		|| (!miphy_phy->base) || (!miphy_phy->pipebase))935		return -EINVAL;936 937	dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);938 939	/* Configure the glue-logic */940	regmap_update_bits(miphy_dev->regmap,941			   miphy_phy->syscfg_reg[SYSCFG_SATA],942			   SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);943 944	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],945			   PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);946 947	/* MiPHY path and clocking init */948	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);949 950	if (err) {951		dev_err(miphy_dev->dev, "PCIe phy setup failed\n");952		return err;953	}954 955	/* initialize miphy */956	err = miphy28lp_configure_pcie(miphy_phy);957	if (err)958		return err;959 960	/* PIPE Wrapper Configuration */961	writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */962	writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */963	writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */964	writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */965	writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */966	writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */967 968	/* Wait for phy_ready */969	return miphy_is_ready(miphy_phy);970}971 972static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)973{974	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;975	int err;976 977	if ((!miphy_phy->base) || (!miphy_phy->pipebase))978		return -EINVAL;979 980	dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);981 982	/* MiPHY path and clocking init */983	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);984	if (err) {985		dev_err(miphy_dev->dev, "USB3 phy setup failed\n");986		return err;987	}988 989	/* initialize miphy */990	miphy28lp_configure_usb3(miphy_phy);991 992	/* PIPE Wrapper Configuration */993	writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);994	writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);995	writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);996	writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);997	writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);998	writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);999 1000	/* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */1001	writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);1002	writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);1003	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);1004	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);1005	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);1006	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);1007	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);1008	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);1009 1010	return miphy_is_ready(miphy_phy);1011}1012 1013static int miphy28lp_init(struct phy *phy)1014{1015	struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);1016	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1017	int ret;1018 1019	mutex_lock(&miphy_dev->miphy_mutex);1020 1021	switch (miphy_phy->type) {1022 1023	case PHY_TYPE_SATA:1024		ret = miphy28lp_init_sata(miphy_phy);1025		break;1026	case PHY_TYPE_PCIE:1027		ret = miphy28lp_init_pcie(miphy_phy);1028		break;1029	case PHY_TYPE_USB3:1030		ret = miphy28lp_init_usb3(miphy_phy);1031		break;1032	default:1033		ret = -EINVAL;1034		break;1035	}1036 1037	mutex_unlock(&miphy_dev->miphy_mutex);1038 1039	return ret;1040}1041 1042static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)1043{1044	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1045	struct device_node *phynode = miphy_phy->phy->dev.of_node;1046	int err;1047 1048	if ((miphy_phy->type != PHY_TYPE_SATA) &&1049	    (miphy_phy->type != PHY_TYPE_PCIE) &&1050	    (miphy_phy->type != PHY_TYPE_USB3)) {1051		return -EINVAL;1052	}1053 1054	err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,1055			PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],1056			&miphy_phy->base);1057	if (err)1058		return err;1059 1060	if ((miphy_phy->type == PHY_TYPE_PCIE) ||1061	    (miphy_phy->type == PHY_TYPE_USB3)) {1062		err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",1063					     &miphy_phy->pipebase);1064		if (err)1065			return err;1066	}1067 1068	return 0;1069}1070 1071static struct phy *miphy28lp_xlate(struct device *dev,1072				   const struct of_phandle_args *args)1073{1074	struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);1075	struct miphy28lp_phy *miphy_phy = NULL;1076	struct device_node *phynode = args->np;1077	int ret, index = 0;1078 1079	if (args->args_count != 1) {1080		dev_err(dev, "Invalid number of cells in 'phy' property\n");1081		return ERR_PTR(-EINVAL);1082	}1083 1084	for (index = 0; index < miphy_dev->nphys; index++)1085		if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {1086			miphy_phy = miphy_dev->phys[index];1087			break;1088		}1089 1090	if (!miphy_phy) {1091		dev_err(dev, "Failed to find appropriate phy\n");1092		return ERR_PTR(-EINVAL);1093	}1094 1095	miphy_phy->type = args->args[0];1096 1097	ret = miphy28lp_get_addr(miphy_phy);1098	if (ret < 0)1099		return ERR_PTR(ret);1100 1101	return miphy_phy->phy;1102}1103 1104static const struct phy_ops miphy28lp_ops = {1105	.init = miphy28lp_init,1106	.owner = THIS_MODULE,1107};1108 1109static int miphy28lp_probe_resets(struct device_node *node,1110				  struct miphy28lp_phy *miphy_phy)1111{1112	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1113	int err;1114 1115	miphy_phy->miphy_rst =1116		of_reset_control_get_shared(node, "miphy-sw-rst");1117 1118	if (IS_ERR(miphy_phy->miphy_rst)) {1119		dev_err(miphy_dev->dev,1120				"miphy soft reset control not defined\n");1121		return PTR_ERR(miphy_phy->miphy_rst);1122	}1123 1124	err = reset_control_deassert(miphy_phy->miphy_rst);1125	if (err) {1126		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");1127		return err;1128	}1129 1130	return 0;1131}1132 1133static int miphy28lp_of_probe(struct device_node *np,1134			      struct miphy28lp_phy *miphy_phy)1135{1136	int i;1137	u32 ctrlreg;1138 1139	miphy_phy->osc_force_ext =1140		of_property_read_bool(np, "st,osc-force-ext");1141 1142	miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");1143 1144	miphy_phy->px_rx_pol_inv =1145		of_property_read_bool(np, "st,px_rx_pol_inv");1146 1147	miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");1148 1149	miphy_phy->tx_impedance =1150		of_property_read_bool(np, "st,tx-impedance-comp");1151 1152	of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);1153	if (!miphy_phy->sata_gen)1154		miphy_phy->sata_gen = SATA_GEN1;1155 1156	for (i = 0; i < SYSCFG_REG_MAX; i++) {1157		if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))1158			miphy_phy->syscfg_reg[i] = ctrlreg;1159	}1160 1161	return 0;1162}1163 1164static int miphy28lp_probe(struct platform_device *pdev)1165{1166	struct device_node *child, *np = pdev->dev.of_node;1167	struct miphy28lp_dev *miphy_dev;1168	struct phy_provider *provider;1169	struct phy *phy;1170	int ret, port = 0;1171 1172	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);1173	if (!miphy_dev)1174		return -ENOMEM;1175 1176	miphy_dev->nphys = of_get_child_count(np);1177	miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,1178				       sizeof(*miphy_dev->phys), GFP_KERNEL);1179	if (!miphy_dev->phys)1180		return -ENOMEM;1181 1182	miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");1183	if (IS_ERR(miphy_dev->regmap)) {1184		dev_err(miphy_dev->dev, "No syscfg phandle specified\n");1185		return PTR_ERR(miphy_dev->regmap);1186	}1187 1188	miphy_dev->dev = &pdev->dev;1189 1190	dev_set_drvdata(&pdev->dev, miphy_dev);1191 1192	mutex_init(&miphy_dev->miphy_mutex);1193 1194	for_each_child_of_node(np, child) {1195		struct miphy28lp_phy *miphy_phy;1196 1197		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),1198					 GFP_KERNEL);1199		if (!miphy_phy) {1200			ret = -ENOMEM;1201			goto put_child;1202		}1203 1204		miphy_dev->phys[port] = miphy_phy;1205 1206		phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);1207		if (IS_ERR(phy)) {1208			dev_err(&pdev->dev, "failed to create PHY\n");1209			ret = PTR_ERR(phy);1210			goto put_child;1211		}1212 1213		miphy_dev->phys[port]->phy = phy;1214		miphy_dev->phys[port]->phydev = miphy_dev;1215 1216		ret = miphy28lp_of_probe(child, miphy_phy);1217		if (ret)1218			goto put_child;1219 1220		ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);1221		if (ret)1222			goto put_child;1223 1224		phy_set_drvdata(phy, miphy_dev->phys[port]);1225		port++;1226 1227	}1228 1229	provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);1230	return PTR_ERR_OR_ZERO(provider);1231put_child:1232	of_node_put(child);1233	return ret;1234}1235 1236static const struct of_device_id miphy28lp_of_match[] = {1237	{.compatible = "st,miphy28lp-phy", },1238	{},1239};1240 1241MODULE_DEVICE_TABLE(of, miphy28lp_of_match);1242 1243static struct platform_driver miphy28lp_driver = {1244	.probe = miphy28lp_probe,1245	.driver = {1246		.name = "miphy28lp-phy",1247		.of_match_table = miphy28lp_of_match,1248	}1249};1250 1251module_platform_driver(miphy28lp_driver);1252 1253MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");1254MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");1255MODULE_LICENSE("GPL v2");1256