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