1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (C) 2018 Marvell International Ltd.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park * https://spdx.org/licenses
6*54fd6939SJiyong Park */
7*54fd6939SJiyong Park
8*54fd6939SJiyong Park /* Marvell CP110 SoC COMPHY unit driver */
9*54fd6939SJiyong Park
10*54fd6939SJiyong Park #include <errno.h>
11*54fd6939SJiyong Park #include <inttypes.h>
12*54fd6939SJiyong Park #include <stdint.h>
13*54fd6939SJiyong Park
14*54fd6939SJiyong Park #include <common/debug.h>
15*54fd6939SJiyong Park #include <drivers/delay_timer.h>
16*54fd6939SJiyong Park #include <mg_conf_cm3/mg_conf_cm3.h>
17*54fd6939SJiyong Park #include <lib/mmio.h>
18*54fd6939SJiyong Park #include <lib/spinlock.h>
19*54fd6939SJiyong Park
20*54fd6939SJiyong Park #include <mvebu_def.h>
21*54fd6939SJiyong Park #include "mvebu.h"
22*54fd6939SJiyong Park #include "comphy-cp110.h"
23*54fd6939SJiyong Park #include "phy-comphy-cp110.h"
24*54fd6939SJiyong Park #include "phy-comphy-common.h"
25*54fd6939SJiyong Park
26*54fd6939SJiyong Park #if __has_include("phy-porting-layer.h")
27*54fd6939SJiyong Park #include "phy-porting-layer.h"
28*54fd6939SJiyong Park #else
29*54fd6939SJiyong Park #include "phy-default-porting-layer.h"
30*54fd6939SJiyong Park #endif
31*54fd6939SJiyong Park
32*54fd6939SJiyong Park /* COMPHY speed macro */
33*54fd6939SJiyong Park #define COMPHY_SPEED_1_25G 0 /* SGMII 1G */
34*54fd6939SJiyong Park #define COMPHY_SPEED_2_5G 1
35*54fd6939SJiyong Park #define COMPHY_SPEED_3_125G 2 /* 2500Base-X */
36*54fd6939SJiyong Park #define COMPHY_SPEED_5G 3
37*54fd6939SJiyong Park #define COMPHY_SPEED_5_15625G 4 /* XFI 5G */
38*54fd6939SJiyong Park #define COMPHY_SPEED_6G 5
39*54fd6939SJiyong Park #define COMPHY_SPEED_10_3125G 6 /* XFI 10G */
40*54fd6939SJiyong Park #define COMPHY_SPEED_MAX 0x3F
41*54fd6939SJiyong Park /* The default speed for IO with fixed known speed */
42*54fd6939SJiyong Park #define COMPHY_SPEED_DEFAULT COMPHY_SPEED_MAX
43*54fd6939SJiyong Park
44*54fd6939SJiyong Park /* Commands for comphy driver */
45*54fd6939SJiyong Park #define COMPHY_COMMAND_DIGITAL_PWR_OFF 0x00000001
46*54fd6939SJiyong Park #define COMPHY_COMMAND_DIGITAL_PWR_ON 0x00000002
47*54fd6939SJiyong Park
48*54fd6939SJiyong Park #define COMPHY_PIPE_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x120000)
49*54fd6939SJiyong Park
50*54fd6939SJiyong Park /* System controller registers */
51*54fd6939SJiyong Park #define PCIE_MAC_RESET_MASK_PORT0 BIT(13)
52*54fd6939SJiyong Park #define PCIE_MAC_RESET_MASK_PORT1 BIT(11)
53*54fd6939SJiyong Park #define PCIE_MAC_RESET_MASK_PORT2 BIT(12)
54*54fd6939SJiyong Park #define SYS_CTRL_UINIT_SOFT_RESET_REG 0x268
55*54fd6939SJiyong Park #define SYS_CTRL_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x440000)
56*54fd6939SJiyong Park
57*54fd6939SJiyong Park /* DFX register spaces */
58*54fd6939SJiyong Park #define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET (30)
59*54fd6939SJiyong Park #define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK (0x1UL << \
60*54fd6939SJiyong Park SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET)
61*54fd6939SJiyong Park #define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET (31)
62*54fd6939SJiyong Park #define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK (0x1UL << \
63*54fd6939SJiyong Park SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET)
64*54fd6939SJiyong Park #define SAR_STATUS_0_REG 0x40600
65*54fd6939SJiyong Park #define DFX_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + DFX_BASE)
66*54fd6939SJiyong Park /* Common Phy training */
67*54fd6939SJiyong Park #define COMPHY_TRX_TRAIN_COMPHY_OFFS 0x1000
68*54fd6939SJiyong Park #define COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE 0x1
69*54fd6939SJiyong Park #define COMPHY_TRX_RELATIVE_ADDR(comphy_index) (comphy_train_base + \
70*54fd6939SJiyong Park (comphy_index) * COMPHY_TRX_TRAIN_COMPHY_OFFS)
71*54fd6939SJiyong Park
72*54fd6939SJiyong Park /* The same Units Soft Reset Config register are accessed in all PCIe ports
73*54fd6939SJiyong Park * initialization, so a spin lock is defined in case when more than 1 CPUs
74*54fd6939SJiyong Park * resets PCIe MAC and need to access the register in the same time. The spin
75*54fd6939SJiyong Park * lock is shared by all CP110 units.
76*54fd6939SJiyong Park */
77*54fd6939SJiyong Park spinlock_t cp110_mac_reset_lock;
78*54fd6939SJiyong Park
79*54fd6939SJiyong Park /* These values come from the PCI Express Spec */
80*54fd6939SJiyong Park enum pcie_link_width {
81*54fd6939SJiyong Park PCIE_LNK_WIDTH_RESRV = 0x00,
82*54fd6939SJiyong Park PCIE_LNK_X1 = 0x01,
83*54fd6939SJiyong Park PCIE_LNK_X2 = 0x02,
84*54fd6939SJiyong Park PCIE_LNK_X4 = 0x04,
85*54fd6939SJiyong Park PCIE_LNK_X8 = 0x08,
86*54fd6939SJiyong Park PCIE_LNK_X12 = 0x0C,
87*54fd6939SJiyong Park PCIE_LNK_X16 = 0x10,
88*54fd6939SJiyong Park PCIE_LNK_X32 = 0x20,
89*54fd6939SJiyong Park PCIE_LNK_WIDTH_UNKNOWN = 0xFF,
90*54fd6939SJiyong Park };
91*54fd6939SJiyong Park
92*54fd6939SJiyong Park _Bool rx_trainng_done[AP_NUM][CP_NUM][MAX_LANE_NR] = {0};
93*54fd6939SJiyong Park
mvebu_cp110_get_ap_and_cp_nr(uint8_t * ap_nr,uint8_t * cp_nr,uint64_t comphy_base)94*54fd6939SJiyong Park static void mvebu_cp110_get_ap_and_cp_nr(uint8_t *ap_nr, uint8_t *cp_nr,
95*54fd6939SJiyong Park uint64_t comphy_base)
96*54fd6939SJiyong Park {
97*54fd6939SJiyong Park #if (AP_NUM == 1)
98*54fd6939SJiyong Park *ap_nr = 0;
99*54fd6939SJiyong Park #else
100*54fd6939SJiyong Park *ap_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(0)) /
101*54fd6939SJiyong Park AP_IO_OFFSET);
102*54fd6939SJiyong Park #endif
103*54fd6939SJiyong Park
104*54fd6939SJiyong Park *cp_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(*ap_nr)) /
105*54fd6939SJiyong Park MVEBU_CP_OFFSET);
106*54fd6939SJiyong Park
107*54fd6939SJiyong Park debug("cp_base 0x%" PRIx64 ", ap_io_base 0x%lx, cp_offset 0x%lx\n",
108*54fd6939SJiyong Park comphy_base, (unsigned long)MVEBU_AP_IO_BASE(*ap_nr),
109*54fd6939SJiyong Park (unsigned long)MVEBU_CP_OFFSET);
110*54fd6939SJiyong Park }
111*54fd6939SJiyong Park
112*54fd6939SJiyong Park /* Clear PIPE selector - avoid collision with previous configuration */
mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base,uint8_t comphy_index)113*54fd6939SJiyong Park static void mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base,
114*54fd6939SJiyong Park uint8_t comphy_index)
115*54fd6939SJiyong Park {
116*54fd6939SJiyong Park uint32_t reg, mask, field;
117*54fd6939SJiyong Park uint32_t comphy_offset =
118*54fd6939SJiyong Park COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
119*54fd6939SJiyong Park
120*54fd6939SJiyong Park mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
121*54fd6939SJiyong Park reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET);
122*54fd6939SJiyong Park field = reg & mask;
123*54fd6939SJiyong Park
124*54fd6939SJiyong Park if (field) {
125*54fd6939SJiyong Park reg &= ~mask;
126*54fd6939SJiyong Park mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET,
127*54fd6939SJiyong Park reg);
128*54fd6939SJiyong Park }
129*54fd6939SJiyong Park }
130*54fd6939SJiyong Park
131*54fd6939SJiyong Park /* Clear PHY selector - avoid collision with previous configuration */
mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base,uint8_t comphy_index)132*54fd6939SJiyong Park static void mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base,
133*54fd6939SJiyong Park uint8_t comphy_index)
134*54fd6939SJiyong Park {
135*54fd6939SJiyong Park uint32_t reg, mask, field;
136*54fd6939SJiyong Park uint32_t comphy_offset =
137*54fd6939SJiyong Park COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
138*54fd6939SJiyong Park
139*54fd6939SJiyong Park mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
140*54fd6939SJiyong Park reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET);
141*54fd6939SJiyong Park field = reg & mask;
142*54fd6939SJiyong Park
143*54fd6939SJiyong Park /* Clear comphy selector - if it was already configured.
144*54fd6939SJiyong Park * (might be that this comphy was configured as PCIe/USB,
145*54fd6939SJiyong Park * in such case, no need to clear comphy selector because PCIe/USB
146*54fd6939SJiyong Park * are controlled by hpipe selector).
147*54fd6939SJiyong Park */
148*54fd6939SJiyong Park if (field) {
149*54fd6939SJiyong Park reg &= ~mask;
150*54fd6939SJiyong Park mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET,
151*54fd6939SJiyong Park reg);
152*54fd6939SJiyong Park }
153*54fd6939SJiyong Park }
154*54fd6939SJiyong Park
155*54fd6939SJiyong Park /* PHY selector configures SATA and Network modes */
mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)156*54fd6939SJiyong Park static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base,
157*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
158*54fd6939SJiyong Park {
159*54fd6939SJiyong Park uint32_t reg, mask;
160*54fd6939SJiyong Park uint32_t comphy_offset =
161*54fd6939SJiyong Park COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
162*54fd6939SJiyong Park int mode;
163*54fd6939SJiyong Park
164*54fd6939SJiyong Park /* If phy selector is used the pipe selector should be marked as
165*54fd6939SJiyong Park * unconnected.
166*54fd6939SJiyong Park */
167*54fd6939SJiyong Park mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index);
168*54fd6939SJiyong Park
169*54fd6939SJiyong Park /* Comphy mode (compound of the IO mode and id). Here, only the IO mode
170*54fd6939SJiyong Park * is required to distinguish between SATA and network modes.
171*54fd6939SJiyong Park */
172*54fd6939SJiyong Park mode = COMPHY_GET_MODE(comphy_mode);
173*54fd6939SJiyong Park
174*54fd6939SJiyong Park mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
175*54fd6939SJiyong Park reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET);
176*54fd6939SJiyong Park reg &= ~mask;
177*54fd6939SJiyong Park
178*54fd6939SJiyong Park /* SATA port 0/1 require the same configuration */
179*54fd6939SJiyong Park if (mode == COMPHY_SATA_MODE) {
180*54fd6939SJiyong Park /* SATA selector values is always 4 */
181*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHYN_SATA << comphy_offset;
182*54fd6939SJiyong Park } else {
183*54fd6939SJiyong Park switch (comphy_index) {
184*54fd6939SJiyong Park case(0):
185*54fd6939SJiyong Park case(1):
186*54fd6939SJiyong Park case(2):
187*54fd6939SJiyong Park /* For comphy 0,1, and 2:
188*54fd6939SJiyong Park * Network selector value is always 1.
189*54fd6939SJiyong Park */
190*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY0_1_2_NETWORK <<
191*54fd6939SJiyong Park comphy_offset;
192*54fd6939SJiyong Park break;
193*54fd6939SJiyong Park case(3):
194*54fd6939SJiyong Park /* For comphy 3:
195*54fd6939SJiyong Park * 0x1 = RXAUI_Lane1
196*54fd6939SJiyong Park * 0x2 = SGMII/Base-X Port1
197*54fd6939SJiyong Park */
198*54fd6939SJiyong Park if (mode == COMPHY_RXAUI_MODE)
199*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY3_RXAUI <<
200*54fd6939SJiyong Park comphy_offset;
201*54fd6939SJiyong Park else
202*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY3_SGMII <<
203*54fd6939SJiyong Park comphy_offset;
204*54fd6939SJiyong Park break;
205*54fd6939SJiyong Park case(4):
206*54fd6939SJiyong Park /* For comphy 4:
207*54fd6939SJiyong Park * 0x1 = SGMII/Base-X Port1, XFI1/SFI1
208*54fd6939SJiyong Park * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0
209*54fd6939SJiyong Park *
210*54fd6939SJiyong Park * We want to check if SGMII1 is the
211*54fd6939SJiyong Park * requested mode in order to determine which value
212*54fd6939SJiyong Park * should be set (all other modes use the same value)
213*54fd6939SJiyong Park * so we need to strip the mode, and check the ID
214*54fd6939SJiyong Park * because we might handle SGMII0 too.
215*54fd6939SJiyong Park */
216*54fd6939SJiyong Park /* TODO: need to distinguish between CP110 and CP115
217*54fd6939SJiyong Park * as SFI1/XFI1 available only for CP115.
218*54fd6939SJiyong Park */
219*54fd6939SJiyong Park if ((mode == COMPHY_SGMII_MODE ||
220*54fd6939SJiyong Park mode == COMPHY_2500BASEX_MODE ||
221*54fd6939SJiyong Park mode == COMPHY_SFI_MODE ||
222*54fd6939SJiyong Park mode == COMPHY_XFI_MODE ||
223*54fd6939SJiyong Park mode == COMPHY_AP_MODE)
224*54fd6939SJiyong Park && COMPHY_GET_ID(comphy_mode) == 1)
225*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
226*54fd6939SJiyong Park comphy_offset;
227*54fd6939SJiyong Park else
228*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY4_ALL_OTHERS <<
229*54fd6939SJiyong Park comphy_offset;
230*54fd6939SJiyong Park break;
231*54fd6939SJiyong Park case(5):
232*54fd6939SJiyong Park /* For comphy 5:
233*54fd6939SJiyong Park * 0x1 = SGMII/Base-X Port2
234*54fd6939SJiyong Park * 0x2 = RXAUI Lane1
235*54fd6939SJiyong Park */
236*54fd6939SJiyong Park if (mode == COMPHY_RXAUI_MODE)
237*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY5_RXAUI <<
238*54fd6939SJiyong Park comphy_offset;
239*54fd6939SJiyong Park else
240*54fd6939SJiyong Park reg |= COMMON_SELECTOR_COMPHY5_SGMII <<
241*54fd6939SJiyong Park comphy_offset;
242*54fd6939SJiyong Park break;
243*54fd6939SJiyong Park }
244*54fd6939SJiyong Park }
245*54fd6939SJiyong Park
246*54fd6939SJiyong Park mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, reg);
247*54fd6939SJiyong Park }
248*54fd6939SJiyong Park
249*54fd6939SJiyong Park /* PIPE selector configures for PCIe, USB 3.0 Host, and USB 3.0 Device mode */
mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)250*54fd6939SJiyong Park static void mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base,
251*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
252*54fd6939SJiyong Park {
253*54fd6939SJiyong Park uint32_t reg;
254*54fd6939SJiyong Park uint32_t shift = COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
255*54fd6939SJiyong Park int mode = COMPHY_GET_MODE(comphy_mode);
256*54fd6939SJiyong Park uint32_t mask = COMMON_SELECTOR_COMPHY_MASK << shift;
257*54fd6939SJiyong Park uint32_t pipe_sel = 0x0;
258*54fd6939SJiyong Park
259*54fd6939SJiyong Park /* If pipe selector is used the phy selector should be marked as
260*54fd6939SJiyong Park * unconnected.
261*54fd6939SJiyong Park */
262*54fd6939SJiyong Park mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index);
263*54fd6939SJiyong Park
264*54fd6939SJiyong Park reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET);
265*54fd6939SJiyong Park reg &= ~mask;
266*54fd6939SJiyong Park
267*54fd6939SJiyong Park switch (mode) {
268*54fd6939SJiyong Park case (COMPHY_PCIE_MODE):
269*54fd6939SJiyong Park /* For lanes support PCIE, selector value are all same */
270*54fd6939SJiyong Park pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_PCIE;
271*54fd6939SJiyong Park break;
272*54fd6939SJiyong Park
273*54fd6939SJiyong Park case (COMPHY_USB3H_MODE):
274*54fd6939SJiyong Park /* Only lane 1-4 support USB host, selector value is same */
275*54fd6939SJiyong Park if (comphy_index == COMPHY_LANE0 ||
276*54fd6939SJiyong Park comphy_index == COMPHY_LANE5)
277*54fd6939SJiyong Park ERROR("COMPHY[%d] mode[%d] is invalid\n",
278*54fd6939SJiyong Park comphy_index, mode);
279*54fd6939SJiyong Park else
280*54fd6939SJiyong Park pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBH;
281*54fd6939SJiyong Park break;
282*54fd6939SJiyong Park
283*54fd6939SJiyong Park case (COMPHY_USB3D_MODE):
284*54fd6939SJiyong Park /* Lane 1 and 4 support USB device, selector value is same */
285*54fd6939SJiyong Park if (comphy_index == COMPHY_LANE1 ||
286*54fd6939SJiyong Park comphy_index == COMPHY_LANE4)
287*54fd6939SJiyong Park pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBD;
288*54fd6939SJiyong Park else
289*54fd6939SJiyong Park ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index,
290*54fd6939SJiyong Park mode);
291*54fd6939SJiyong Park break;
292*54fd6939SJiyong Park
293*54fd6939SJiyong Park default:
294*54fd6939SJiyong Park ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode);
295*54fd6939SJiyong Park break;
296*54fd6939SJiyong Park }
297*54fd6939SJiyong Park
298*54fd6939SJiyong Park mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, reg |
299*54fd6939SJiyong Park (pipe_sel << shift));
300*54fd6939SJiyong Park }
301*54fd6939SJiyong Park
mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base,uint8_t comphy_index)302*54fd6939SJiyong Park int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, uint8_t comphy_index)
303*54fd6939SJiyong Park {
304*54fd6939SJiyong Park uintptr_t sd_ip_addr, addr;
305*54fd6939SJiyong Park uint32_t mask, data;
306*54fd6939SJiyong Park int ret = 0;
307*54fd6939SJiyong Park
308*54fd6939SJiyong Park debug_enter();
309*54fd6939SJiyong Park
310*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
311*54fd6939SJiyong Park comphy_index);
312*54fd6939SJiyong Park
313*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
314*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_PLL_TX_MASK &
315*54fd6939SJiyong Park SD_EXTERNAL_STATUS0_PLL_RX_MASK;
316*54fd6939SJiyong Park mask = data;
317*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask,
318*54fd6939SJiyong Park PLL_LOCK_TIMEOUT, REG_32BIT);
319*54fd6939SJiyong Park if (data != 0) {
320*54fd6939SJiyong Park if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)
321*54fd6939SJiyong Park ERROR("RX PLL is not locked\n");
322*54fd6939SJiyong Park if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)
323*54fd6939SJiyong Park ERROR("TX PLL is not locked\n");
324*54fd6939SJiyong Park
325*54fd6939SJiyong Park ret = -ETIMEDOUT;
326*54fd6939SJiyong Park }
327*54fd6939SJiyong Park
328*54fd6939SJiyong Park debug_exit();
329*54fd6939SJiyong Park
330*54fd6939SJiyong Park return ret;
331*54fd6939SJiyong Park }
332*54fd6939SJiyong Park
mvebu_cp110_polarity_invert(uintptr_t addr,uint8_t phy_polarity_invert)333*54fd6939SJiyong Park static void mvebu_cp110_polarity_invert(uintptr_t addr, uint8_t phy_polarity_invert)
334*54fd6939SJiyong Park {
335*54fd6939SJiyong Park uint32_t mask, data;
336*54fd6939SJiyong Park
337*54fd6939SJiyong Park /* Set RX / TX polarity */
338*54fd6939SJiyong Park data = mask = 0x0U;
339*54fd6939SJiyong Park if ((phy_polarity_invert & COMPHY_POLARITY_TXD_INVERT) != 0) {
340*54fd6939SJiyong Park data |= (1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET);
341*54fd6939SJiyong Park mask |= HPIPE_SYNC_PATTERN_TXD_INV_MASK;
342*54fd6939SJiyong Park debug("%s: inverting TX polarity\n", __func__);
343*54fd6939SJiyong Park }
344*54fd6939SJiyong Park
345*54fd6939SJiyong Park if ((phy_polarity_invert & COMPHY_POLARITY_RXD_INVERT) != 0) {
346*54fd6939SJiyong Park data |= (1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET);
347*54fd6939SJiyong Park mask |= HPIPE_SYNC_PATTERN_RXD_INV_MASK;
348*54fd6939SJiyong Park debug("%s: inverting RX polarity\n", __func__);
349*54fd6939SJiyong Park }
350*54fd6939SJiyong Park
351*54fd6939SJiyong Park reg_set(addr, data, mask);
352*54fd6939SJiyong Park }
353*54fd6939SJiyong Park
mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)354*54fd6939SJiyong Park static int mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base,
355*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
356*54fd6939SJiyong Park {
357*54fd6939SJiyong Park uintptr_t hpipe_addr, sd_ip_addr, comphy_addr;
358*54fd6939SJiyong Park uint32_t mask, data;
359*54fd6939SJiyong Park uint8_t ap_nr, cp_nr, phy_polarity_invert;
360*54fd6939SJiyong Park int ret = 0;
361*54fd6939SJiyong Park
362*54fd6939SJiyong Park debug_enter();
363*54fd6939SJiyong Park
364*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
365*54fd6939SJiyong Park
366*54fd6939SJiyong Park const struct sata_params *sata_static_values =
367*54fd6939SJiyong Park &sata_static_values_tab[ap_nr][cp_nr][comphy_index];
368*54fd6939SJiyong Park
369*54fd6939SJiyong Park phy_polarity_invert = sata_static_values->polarity_invert;
370*54fd6939SJiyong Park
371*54fd6939SJiyong Park /* configure phy selector for SATA */
372*54fd6939SJiyong Park mvebu_cp110_comphy_set_phy_selector(comphy_base,
373*54fd6939SJiyong Park comphy_index, comphy_mode);
374*54fd6939SJiyong Park
375*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
376*54fd6939SJiyong Park comphy_index);
377*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
378*54fd6939SJiyong Park comphy_index);
379*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
380*54fd6939SJiyong Park
381*54fd6939SJiyong Park debug(" add hpipe 0x%lx, sd 0x%lx, comphy 0x%lx\n",
382*54fd6939SJiyong Park hpipe_addr, sd_ip_addr, comphy_addr);
383*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
384*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
385*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
386*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
387*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
388*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
389*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
390*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
391*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
392*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
393*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
394*54fd6939SJiyong Park
395*54fd6939SJiyong Park /* Set select data width 40Bit - SATA mode only */
396*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG6_REG,
397*54fd6939SJiyong Park 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET,
398*54fd6939SJiyong Park COMMON_PHY_CFG6_IF_40_SEL_MASK);
399*54fd6939SJiyong Park
400*54fd6939SJiyong Park /* release from hard reset in SD external */
401*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
402*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
403*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
404*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
405*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
406*54fd6939SJiyong Park
407*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
408*54fd6939SJiyong Park mdelay(1);
409*54fd6939SJiyong Park
410*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
411*54fd6939SJiyong Park /* Start comphy Configuration */
412*54fd6939SJiyong Park /* Set reference clock to comes from group 1 - choose 25Mhz */
413*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG,
414*54fd6939SJiyong Park 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
415*54fd6939SJiyong Park HPIPE_MISC_REFCLK_SEL_MASK);
416*54fd6939SJiyong Park /* Reference frequency select set 1 (for SATA = 25Mhz) */
417*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
418*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
419*54fd6939SJiyong Park /* PHY mode select (set SATA = 0x0 */
420*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
421*54fd6939SJiyong Park data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
422*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
423*54fd6939SJiyong Park /* Set max PHY generation setting - 6Gbps */
424*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
425*54fd6939SJiyong Park 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
426*54fd6939SJiyong Park HPIPE_INTERFACE_GEN_MAX_MASK);
427*54fd6939SJiyong Park /* Set select data width 40Bit (SEL_BITS[2:0]) */
428*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
429*54fd6939SJiyong Park 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
430*54fd6939SJiyong Park
431*54fd6939SJiyong Park debug("stage: Analog parameters from ETP(HW)\n");
432*54fd6939SJiyong Park /* G1 settings */
433*54fd6939SJiyong Park mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
434*54fd6939SJiyong Park data = sata_static_values->g1_rx_selmupi <<
435*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
436*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
437*54fd6939SJiyong Park data |= sata_static_values->g1_rx_selmupf <<
438*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
439*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
440*54fd6939SJiyong Park data |= sata_static_values->g1_rx_selmufi <<
441*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
442*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
443*54fd6939SJiyong Park data |= sata_static_values->g1_rx_selmuff <<
444*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
445*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
446*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
447*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
448*54fd6939SJiyong Park
449*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
450*54fd6939SJiyong Park data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
451*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
452*54fd6939SJiyong Park data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
453*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
454*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
455*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK;
456*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET;
457*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK;
458*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET;
459*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
460*54fd6939SJiyong Park
461*54fd6939SJiyong Park /* G2 settings */
462*54fd6939SJiyong Park mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
463*54fd6939SJiyong Park data = sata_static_values->g2_rx_selmupi <<
464*54fd6939SJiyong Park HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
465*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK;
466*54fd6939SJiyong Park data |= sata_static_values->g2_rx_selmupf <<
467*54fd6939SJiyong Park HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET;
468*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
469*54fd6939SJiyong Park data |= sata_static_values->g2_rx_selmufi <<
470*54fd6939SJiyong Park HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
471*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK;
472*54fd6939SJiyong Park data |= sata_static_values->g2_rx_selmuff <<
473*54fd6939SJiyong Park HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET;
474*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK;
475*54fd6939SJiyong Park data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET;
476*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
477*54fd6939SJiyong Park
478*54fd6939SJiyong Park /* G3 settings */
479*54fd6939SJiyong Park mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
480*54fd6939SJiyong Park data = sata_static_values->g3_rx_selmupi <<
481*54fd6939SJiyong Park HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
482*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
483*54fd6939SJiyong Park data |= sata_static_values->g3_rx_selmupf <<
484*54fd6939SJiyong Park HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
485*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK;
486*54fd6939SJiyong Park data |= sata_static_values->g3_rx_selmufi <<
487*54fd6939SJiyong Park HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET;
488*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK;
489*54fd6939SJiyong Park data |= sata_static_values->g3_rx_selmuff <<
490*54fd6939SJiyong Park HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET;
491*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK;
492*54fd6939SJiyong Park data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET;
493*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK;
494*54fd6939SJiyong Park data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET;
495*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
496*54fd6939SJiyong Park data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
497*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask);
498*54fd6939SJiyong Park
499*54fd6939SJiyong Park /* DTL Control */
500*54fd6939SJiyong Park mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK;
501*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET;
502*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK;
503*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET;
504*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
505*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
506*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK;
507*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET;
508*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK;
509*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET;
510*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK;
511*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET;
512*54fd6939SJiyong Park mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK;
513*54fd6939SJiyong Park data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET;
514*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
515*54fd6939SJiyong Park
516*54fd6939SJiyong Park /* Trigger sampler enable pulse */
517*54fd6939SJiyong Park mask = HPIPE_SMAPLER_MASK;
518*54fd6939SJiyong Park data = 0x1 << HPIPE_SMAPLER_OFFSET;
519*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
520*54fd6939SJiyong Park mask = HPIPE_SMAPLER_MASK;
521*54fd6939SJiyong Park data = 0x0 << HPIPE_SMAPLER_OFFSET;
522*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
523*54fd6939SJiyong Park
524*54fd6939SJiyong Park /* VDD Calibration Control 3 */
525*54fd6939SJiyong Park mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
526*54fd6939SJiyong Park data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
527*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
528*54fd6939SJiyong Park
529*54fd6939SJiyong Park /* DFE Resolution Control */
530*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
531*54fd6939SJiyong Park data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
532*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
533*54fd6939SJiyong Park
534*54fd6939SJiyong Park /* DFE F3-F5 Coefficient Control */
535*54fd6939SJiyong Park mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
536*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
537*54fd6939SJiyong Park mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
538*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
539*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
540*54fd6939SJiyong Park
541*54fd6939SJiyong Park /* G3 Setting 3 */
542*54fd6939SJiyong Park mask = HPIPE_G3_FFE_CAP_SEL_MASK;
543*54fd6939SJiyong Park data = sata_static_values->g3_ffe_cap_sel <<
544*54fd6939SJiyong Park HPIPE_G3_FFE_CAP_SEL_OFFSET;
545*54fd6939SJiyong Park mask |= HPIPE_G3_FFE_RES_SEL_MASK;
546*54fd6939SJiyong Park data |= sata_static_values->g3_ffe_res_sel <<
547*54fd6939SJiyong Park HPIPE_G3_FFE_RES_SEL_OFFSET;
548*54fd6939SJiyong Park mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK;
549*54fd6939SJiyong Park data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET;
550*54fd6939SJiyong Park mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
551*54fd6939SJiyong Park data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
552*54fd6939SJiyong Park mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
553*54fd6939SJiyong Park data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
554*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
555*54fd6939SJiyong Park
556*54fd6939SJiyong Park /* G3 Setting 4 */
557*54fd6939SJiyong Park mask = HPIPE_G3_DFE_RES_MASK;
558*54fd6939SJiyong Park data = sata_static_values->g3_dfe_res << HPIPE_G3_DFE_RES_OFFSET;
559*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
560*54fd6939SJiyong Park
561*54fd6939SJiyong Park /* Offset Phase Control */
562*54fd6939SJiyong Park mask = HPIPE_OS_PH_OFFSET_MASK;
563*54fd6939SJiyong Park data = sata_static_values->align90 << HPIPE_OS_PH_OFFSET_OFFSET;
564*54fd6939SJiyong Park mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK;
565*54fd6939SJiyong Park data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET;
566*54fd6939SJiyong Park mask |= HPIPE_OS_PH_VALID_MASK;
567*54fd6939SJiyong Park data |= 0x0 << HPIPE_OS_PH_VALID_OFFSET;
568*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
569*54fd6939SJiyong Park mask = HPIPE_OS_PH_VALID_MASK;
570*54fd6939SJiyong Park data = 0x1 << HPIPE_OS_PH_VALID_OFFSET;
571*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
572*54fd6939SJiyong Park mask = HPIPE_OS_PH_VALID_MASK;
573*54fd6939SJiyong Park data = 0x0 << HPIPE_OS_PH_VALID_OFFSET;
574*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
575*54fd6939SJiyong Park
576*54fd6939SJiyong Park /* Set G1 TX amplitude and TX post emphasis value */
577*54fd6939SJiyong Park mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
578*54fd6939SJiyong Park data = sata_static_values->g1_amp << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
579*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK;
580*54fd6939SJiyong Park data |= sata_static_values->g1_tx_amp_adj <<
581*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET;
582*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
583*54fd6939SJiyong Park data |= sata_static_values->g1_emph <<
584*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
585*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK;
586*54fd6939SJiyong Park data |= sata_static_values->g1_emph_en <<
587*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET;
588*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
589*54fd6939SJiyong Park
590*54fd6939SJiyong Park /* Set G1 emph */
591*54fd6939SJiyong Park mask = HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
592*54fd6939SJiyong Park data = sata_static_values->g1_tx_emph_en <<
593*54fd6939SJiyong Park HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
594*54fd6939SJiyong Park mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
595*54fd6939SJiyong Park data |= sata_static_values->g1_tx_emph <<
596*54fd6939SJiyong Park HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
597*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
598*54fd6939SJiyong Park
599*54fd6939SJiyong Park /* Set G2 TX amplitude and TX post emphasis value */
600*54fd6939SJiyong Park mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK;
601*54fd6939SJiyong Park data = sata_static_values->g2_amp << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET;
602*54fd6939SJiyong Park mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK;
603*54fd6939SJiyong Park data |= sata_static_values->g2_tx_amp_adj <<
604*54fd6939SJiyong Park HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET;
605*54fd6939SJiyong Park mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK;
606*54fd6939SJiyong Park data |= sata_static_values->g2_emph <<
607*54fd6939SJiyong Park HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET;
608*54fd6939SJiyong Park mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK;
609*54fd6939SJiyong Park data |= sata_static_values->g2_emph_en <<
610*54fd6939SJiyong Park HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET;
611*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask);
612*54fd6939SJiyong Park
613*54fd6939SJiyong Park /* Set G2 emph */
614*54fd6939SJiyong Park mask = HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK;
615*54fd6939SJiyong Park data = sata_static_values->g2_tx_emph_en <<
616*54fd6939SJiyong Park HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET;
617*54fd6939SJiyong Park mask |= HPIPE_G2_SET_2_G2_TX_EMPH0_MASK;
618*54fd6939SJiyong Park data |= sata_static_values->g2_tx_emph <<
619*54fd6939SJiyong Park HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET;
620*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask);
621*54fd6939SJiyong Park
622*54fd6939SJiyong Park /* Set G3 TX amplitude and TX post emphasis value */
623*54fd6939SJiyong Park mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK;
624*54fd6939SJiyong Park data = sata_static_values->g3_amp << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET;
625*54fd6939SJiyong Park mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK;
626*54fd6939SJiyong Park data |= sata_static_values->g3_tx_amp_adj <<
627*54fd6939SJiyong Park HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET;
628*54fd6939SJiyong Park mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK;
629*54fd6939SJiyong Park data |= sata_static_values->g3_emph <<
630*54fd6939SJiyong Park HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET;
631*54fd6939SJiyong Park mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK;
632*54fd6939SJiyong Park data |= sata_static_values->g3_emph_en <<
633*54fd6939SJiyong Park HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET;
634*54fd6939SJiyong Park mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK;
635*54fd6939SJiyong Park data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET;
636*54fd6939SJiyong Park mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK;
637*54fd6939SJiyong Park data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET;
638*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask);
639*54fd6939SJiyong Park
640*54fd6939SJiyong Park /* Set G3 emph */
641*54fd6939SJiyong Park mask = HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK;
642*54fd6939SJiyong Park data = sata_static_values->g3_tx_emph_en <<
643*54fd6939SJiyong Park HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET;
644*54fd6939SJiyong Park mask |= HPIPE_G3_SET_2_G3_TX_EMPH0_MASK;
645*54fd6939SJiyong Park data |= sata_static_values->g3_tx_emph <<
646*54fd6939SJiyong Park HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET;
647*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SET_2_REG, data, mask);
648*54fd6939SJiyong Park
649*54fd6939SJiyong Park /* SERDES External Configuration 2 register */
650*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK;
651*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET;
652*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
653*54fd6939SJiyong Park
654*54fd6939SJiyong Park /* DFE reset sequence */
655*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
656*54fd6939SJiyong Park 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
657*54fd6939SJiyong Park HPIPE_PWR_CTR_RST_DFE_MASK);
658*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
659*54fd6939SJiyong Park 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
660*54fd6939SJiyong Park HPIPE_PWR_CTR_RST_DFE_MASK);
661*54fd6939SJiyong Park
662*54fd6939SJiyong Park if (phy_polarity_invert != 0)
663*54fd6939SJiyong Park mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG,
664*54fd6939SJiyong Park phy_polarity_invert);
665*54fd6939SJiyong Park
666*54fd6939SJiyong Park /* SW reset for interrupt logic */
667*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
668*54fd6939SJiyong Park 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
669*54fd6939SJiyong Park HPIPE_PWR_CTR_SFT_RST_MASK);
670*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
671*54fd6939SJiyong Park 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
672*54fd6939SJiyong Park HPIPE_PWR_CTR_SFT_RST_MASK);
673*54fd6939SJiyong Park
674*54fd6939SJiyong Park debug_exit();
675*54fd6939SJiyong Park
676*54fd6939SJiyong Park return ret;
677*54fd6939SJiyong Park }
678*54fd6939SJiyong Park
mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)679*54fd6939SJiyong Park static int mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base,
680*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
681*54fd6939SJiyong Park {
682*54fd6939SJiyong Park uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
683*54fd6939SJiyong Park uint32_t mask, data, sgmii_speed = COMPHY_GET_SPEED(comphy_mode);
684*54fd6939SJiyong Park int ret = 0;
685*54fd6939SJiyong Park
686*54fd6939SJiyong Park debug_enter();
687*54fd6939SJiyong Park
688*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
689*54fd6939SJiyong Park comphy_index);
690*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
691*54fd6939SJiyong Park comphy_index);
692*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
693*54fd6939SJiyong Park
694*54fd6939SJiyong Park /* configure phy selector for SGMII */
695*54fd6939SJiyong Park mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
696*54fd6939SJiyong Park comphy_mode);
697*54fd6939SJiyong Park
698*54fd6939SJiyong Park /* Confiugre the lane */
699*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
700*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
701*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
702*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
703*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
704*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
705*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
706*54fd6939SJiyong Park
707*54fd6939SJiyong Park /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
708*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
709*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
710*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
711*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
712*54fd6939SJiyong Park
713*54fd6939SJiyong Park if (sgmii_speed == COMPHY_SPEED_1_25G) {
714*54fd6939SJiyong Park /* SGMII 1G, SerDes speed 1.25G */
715*54fd6939SJiyong Park data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
716*54fd6939SJiyong Park data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
717*54fd6939SJiyong Park } else if (sgmii_speed == COMPHY_SPEED_3_125G) {
718*54fd6939SJiyong Park /* 2500Base-X, SerDes speed 3.125G */
719*54fd6939SJiyong Park data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
720*54fd6939SJiyong Park data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
721*54fd6939SJiyong Park } else {
722*54fd6939SJiyong Park /* Other rates are not supported */
723*54fd6939SJiyong Park ERROR("unsupported SGMII speed on comphy%d\n", comphy_index);
724*54fd6939SJiyong Park return -EINVAL;
725*54fd6939SJiyong Park }
726*54fd6939SJiyong Park
727*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
728*54fd6939SJiyong Park data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
729*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
730*54fd6939SJiyong Park data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
731*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
732*54fd6939SJiyong Park data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
733*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
734*54fd6939SJiyong Park
735*54fd6939SJiyong Park /* Set hard reset */
736*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
737*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
738*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
739*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
740*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
741*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
742*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
743*54fd6939SJiyong Park
744*54fd6939SJiyong Park /* Release hard reset */
745*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
746*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
747*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
748*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
749*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
750*54fd6939SJiyong Park
751*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
752*54fd6939SJiyong Park mdelay(1);
753*54fd6939SJiyong Park
754*54fd6939SJiyong Park /* Make sure that 40 data bits is disabled
755*54fd6939SJiyong Park * This bit is not cleared by reset
756*54fd6939SJiyong Park */
757*54fd6939SJiyong Park mask = COMMON_PHY_CFG6_IF_40_SEL_MASK;
758*54fd6939SJiyong Park data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET;
759*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask);
760*54fd6939SJiyong Park
761*54fd6939SJiyong Park /* Start comphy Configuration */
762*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
763*54fd6939SJiyong Park /* set reference clock */
764*54fd6939SJiyong Park mask = HPIPE_MISC_REFCLK_SEL_MASK;
765*54fd6939SJiyong Park data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
766*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
767*54fd6939SJiyong Park /* Power and PLL Control */
768*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
769*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
770*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
771*54fd6939SJiyong Park data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
772*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
773*54fd6939SJiyong Park /* Loopback register */
774*54fd6939SJiyong Park mask = HPIPE_LOOPBACK_SEL_MASK;
775*54fd6939SJiyong Park data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
776*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
777*54fd6939SJiyong Park /* rx control 1 */
778*54fd6939SJiyong Park mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
779*54fd6939SJiyong Park data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
780*54fd6939SJiyong Park mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
781*54fd6939SJiyong Park data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
782*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
783*54fd6939SJiyong Park /* DTL Control */
784*54fd6939SJiyong Park mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
785*54fd6939SJiyong Park data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
786*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
787*54fd6939SJiyong Park
788*54fd6939SJiyong Park /* Set analog parameters from ETP(HW) - for now use the default data */
789*54fd6939SJiyong Park debug("stage: Analog parameters from ETP(HW)\n");
790*54fd6939SJiyong Park
791*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
792*54fd6939SJiyong Park 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
793*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
794*54fd6939SJiyong Park
795*54fd6939SJiyong Park debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
796*54fd6939SJiyong Park /* SERDES External Configuration */
797*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
798*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
799*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
800*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
801*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
802*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
803*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
804*54fd6939SJiyong Park
805*54fd6939SJiyong Park ret = mvebu_cp110_comphy_is_pll_locked(comphy_base, comphy_index);
806*54fd6939SJiyong Park if (ret)
807*54fd6939SJiyong Park return ret;
808*54fd6939SJiyong Park
809*54fd6939SJiyong Park /* RX init */
810*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
811*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
812*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
813*54fd6939SJiyong Park
814*54fd6939SJiyong Park /* check that RX init done */
815*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
816*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
817*54fd6939SJiyong Park mask = data;
818*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
819*54fd6939SJiyong Park if (data != 0) {
820*54fd6939SJiyong Park ERROR("RX init failed\n");
821*54fd6939SJiyong Park ret = -ETIMEDOUT;
822*54fd6939SJiyong Park }
823*54fd6939SJiyong Park
824*54fd6939SJiyong Park debug("stage: RF Reset\n");
825*54fd6939SJiyong Park /* RF Reset */
826*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
827*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
828*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
829*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
830*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
831*54fd6939SJiyong Park
832*54fd6939SJiyong Park debug_exit();
833*54fd6939SJiyong Park
834*54fd6939SJiyong Park return ret;
835*54fd6939SJiyong Park }
836*54fd6939SJiyong Park
mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode,uint64_t comphy_train_base)837*54fd6939SJiyong Park static int mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base,
838*54fd6939SJiyong Park uint8_t comphy_index,
839*54fd6939SJiyong Park uint32_t comphy_mode,
840*54fd6939SJiyong Park uint64_t comphy_train_base)
841*54fd6939SJiyong Park {
842*54fd6939SJiyong Park uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
843*54fd6939SJiyong Park uint32_t mask, data, speed = COMPHY_GET_SPEED(comphy_mode);
844*54fd6939SJiyong Park int ret = 0;
845*54fd6939SJiyong Park uint8_t ap_nr, cp_nr;
846*54fd6939SJiyong Park
847*54fd6939SJiyong Park debug_enter();
848*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
849*54fd6939SJiyong Park
850*54fd6939SJiyong Park if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
851*54fd6939SJiyong Park debug("Skip %s for comphy[%d][%d][%d], due to rx training\n",
852*54fd6939SJiyong Park __func__, ap_nr, cp_nr, comphy_index);
853*54fd6939SJiyong Park return 0;
854*54fd6939SJiyong Park }
855*54fd6939SJiyong Park
856*54fd6939SJiyong Park const struct xfi_params *xfi_static_values =
857*54fd6939SJiyong Park &xfi_static_values_tab[ap_nr][cp_nr][comphy_index];
858*54fd6939SJiyong Park
859*54fd6939SJiyong Park debug("%s: the ap_nr = %d, cp_nr = %d, comphy_index %d\n",
860*54fd6939SJiyong Park __func__, ap_nr, cp_nr, comphy_index);
861*54fd6939SJiyong Park
862*54fd6939SJiyong Park debug("g1_ffe_cap_sel= 0x%x, g1_ffe_res_sel= 0x%x, g1_dfe_res= 0x%x\n",
863*54fd6939SJiyong Park xfi_static_values->g1_ffe_cap_sel,
864*54fd6939SJiyong Park xfi_static_values->g1_ffe_res_sel,
865*54fd6939SJiyong Park xfi_static_values->g1_dfe_res);
866*54fd6939SJiyong Park
867*54fd6939SJiyong Park if (!xfi_static_values->valid) {
868*54fd6939SJiyong Park ERROR("[ap%d][cp[%d][comphy:%d]: Has no valid static params\n",
869*54fd6939SJiyong Park ap_nr, cp_nr, comphy_index);
870*54fd6939SJiyong Park ERROR("[ap%d][cp[%d][comphy:%d]: porting layer needs update\n",
871*54fd6939SJiyong Park ap_nr, cp_nr, comphy_index);
872*54fd6939SJiyong Park return -EINVAL;
873*54fd6939SJiyong Park }
874*54fd6939SJiyong Park
875*54fd6939SJiyong Park if ((speed != COMPHY_SPEED_5_15625G) &&
876*54fd6939SJiyong Park (speed != COMPHY_SPEED_10_3125G) &&
877*54fd6939SJiyong Park (speed != COMPHY_SPEED_DEFAULT)) {
878*54fd6939SJiyong Park ERROR("comphy:%d: unsupported sfi/xfi speed\n", comphy_index);
879*54fd6939SJiyong Park return -EINVAL;
880*54fd6939SJiyong Park }
881*54fd6939SJiyong Park
882*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
883*54fd6939SJiyong Park comphy_index);
884*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
885*54fd6939SJiyong Park comphy_index);
886*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
887*54fd6939SJiyong Park
888*54fd6939SJiyong Park /* configure phy selector for XFI/SFI */
889*54fd6939SJiyong Park mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
890*54fd6939SJiyong Park comphy_mode);
891*54fd6939SJiyong Park
892*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
893*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
894*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
895*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
896*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
897*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
898*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
899*54fd6939SJiyong Park
900*54fd6939SJiyong Park /* Make sure that 40 data bits is disabled
901*54fd6939SJiyong Park * This bit is not cleared by reset
902*54fd6939SJiyong Park */
903*54fd6939SJiyong Park mask = COMMON_PHY_CFG6_IF_40_SEL_MASK;
904*54fd6939SJiyong Park data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET;
905*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask);
906*54fd6939SJiyong Park
907*54fd6939SJiyong Park /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
908*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
909*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
910*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
911*54fd6939SJiyong Park data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
912*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
913*54fd6939SJiyong Park data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
914*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
915*54fd6939SJiyong Park data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
916*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
917*54fd6939SJiyong Park data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
918*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
919*54fd6939SJiyong Park data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
920*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
921*54fd6939SJiyong Park
922*54fd6939SJiyong Park /* release from hard reset */
923*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
924*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
925*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
926*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
927*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
928*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
929*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
930*54fd6939SJiyong Park
931*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
932*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
933*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
934*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
935*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_TX_IDLE_MASK;
936*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET;
937*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
938*54fd6939SJiyong Park
939*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
940*54fd6939SJiyong Park mdelay(1);
941*54fd6939SJiyong Park
942*54fd6939SJiyong Park /*
943*54fd6939SJiyong Park * Erratum IPCE_COMPHY-1353: toggle TX_IDLE bit in
944*54fd6939SJiyong Park * addition to the PHY reset
945*54fd6939SJiyong Park */
946*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_TX_IDLE_MASK;
947*54fd6939SJiyong Park data = 0x0U;
948*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
949*54fd6939SJiyong Park
950*54fd6939SJiyong Park /* Start comphy Configuration */
951*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
952*54fd6939SJiyong Park /* set reference clock */
953*54fd6939SJiyong Park mask = HPIPE_MISC_ICP_FORCE_MASK;
954*54fd6939SJiyong Park data = (speed == COMPHY_SPEED_5_15625G) ?
955*54fd6939SJiyong Park (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) :
956*54fd6939SJiyong Park (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET);
957*54fd6939SJiyong Park mask |= HPIPE_MISC_REFCLK_SEL_MASK;
958*54fd6939SJiyong Park data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
959*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
960*54fd6939SJiyong Park /* Power and PLL Control */
961*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
962*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
963*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
964*54fd6939SJiyong Park data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
965*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
966*54fd6939SJiyong Park /* Loopback register */
967*54fd6939SJiyong Park mask = HPIPE_LOOPBACK_SEL_MASK;
968*54fd6939SJiyong Park data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
969*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
970*54fd6939SJiyong Park /* rx control 1 */
971*54fd6939SJiyong Park mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
972*54fd6939SJiyong Park data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
973*54fd6939SJiyong Park mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
974*54fd6939SJiyong Park data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
975*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
976*54fd6939SJiyong Park /* DTL Control */
977*54fd6939SJiyong Park mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
978*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
979*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
980*54fd6939SJiyong Park
981*54fd6939SJiyong Park /* Transmitter/Receiver Speed Divider Force */
982*54fd6939SJiyong Park if (speed == COMPHY_SPEED_5_15625G) {
983*54fd6939SJiyong Park mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK;
984*54fd6939SJiyong Park data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET;
985*54fd6939SJiyong Park mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK;
986*54fd6939SJiyong Park data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET;
987*54fd6939SJiyong Park mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK;
988*54fd6939SJiyong Park data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET;
989*54fd6939SJiyong Park mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK;
990*54fd6939SJiyong Park data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET;
991*54fd6939SJiyong Park } else {
992*54fd6939SJiyong Park mask = HPIPE_TXDIGCK_DIV_FORCE_MASK;
993*54fd6939SJiyong Park data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET;
994*54fd6939SJiyong Park }
995*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask);
996*54fd6939SJiyong Park
997*54fd6939SJiyong Park /* Set analog parameters from ETP(HW) */
998*54fd6939SJiyong Park debug("stage: Analog parameters from ETP(HW)\n");
999*54fd6939SJiyong Park /* SERDES External Configuration 2 */
1000*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK;
1001*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET;
1002*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
1003*54fd6939SJiyong Park /* 0x7-DFE Resolution control */
1004*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
1005*54fd6939SJiyong Park data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
1006*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
1007*54fd6939SJiyong Park /* 0xd-G1_Setting_0 */
1008*54fd6939SJiyong Park if (speed == COMPHY_SPEED_5_15625G) {
1009*54fd6939SJiyong Park mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
1010*54fd6939SJiyong Park data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
1011*54fd6939SJiyong Park } else {
1012*54fd6939SJiyong Park mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
1013*54fd6939SJiyong Park data = xfi_static_values->g1_amp <<
1014*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
1015*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
1016*54fd6939SJiyong Park data |= xfi_static_values->g1_emph <<
1017*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
1018*54fd6939SJiyong Park
1019*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK;
1020*54fd6939SJiyong Park data |= xfi_static_values->g1_emph_en <<
1021*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET;
1022*54fd6939SJiyong Park mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK;
1023*54fd6939SJiyong Park data |= xfi_static_values->g1_tx_amp_adj <<
1024*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET;
1025*54fd6939SJiyong Park }
1026*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
1027*54fd6939SJiyong Park /* Genration 1 setting 2 (G1_Setting_2) */
1028*54fd6939SJiyong Park mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
1029*54fd6939SJiyong Park data = xfi_static_values->g1_tx_emph <<
1030*54fd6939SJiyong Park HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
1031*54fd6939SJiyong Park mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
1032*54fd6939SJiyong Park data |= xfi_static_values->g1_tx_emph_en <<
1033*54fd6939SJiyong Park HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
1034*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
1035*54fd6939SJiyong Park /* Transmitter Slew Rate Control register (tx_reg1) */
1036*54fd6939SJiyong Park mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK;
1037*54fd6939SJiyong Park data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET;
1038*54fd6939SJiyong Park mask |= HPIPE_TX_REG1_SLC_EN_MASK;
1039*54fd6939SJiyong Park data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET;
1040*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask);
1041*54fd6939SJiyong Park /* Impedance Calibration Control register (cal_reg1) */
1042*54fd6939SJiyong Park mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK;
1043*54fd6939SJiyong Park data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
1044*54fd6939SJiyong Park mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK;
1045*54fd6939SJiyong Park data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET;
1046*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask);
1047*54fd6939SJiyong Park /* Generation 1 Setting 5 (g1_setting_5) */
1048*54fd6939SJiyong Park mask = HPIPE_G1_SETTING_5_G1_ICP_MASK;
1049*54fd6939SJiyong Park data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
1050*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask);
1051*54fd6939SJiyong Park
1052*54fd6939SJiyong Park /* 0xE-G1_Setting_1 */
1053*54fd6939SJiyong Park mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
1054*54fd6939SJiyong Park data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
1055*54fd6939SJiyong Park if (speed == COMPHY_SPEED_5_15625G) {
1056*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
1057*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
1058*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
1059*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
1060*54fd6939SJiyong Park } else {
1061*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
1062*54fd6939SJiyong Park data |= xfi_static_values->g1_rx_selmupi <<
1063*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
1064*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
1065*54fd6939SJiyong Park data |= xfi_static_values->g1_rx_selmupf <<
1066*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
1067*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
1068*54fd6939SJiyong Park data |= xfi_static_values->g1_rx_selmufi <<
1069*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
1070*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
1071*54fd6939SJiyong Park data |= xfi_static_values->g1_rx_selmuff <<
1072*54fd6939SJiyong Park HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
1073*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
1074*54fd6939SJiyong Park data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
1075*54fd6939SJiyong Park }
1076*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
1077*54fd6939SJiyong Park
1078*54fd6939SJiyong Park /* 0xA-DFE_Reg3 */
1079*54fd6939SJiyong Park mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
1080*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
1081*54fd6939SJiyong Park mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
1082*54fd6939SJiyong Park data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
1083*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
1084*54fd6939SJiyong Park
1085*54fd6939SJiyong Park /* 0x111-G1_Setting_4 */
1086*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
1087*54fd6939SJiyong Park data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
1088*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
1089*54fd6939SJiyong Park /* Genration 1 setting 3 (G1_Setting_3) */
1090*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK;
1091*54fd6939SJiyong Park data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET;
1092*54fd6939SJiyong Park if (speed == COMPHY_SPEED_5_15625G) {
1093*54fd6939SJiyong Park /* Force FFE (Feed Forward Equalization) to 5G */
1094*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
1095*54fd6939SJiyong Park data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
1096*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
1097*54fd6939SJiyong Park data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
1098*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
1099*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
1100*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
1101*54fd6939SJiyong Park } else {
1102*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
1103*54fd6939SJiyong Park data |= xfi_static_values->g1_ffe_cap_sel <<
1104*54fd6939SJiyong Park HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
1105*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
1106*54fd6939SJiyong Park data |= xfi_static_values->g1_ffe_res_sel <<
1107*54fd6939SJiyong Park HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
1108*54fd6939SJiyong Park mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
1109*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
1110*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
1111*54fd6939SJiyong Park
1112*54fd6939SJiyong Park /* Use the value from CAL_OS_PH_EXT */
1113*54fd6939SJiyong Park mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
1114*54fd6939SJiyong Park data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
1115*54fd6939SJiyong Park reg_set(hpipe_addr +
1116*54fd6939SJiyong Park HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
1117*54fd6939SJiyong Park data, mask);
1118*54fd6939SJiyong Park
1119*54fd6939SJiyong Park /* Update align90 */
1120*54fd6939SJiyong Park mask = HPIPE_CAL_OS_PH_EXT_MASK;
1121*54fd6939SJiyong Park data = xfi_static_values->align90 << HPIPE_CAL_OS_PH_EXT_OFFSET;
1122*54fd6939SJiyong Park reg_set(hpipe_addr +
1123*54fd6939SJiyong Park HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
1124*54fd6939SJiyong Park data, mask);
1125*54fd6939SJiyong Park
1126*54fd6939SJiyong Park /* Force DFE resolution (use gen table value) */
1127*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
1128*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
1129*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
1130*54fd6939SJiyong Park
1131*54fd6939SJiyong Park /* 0x111-G1 DFE_Setting_4 */
1132*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
1133*54fd6939SJiyong Park data = xfi_static_values->g1_dfe_res <<
1134*54fd6939SJiyong Park HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
1135*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
1136*54fd6939SJiyong Park }
1137*54fd6939SJiyong Park
1138*54fd6939SJiyong Park /* Connfigure RX training timer */
1139*54fd6939SJiyong Park mask = HPIPE_RX_TRAIN_TIMER_MASK;
1140*54fd6939SJiyong Park data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET;
1141*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
1142*54fd6939SJiyong Park
1143*54fd6939SJiyong Park /* Enable TX train peak to peak hold */
1144*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
1145*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
1146*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
1147*54fd6939SJiyong Park
1148*54fd6939SJiyong Park /* Configure TX preset index */
1149*54fd6939SJiyong Park mask = HPIPE_TX_PRESET_INDEX_MASK;
1150*54fd6939SJiyong Park data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET;
1151*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask);
1152*54fd6939SJiyong Park
1153*54fd6939SJiyong Park /* Disable pattern lock lost timeout */
1154*54fd6939SJiyong Park mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
1155*54fd6939SJiyong Park data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
1156*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
1157*54fd6939SJiyong Park
1158*54fd6939SJiyong Park /* Configure TX training pattern and TX training 16bit auto */
1159*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK;
1160*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET;
1161*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK;
1162*54fd6939SJiyong Park data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET;
1163*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
1164*54fd6939SJiyong Park
1165*54fd6939SJiyong Park /* Configure Training patten number */
1166*54fd6939SJiyong Park mask = HPIPE_TRAIN_PAT_NUM_MASK;
1167*54fd6939SJiyong Park data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET;
1168*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask);
1169*54fd6939SJiyong Park
1170*54fd6939SJiyong Park /* Configure differencial manchester encoter to ethernet mode */
1171*54fd6939SJiyong Park mask = HPIPE_DME_ETHERNET_MODE_MASK;
1172*54fd6939SJiyong Park data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET;
1173*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DME_REG, data, mask);
1174*54fd6939SJiyong Park
1175*54fd6939SJiyong Park /* Configure VDD Continuous Calibration */
1176*54fd6939SJiyong Park mask = HPIPE_CAL_VDD_CONT_MODE_MASK;
1177*54fd6939SJiyong Park data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET;
1178*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask);
1179*54fd6939SJiyong Park
1180*54fd6939SJiyong Park /* Trigger sampler enable pulse (by toggleing the bit) */
1181*54fd6939SJiyong Park mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK;
1182*54fd6939SJiyong Park data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET;
1183*54fd6939SJiyong Park mask |= HPIPE_SMAPLER_MASK;
1184*54fd6939SJiyong Park data |= 0x1 << HPIPE_SMAPLER_OFFSET;
1185*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
1186*54fd6939SJiyong Park mask = HPIPE_SMAPLER_MASK;
1187*54fd6939SJiyong Park data = 0x0 << HPIPE_SMAPLER_OFFSET;
1188*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
1189*54fd6939SJiyong Park
1190*54fd6939SJiyong Park /* Set External RX Regulator Control */
1191*54fd6939SJiyong Park mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
1192*54fd6939SJiyong Park data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
1193*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
1194*54fd6939SJiyong Park
1195*54fd6939SJiyong Park debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
1196*54fd6939SJiyong Park /* SERDES External Configuration */
1197*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
1198*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
1199*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
1200*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
1201*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
1202*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
1203*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
1204*54fd6939SJiyong Park
1205*54fd6939SJiyong Park /* check PLL rx & tx ready */
1206*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
1207*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
1208*54fd6939SJiyong Park SD_EXTERNAL_STATUS0_PLL_TX_MASK;
1209*54fd6939SJiyong Park mask = data;
1210*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask,
1211*54fd6939SJiyong Park PLL_LOCK_TIMEOUT, REG_32BIT);
1212*54fd6939SJiyong Park if (data != 0) {
1213*54fd6939SJiyong Park if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)
1214*54fd6939SJiyong Park ERROR("RX PLL is not locked\n");
1215*54fd6939SJiyong Park if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)
1216*54fd6939SJiyong Park ERROR("TX PLL is not locked\n");
1217*54fd6939SJiyong Park
1218*54fd6939SJiyong Park ret = -ETIMEDOUT;
1219*54fd6939SJiyong Park }
1220*54fd6939SJiyong Park
1221*54fd6939SJiyong Park /* RX init */
1222*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
1223*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
1224*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
1225*54fd6939SJiyong Park
1226*54fd6939SJiyong Park /* check that RX init done */
1227*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
1228*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
1229*54fd6939SJiyong Park mask = data;
1230*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
1231*54fd6939SJiyong Park if (data != 0) {
1232*54fd6939SJiyong Park ERROR("RX init failed\n");
1233*54fd6939SJiyong Park ret = -ETIMEDOUT;
1234*54fd6939SJiyong Park }
1235*54fd6939SJiyong Park
1236*54fd6939SJiyong Park debug("stage: RF Reset\n");
1237*54fd6939SJiyong Park /* RF Reset */
1238*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
1239*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
1240*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
1241*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
1242*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
1243*54fd6939SJiyong Park
1244*54fd6939SJiyong Park /* Force rx training on 10G port */
1245*54fd6939SJiyong Park data = mmio_read_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index));
1246*54fd6939SJiyong Park data |= COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE;
1247*54fd6939SJiyong Park mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data);
1248*54fd6939SJiyong Park mdelay(200);
1249*54fd6939SJiyong Park data &= ~COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE;
1250*54fd6939SJiyong Park mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data);
1251*54fd6939SJiyong Park
1252*54fd6939SJiyong Park debug_exit();
1253*54fd6939SJiyong Park
1254*54fd6939SJiyong Park return ret;
1255*54fd6939SJiyong Park }
1256*54fd6939SJiyong Park
mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)1257*54fd6939SJiyong Park static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base,
1258*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
1259*54fd6939SJiyong Park {
1260*54fd6939SJiyong Park int ret = 0;
1261*54fd6939SJiyong Park uint32_t reg, mask, data, pcie_width;
1262*54fd6939SJiyong Park uint32_t clk_dir;
1263*54fd6939SJiyong Park uintptr_t hpipe_addr, comphy_addr, addr;
1264*54fd6939SJiyong Park _Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode);
1265*54fd6939SJiyong Park _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
1266*54fd6939SJiyong Park
1267*54fd6939SJiyong Park /* In Armada 8K DB boards, PCIe initialization can be executed
1268*54fd6939SJiyong Park * only once (PCIe reset performed during chip power on and
1269*54fd6939SJiyong Park * it cannot be executed via GPIO later).
1270*54fd6939SJiyong Park * This means that power on can be executed only once, so let's
1271*54fd6939SJiyong Park * mark if the caller is bootloader or Linux.
1272*54fd6939SJiyong Park * If bootloader -> run power on.
1273*54fd6939SJiyong Park * If Linux -> exit.
1274*54fd6939SJiyong Park *
1275*54fd6939SJiyong Park * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
1276*54fd6939SJiyong Park * so after GPIO reset is added to Linux Kernel, it can be
1277*54fd6939SJiyong Park * powered-on by Linux.
1278*54fd6939SJiyong Park */
1279*54fd6939SJiyong Park if (!called_from_uboot)
1280*54fd6939SJiyong Park return ret;
1281*54fd6939SJiyong Park
1282*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
1283*54fd6939SJiyong Park comphy_index);
1284*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
1285*54fd6939SJiyong Park pcie_width = COMPHY_GET_PCIE_WIDTH(comphy_mode);
1286*54fd6939SJiyong Park
1287*54fd6939SJiyong Park debug_enter();
1288*54fd6939SJiyong Park
1289*54fd6939SJiyong Park spin_lock(&cp110_mac_reset_lock);
1290*54fd6939SJiyong Park
1291*54fd6939SJiyong Park reg = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
1292*54fd6939SJiyong Park SYS_CTRL_UINIT_SOFT_RESET_REG);
1293*54fd6939SJiyong Park switch (comphy_index) {
1294*54fd6939SJiyong Park case COMPHY_LANE0:
1295*54fd6939SJiyong Park reg |= PCIE_MAC_RESET_MASK_PORT0;
1296*54fd6939SJiyong Park break;
1297*54fd6939SJiyong Park case COMPHY_LANE4:
1298*54fd6939SJiyong Park reg |= PCIE_MAC_RESET_MASK_PORT1;
1299*54fd6939SJiyong Park break;
1300*54fd6939SJiyong Park case COMPHY_LANE5:
1301*54fd6939SJiyong Park reg |= PCIE_MAC_RESET_MASK_PORT2;
1302*54fd6939SJiyong Park break;
1303*54fd6939SJiyong Park }
1304*54fd6939SJiyong Park
1305*54fd6939SJiyong Park mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
1306*54fd6939SJiyong Park SYS_CTRL_UINIT_SOFT_RESET_REG, reg);
1307*54fd6939SJiyong Park spin_unlock(&cp110_mac_reset_lock);
1308*54fd6939SJiyong Park
1309*54fd6939SJiyong Park /* Configure PIPE selector for PCIE */
1310*54fd6939SJiyong Park mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index,
1311*54fd6939SJiyong Park comphy_mode);
1312*54fd6939SJiyong Park
1313*54fd6939SJiyong Park /*
1314*54fd6939SJiyong Park * Read SAR (Sample-At-Reset) configuration for the PCIe clock
1315*54fd6939SJiyong Park * direction.
1316*54fd6939SJiyong Park *
1317*54fd6939SJiyong Park * SerDes Lane 4/5 got the PCIe ref-clock #1,
1318*54fd6939SJiyong Park * and SerDes Lane 0 got PCIe ref-clock #0
1319*54fd6939SJiyong Park */
1320*54fd6939SJiyong Park reg = mmio_read_32(DFX_FROM_COMPHY_ADDR(comphy_base) +
1321*54fd6939SJiyong Park SAR_STATUS_0_REG);
1322*54fd6939SJiyong Park if (comphy_index == COMPHY_LANE4 || comphy_index == COMPHY_LANE5)
1323*54fd6939SJiyong Park clk_dir = (reg & SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK) >>
1324*54fd6939SJiyong Park SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET;
1325*54fd6939SJiyong Park else
1326*54fd6939SJiyong Park clk_dir = (reg & SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK) >>
1327*54fd6939SJiyong Park SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET;
1328*54fd6939SJiyong Park
1329*54fd6939SJiyong Park debug("On lane %d\n", comphy_index);
1330*54fd6939SJiyong Park debug("PCIe clock direction = %x\n", clk_dir);
1331*54fd6939SJiyong Park debug("PCIe Width = %d\n", pcie_width);
1332*54fd6939SJiyong Park
1333*54fd6939SJiyong Park /* enable PCIe X4 and X2 */
1334*54fd6939SJiyong Park if (comphy_index == COMPHY_LANE0) {
1335*54fd6939SJiyong Park if (pcie_width == PCIE_LNK_X4) {
1336*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET;
1337*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK;
1338*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
1339*54fd6939SJiyong Park data, mask);
1340*54fd6939SJiyong Park } else if (pcie_width == PCIE_LNK_X2) {
1341*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET;
1342*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK;
1343*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask);
1344*54fd6939SJiyong Park }
1345*54fd6939SJiyong Park }
1346*54fd6939SJiyong Park
1347*54fd6939SJiyong Park /* If PCIe clock is output and clock source from SerDes lane 5,
1348*54fd6939SJiyong Park * need to configure the clock-source MUX.
1349*54fd6939SJiyong Park * By default, the clock source is from lane 4
1350*54fd6939SJiyong Park */
1351*54fd6939SJiyong Park if (clk_dir && clk_src && (comphy_index == COMPHY_LANE5)) {
1352*54fd6939SJiyong Park data = DFX_DEV_GEN_PCIE_CLK_SRC_MUX <<
1353*54fd6939SJiyong Park DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET;
1354*54fd6939SJiyong Park mask = DFX_DEV_GEN_PCIE_CLK_SRC_MASK;
1355*54fd6939SJiyong Park reg_set(DFX_FROM_COMPHY_ADDR(comphy_base) +
1356*54fd6939SJiyong Park DFX_DEV_GEN_CTRL12_REG, data, mask);
1357*54fd6939SJiyong Park }
1358*54fd6939SJiyong Park
1359*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
1360*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
1361*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
1362*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
1363*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
1364*54fd6939SJiyong Park data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
1365*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
1366*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
1367*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
1368*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
1369*54fd6939SJiyong Park mask |= COMMON_PHY_PHY_MODE_MASK;
1370*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET;
1371*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
1372*54fd6939SJiyong Park
1373*54fd6939SJiyong Park /* release from hard reset */
1374*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
1375*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
1376*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
1377*54fd6939SJiyong Park data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
1378*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
1379*54fd6939SJiyong Park
1380*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
1381*54fd6939SJiyong Park mdelay(1);
1382*54fd6939SJiyong Park /* Start comphy Configuration */
1383*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
1384*54fd6939SJiyong Park /* Set PIPE soft reset */
1385*54fd6939SJiyong Park mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
1386*54fd6939SJiyong Park data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
1387*54fd6939SJiyong Park /* Set PHY datapath width mode for V0 */
1388*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
1389*54fd6939SJiyong Park data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
1390*54fd6939SJiyong Park /* Set Data bus width USB mode for V0 */
1391*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
1392*54fd6939SJiyong Park data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
1393*54fd6939SJiyong Park /* Set CORE_CLK output frequency for 250Mhz */
1394*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
1395*54fd6939SJiyong Park data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
1396*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
1397*54fd6939SJiyong Park /* Set PLL ready delay for 0x2 */
1398*54fd6939SJiyong Park data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET;
1399*54fd6939SJiyong Park mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK;
1400*54fd6939SJiyong Park if (pcie_width != PCIE_LNK_X1) {
1401*54fd6939SJiyong Park data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET;
1402*54fd6939SJiyong Park mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK;
1403*54fd6939SJiyong Park data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET;
1404*54fd6939SJiyong Park mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK;
1405*54fd6939SJiyong Park }
1406*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask);
1407*54fd6939SJiyong Park
1408*54fd6939SJiyong Park /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */
1409*54fd6939SJiyong Park data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET;
1410*54fd6939SJiyong Park mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK;
1411*54fd6939SJiyong Park if (pcie_width != PCIE_LNK_X1) {
1412*54fd6939SJiyong Park mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK;
1413*54fd6939SJiyong Park mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK;
1414*54fd6939SJiyong Park mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK;
1415*54fd6939SJiyong Park if (comphy_index == 0) {
1416*54fd6939SJiyong Park data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET;
1417*54fd6939SJiyong Park data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET;
1418*54fd6939SJiyong Park } else if (comphy_index == (pcie_width - 1)) {
1419*54fd6939SJiyong Park data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET;
1420*54fd6939SJiyong Park }
1421*54fd6939SJiyong Park }
1422*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask);
1423*54fd6939SJiyong Park /* Config update polarity equalization */
1424*54fd6939SJiyong Park data = 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET;
1425*54fd6939SJiyong Park mask = HPIPE_CFG_UPDATE_POLARITY_MASK;
1426*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, data, mask);
1427*54fd6939SJiyong Park /* Set PIPE version 4 to mode enable */
1428*54fd6939SJiyong Park data = 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET;
1429*54fd6939SJiyong Park mask = HPIPE_DFE_CTRL_28_PIPE4_MASK;
1430*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, data, mask);
1431*54fd6939SJiyong Park /* TODO: check if pcie clock is output/input - for bringup use input*/
1432*54fd6939SJiyong Park /* Enable PIN clock 100M_125M */
1433*54fd6939SJiyong Park mask = 0;
1434*54fd6939SJiyong Park data = 0;
1435*54fd6939SJiyong Park /* Only if clock is output, configure the clock-source mux */
1436*54fd6939SJiyong Park if (clk_dir) {
1437*54fd6939SJiyong Park mask |= HPIPE_MISC_CLK100M_125M_MASK;
1438*54fd6939SJiyong Park data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET;
1439*54fd6939SJiyong Park }
1440*54fd6939SJiyong Park /* Set PIN_TXDCLK_2X Clock Freq. Selection for outputs 500MHz clock */
1441*54fd6939SJiyong Park mask |= HPIPE_MISC_TXDCLK_2X_MASK;
1442*54fd6939SJiyong Park data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET;
1443*54fd6939SJiyong Park /* Enable 500MHz Clock */
1444*54fd6939SJiyong Park mask |= HPIPE_MISC_CLK500_EN_MASK;
1445*54fd6939SJiyong Park data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET;
1446*54fd6939SJiyong Park if (clk_dir) { /* output */
1447*54fd6939SJiyong Park /* Set reference clock comes from group 1 */
1448*54fd6939SJiyong Park mask |= HPIPE_MISC_REFCLK_SEL_MASK;
1449*54fd6939SJiyong Park data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
1450*54fd6939SJiyong Park } else {
1451*54fd6939SJiyong Park /* Set reference clock comes from group 2 */
1452*54fd6939SJiyong Park mask |= HPIPE_MISC_REFCLK_SEL_MASK;
1453*54fd6939SJiyong Park data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET;
1454*54fd6939SJiyong Park }
1455*54fd6939SJiyong Park mask |= HPIPE_MISC_ICP_FORCE_MASK;
1456*54fd6939SJiyong Park data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET;
1457*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
1458*54fd6939SJiyong Park if (clk_dir) { /* output */
1459*54fd6939SJiyong Park /* Set reference frequcency select - 0x2 for 25MHz*/
1460*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
1461*54fd6939SJiyong Park data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
1462*54fd6939SJiyong Park } else {
1463*54fd6939SJiyong Park /* Set reference frequcency select - 0x0 for 100MHz*/
1464*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
1465*54fd6939SJiyong Park data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
1466*54fd6939SJiyong Park }
1467*54fd6939SJiyong Park /* Set PHY mode to PCIe */
1468*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
1469*54fd6939SJiyong Park data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
1470*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
1471*54fd6939SJiyong Park
1472*54fd6939SJiyong Park /* ref clock alignment */
1473*54fd6939SJiyong Park if (pcie_width != PCIE_LNK_X1) {
1474*54fd6939SJiyong Park mask = HPIPE_LANE_ALIGN_OFF_MASK;
1475*54fd6939SJiyong Park data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET;
1476*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask);
1477*54fd6939SJiyong Park }
1478*54fd6939SJiyong Park
1479*54fd6939SJiyong Park /* Set the amount of time spent in the LoZ state - set for 0x7 only if
1480*54fd6939SJiyong Park * the PCIe clock is output
1481*54fd6939SJiyong Park */
1482*54fd6939SJiyong Park if (clk_dir)
1483*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
1484*54fd6939SJiyong Park 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
1485*54fd6939SJiyong Park HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
1486*54fd6939SJiyong Park
1487*54fd6939SJiyong Park /* Set Maximal PHY Generation Setting(8Gbps) */
1488*54fd6939SJiyong Park mask = HPIPE_INTERFACE_GEN_MAX_MASK;
1489*54fd6939SJiyong Park data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET;
1490*54fd6939SJiyong Park /* Bypass frame detection and sync detection for RX DATA */
1491*54fd6939SJiyong Park mask |= HPIPE_INTERFACE_DET_BYPASS_MASK;
1492*54fd6939SJiyong Park data |= 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET;
1493*54fd6939SJiyong Park /* Set Link Train Mode (Tx training control pins are used) */
1494*54fd6939SJiyong Park mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK;
1495*54fd6939SJiyong Park data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET;
1496*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask);
1497*54fd6939SJiyong Park
1498*54fd6939SJiyong Park /* Set Idle_sync enable */
1499*54fd6939SJiyong Park mask = HPIPE_PCIE_IDLE_SYNC_MASK;
1500*54fd6939SJiyong Park data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET;
1501*54fd6939SJiyong Park /* Select bits for PCIE Gen3(32bit) */
1502*54fd6939SJiyong Park mask |= HPIPE_PCIE_SEL_BITS_MASK;
1503*54fd6939SJiyong Park data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET;
1504*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask);
1505*54fd6939SJiyong Park
1506*54fd6939SJiyong Park /* Enable Tx_adapt_g1 */
1507*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_CTRL_G1_MASK;
1508*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET;
1509*54fd6939SJiyong Park /* Enable Tx_adapt_gn1 */
1510*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK;
1511*54fd6939SJiyong Park data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET;
1512*54fd6939SJiyong Park /* Disable Tx_adapt_g0 */
1513*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK;
1514*54fd6939SJiyong Park data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
1515*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
1516*54fd6939SJiyong Park
1517*54fd6939SJiyong Park /* Set reg_tx_train_chk_init */
1518*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_CHK_INIT_MASK;
1519*54fd6939SJiyong Park data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET;
1520*54fd6939SJiyong Park /* Enable TX_COE_FM_PIN_PCIE3_EN */
1521*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK;
1522*54fd6939SJiyong Park data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET;
1523*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
1524*54fd6939SJiyong Park
1525*54fd6939SJiyong Park debug("stage: TRx training parameters\n");
1526*54fd6939SJiyong Park /* Set Preset sweep configurations */
1527*54fd6939SJiyong Park mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK;
1528*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET;
1529*54fd6939SJiyong Park mask |= HPIPE_TX_NUM_OF_PRESET_MASK;
1530*54fd6939SJiyong Park data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET;
1531*54fd6939SJiyong Park mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK;
1532*54fd6939SJiyong Park data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET;
1533*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask);
1534*54fd6939SJiyong Park
1535*54fd6939SJiyong Park /* Tx train start configuration */
1536*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK;
1537*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET;
1538*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK;
1539*54fd6939SJiyong Park data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET;
1540*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK;
1541*54fd6939SJiyong Park data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET;
1542*54fd6939SJiyong Park mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK;
1543*54fd6939SJiyong Park data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET;
1544*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
1545*54fd6939SJiyong Park
1546*54fd6939SJiyong Park /* Enable Tx train P2P */
1547*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
1548*54fd6939SJiyong Park data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
1549*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
1550*54fd6939SJiyong Park
1551*54fd6939SJiyong Park /* Configure Tx train timeout */
1552*54fd6939SJiyong Park mask = HPIPE_TRX_TRAIN_TIMER_MASK;
1553*54fd6939SJiyong Park data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET;
1554*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask);
1555*54fd6939SJiyong Park
1556*54fd6939SJiyong Park /* Disable G0/G1/GN1 adaptation */
1557*54fd6939SJiyong Park mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK
1558*54fd6939SJiyong Park | HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
1559*54fd6939SJiyong Park data = 0;
1560*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
1561*54fd6939SJiyong Park
1562*54fd6939SJiyong Park /* Disable DTL frequency loop */
1563*54fd6939SJiyong Park mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
1564*54fd6939SJiyong Park data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
1565*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
1566*54fd6939SJiyong Park
1567*54fd6939SJiyong Park /* Configure G3 DFE */
1568*54fd6939SJiyong Park mask = HPIPE_G3_DFE_RES_MASK;
1569*54fd6939SJiyong Park data = 0x3 << HPIPE_G3_DFE_RES_OFFSET;
1570*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
1571*54fd6939SJiyong Park
1572*54fd6939SJiyong Park /* Use TX/RX training result for DFE */
1573*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
1574*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
1575*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
1576*54fd6939SJiyong Park
1577*54fd6939SJiyong Park /* Configure initial and final coefficient value for receiver */
1578*54fd6939SJiyong Park mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
1579*54fd6939SJiyong Park data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
1580*54fd6939SJiyong Park
1581*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
1582*54fd6939SJiyong Park data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
1583*54fd6939SJiyong Park
1584*54fd6939SJiyong Park mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
1585*54fd6939SJiyong Park data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
1586*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask);
1587*54fd6939SJiyong Park
1588*54fd6939SJiyong Park /* Trigger sampler enable pulse */
1589*54fd6939SJiyong Park mask = HPIPE_SMAPLER_MASK;
1590*54fd6939SJiyong Park data = 0x1 << HPIPE_SMAPLER_OFFSET;
1591*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
1592*54fd6939SJiyong Park udelay(5);
1593*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask);
1594*54fd6939SJiyong Park
1595*54fd6939SJiyong Park /* FFE resistor tuning for different bandwidth */
1596*54fd6939SJiyong Park mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
1597*54fd6939SJiyong Park data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
1598*54fd6939SJiyong Park mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
1599*54fd6939SJiyong Park data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
1600*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
1601*54fd6939SJiyong Park
1602*54fd6939SJiyong Park /* Pattern lock lost timeout disable */
1603*54fd6939SJiyong Park mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
1604*54fd6939SJiyong Park data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
1605*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
1606*54fd6939SJiyong Park
1607*54fd6939SJiyong Park /* Configure DFE adaptations */
1608*54fd6939SJiyong Park mask = HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK;
1609*54fd6939SJiyong Park data = 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET;
1610*54fd6939SJiyong Park mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK;
1611*54fd6939SJiyong Park data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET;
1612*54fd6939SJiyong Park mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK;
1613*54fd6939SJiyong Park data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET;
1614*54fd6939SJiyong Park mask |= HPIPE_CDR_MAX_DFE_ADAPT_1_MASK;
1615*54fd6939SJiyong Park data |= 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET;
1616*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
1617*54fd6939SJiyong Park
1618*54fd6939SJiyong Park mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK;
1619*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET;
1620*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask);
1621*54fd6939SJiyong Park
1622*54fd6939SJiyong Park /* Genration 2 setting 1*/
1623*54fd6939SJiyong Park mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
1624*54fd6939SJiyong Park data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
1625*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK;
1626*54fd6939SJiyong Park data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET;
1627*54fd6939SJiyong Park mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
1628*54fd6939SJiyong Park data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
1629*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
1630*54fd6939SJiyong Park
1631*54fd6939SJiyong Park /* DFE enable */
1632*54fd6939SJiyong Park mask = HPIPE_G2_DFE_RES_MASK;
1633*54fd6939SJiyong Park data = 0x3 << HPIPE_G2_DFE_RES_OFFSET;
1634*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask);
1635*54fd6939SJiyong Park
1636*54fd6939SJiyong Park /* Configure DFE Resolution */
1637*54fd6939SJiyong Park mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK;
1638*54fd6939SJiyong Park data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET;
1639*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
1640*54fd6939SJiyong Park
1641*54fd6939SJiyong Park /* VDD calibration control */
1642*54fd6939SJiyong Park mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
1643*54fd6939SJiyong Park data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
1644*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
1645*54fd6939SJiyong Park
1646*54fd6939SJiyong Park /* Set PLL Charge-pump Current Control */
1647*54fd6939SJiyong Park mask = HPIPE_G3_SETTING_5_G3_ICP_MASK;
1648*54fd6939SJiyong Park data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET;
1649*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask);
1650*54fd6939SJiyong Park
1651*54fd6939SJiyong Park /* Set lane rqualization remote setting */
1652*54fd6939SJiyong Park mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK;
1653*54fd6939SJiyong Park data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET;
1654*54fd6939SJiyong Park mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK;
1655*54fd6939SJiyong Park data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET;
1656*54fd6939SJiyong Park mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK;
1657*54fd6939SJiyong Park data |= 0x6 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET;
1658*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask);
1659*54fd6939SJiyong Park
1660*54fd6939SJiyong Park mask = HPIPE_CFG_EQ_BUNDLE_DIS_MASK;
1661*54fd6939SJiyong Park data = 0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET;
1662*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG2_REG, data, mask);
1663*54fd6939SJiyong Park
1664*54fd6939SJiyong Park debug("stage: Comphy power up\n");
1665*54fd6939SJiyong Park
1666*54fd6939SJiyong Park /* For PCIe X4 or X2:
1667*54fd6939SJiyong Park * release from reset only after finish to configure all lanes
1668*54fd6939SJiyong Park */
1669*54fd6939SJiyong Park if ((pcie_width == PCIE_LNK_X1) || (comphy_index == (pcie_width - 1))) {
1670*54fd6939SJiyong Park uint32_t i, start_lane, end_lane;
1671*54fd6939SJiyong Park
1672*54fd6939SJiyong Park if (pcie_width != PCIE_LNK_X1) {
1673*54fd6939SJiyong Park /* allows writing to all lanes in one write */
1674*54fd6939SJiyong Park data = 0x0;
1675*54fd6939SJiyong Park if (pcie_width == PCIE_LNK_X2)
1676*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK;
1677*54fd6939SJiyong Park else if (pcie_width == PCIE_LNK_X4)
1678*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK;
1679*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask);
1680*54fd6939SJiyong Park start_lane = 0;
1681*54fd6939SJiyong Park end_lane = pcie_width;
1682*54fd6939SJiyong Park
1683*54fd6939SJiyong Park /* Release from PIPE soft reset
1684*54fd6939SJiyong Park * For PCIe by4 or by2:
1685*54fd6939SJiyong Park * release from soft reset all lanes - can't use
1686*54fd6939SJiyong Park * read modify write
1687*54fd6939SJiyong Park */
1688*54fd6939SJiyong Park reg_set(HPIPE_ADDR(
1689*54fd6939SJiyong Park COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), 0) +
1690*54fd6939SJiyong Park HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff);
1691*54fd6939SJiyong Park } else {
1692*54fd6939SJiyong Park start_lane = comphy_index;
1693*54fd6939SJiyong Park end_lane = comphy_index + 1;
1694*54fd6939SJiyong Park
1695*54fd6939SJiyong Park /* Release from PIPE soft reset
1696*54fd6939SJiyong Park * for PCIe by4 or by2:
1697*54fd6939SJiyong Park * release from soft reset all lanes
1698*54fd6939SJiyong Park */
1699*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
1700*54fd6939SJiyong Park 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
1701*54fd6939SJiyong Park HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
1702*54fd6939SJiyong Park }
1703*54fd6939SJiyong Park
1704*54fd6939SJiyong Park if (pcie_width != PCIE_LNK_X1) {
1705*54fd6939SJiyong Park /* disable writing to all lanes with one write */
1706*54fd6939SJiyong Park if (pcie_width == PCIE_LNK_X2) {
1707*54fd6939SJiyong Park data = (COMPHY_LANE0 <<
1708*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) |
1709*54fd6939SJiyong Park (COMPHY_LANE1 <<
1710*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET);
1711*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK;
1712*54fd6939SJiyong Park } else if (pcie_width == PCIE_LNK_X4) {
1713*54fd6939SJiyong Park data = (COMPHY_LANE0 <<
1714*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) |
1715*54fd6939SJiyong Park (COMPHY_LANE1 <<
1716*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET) |
1717*54fd6939SJiyong Park (COMPHY_LANE2 <<
1718*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET) |
1719*54fd6939SJiyong Park (COMPHY_LANE3 <<
1720*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET);
1721*54fd6939SJiyong Park mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK;
1722*54fd6939SJiyong Park }
1723*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
1724*54fd6939SJiyong Park data, mask);
1725*54fd6939SJiyong Park }
1726*54fd6939SJiyong Park
1727*54fd6939SJiyong Park debug("stage: Check PLL\n");
1728*54fd6939SJiyong Park /* Read lane status */
1729*54fd6939SJiyong Park for (i = start_lane; i < end_lane; i++) {
1730*54fd6939SJiyong Park addr = HPIPE_ADDR(
1731*54fd6939SJiyong Park COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), i) +
1732*54fd6939SJiyong Park HPIPE_LANE_STATUS1_REG;
1733*54fd6939SJiyong Park data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
1734*54fd6939SJiyong Park mask = data;
1735*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask,
1736*54fd6939SJiyong Park PLL_LOCK_TIMEOUT,
1737*54fd6939SJiyong Park REG_32BIT);
1738*54fd6939SJiyong Park if (data) {
1739*54fd6939SJiyong Park ERROR("Failed to lock PCIE PLL\n");
1740*54fd6939SJiyong Park ret = -ETIMEDOUT;
1741*54fd6939SJiyong Park }
1742*54fd6939SJiyong Park }
1743*54fd6939SJiyong Park }
1744*54fd6939SJiyong Park
1745*54fd6939SJiyong Park debug_exit();
1746*54fd6939SJiyong Park
1747*54fd6939SJiyong Park return ret;
1748*54fd6939SJiyong Park }
1749*54fd6939SJiyong Park
mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)1750*54fd6939SJiyong Park static int mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base,
1751*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
1752*54fd6939SJiyong Park {
1753*54fd6939SJiyong Park uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
1754*54fd6939SJiyong Park uint32_t mask, data;
1755*54fd6939SJiyong Park int ret = 0;
1756*54fd6939SJiyong Park
1757*54fd6939SJiyong Park debug_enter();
1758*54fd6939SJiyong Park
1759*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
1760*54fd6939SJiyong Park comphy_index);
1761*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
1762*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
1763*54fd6939SJiyong Park comphy_index);
1764*54fd6939SJiyong Park
1765*54fd6939SJiyong Park /* configure phy selector for RXAUI */
1766*54fd6939SJiyong Park mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
1767*54fd6939SJiyong Park comphy_mode);
1768*54fd6939SJiyong Park
1769*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
1770*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
1771*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
1772*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
1773*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
1774*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
1775*54fd6939SJiyong Park
1776*54fd6939SJiyong Park if (comphy_index == 2) {
1777*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
1778*54fd6939SJiyong Park 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET,
1779*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_RXAUI0_MASK);
1780*54fd6939SJiyong Park }
1781*54fd6939SJiyong Park if (comphy_index == 4) {
1782*54fd6939SJiyong Park reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
1783*54fd6939SJiyong Park 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET,
1784*54fd6939SJiyong Park COMMON_PHY_SD_CTRL1_RXAUI1_MASK);
1785*54fd6939SJiyong Park }
1786*54fd6939SJiyong Park
1787*54fd6939SJiyong Park /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
1788*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
1789*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
1790*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
1791*54fd6939SJiyong Park data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
1792*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
1793*54fd6939SJiyong Park data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
1794*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
1795*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
1796*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
1797*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
1798*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
1799*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
1800*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK;
1801*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET;
1802*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
1803*54fd6939SJiyong Park
1804*54fd6939SJiyong Park /* release from hard reset */
1805*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
1806*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
1807*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
1808*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
1809*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
1810*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
1811*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
1812*54fd6939SJiyong Park
1813*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
1814*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
1815*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
1816*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
1817*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
1818*54fd6939SJiyong Park
1819*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
1820*54fd6939SJiyong Park mdelay(1);
1821*54fd6939SJiyong Park
1822*54fd6939SJiyong Park /* Start comphy Configuration */
1823*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
1824*54fd6939SJiyong Park /* set reference clock */
1825*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG,
1826*54fd6939SJiyong Park 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
1827*54fd6939SJiyong Park HPIPE_MISC_REFCLK_SEL_MASK);
1828*54fd6939SJiyong Park /* Power and PLL Control */
1829*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
1830*54fd6939SJiyong Park data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
1831*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
1832*54fd6939SJiyong Park data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
1833*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
1834*54fd6939SJiyong Park /* Loopback register */
1835*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
1836*54fd6939SJiyong Park 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
1837*54fd6939SJiyong Park /* rx control 1 */
1838*54fd6939SJiyong Park mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
1839*54fd6939SJiyong Park data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
1840*54fd6939SJiyong Park mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
1841*54fd6939SJiyong Park data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
1842*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
1843*54fd6939SJiyong Park /* DTL Control */
1844*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG,
1845*54fd6939SJiyong Park 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET,
1846*54fd6939SJiyong Park HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK);
1847*54fd6939SJiyong Park
1848*54fd6939SJiyong Park /* Set analog parameters from ETP(HW) */
1849*54fd6939SJiyong Park debug("stage: Analog parameters from ETP(HW)\n");
1850*54fd6939SJiyong Park /* SERDES External Configuration 2 */
1851*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG,
1852*54fd6939SJiyong Park 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET,
1853*54fd6939SJiyong Park SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK);
1854*54fd6939SJiyong Park /* 0x7-DFE Resolution control */
1855*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET,
1856*54fd6939SJiyong Park HPIPE_DFE_RES_FORCE_MASK);
1857*54fd6939SJiyong Park /* 0xd-G1_Setting_0 */
1858*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
1859*54fd6939SJiyong Park 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
1860*54fd6939SJiyong Park HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
1861*54fd6939SJiyong Park /* 0xE-G1_Setting_1 */
1862*54fd6939SJiyong Park mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
1863*54fd6939SJiyong Park data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
1864*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
1865*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
1866*54fd6939SJiyong Park mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
1867*54fd6939SJiyong Park data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
1868*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
1869*54fd6939SJiyong Park /* 0xA-DFE_Reg3 */
1870*54fd6939SJiyong Park mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
1871*54fd6939SJiyong Park data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
1872*54fd6939SJiyong Park mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
1873*54fd6939SJiyong Park data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
1874*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
1875*54fd6939SJiyong Park
1876*54fd6939SJiyong Park /* 0x111-G1_Setting_4 */
1877*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
1878*54fd6939SJiyong Park data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
1879*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
1880*54fd6939SJiyong Park
1881*54fd6939SJiyong Park debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
1882*54fd6939SJiyong Park /* SERDES External Configuration */
1883*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
1884*54fd6939SJiyong Park data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
1885*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
1886*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
1887*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
1888*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
1889*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
1890*54fd6939SJiyong Park
1891*54fd6939SJiyong Park
1892*54fd6939SJiyong Park /* check PLL rx & tx ready */
1893*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
1894*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
1895*54fd6939SJiyong Park SD_EXTERNAL_STATUS0_PLL_TX_MASK;
1896*54fd6939SJiyong Park mask = data;
1897*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT);
1898*54fd6939SJiyong Park if (data != 0) {
1899*54fd6939SJiyong Park debug("Read from reg = %lx - value = 0x%x\n",
1900*54fd6939SJiyong Park sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
1901*54fd6939SJiyong Park ERROR("SD_EXTERNAL_STATUS0_PLL_RX is %d, -\"-_PLL_TX is %d\n",
1902*54fd6939SJiyong Park (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
1903*54fd6939SJiyong Park (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
1904*54fd6939SJiyong Park ret = -ETIMEDOUT;
1905*54fd6939SJiyong Park }
1906*54fd6939SJiyong Park
1907*54fd6939SJiyong Park /* RX init */
1908*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG,
1909*54fd6939SJiyong Park 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET,
1910*54fd6939SJiyong Park SD_EXTERNAL_CONFIG1_RX_INIT_MASK);
1911*54fd6939SJiyong Park
1912*54fd6939SJiyong Park /* check that RX init done */
1913*54fd6939SJiyong Park addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
1914*54fd6939SJiyong Park data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
1915*54fd6939SJiyong Park mask = data;
1916*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
1917*54fd6939SJiyong Park if (data != 0) {
1918*54fd6939SJiyong Park debug("Read from reg = %lx - value = 0x%x\n",
1919*54fd6939SJiyong Park sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
1920*54fd6939SJiyong Park ERROR("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
1921*54fd6939SJiyong Park ret = -ETIMEDOUT;
1922*54fd6939SJiyong Park }
1923*54fd6939SJiyong Park
1924*54fd6939SJiyong Park debug("stage: RF Reset\n");
1925*54fd6939SJiyong Park /* RF Reset */
1926*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
1927*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
1928*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
1929*54fd6939SJiyong Park data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
1930*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
1931*54fd6939SJiyong Park
1932*54fd6939SJiyong Park debug_exit();
1933*54fd6939SJiyong Park
1934*54fd6939SJiyong Park return ret;
1935*54fd6939SJiyong Park }
1936*54fd6939SJiyong Park
mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)1937*54fd6939SJiyong Park static int mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base,
1938*54fd6939SJiyong Park uint8_t comphy_index, uint32_t comphy_mode)
1939*54fd6939SJiyong Park {
1940*54fd6939SJiyong Park uintptr_t hpipe_addr, comphy_addr, addr;
1941*54fd6939SJiyong Park uint32_t mask, data;
1942*54fd6939SJiyong Park uint8_t ap_nr, cp_nr, phy_polarity_invert;
1943*54fd6939SJiyong Park int ret = 0;
1944*54fd6939SJiyong Park
1945*54fd6939SJiyong Park debug_enter();
1946*54fd6939SJiyong Park
1947*54fd6939SJiyong Park /* Configure PIPE selector for USB3 */
1948*54fd6939SJiyong Park mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index,
1949*54fd6939SJiyong Park comphy_mode);
1950*54fd6939SJiyong Park
1951*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
1952*54fd6939SJiyong Park
1953*54fd6939SJiyong Park const struct usb_params *usb_static_values =
1954*54fd6939SJiyong Park &usb_static_values_tab[ap_nr][cp_nr][comphy_index];
1955*54fd6939SJiyong Park
1956*54fd6939SJiyong Park phy_polarity_invert = usb_static_values->polarity_invert;
1957*54fd6939SJiyong Park
1958*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
1959*54fd6939SJiyong Park comphy_index);
1960*54fd6939SJiyong Park comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
1961*54fd6939SJiyong Park
1962*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
1963*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
1964*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
1965*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
1966*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
1967*54fd6939SJiyong Park data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
1968*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
1969*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
1970*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
1971*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
1972*54fd6939SJiyong Park mask |= COMMON_PHY_PHY_MODE_MASK;
1973*54fd6939SJiyong Park data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET;
1974*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
1975*54fd6939SJiyong Park
1976*54fd6939SJiyong Park /* release from hard reset */
1977*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
1978*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
1979*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
1980*54fd6939SJiyong Park data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
1981*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
1982*54fd6939SJiyong Park
1983*54fd6939SJiyong Park /* Wait 1ms - until band gap and ref clock ready */
1984*54fd6939SJiyong Park mdelay(1);
1985*54fd6939SJiyong Park
1986*54fd6939SJiyong Park /* Start comphy Configuration */
1987*54fd6939SJiyong Park debug("stage: Comphy configuration\n");
1988*54fd6939SJiyong Park /* Set PIPE soft reset */
1989*54fd6939SJiyong Park mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
1990*54fd6939SJiyong Park data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
1991*54fd6939SJiyong Park /* Set PHY datapath width mode for V0 */
1992*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
1993*54fd6939SJiyong Park data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
1994*54fd6939SJiyong Park /* Set Data bus width USB mode for V0 */
1995*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
1996*54fd6939SJiyong Park data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
1997*54fd6939SJiyong Park /* Set CORE_CLK output frequency for 250Mhz */
1998*54fd6939SJiyong Park mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
1999*54fd6939SJiyong Park data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
2000*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
2001*54fd6939SJiyong Park /* Set PLL ready delay for 0x2 */
2002*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG,
2003*54fd6939SJiyong Park 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET,
2004*54fd6939SJiyong Park HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK);
2005*54fd6939SJiyong Park /* Set reference clock to come from group 1 - 25Mhz */
2006*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_MISC_REG,
2007*54fd6939SJiyong Park 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
2008*54fd6939SJiyong Park HPIPE_MISC_REFCLK_SEL_MASK);
2009*54fd6939SJiyong Park /* Set reference frequcency select - 0x2 */
2010*54fd6939SJiyong Park mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
2011*54fd6939SJiyong Park data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
2012*54fd6939SJiyong Park /* Set PHY mode to USB - 0x5 */
2013*54fd6939SJiyong Park mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
2014*54fd6939SJiyong Park data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
2015*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
2016*54fd6939SJiyong Park /* Set the amount of time spent in the LoZ state - set for 0x7 */
2017*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
2018*54fd6939SJiyong Park 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
2019*54fd6939SJiyong Park HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
2020*54fd6939SJiyong Park /* Set max PHY generation setting - 5Gbps */
2021*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
2022*54fd6939SJiyong Park 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
2023*54fd6939SJiyong Park HPIPE_INTERFACE_GEN_MAX_MASK);
2024*54fd6939SJiyong Park /* Set select data width 20Bit (SEL_BITS[2:0]) */
2025*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
2026*54fd6939SJiyong Park 0x1 << HPIPE_LOOPBACK_SEL_OFFSET,
2027*54fd6939SJiyong Park HPIPE_LOOPBACK_SEL_MASK);
2028*54fd6939SJiyong Park /* select de-emphasize 3.5db */
2029*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG,
2030*54fd6939SJiyong Park 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET,
2031*54fd6939SJiyong Park HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK);
2032*54fd6939SJiyong Park /* override tx margining from the MAC */
2033*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG,
2034*54fd6939SJiyong Park 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET,
2035*54fd6939SJiyong Park HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK);
2036*54fd6939SJiyong Park
2037*54fd6939SJiyong Park /* The polarity inversion for USB was not tested due to lack of hw
2038*54fd6939SJiyong Park * design which requires it. Support is added for customer needs.
2039*54fd6939SJiyong Park */
2040*54fd6939SJiyong Park if (phy_polarity_invert)
2041*54fd6939SJiyong Park mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG,
2042*54fd6939SJiyong Park phy_polarity_invert);
2043*54fd6939SJiyong Park
2044*54fd6939SJiyong Park /* Start analog parameters from ETP(HW) */
2045*54fd6939SJiyong Park debug("stage: Analog parameters from ETP(HW)\n");
2046*54fd6939SJiyong Park /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */
2047*54fd6939SJiyong Park mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK;
2048*54fd6939SJiyong Park data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET;
2049*54fd6939SJiyong Park /* Set Override PHY DFE control pins for 0x1 */
2050*54fd6939SJiyong Park mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK;
2051*54fd6939SJiyong Park data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET;
2052*54fd6939SJiyong Park /* Set Spread Spectrum Clock Enable fot 0x1 */
2053*54fd6939SJiyong Park mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK;
2054*54fd6939SJiyong Park data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET;
2055*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
2056*54fd6939SJiyong Park /* Confifure SSC amplitude */
2057*54fd6939SJiyong Park mask = HPIPE_G2_TX_SSC_AMP_MASK;
2058*54fd6939SJiyong Park data = 0x1f << HPIPE_G2_TX_SSC_AMP_OFFSET;
2059*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask);
2060*54fd6939SJiyong Park /* End of analog parameters */
2061*54fd6939SJiyong Park
2062*54fd6939SJiyong Park debug("stage: Comphy power up\n");
2063*54fd6939SJiyong Park /* Release from PIPE soft reset */
2064*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
2065*54fd6939SJiyong Park 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
2066*54fd6939SJiyong Park HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
2067*54fd6939SJiyong Park
2068*54fd6939SJiyong Park /* wait 15ms - for comphy calibration done */
2069*54fd6939SJiyong Park debug("stage: Check PLL\n");
2070*54fd6939SJiyong Park /* Read lane status */
2071*54fd6939SJiyong Park addr = hpipe_addr + HPIPE_LANE_STATUS1_REG;
2072*54fd6939SJiyong Park data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
2073*54fd6939SJiyong Park mask = data;
2074*54fd6939SJiyong Park data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT);
2075*54fd6939SJiyong Park if (data != 0) {
2076*54fd6939SJiyong Park debug("Read from reg = %lx - value = 0x%x\n",
2077*54fd6939SJiyong Park hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
2078*54fd6939SJiyong Park ERROR("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
2079*54fd6939SJiyong Park ret = -ETIMEDOUT;
2080*54fd6939SJiyong Park }
2081*54fd6939SJiyong Park
2082*54fd6939SJiyong Park debug_exit();
2083*54fd6939SJiyong Park
2084*54fd6939SJiyong Park return ret;
2085*54fd6939SJiyong Park }
2086*54fd6939SJiyong Park
rx_pre_train(uint64_t comphy_base,uint8_t comphy_index)2087*54fd6939SJiyong Park static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index)
2088*54fd6939SJiyong Park {
2089*54fd6939SJiyong Park uintptr_t hpipe_addr;
2090*54fd6939SJiyong Park uint32_t mask, data;
2091*54fd6939SJiyong Park
2092*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
2093*54fd6939SJiyong Park comphy_index);
2094*54fd6939SJiyong Park
2095*54fd6939SJiyong Park debug("rx_training preparation\n\n");
2096*54fd6939SJiyong Park
2097*54fd6939SJiyong Park mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK;
2098*54fd6939SJiyong Park data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF);
2099*54fd6939SJiyong Park mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK;
2100*54fd6939SJiyong Park data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF);
2101*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask);
2102*54fd6939SJiyong Park
2103*54fd6939SJiyong Park
2104*54fd6939SJiyong Park mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
2105*54fd6939SJiyong Park data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
2106*54fd6939SJiyong Park mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK;
2107*54fd6939SJiyong Park data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF);
2108*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask);
2109*54fd6939SJiyong Park
2110*54fd6939SJiyong Park mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK;
2111*54fd6939SJiyong Park data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF);
2112*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
2113*54fd6939SJiyong Park
2114*54fd6939SJiyong Park mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK;
2115*54fd6939SJiyong Park data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF);
2116*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask);
2117*54fd6939SJiyong Park
2118*54fd6939SJiyong Park mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK;
2119*54fd6939SJiyong Park data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF);
2120*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask);
2121*54fd6939SJiyong Park
2122*54fd6939SJiyong Park mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK;
2123*54fd6939SJiyong Park data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET);
2124*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
2125*54fd6939SJiyong Park
2126*54fd6939SJiyong Park mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK;
2127*54fd6939SJiyong Park data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF);
2128*54fd6939SJiyong Park mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
2129*54fd6939SJiyong Park data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
2130*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
2131*54fd6939SJiyong Park }
2132*54fd6939SJiyong Park
mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,uint8_t comphy_index)2133*54fd6939SJiyong Park int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
2134*54fd6939SJiyong Park uint8_t comphy_index)
2135*54fd6939SJiyong Park {
2136*54fd6939SJiyong Park uint32_t mask, data, timeout;
2137*54fd6939SJiyong Park uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res;
2138*54fd6939SJiyong Park uintptr_t hpipe_addr;
2139*54fd6939SJiyong Park
2140*54fd6939SJiyong Park uint8_t ap_nr, cp_nr;
2141*54fd6939SJiyong Park
2142*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
2143*54fd6939SJiyong Park
2144*54fd6939SJiyong Park hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
2145*54fd6939SJiyong Park comphy_index);
2146*54fd6939SJiyong Park
2147*54fd6939SJiyong Park debug_enter();
2148*54fd6939SJiyong Park
2149*54fd6939SJiyong Park rx_pre_train(comphy_base, comphy_index);
2150*54fd6939SJiyong Park
2151*54fd6939SJiyong Park debug("Preparation for rx_training\n\n");
2152*54fd6939SJiyong Park
2153*54fd6939SJiyong Park /* Use the FFE table */
2154*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
2155*54fd6939SJiyong Park data = 0 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
2156*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
2157*54fd6939SJiyong Park
2158*54fd6939SJiyong Park /* Use auto-calibration value */
2159*54fd6939SJiyong Park mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
2160*54fd6939SJiyong Park data = 0 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
2161*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
2162*54fd6939SJiyong Park data, mask);
2163*54fd6939SJiyong Park
2164*54fd6939SJiyong Park /* Use Tx/Rx training results */
2165*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
2166*54fd6939SJiyong Park data = 0 << HPIPE_DFE_RES_FORCE_OFFSET;
2167*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
2168*54fd6939SJiyong Park
2169*54fd6939SJiyong Park debug("Enable RX training\n\n");
2170*54fd6939SJiyong Park
2171*54fd6939SJiyong Park mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
2172*54fd6939SJiyong Park data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
2173*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
2174*54fd6939SJiyong Park
2175*54fd6939SJiyong Park /* Check the result of RX training */
2176*54fd6939SJiyong Park timeout = RX_TRAINING_TIMEOUT;
2177*54fd6939SJiyong Park mask = HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET |
2178*54fd6939SJiyong Park HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET |
2179*54fd6939SJiyong Park HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK;
2180*54fd6939SJiyong Park while (timeout) {
2181*54fd6939SJiyong Park data = mmio_read_32(hpipe_addr + HPIPE_INTERRUPT_1_REGISTER);
2182*54fd6939SJiyong Park if (data & mask)
2183*54fd6939SJiyong Park break;
2184*54fd6939SJiyong Park mdelay(1);
2185*54fd6939SJiyong Park timeout--;
2186*54fd6939SJiyong Park }
2187*54fd6939SJiyong Park
2188*54fd6939SJiyong Park debug("RX training result: interrupt reg 0x%lx = 0x%x\n\n",
2189*54fd6939SJiyong Park hpipe_addr + HPIPE_INTERRUPT_1_REGISTER, data);
2190*54fd6939SJiyong Park
2191*54fd6939SJiyong Park if (timeout == 0 || data & HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK) {
2192*54fd6939SJiyong Park ERROR("Rx training timeout...\n");
2193*54fd6939SJiyong Park return -ETIMEDOUT;
2194*54fd6939SJiyong Park }
2195*54fd6939SJiyong Park
2196*54fd6939SJiyong Park if (data & HPIPE_TRX_TRAIN_FAILED_MASK) {
2197*54fd6939SJiyong Park ERROR("Rx training failed...\n");
2198*54fd6939SJiyong Park return -EINVAL;
2199*54fd6939SJiyong Park }
2200*54fd6939SJiyong Park
2201*54fd6939SJiyong Park mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
2202*54fd6939SJiyong Park data = 0x0 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
2203*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
2204*54fd6939SJiyong Park
2205*54fd6939SJiyong Park debug("Training done, reading results...\n\n");
2206*54fd6939SJiyong Park
2207*54fd6939SJiyong Park mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK;
2208*54fd6939SJiyong Park g1_ffe_res_sel = ((mmio_read_32(hpipe_addr +
2209*54fd6939SJiyong Park HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
2210*54fd6939SJiyong Park & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET);
2211*54fd6939SJiyong Park
2212*54fd6939SJiyong Park mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK;
2213*54fd6939SJiyong Park g1_ffe_cap_sel = ((mmio_read_32(hpipe_addr +
2214*54fd6939SJiyong Park HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
2215*54fd6939SJiyong Park & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET);
2216*54fd6939SJiyong Park
2217*54fd6939SJiyong Park mask = HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK;
2218*54fd6939SJiyong Park align90 = ((mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG)
2219*54fd6939SJiyong Park & mask) >> HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET);
2220*54fd6939SJiyong Park
2221*54fd6939SJiyong Park mask = HPIPE_ADAPTED_DFE_RES_MASK;
2222*54fd6939SJiyong Park g1_dfe_res = ((mmio_read_32(hpipe_addr +
2223*54fd6939SJiyong Park HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG)
2224*54fd6939SJiyong Park & mask) >> HPIPE_ADAPTED_DFE_RES_OFFSET);
2225*54fd6939SJiyong Park
2226*54fd6939SJiyong Park debug("================================================\n");
2227*54fd6939SJiyong Park debug("Switching to static configuration:\n");
2228*54fd6939SJiyong Park debug("FFE_RES = 0x%x FFE_CAP = 0x%x align90 = 0x%x g1_dfe_res 0x%x\n",
2229*54fd6939SJiyong Park g1_ffe_res_sel, g1_ffe_cap_sel, align90, g1_dfe_res);
2230*54fd6939SJiyong Park debug("Result after training: 0x%lx= 0x%x, 0x%lx= 0x%x, 0x%lx = 0x%x\n",
2231*54fd6939SJiyong Park (hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
2232*54fd6939SJiyong Park mmio_read_32(hpipe_addr +
2233*54fd6939SJiyong Park HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
2234*54fd6939SJiyong Park (hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
2235*54fd6939SJiyong Park mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
2236*54fd6939SJiyong Park (hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG),
2237*54fd6939SJiyong Park mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG));
2238*54fd6939SJiyong Park debug("================================================\n");
2239*54fd6939SJiyong Park
2240*54fd6939SJiyong Park /* Update FFE_RES */
2241*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
2242*54fd6939SJiyong Park data = g1_ffe_res_sel << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
2243*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
2244*54fd6939SJiyong Park
2245*54fd6939SJiyong Park /* Update FFE_CAP */
2246*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
2247*54fd6939SJiyong Park data = g1_ffe_cap_sel << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
2248*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
2249*54fd6939SJiyong Park
2250*54fd6939SJiyong Park /* Bypass the FFE table settings and use the FFE settings directly from
2251*54fd6939SJiyong Park * registers FFE_RES_SEL and FFE_CAP_SEL
2252*54fd6939SJiyong Park */
2253*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
2254*54fd6939SJiyong Park data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
2255*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
2256*54fd6939SJiyong Park
2257*54fd6939SJiyong Park /* Force DFE resolution (use gen table value) */
2258*54fd6939SJiyong Park mask = HPIPE_DFE_RES_FORCE_MASK;
2259*54fd6939SJiyong Park data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
2260*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
2261*54fd6939SJiyong Park
2262*54fd6939SJiyong Park /* 0x111-G1 DFE_Setting_4 */
2263*54fd6939SJiyong Park mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
2264*54fd6939SJiyong Park data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
2265*54fd6939SJiyong Park reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
2266*54fd6939SJiyong Park
2267*54fd6939SJiyong Park printf("########################################################\n");
2268*54fd6939SJiyong Park printf("# To use trained values update the ATF sources:\n");
2269*54fd6939SJiyong Park printf("# plat/marvell/armada/a8k/<board_type>/board/phy-porting-layer.h ");
2270*54fd6939SJiyong Park printf("file\n# with new values as below (for appropriate AP nr %d",
2271*54fd6939SJiyong Park ap_nr);
2272*54fd6939SJiyong Park printf("and CP nr: %d comphy_index %d\n\n",
2273*54fd6939SJiyong Park cp_nr, comphy_index);
2274*54fd6939SJiyong Park printf("static struct xfi_params xfi_static_values_tab[AP_NUM]");
2275*54fd6939SJiyong Park printf("[CP_NUM][MAX_LANE_NR] = {\n");
2276*54fd6939SJiyong Park printf("\t...\n");
2277*54fd6939SJiyong Park printf("\t.g1_ffe_res_sel = 0x%x,\n", g1_ffe_res_sel);
2278*54fd6939SJiyong Park printf("\t.g1_ffe_cap_sel = 0x%x,\n", g1_ffe_cap_sel);
2279*54fd6939SJiyong Park printf("\t.align90 = 0x%x,\n", align90);
2280*54fd6939SJiyong Park printf("\t.g1_dfe_res = 0x%x\n", g1_dfe_res);
2281*54fd6939SJiyong Park printf("\t...\n");
2282*54fd6939SJiyong Park printf("};\n\n");
2283*54fd6939SJiyong Park printf("########################################################\n");
2284*54fd6939SJiyong Park
2285*54fd6939SJiyong Park rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1;
2286*54fd6939SJiyong Park
2287*54fd6939SJiyong Park return 0;
2288*54fd6939SJiyong Park }
2289*54fd6939SJiyong Park
2290*54fd6939SJiyong Park /* During AP the proper mode is auto-negotiated and the mac, pcs and serdes
2291*54fd6939SJiyong Park * configuration are done by the firmware loaded to the MG's CM3 for appropriate
2292*54fd6939SJiyong Park * negotiated mode. Therefore there is no need to configure the mac, pcs and
2293*54fd6939SJiyong Park * serdes from u-boot. The only thing that need to be setup is powering up
2294*54fd6939SJiyong Park * the comphy, which is done through Common PHY<n> Configuration 1 Register
2295*54fd6939SJiyong Park * (CP0: 0xF2441000, CP1: 0xF4441000). This step can't be done by MG's CM3,
2296*54fd6939SJiyong Park * since it doesn't have an access to this register-set (but it has access to
2297*54fd6939SJiyong Park * the network registers like: MG, AP, MAC, PCS, Serdes etc.)
2298*54fd6939SJiyong Park */
mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)2299*54fd6939SJiyong Park static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,
2300*54fd6939SJiyong Park uint8_t comphy_index,
2301*54fd6939SJiyong Park uint32_t comphy_mode)
2302*54fd6939SJiyong Park {
2303*54fd6939SJiyong Park uint32_t mask, data;
2304*54fd6939SJiyong Park uintptr_t comphy_addr = comphy_addr =
2305*54fd6939SJiyong Park COMPHY_ADDR(comphy_base, comphy_index);
2306*54fd6939SJiyong Park
2307*54fd6939SJiyong Park /* configure phy selector for XFI/SFI */
2308*54fd6939SJiyong Park mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
2309*54fd6939SJiyong Park comphy_mode);
2310*54fd6939SJiyong Park debug_enter();
2311*54fd6939SJiyong Park debug("stage: RFU configurations - hard reset comphy\n");
2312*54fd6939SJiyong Park /* RFU configurations - hard reset comphy */
2313*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_UP_MASK;
2314*54fd6939SJiyong Park data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
2315*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
2316*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
2317*54fd6939SJiyong Park reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
2318*54fd6939SJiyong Park debug_exit();
2319*54fd6939SJiyong Park
2320*54fd6939SJiyong Park #if MSS_SUPPORT
2321*54fd6939SJiyong Park do {
2322*54fd6939SJiyong Park uint8_t ap_nr, cp_nr;
2323*54fd6939SJiyong Park
2324*54fd6939SJiyong Park /* start ap fw */
2325*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
2326*54fd6939SJiyong Park mg_start_ap_fw(cp_nr, comphy_index);
2327*54fd6939SJiyong Park
2328*54fd6939SJiyong Park } while (0);
2329*54fd6939SJiyong Park #endif
2330*54fd6939SJiyong Park return 0;
2331*54fd6939SJiyong Park }
2332*54fd6939SJiyong Park
2333*54fd6939SJiyong Park /*
2334*54fd6939SJiyong Park * This function allows to reset the digital synchronizers between
2335*54fd6939SJiyong Park * the MAC and the PHY, it is required when the MAC changes its state.
2336*54fd6939SJiyong Park */
mvebu_cp110_comphy_digital_reset(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode,uint32_t command)2337*54fd6939SJiyong Park int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base,
2338*54fd6939SJiyong Park uint8_t comphy_index,
2339*54fd6939SJiyong Park uint32_t comphy_mode, uint32_t command)
2340*54fd6939SJiyong Park {
2341*54fd6939SJiyong Park int mode = COMPHY_GET_MODE(comphy_mode);
2342*54fd6939SJiyong Park uintptr_t sd_ip_addr;
2343*54fd6939SJiyong Park uint32_t mask, data;
2344*54fd6939SJiyong Park
2345*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
2346*54fd6939SJiyong Park comphy_index);
2347*54fd6939SJiyong Park
2348*54fd6939SJiyong Park switch (mode) {
2349*54fd6939SJiyong Park case (COMPHY_SGMII_MODE):
2350*54fd6939SJiyong Park case (COMPHY_2500BASEX_MODE):
2351*54fd6939SJiyong Park case (COMPHY_XFI_MODE):
2352*54fd6939SJiyong Park case (COMPHY_SFI_MODE):
2353*54fd6939SJiyong Park case (COMPHY_RXAUI_MODE):
2354*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
2355*54fd6939SJiyong Park data = ((command == COMPHY_COMMAND_DIGITAL_PWR_OFF) ?
2356*54fd6939SJiyong Park 0x0 : 0x1) << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
2357*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
2358*54fd6939SJiyong Park break;
2359*54fd6939SJiyong Park default:
2360*54fd6939SJiyong Park ERROR("comphy%d: Digital PWR ON/OFF is not supported\n",
2361*54fd6939SJiyong Park comphy_index);
2362*54fd6939SJiyong Park return -EINVAL;
2363*54fd6939SJiyong Park }
2364*54fd6939SJiyong Park
2365*54fd6939SJiyong Park return 0;
2366*54fd6939SJiyong Park }
2367*54fd6939SJiyong Park
mvebu_cp110_comphy_power_on(uint64_t comphy_base,uint8_t comphy_index,uint64_t comphy_mode,uint64_t comphy_train_base)2368*54fd6939SJiyong Park int mvebu_cp110_comphy_power_on(uint64_t comphy_base,
2369*54fd6939SJiyong Park uint8_t comphy_index,
2370*54fd6939SJiyong Park uint64_t comphy_mode,
2371*54fd6939SJiyong Park uint64_t comphy_train_base)
2372*54fd6939SJiyong Park {
2373*54fd6939SJiyong Park int mode = COMPHY_GET_MODE(comphy_mode);
2374*54fd6939SJiyong Park int err = 0;
2375*54fd6939SJiyong Park
2376*54fd6939SJiyong Park debug_enter();
2377*54fd6939SJiyong Park
2378*54fd6939SJiyong Park switch (mode) {
2379*54fd6939SJiyong Park case(COMPHY_SATA_MODE):
2380*54fd6939SJiyong Park err = mvebu_cp110_comphy_sata_power_on(comphy_base,
2381*54fd6939SJiyong Park comphy_index,
2382*54fd6939SJiyong Park comphy_mode);
2383*54fd6939SJiyong Park break;
2384*54fd6939SJiyong Park case(COMPHY_SGMII_MODE):
2385*54fd6939SJiyong Park case(COMPHY_2500BASEX_MODE):
2386*54fd6939SJiyong Park err = mvebu_cp110_comphy_sgmii_power_on(comphy_base,
2387*54fd6939SJiyong Park comphy_index,
2388*54fd6939SJiyong Park comphy_mode);
2389*54fd6939SJiyong Park break;
2390*54fd6939SJiyong Park /* From comphy perspective, XFI and SFI are the same */
2391*54fd6939SJiyong Park case (COMPHY_XFI_MODE):
2392*54fd6939SJiyong Park case (COMPHY_SFI_MODE):
2393*54fd6939SJiyong Park err = mvebu_cp110_comphy_xfi_power_on(comphy_base,
2394*54fd6939SJiyong Park comphy_index,
2395*54fd6939SJiyong Park comphy_mode,
2396*54fd6939SJiyong Park comphy_train_base);
2397*54fd6939SJiyong Park break;
2398*54fd6939SJiyong Park case (COMPHY_PCIE_MODE):
2399*54fd6939SJiyong Park err = mvebu_cp110_comphy_pcie_power_on(comphy_base,
2400*54fd6939SJiyong Park comphy_index,
2401*54fd6939SJiyong Park comphy_mode);
2402*54fd6939SJiyong Park break;
2403*54fd6939SJiyong Park case (COMPHY_RXAUI_MODE):
2404*54fd6939SJiyong Park err = mvebu_cp110_comphy_rxaui_power_on(comphy_base,
2405*54fd6939SJiyong Park comphy_index,
2406*54fd6939SJiyong Park comphy_mode);
2407*54fd6939SJiyong Park break;
2408*54fd6939SJiyong Park case (COMPHY_USB3H_MODE):
2409*54fd6939SJiyong Park case (COMPHY_USB3D_MODE):
2410*54fd6939SJiyong Park err = mvebu_cp110_comphy_usb3_power_on(comphy_base,
2411*54fd6939SJiyong Park comphy_index,
2412*54fd6939SJiyong Park comphy_mode);
2413*54fd6939SJiyong Park break;
2414*54fd6939SJiyong Park case (COMPHY_AP_MODE):
2415*54fd6939SJiyong Park err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index,
2416*54fd6939SJiyong Park comphy_mode);
2417*54fd6939SJiyong Park break;
2418*54fd6939SJiyong Park default:
2419*54fd6939SJiyong Park ERROR("comphy%d: unsupported comphy mode\n", comphy_index);
2420*54fd6939SJiyong Park err = -EINVAL;
2421*54fd6939SJiyong Park break;
2422*54fd6939SJiyong Park }
2423*54fd6939SJiyong Park
2424*54fd6939SJiyong Park debug_exit();
2425*54fd6939SJiyong Park
2426*54fd6939SJiyong Park return err;
2427*54fd6939SJiyong Park }
2428*54fd6939SJiyong Park
mvebu_cp110_comphy_power_off(uint64_t comphy_base,uint8_t comphy_index,uint64_t comphy_mode)2429*54fd6939SJiyong Park int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index,
2430*54fd6939SJiyong Park uint64_t comphy_mode)
2431*54fd6939SJiyong Park {
2432*54fd6939SJiyong Park uintptr_t sd_ip_addr, comphy_ip_addr;
2433*54fd6939SJiyong Park uint32_t mask, data;
2434*54fd6939SJiyong Park uint8_t ap_nr, cp_nr;
2435*54fd6939SJiyong Park _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
2436*54fd6939SJiyong Park
2437*54fd6939SJiyong Park debug_enter();
2438*54fd6939SJiyong Park
2439*54fd6939SJiyong Park /* Power-off might happen because of 2 things:
2440*54fd6939SJiyong Park * 1. Bootloader turns off unconnected lanes
2441*54fd6939SJiyong Park * 2. Linux turns off all lanes during boot
2442*54fd6939SJiyong Park * (and then reconfigure it).
2443*54fd6939SJiyong Park *
2444*54fd6939SJiyong Park * For PCIe, there's a problem:
2445*54fd6939SJiyong Park * In Armada 8K DB boards, PCIe initialization can be executed
2446*54fd6939SJiyong Park * only once (PCIe reset performed during chip power on and
2447*54fd6939SJiyong Park * it cannot be executed via GPIO later) so a lane configured to
2448*54fd6939SJiyong Park * PCIe should not be powered off by Linux.
2449*54fd6939SJiyong Park *
2450*54fd6939SJiyong Park * So, check 2 things:
2451*54fd6939SJiyong Park * 1. Is Linux called for power-off?
2452*54fd6939SJiyong Park * 2. Is the comphy configured to PCIe?
2453*54fd6939SJiyong Park * If the answer is YES for both 1 and 2, skip the power-off.
2454*54fd6939SJiyong Park *
2455*54fd6939SJiyong Park * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
2456*54fd6939SJiyong Park * so after GPIO reset is added to Linux Kernel, it can be
2457*54fd6939SJiyong Park * powered-off.
2458*54fd6939SJiyong Park */
2459*54fd6939SJiyong Park if (!called_from_uboot) {
2460*54fd6939SJiyong Park data = mmio_read_32(comphy_base +
2461*54fd6939SJiyong Park COMMON_SELECTOR_PIPE_REG_OFFSET);
2462*54fd6939SJiyong Park data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index);
2463*54fd6939SJiyong Park data &= COMMON_SELECTOR_COMPHY_MASK;
2464*54fd6939SJiyong Park if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE)
2465*54fd6939SJiyong Park return 0;
2466*54fd6939SJiyong Park }
2467*54fd6939SJiyong Park
2468*54fd6939SJiyong Park mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
2469*54fd6939SJiyong Park
2470*54fd6939SJiyong Park if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
2471*54fd6939SJiyong Park debug("Skip %s for comphy[%d][%d][%d], due to rx training\n",
2472*54fd6939SJiyong Park __func__, ap_nr, cp_nr, comphy_index);
2473*54fd6939SJiyong Park return 0;
2474*54fd6939SJiyong Park }
2475*54fd6939SJiyong Park
2476*54fd6939SJiyong Park sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
2477*54fd6939SJiyong Park comphy_index);
2478*54fd6939SJiyong Park comphy_ip_addr = COMPHY_ADDR(comphy_base, comphy_index);
2479*54fd6939SJiyong Park
2480*54fd6939SJiyong Park /* Hard reset the comphy, for Ethernet modes and Sata */
2481*54fd6939SJiyong Park mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
2482*54fd6939SJiyong Park data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
2483*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
2484*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
2485*54fd6939SJiyong Park mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
2486*54fd6939SJiyong Park data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
2487*54fd6939SJiyong Park reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
2488*54fd6939SJiyong Park
2489*54fd6939SJiyong Park /* PCIe reset */
2490*54fd6939SJiyong Park spin_lock(&cp110_mac_reset_lock);
2491*54fd6939SJiyong Park
2492*54fd6939SJiyong Park /* The mvebu_cp110_comphy_power_off will be called only from Linux (to
2493*54fd6939SJiyong Park * override settings done by bootloader) and it will be relevant only
2494*54fd6939SJiyong Park * to PCIe (called before check if to skip pcie power off or not).
2495*54fd6939SJiyong Park */
2496*54fd6939SJiyong Park data = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
2497*54fd6939SJiyong Park SYS_CTRL_UINIT_SOFT_RESET_REG);
2498*54fd6939SJiyong Park switch (comphy_index) {
2499*54fd6939SJiyong Park case COMPHY_LANE0:
2500*54fd6939SJiyong Park data &= ~PCIE_MAC_RESET_MASK_PORT0;
2501*54fd6939SJiyong Park break;
2502*54fd6939SJiyong Park case COMPHY_LANE4:
2503*54fd6939SJiyong Park data &= ~PCIE_MAC_RESET_MASK_PORT1;
2504*54fd6939SJiyong Park break;
2505*54fd6939SJiyong Park case COMPHY_LANE5:
2506*54fd6939SJiyong Park data &= ~PCIE_MAC_RESET_MASK_PORT2;
2507*54fd6939SJiyong Park break;
2508*54fd6939SJiyong Park }
2509*54fd6939SJiyong Park
2510*54fd6939SJiyong Park mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
2511*54fd6939SJiyong Park SYS_CTRL_UINIT_SOFT_RESET_REG, data);
2512*54fd6939SJiyong Park spin_unlock(&cp110_mac_reset_lock);
2513*54fd6939SJiyong Park
2514*54fd6939SJiyong Park /* Hard reset the comphy, for PCIe and usb3 */
2515*54fd6939SJiyong Park mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
2516*54fd6939SJiyong Park data = 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
2517*54fd6939SJiyong Park mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
2518*54fd6939SJiyong Park data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
2519*54fd6939SJiyong Park reg_set(comphy_ip_addr + COMMON_PHY_CFG1_REG, data, mask);
2520*54fd6939SJiyong Park
2521*54fd6939SJiyong Park /* Clear comphy PHY and PIPE selector, can't rely on previous config. */
2522*54fd6939SJiyong Park mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index);
2523*54fd6939SJiyong Park mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index);
2524*54fd6939SJiyong Park
2525*54fd6939SJiyong Park debug_exit();
2526*54fd6939SJiyong Park
2527*54fd6939SJiyong Park return 0;
2528*54fd6939SJiyong Park }
2529