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