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