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