10ade8cd8SKonstantin Porotchkin /*
20ade8cd8SKonstantin Porotchkin * Copyright (C) 2018 Marvell International Ltd.
30ade8cd8SKonstantin Porotchkin *
40ade8cd8SKonstantin Porotchkin * SPDX-License-Identifier: BSD-3-Clause
50ade8cd8SKonstantin Porotchkin * https://spdx.org/licenses
60ade8cd8SKonstantin Porotchkin */
70ade8cd8SKonstantin Porotchkin
80ade8cd8SKonstantin Porotchkin /* Marvell CP110 SoC COMPHY unit driver */
90ade8cd8SKonstantin Porotchkin
100ade8cd8SKonstantin Porotchkin #include <errno.h>
114ce3e99aSScott Branden #include <inttypes.h>
124ce3e99aSScott Branden #include <stdint.h>
1309d40e0eSAntonio Nino Diaz
1409d40e0eSAntonio Nino Diaz #include <common/debug.h>
1509d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
165a9e46e6SGrzegorz Jaszczyk #include <mg_conf_cm3/mg_conf_cm3.h>
1709d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
1809d40e0eSAntonio Nino Diaz #include <lib/spinlock.h>
1909d40e0eSAntonio Nino Diaz
200ade8cd8SKonstantin Porotchkin #include <mvebu_def.h>
210ade8cd8SKonstantin Porotchkin #include "mvebu.h"
220ade8cd8SKonstantin Porotchkin #include "comphy-cp110.h"
2342a29337SGrzegorz Jaszczyk #include "phy-comphy-cp110.h"
2442a29337SGrzegorz Jaszczyk #include "phy-comphy-common.h"
250ade8cd8SKonstantin Porotchkin
2642a29337SGrzegorz Jaszczyk #if __has_include("phy-porting-layer.h")
2742a29337SGrzegorz Jaszczyk #include "phy-porting-layer.h"
280ade8cd8SKonstantin Porotchkin #else
2942a29337SGrzegorz Jaszczyk #include "phy-default-porting-layer.h"
300ade8cd8SKonstantin Porotchkin #endif
310ade8cd8SKonstantin Porotchkin
320ade8cd8SKonstantin Porotchkin /* COMPHY speed macro */
330ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_1_25G 0 /* SGMII 1G */
340ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_2_5G 1
35a669983cSPali Rohár #define COMPHY_SPEED_3_125G 2 /* 2500Base-X */
360ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_5G 3
370ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_5_15625G 4 /* XFI 5G */
380ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_6G 5
390ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_10_3125G 6 /* XFI 10G */
400ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_MAX 0x3F
410ade8cd8SKonstantin Porotchkin /* The default speed for IO with fixed known speed */
420ade8cd8SKonstantin Porotchkin #define COMPHY_SPEED_DEFAULT COMPHY_SPEED_MAX
430ade8cd8SKonstantin Porotchkin
440ade8cd8SKonstantin Porotchkin /* Commands for comphy driver */
450ade8cd8SKonstantin Porotchkin #define COMPHY_COMMAND_DIGITAL_PWR_OFF 0x00000001
460ade8cd8SKonstantin Porotchkin #define COMPHY_COMMAND_DIGITAL_PWR_ON 0x00000002
470ade8cd8SKonstantin Porotchkin
480ade8cd8SKonstantin Porotchkin #define COMPHY_PIPE_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x120000)
490ade8cd8SKonstantin Porotchkin
500ade8cd8SKonstantin Porotchkin /* System controller registers */
510ade8cd8SKonstantin Porotchkin #define PCIE_MAC_RESET_MASK_PORT0 BIT(13)
520ade8cd8SKonstantin Porotchkin #define PCIE_MAC_RESET_MASK_PORT1 BIT(11)
530ade8cd8SKonstantin Porotchkin #define PCIE_MAC_RESET_MASK_PORT2 BIT(12)
540ade8cd8SKonstantin Porotchkin #define SYS_CTRL_UINIT_SOFT_RESET_REG 0x268
550ade8cd8SKonstantin Porotchkin #define SYS_CTRL_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x440000)
560ade8cd8SKonstantin Porotchkin
570ade8cd8SKonstantin Porotchkin /* DFX register spaces */
58371648e1SGuo Yi #define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET (30)
59371648e1SGuo Yi #define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK (0x1UL << \
60371648e1SGuo Yi SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET)
61371648e1SGuo Yi #define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET (31)
62371648e1SGuo Yi #define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK (0x1UL << \
63371648e1SGuo Yi SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET)
64371648e1SGuo Yi #define SAR_STATUS_0_REG 0x40600
650ade8cd8SKonstantin Porotchkin #define DFX_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + DFX_BASE)
66550a06dfSAlex Evraev /* Common Phy training */
67550a06dfSAlex Evraev #define COMPHY_TRX_TRAIN_COMPHY_OFFS 0x1000
68550a06dfSAlex Evraev #define COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE 0x1
69550a06dfSAlex Evraev #define COMPHY_TRX_RELATIVE_ADDR(comphy_index) (comphy_train_base + \
70550a06dfSAlex Evraev (comphy_index) * COMPHY_TRX_TRAIN_COMPHY_OFFS)
710ade8cd8SKonstantin Porotchkin
720ade8cd8SKonstantin Porotchkin /* The same Units Soft Reset Config register are accessed in all PCIe ports
730ade8cd8SKonstantin Porotchkin * initialization, so a spin lock is defined in case when more than 1 CPUs
740ade8cd8SKonstantin Porotchkin * resets PCIe MAC and need to access the register in the same time. The spin
750ade8cd8SKonstantin Porotchkin * lock is shared by all CP110 units.
760ade8cd8SKonstantin Porotchkin */
770ade8cd8SKonstantin Porotchkin spinlock_t cp110_mac_reset_lock;
780ade8cd8SKonstantin Porotchkin
790ade8cd8SKonstantin Porotchkin /* These values come from the PCI Express Spec */
800ade8cd8SKonstantin Porotchkin enum pcie_link_width {
810ade8cd8SKonstantin Porotchkin PCIE_LNK_WIDTH_RESRV = 0x00,
820ade8cd8SKonstantin Porotchkin PCIE_LNK_X1 = 0x01,
830ade8cd8SKonstantin Porotchkin PCIE_LNK_X2 = 0x02,
840ade8cd8SKonstantin Porotchkin PCIE_LNK_X4 = 0x04,
850ade8cd8SKonstantin Porotchkin PCIE_LNK_X8 = 0x08,
860ade8cd8SKonstantin Porotchkin PCIE_LNK_X12 = 0x0C,
870ade8cd8SKonstantin Porotchkin PCIE_LNK_X16 = 0x10,
880ade8cd8SKonstantin Porotchkin PCIE_LNK_X32 = 0x20,
890ade8cd8SKonstantin Porotchkin PCIE_LNK_WIDTH_UNKNOWN = 0xFF,
900ade8cd8SKonstantin Porotchkin };
910ade8cd8SKonstantin Porotchkin
9242a29337SGrzegorz Jaszczyk _Bool rx_trainng_done[AP_NUM][CP_NUM][MAX_LANE_NR] = {0};
9342a29337SGrzegorz Jaszczyk
mvebu_cp110_get_ap_and_cp_nr(uint8_t * ap_nr,uint8_t * cp_nr,uint64_t comphy_base)9442a29337SGrzegorz Jaszczyk static void mvebu_cp110_get_ap_and_cp_nr(uint8_t *ap_nr, uint8_t *cp_nr,
9542a29337SGrzegorz Jaszczyk uint64_t comphy_base)
960ade8cd8SKonstantin Porotchkin {
9742a29337SGrzegorz Jaszczyk #if (AP_NUM == 1)
9842a29337SGrzegorz Jaszczyk *ap_nr = 0;
9942a29337SGrzegorz Jaszczyk #else
10042a29337SGrzegorz Jaszczyk *ap_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(0)) /
10142a29337SGrzegorz Jaszczyk AP_IO_OFFSET);
10242a29337SGrzegorz Jaszczyk #endif
1030ade8cd8SKonstantin Porotchkin
10442a29337SGrzegorz Jaszczyk *cp_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(*ap_nr)) /
10542a29337SGrzegorz Jaszczyk MVEBU_CP_OFFSET);
1060ade8cd8SKonstantin Porotchkin
1074ce3e99aSScott Branden debug("cp_base 0x%" PRIx64 ", ap_io_base 0x%lx, cp_offset 0x%lx\n",
10842a29337SGrzegorz Jaszczyk comphy_base, (unsigned long)MVEBU_AP_IO_BASE(*ap_nr),
10942a29337SGrzegorz Jaszczyk (unsigned long)MVEBU_CP_OFFSET);
1100ade8cd8SKonstantin Porotchkin }
1110ade8cd8SKonstantin Porotchkin
1120ade8cd8SKonstantin Porotchkin /* Clear PIPE selector - avoid collision with previous configuration */
mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base,uint8_t comphy_index)1130ade8cd8SKonstantin Porotchkin static void mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base,
1140ade8cd8SKonstantin Porotchkin uint8_t comphy_index)
1150ade8cd8SKonstantin Porotchkin {
1160ade8cd8SKonstantin Porotchkin uint32_t reg, mask, field;
1170ade8cd8SKonstantin Porotchkin uint32_t comphy_offset =
1180ade8cd8SKonstantin Porotchkin COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
1190ade8cd8SKonstantin Porotchkin
1200ade8cd8SKonstantin Porotchkin mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
1210ade8cd8SKonstantin Porotchkin reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET);
1220ade8cd8SKonstantin Porotchkin field = reg & mask;
1230ade8cd8SKonstantin Porotchkin
1240ade8cd8SKonstantin Porotchkin if (field) {
1250ade8cd8SKonstantin Porotchkin reg &= ~mask;
1260ade8cd8SKonstantin Porotchkin mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET,
1270ade8cd8SKonstantin Porotchkin reg);
1280ade8cd8SKonstantin Porotchkin }
1290ade8cd8SKonstantin Porotchkin }
1300ade8cd8SKonstantin Porotchkin
1310ade8cd8SKonstantin Porotchkin /* Clear PHY selector - avoid collision with previous configuration */
mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base,uint8_t comphy_index)1320ade8cd8SKonstantin Porotchkin static void mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base,
1330ade8cd8SKonstantin Porotchkin uint8_t comphy_index)
1340ade8cd8SKonstantin Porotchkin {
1350ade8cd8SKonstantin Porotchkin uint32_t reg, mask, field;
1360ade8cd8SKonstantin Porotchkin uint32_t comphy_offset =
1370ade8cd8SKonstantin Porotchkin COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
1380ade8cd8SKonstantin Porotchkin
1390ade8cd8SKonstantin Porotchkin mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
1400ade8cd8SKonstantin Porotchkin reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET);
1410ade8cd8SKonstantin Porotchkin field = reg & mask;
1420ade8cd8SKonstantin Porotchkin
1430ade8cd8SKonstantin Porotchkin /* Clear comphy selector - if it was already configured.
1440ade8cd8SKonstantin Porotchkin * (might be that this comphy was configured as PCIe/USB,
1450ade8cd8SKonstantin Porotchkin * in such case, no need to clear comphy selector because PCIe/USB
1460ade8cd8SKonstantin Porotchkin * are controlled by hpipe selector).
1470ade8cd8SKonstantin Porotchkin */
1480ade8cd8SKonstantin Porotchkin if (field) {
1490ade8cd8SKonstantin Porotchkin reg &= ~mask;
1500ade8cd8SKonstantin Porotchkin mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET,
1510ade8cd8SKonstantin Porotchkin reg);
1520ade8cd8SKonstantin Porotchkin }
1530ade8cd8SKonstantin Porotchkin }
1540ade8cd8SKonstantin Porotchkin
1550ade8cd8SKonstantin Porotchkin /* PHY selector configures SATA and Network modes */
mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)1560ade8cd8SKonstantin Porotchkin static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base,
1570ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
1580ade8cd8SKonstantin Porotchkin {
1590ade8cd8SKonstantin Porotchkin uint32_t reg, mask;
1600ade8cd8SKonstantin Porotchkin uint32_t comphy_offset =
1610ade8cd8SKonstantin Porotchkin COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
1620ade8cd8SKonstantin Porotchkin int mode;
1630ade8cd8SKonstantin Porotchkin
1640ade8cd8SKonstantin Porotchkin /* If phy selector is used the pipe selector should be marked as
1650ade8cd8SKonstantin Porotchkin * unconnected.
1660ade8cd8SKonstantin Porotchkin */
1670ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index);
1680ade8cd8SKonstantin Porotchkin
1690ade8cd8SKonstantin Porotchkin /* Comphy mode (compound of the IO mode and id). Here, only the IO mode
1700ade8cd8SKonstantin Porotchkin * is required to distinguish between SATA and network modes.
1710ade8cd8SKonstantin Porotchkin */
1720ade8cd8SKonstantin Porotchkin mode = COMPHY_GET_MODE(comphy_mode);
1730ade8cd8SKonstantin Porotchkin
1740ade8cd8SKonstantin Porotchkin mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset;
1750ade8cd8SKonstantin Porotchkin reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET);
1760ade8cd8SKonstantin Porotchkin reg &= ~mask;
1770ade8cd8SKonstantin Porotchkin
1780ade8cd8SKonstantin Porotchkin /* SATA port 0/1 require the same configuration */
1790ade8cd8SKonstantin Porotchkin if (mode == COMPHY_SATA_MODE) {
1800ade8cd8SKonstantin Porotchkin /* SATA selector values is always 4 */
1810ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHYN_SATA << comphy_offset;
1820ade8cd8SKonstantin Porotchkin } else {
1830ade8cd8SKonstantin Porotchkin switch (comphy_index) {
1840ade8cd8SKonstantin Porotchkin case(0):
1850ade8cd8SKonstantin Porotchkin case(1):
1860ade8cd8SKonstantin Porotchkin case(2):
1870ade8cd8SKonstantin Porotchkin /* For comphy 0,1, and 2:
1880ade8cd8SKonstantin Porotchkin * Network selector value is always 1.
1890ade8cd8SKonstantin Porotchkin */
1900ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY0_1_2_NETWORK <<
1910ade8cd8SKonstantin Porotchkin comphy_offset;
1920ade8cd8SKonstantin Porotchkin break;
1930ade8cd8SKonstantin Porotchkin case(3):
1940ade8cd8SKonstantin Porotchkin /* For comphy 3:
1950ade8cd8SKonstantin Porotchkin * 0x1 = RXAUI_Lane1
196a669983cSPali Rohár * 0x2 = SGMII/Base-X Port1
1970ade8cd8SKonstantin Porotchkin */
1980ade8cd8SKonstantin Porotchkin if (mode == COMPHY_RXAUI_MODE)
1990ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY3_RXAUI <<
2000ade8cd8SKonstantin Porotchkin comphy_offset;
2010ade8cd8SKonstantin Porotchkin else
2020ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY3_SGMII <<
2030ade8cd8SKonstantin Porotchkin comphy_offset;
2040ade8cd8SKonstantin Porotchkin break;
2050ade8cd8SKonstantin Porotchkin case(4):
2060ade8cd8SKonstantin Porotchkin /* For comphy 4:
207a669983cSPali Rohár * 0x1 = SGMII/Base-X Port1, XFI1/SFI1
208a669983cSPali Rohár * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0
2090ade8cd8SKonstantin Porotchkin *
210a669983cSPali Rohár * We want to check if SGMII1 is the
2110ade8cd8SKonstantin Porotchkin * requested mode in order to determine which value
2120ade8cd8SKonstantin Porotchkin * should be set (all other modes use the same value)
2130ade8cd8SKonstantin Porotchkin * so we need to strip the mode, and check the ID
214a669983cSPali Rohár * because we might handle SGMII0 too.
2150ade8cd8SKonstantin Porotchkin */
2160ade8cd8SKonstantin Porotchkin /* TODO: need to distinguish between CP110 and CP115
2170ade8cd8SKonstantin Porotchkin * as SFI1/XFI1 available only for CP115.
2180ade8cd8SKonstantin Porotchkin */
2190ade8cd8SKonstantin Porotchkin if ((mode == COMPHY_SGMII_MODE ||
220a669983cSPali Rohár mode == COMPHY_2500BASEX_MODE ||
221050eb19cSGrzegorz Jaszczyk mode == COMPHY_SFI_MODE ||
222050eb19cSGrzegorz Jaszczyk mode == COMPHY_XFI_MODE ||
223050eb19cSGrzegorz Jaszczyk mode == COMPHY_AP_MODE)
2240529106cSGrzegorz Jaszczyk && COMPHY_GET_ID(comphy_mode) == 1)
2250ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
2260ade8cd8SKonstantin Porotchkin comphy_offset;
2270ade8cd8SKonstantin Porotchkin else
2280ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY4_ALL_OTHERS <<
2290ade8cd8SKonstantin Porotchkin comphy_offset;
2300ade8cd8SKonstantin Porotchkin break;
2310ade8cd8SKonstantin Porotchkin case(5):
2320ade8cd8SKonstantin Porotchkin /* For comphy 5:
233a669983cSPali Rohár * 0x1 = SGMII/Base-X Port2
2340ade8cd8SKonstantin Porotchkin * 0x2 = RXAUI Lane1
2350ade8cd8SKonstantin Porotchkin */
2360ade8cd8SKonstantin Porotchkin if (mode == COMPHY_RXAUI_MODE)
2370ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY5_RXAUI <<
2380ade8cd8SKonstantin Porotchkin comphy_offset;
2390ade8cd8SKonstantin Porotchkin else
2400ade8cd8SKonstantin Porotchkin reg |= COMMON_SELECTOR_COMPHY5_SGMII <<
2410ade8cd8SKonstantin Porotchkin comphy_offset;
2420ade8cd8SKonstantin Porotchkin break;
2430ade8cd8SKonstantin Porotchkin }
2440ade8cd8SKonstantin Porotchkin }
2450ade8cd8SKonstantin Porotchkin
2460ade8cd8SKonstantin Porotchkin mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, reg);
2470ade8cd8SKonstantin Porotchkin }
2480ade8cd8SKonstantin Porotchkin
2490ade8cd8SKonstantin Porotchkin /* PIPE selector configures for PCIe, USB 3.0 Host, and USB 3.0 Device mode */
mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)2500ade8cd8SKonstantin Porotchkin static void mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base,
2510ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
2520ade8cd8SKonstantin Porotchkin {
2530ade8cd8SKonstantin Porotchkin uint32_t reg;
2540ade8cd8SKonstantin Porotchkin uint32_t shift = COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index;
2550ade8cd8SKonstantin Porotchkin int mode = COMPHY_GET_MODE(comphy_mode);
2560ade8cd8SKonstantin Porotchkin uint32_t mask = COMMON_SELECTOR_COMPHY_MASK << shift;
2570ade8cd8SKonstantin Porotchkin uint32_t pipe_sel = 0x0;
2580ade8cd8SKonstantin Porotchkin
2590ade8cd8SKonstantin Porotchkin /* If pipe selector is used the phy selector should be marked as
2600ade8cd8SKonstantin Porotchkin * unconnected.
2610ade8cd8SKonstantin Porotchkin */
2620ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index);
2630ade8cd8SKonstantin Porotchkin
2640ade8cd8SKonstantin Porotchkin reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET);
2650ade8cd8SKonstantin Porotchkin reg &= ~mask;
2660ade8cd8SKonstantin Porotchkin
2670ade8cd8SKonstantin Porotchkin switch (mode) {
2680ade8cd8SKonstantin Porotchkin case (COMPHY_PCIE_MODE):
2690ade8cd8SKonstantin Porotchkin /* For lanes support PCIE, selector value are all same */
2700ade8cd8SKonstantin Porotchkin pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_PCIE;
2710ade8cd8SKonstantin Porotchkin break;
2720ade8cd8SKonstantin Porotchkin
2730ade8cd8SKonstantin Porotchkin case (COMPHY_USB3H_MODE):
2740ade8cd8SKonstantin Porotchkin /* Only lane 1-4 support USB host, selector value is same */
2750ade8cd8SKonstantin Porotchkin if (comphy_index == COMPHY_LANE0 ||
2760ade8cd8SKonstantin Porotchkin comphy_index == COMPHY_LANE5)
2770ade8cd8SKonstantin Porotchkin ERROR("COMPHY[%d] mode[%d] is invalid\n",
2780ade8cd8SKonstantin Porotchkin comphy_index, mode);
2790ade8cd8SKonstantin Porotchkin else
2800ade8cd8SKonstantin Porotchkin pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBH;
2810ade8cd8SKonstantin Porotchkin break;
2820ade8cd8SKonstantin Porotchkin
2830ade8cd8SKonstantin Porotchkin case (COMPHY_USB3D_MODE):
2840ade8cd8SKonstantin Porotchkin /* Lane 1 and 4 support USB device, selector value is same */
2850ade8cd8SKonstantin Porotchkin if (comphy_index == COMPHY_LANE1 ||
2860ade8cd8SKonstantin Porotchkin comphy_index == COMPHY_LANE4)
2870ade8cd8SKonstantin Porotchkin pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBD;
2880ade8cd8SKonstantin Porotchkin else
2890ade8cd8SKonstantin Porotchkin ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index,
2900ade8cd8SKonstantin Porotchkin mode);
2910ade8cd8SKonstantin Porotchkin break;
2920ade8cd8SKonstantin Porotchkin
2930ade8cd8SKonstantin Porotchkin default:
2940ade8cd8SKonstantin Porotchkin ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode);
2950ade8cd8SKonstantin Porotchkin break;
2960ade8cd8SKonstantin Porotchkin }
2970ade8cd8SKonstantin Porotchkin
2980ade8cd8SKonstantin Porotchkin mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, reg |
2990ade8cd8SKonstantin Porotchkin (pipe_sel << shift));
3000ade8cd8SKonstantin Porotchkin }
3010ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base,uint8_t comphy_index)3020ade8cd8SKonstantin Porotchkin int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, uint8_t comphy_index)
3030ade8cd8SKonstantin Porotchkin {
3040ade8cd8SKonstantin Porotchkin uintptr_t sd_ip_addr, addr;
3050ade8cd8SKonstantin Porotchkin uint32_t mask, data;
3060ade8cd8SKonstantin Porotchkin int ret = 0;
3070ade8cd8SKonstantin Porotchkin
3080ade8cd8SKonstantin Porotchkin debug_enter();
3090ade8cd8SKonstantin Porotchkin
3100ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
3110ade8cd8SKonstantin Porotchkin comphy_index);
3120ade8cd8SKonstantin Porotchkin
3130ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
3140ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_PLL_TX_MASK &
3150ade8cd8SKonstantin Porotchkin SD_EXTERNAL_STATUS0_PLL_RX_MASK;
3160ade8cd8SKonstantin Porotchkin mask = data;
3170ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask,
3180ade8cd8SKonstantin Porotchkin PLL_LOCK_TIMEOUT, REG_32BIT);
3190ade8cd8SKonstantin Porotchkin if (data != 0) {
3200ade8cd8SKonstantin Porotchkin if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)
3210ade8cd8SKonstantin Porotchkin ERROR("RX PLL is not locked\n");
3220ade8cd8SKonstantin Porotchkin if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)
3230ade8cd8SKonstantin Porotchkin ERROR("TX PLL is not locked\n");
3240ade8cd8SKonstantin Porotchkin
3250ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
3260ade8cd8SKonstantin Porotchkin }
3270ade8cd8SKonstantin Porotchkin
3280ade8cd8SKonstantin Porotchkin debug_exit();
3290ade8cd8SKonstantin Porotchkin
3300ade8cd8SKonstantin Porotchkin return ret;
3310ade8cd8SKonstantin Porotchkin }
3320ade8cd8SKonstantin Porotchkin
mvebu_cp110_polarity_invert(uintptr_t addr,uint8_t phy_polarity_invert)33338f6dacaSGrzegorz Jaszczyk static void mvebu_cp110_polarity_invert(uintptr_t addr, uint8_t phy_polarity_invert)
33438f6dacaSGrzegorz Jaszczyk {
33538f6dacaSGrzegorz Jaszczyk uint32_t mask, data;
33638f6dacaSGrzegorz Jaszczyk
33738f6dacaSGrzegorz Jaszczyk /* Set RX / TX polarity */
33838f6dacaSGrzegorz Jaszczyk data = mask = 0x0U;
33938f6dacaSGrzegorz Jaszczyk if ((phy_polarity_invert & COMPHY_POLARITY_TXD_INVERT) != 0) {
34038f6dacaSGrzegorz Jaszczyk data |= (1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET);
34138f6dacaSGrzegorz Jaszczyk mask |= HPIPE_SYNC_PATTERN_TXD_INV_MASK;
34238f6dacaSGrzegorz Jaszczyk debug("%s: inverting TX polarity\n", __func__);
34338f6dacaSGrzegorz Jaszczyk }
34438f6dacaSGrzegorz Jaszczyk
34538f6dacaSGrzegorz Jaszczyk if ((phy_polarity_invert & COMPHY_POLARITY_RXD_INVERT) != 0) {
34638f6dacaSGrzegorz Jaszczyk data |= (1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET);
34738f6dacaSGrzegorz Jaszczyk mask |= HPIPE_SYNC_PATTERN_RXD_INV_MASK;
34838f6dacaSGrzegorz Jaszczyk debug("%s: inverting RX polarity\n", __func__);
34938f6dacaSGrzegorz Jaszczyk }
35038f6dacaSGrzegorz Jaszczyk
35138f6dacaSGrzegorz Jaszczyk reg_set(addr, data, mask);
35238f6dacaSGrzegorz Jaszczyk }
35338f6dacaSGrzegorz Jaszczyk
mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)3540ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base,
3550ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
3560ade8cd8SKonstantin Porotchkin {
3570ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, sd_ip_addr, comphy_addr;
3580ade8cd8SKonstantin Porotchkin uint32_t mask, data;
35938f6dacaSGrzegorz Jaszczyk uint8_t ap_nr, cp_nr, phy_polarity_invert;
3600ade8cd8SKonstantin Porotchkin int ret = 0;
3610ade8cd8SKonstantin Porotchkin
3620ade8cd8SKonstantin Porotchkin debug_enter();
3630ade8cd8SKonstantin Porotchkin
36442a29337SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
36542a29337SGrzegorz Jaszczyk
36642a29337SGrzegorz Jaszczyk const struct sata_params *sata_static_values =
36742a29337SGrzegorz Jaszczyk &sata_static_values_tab[ap_nr][cp_nr][comphy_index];
36842a29337SGrzegorz Jaszczyk
36938f6dacaSGrzegorz Jaszczyk phy_polarity_invert = sata_static_values->polarity_invert;
37042a29337SGrzegorz Jaszczyk
3710ade8cd8SKonstantin Porotchkin /* configure phy selector for SATA */
3720ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_phy_selector(comphy_base,
3730ade8cd8SKonstantin Porotchkin comphy_index, comphy_mode);
3740ade8cd8SKonstantin Porotchkin
3750ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
3760ade8cd8SKonstantin Porotchkin comphy_index);
3770ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
3780ade8cd8SKonstantin Porotchkin comphy_index);
3790ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
3800ade8cd8SKonstantin Porotchkin
3810ade8cd8SKonstantin Porotchkin debug(" add hpipe 0x%lx, sd 0x%lx, comphy 0x%lx\n",
3820ade8cd8SKonstantin Porotchkin hpipe_addr, sd_ip_addr, comphy_addr);
3830ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
3840ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
3850ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
3860ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
3870ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
3880ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
3890ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
3900ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
3910ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
3920ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
3930ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
3940ade8cd8SKonstantin Porotchkin
3950ade8cd8SKonstantin Porotchkin /* Set select data width 40Bit - SATA mode only */
3960ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG6_REG,
3970ade8cd8SKonstantin Porotchkin 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET,
3980ade8cd8SKonstantin Porotchkin COMMON_PHY_CFG6_IF_40_SEL_MASK);
3990ade8cd8SKonstantin Porotchkin
4000ade8cd8SKonstantin Porotchkin /* release from hard reset in SD external */
4010ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
4020ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
4030ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
4040ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
4050ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
4060ade8cd8SKonstantin Porotchkin
4070ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
4080ade8cd8SKonstantin Porotchkin mdelay(1);
4090ade8cd8SKonstantin Porotchkin
4100ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
4110ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
4120ade8cd8SKonstantin Porotchkin /* Set reference clock to comes from group 1 - choose 25Mhz */
4130ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG,
4140ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
4150ade8cd8SKonstantin Porotchkin HPIPE_MISC_REFCLK_SEL_MASK);
4160ade8cd8SKonstantin Porotchkin /* Reference frequency select set 1 (for SATA = 25Mhz) */
4170ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
4180ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
4190ade8cd8SKonstantin Porotchkin /* PHY mode select (set SATA = 0x0 */
4200ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
4210ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
4220ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
4230ade8cd8SKonstantin Porotchkin /* Set max PHY generation setting - 6Gbps */
4240ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
4250ade8cd8SKonstantin Porotchkin 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
4260ade8cd8SKonstantin Porotchkin HPIPE_INTERFACE_GEN_MAX_MASK);
4270ade8cd8SKonstantin Porotchkin /* Set select data width 40Bit (SEL_BITS[2:0]) */
4280ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
4290ade8cd8SKonstantin Porotchkin 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
4300ade8cd8SKonstantin Porotchkin
4310ade8cd8SKonstantin Porotchkin debug("stage: Analog parameters from ETP(HW)\n");
4320ade8cd8SKonstantin Porotchkin /* G1 settings */
4330ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
43442a29337SGrzegorz Jaszczyk data = sata_static_values->g1_rx_selmupi <<
43542a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
4363c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
43742a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_rx_selmupf <<
43842a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
4390ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
44042a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_rx_selmufi <<
44142a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
4420ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
44342a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_rx_selmuff <<
44442a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
4450ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
4460ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
4470ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
4480ade8cd8SKonstantin Porotchkin
4490ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
4500ade8cd8SKonstantin Porotchkin data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
4510ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
4520ade8cd8SKonstantin Porotchkin data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
4530ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
4540ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
4550ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK;
4560ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET;
4570ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK;
4580ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET;
4590ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
4600ade8cd8SKonstantin Porotchkin
4610ade8cd8SKonstantin Porotchkin /* G2 settings */
4620ade8cd8SKonstantin Porotchkin mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
46342a29337SGrzegorz Jaszczyk data = sata_static_values->g2_rx_selmupi <<
46442a29337SGrzegorz Jaszczyk HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
4653c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK;
46642a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_rx_selmupf <<
46742a29337SGrzegorz Jaszczyk HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET;
4680ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
46942a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_rx_selmufi <<
47042a29337SGrzegorz Jaszczyk HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
4710ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK;
47242a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_rx_selmuff <<
47342a29337SGrzegorz Jaszczyk HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET;
4740ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK;
4750ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET;
4760ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
4770ade8cd8SKonstantin Porotchkin
4780ade8cd8SKonstantin Porotchkin /* G3 settings */
4790ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
48042a29337SGrzegorz Jaszczyk data = sata_static_values->g3_rx_selmupi <<
48142a29337SGrzegorz Jaszczyk HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
4820ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
48342a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_rx_selmupf <<
48442a29337SGrzegorz Jaszczyk HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
4850ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK;
48642a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_rx_selmufi <<
48742a29337SGrzegorz Jaszczyk HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET;
4880ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK;
48942a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_rx_selmuff <<
49042a29337SGrzegorz Jaszczyk HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET;
4910ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK;
4920ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET;
4930ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK;
4940ade8cd8SKonstantin Porotchkin data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET;
4950ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
4960ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
4970ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask);
4980ade8cd8SKonstantin Porotchkin
4990ade8cd8SKonstantin Porotchkin /* DTL Control */
5000ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK;
5010ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET;
5020ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK;
5030ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET;
5040ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
5050ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
5060ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK;
5070ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET;
5080ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK;
5090ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET;
5100ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK;
5110ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET;
5120ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK;
5130ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET;
5140ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
5150ade8cd8SKonstantin Porotchkin
5160ade8cd8SKonstantin Porotchkin /* Trigger sampler enable pulse */
5170ade8cd8SKonstantin Porotchkin mask = HPIPE_SMAPLER_MASK;
5180ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_SMAPLER_OFFSET;
5190ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
5200ade8cd8SKonstantin Porotchkin mask = HPIPE_SMAPLER_MASK;
5210ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_SMAPLER_OFFSET;
5220ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
5230ade8cd8SKonstantin Porotchkin
5240ade8cd8SKonstantin Porotchkin /* VDD Calibration Control 3 */
5250ade8cd8SKonstantin Porotchkin mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
5260ade8cd8SKonstantin Porotchkin data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
5270ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
5280ade8cd8SKonstantin Porotchkin
5290ade8cd8SKonstantin Porotchkin /* DFE Resolution Control */
5300ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_RES_FORCE_MASK;
5310ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
5320ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
5330ade8cd8SKonstantin Porotchkin
5340ade8cd8SKonstantin Porotchkin /* DFE F3-F5 Coefficient Control */
5350ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
5360ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
5370ade8cd8SKonstantin Porotchkin mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
5380ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
5390ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
5400ade8cd8SKonstantin Porotchkin
5410ade8cd8SKonstantin Porotchkin /* G3 Setting 3 */
5420ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_FFE_CAP_SEL_MASK;
54342a29337SGrzegorz Jaszczyk data = sata_static_values->g3_ffe_cap_sel <<
54442a29337SGrzegorz Jaszczyk HPIPE_G3_FFE_CAP_SEL_OFFSET;
5450ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_FFE_RES_SEL_MASK;
54642a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_ffe_res_sel <<
54742a29337SGrzegorz Jaszczyk HPIPE_G3_FFE_RES_SEL_OFFSET;
5480ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK;
5490ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET;
5500ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
5510ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
5520ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
5530ade8cd8SKonstantin Porotchkin data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
5540ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
5550ade8cd8SKonstantin Porotchkin
5560ade8cd8SKonstantin Porotchkin /* G3 Setting 4 */
5570ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_DFE_RES_MASK;
55842a29337SGrzegorz Jaszczyk data = sata_static_values->g3_dfe_res << HPIPE_G3_DFE_RES_OFFSET;
5590ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
5600ade8cd8SKonstantin Porotchkin
5610ade8cd8SKonstantin Porotchkin /* Offset Phase Control */
5620ade8cd8SKonstantin Porotchkin mask = HPIPE_OS_PH_OFFSET_MASK;
56342a29337SGrzegorz Jaszczyk data = sata_static_values->align90 << HPIPE_OS_PH_OFFSET_OFFSET;
5640ade8cd8SKonstantin Porotchkin mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK;
5650ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET;
5660ade8cd8SKonstantin Porotchkin mask |= HPIPE_OS_PH_VALID_MASK;
5670ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_OS_PH_VALID_OFFSET;
5680ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
5690ade8cd8SKonstantin Porotchkin mask = HPIPE_OS_PH_VALID_MASK;
5700ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_OS_PH_VALID_OFFSET;
5710ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
5720ade8cd8SKonstantin Porotchkin mask = HPIPE_OS_PH_VALID_MASK;
5730ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_OS_PH_VALID_OFFSET;
5740ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
5750ade8cd8SKonstantin Porotchkin
5760ade8cd8SKonstantin Porotchkin /* Set G1 TX amplitude and TX post emphasis value */
5770ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
57842a29337SGrzegorz Jaszczyk data = sata_static_values->g1_amp << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
5790ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK;
58042a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_tx_amp_adj <<
58142a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET;
5820ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
58342a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_emph <<
58442a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
5850ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK;
58642a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_emph_en <<
58742a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET;
5880ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
5890ade8cd8SKonstantin Porotchkin
59042a29337SGrzegorz Jaszczyk /* Set G1 emph */
59142a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
59242a29337SGrzegorz Jaszczyk data = sata_static_values->g1_tx_emph_en <<
59342a29337SGrzegorz Jaszczyk HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
59442a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
59542a29337SGrzegorz Jaszczyk data |= sata_static_values->g1_tx_emph <<
59642a29337SGrzegorz Jaszczyk HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
59742a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
59842a29337SGrzegorz Jaszczyk
5990ade8cd8SKonstantin Porotchkin /* Set G2 TX amplitude and TX post emphasis value */
6000ade8cd8SKonstantin Porotchkin mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK;
60142a29337SGrzegorz Jaszczyk data = sata_static_values->g2_amp << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET;
6020ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK;
60342a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_tx_amp_adj <<
60442a29337SGrzegorz Jaszczyk HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET;
6050ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK;
60642a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_emph <<
60742a29337SGrzegorz Jaszczyk HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET;
6080ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK;
60942a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_emph_en <<
61042a29337SGrzegorz Jaszczyk HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET;
6110ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask);
6120ade8cd8SKonstantin Porotchkin
61342a29337SGrzegorz Jaszczyk /* Set G2 emph */
61442a29337SGrzegorz Jaszczyk mask = HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK;
61542a29337SGrzegorz Jaszczyk data = sata_static_values->g2_tx_emph_en <<
61642a29337SGrzegorz Jaszczyk HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET;
61742a29337SGrzegorz Jaszczyk mask |= HPIPE_G2_SET_2_G2_TX_EMPH0_MASK;
61842a29337SGrzegorz Jaszczyk data |= sata_static_values->g2_tx_emph <<
61942a29337SGrzegorz Jaszczyk HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET;
62042a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask);
62142a29337SGrzegorz Jaszczyk
6220ade8cd8SKonstantin Porotchkin /* Set G3 TX amplitude and TX post emphasis value */
6230ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK;
62442a29337SGrzegorz Jaszczyk data = sata_static_values->g3_amp << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET;
6250ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK;
62642a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_tx_amp_adj <<
62742a29337SGrzegorz Jaszczyk HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET;
6280ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK;
62942a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_emph <<
63042a29337SGrzegorz Jaszczyk HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET;
6310ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK;
63242a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_emph_en <<
63342a29337SGrzegorz Jaszczyk HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET;
6340ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK;
6350ade8cd8SKonstantin Porotchkin data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET;
6360ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK;
6370ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET;
6380ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask);
6390ade8cd8SKonstantin Porotchkin
64042a29337SGrzegorz Jaszczyk /* Set G3 emph */
64142a29337SGrzegorz Jaszczyk mask = HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK;
64242a29337SGrzegorz Jaszczyk data = sata_static_values->g3_tx_emph_en <<
64342a29337SGrzegorz Jaszczyk HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET;
64442a29337SGrzegorz Jaszczyk mask |= HPIPE_G3_SET_2_G3_TX_EMPH0_MASK;
64542a29337SGrzegorz Jaszczyk data |= sata_static_values->g3_tx_emph <<
64642a29337SGrzegorz Jaszczyk HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET;
64742a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G3_SET_2_REG, data, mask);
64842a29337SGrzegorz Jaszczyk
6490ade8cd8SKonstantin Porotchkin /* SERDES External Configuration 2 register */
6500ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK;
6510ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET;
6520ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
6530ade8cd8SKonstantin Porotchkin
6540ade8cd8SKonstantin Porotchkin /* DFE reset sequence */
6550ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
6560ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
6570ade8cd8SKonstantin Porotchkin HPIPE_PWR_CTR_RST_DFE_MASK);
6580ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
6590ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
6600ade8cd8SKonstantin Porotchkin HPIPE_PWR_CTR_RST_DFE_MASK);
66138f6dacaSGrzegorz Jaszczyk
66238f6dacaSGrzegorz Jaszczyk if (phy_polarity_invert != 0)
66338f6dacaSGrzegorz Jaszczyk mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG,
66438f6dacaSGrzegorz Jaszczyk phy_polarity_invert);
66538f6dacaSGrzegorz Jaszczyk
6660ade8cd8SKonstantin Porotchkin /* SW reset for interrupt logic */
6670ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
6680ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
6690ade8cd8SKonstantin Porotchkin HPIPE_PWR_CTR_SFT_RST_MASK);
6700ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
6710ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
6720ade8cd8SKonstantin Porotchkin HPIPE_PWR_CTR_SFT_RST_MASK);
6730ade8cd8SKonstantin Porotchkin
6740ade8cd8SKonstantin Porotchkin debug_exit();
6750ade8cd8SKonstantin Porotchkin
6760ade8cd8SKonstantin Porotchkin return ret;
6770ade8cd8SKonstantin Porotchkin }
6780ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)6790ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base,
6800ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
6810ade8cd8SKonstantin Porotchkin {
6820ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
6830ade8cd8SKonstantin Porotchkin uint32_t mask, data, sgmii_speed = COMPHY_GET_SPEED(comphy_mode);
6840ade8cd8SKonstantin Porotchkin int ret = 0;
6850ade8cd8SKonstantin Porotchkin
6860ade8cd8SKonstantin Porotchkin debug_enter();
6870ade8cd8SKonstantin Porotchkin
6880ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
6890ade8cd8SKonstantin Porotchkin comphy_index);
6900ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
6910ade8cd8SKonstantin Porotchkin comphy_index);
6920ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
6930ade8cd8SKonstantin Porotchkin
6940ade8cd8SKonstantin Porotchkin /* configure phy selector for SGMII */
6950ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
6960ade8cd8SKonstantin Porotchkin comphy_mode);
6970ade8cd8SKonstantin Porotchkin
6980ade8cd8SKonstantin Porotchkin /* Confiugre the lane */
6990ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
7000ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
7010ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
7020ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
7030ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
7040ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
7050ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
7060ade8cd8SKonstantin Porotchkin
7070ade8cd8SKonstantin Porotchkin /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
7080ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
7090ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
7100ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
7110ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
7120ade8cd8SKonstantin Porotchkin
7130ade8cd8SKonstantin Porotchkin if (sgmii_speed == COMPHY_SPEED_1_25G) {
7140ade8cd8SKonstantin Porotchkin /* SGMII 1G, SerDes speed 1.25G */
7150ade8cd8SKonstantin Porotchkin data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
7160ade8cd8SKonstantin Porotchkin data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
7170ade8cd8SKonstantin Porotchkin } else if (sgmii_speed == COMPHY_SPEED_3_125G) {
718a669983cSPali Rohár /* 2500Base-X, SerDes speed 3.125G */
7190ade8cd8SKonstantin Porotchkin data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
7200ade8cd8SKonstantin Porotchkin data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
7210ade8cd8SKonstantin Porotchkin } else {
7220ade8cd8SKonstantin Porotchkin /* Other rates are not supported */
7230ade8cd8SKonstantin Porotchkin ERROR("unsupported SGMII speed on comphy%d\n", comphy_index);
7240ade8cd8SKonstantin Porotchkin return -EINVAL;
7250ade8cd8SKonstantin Porotchkin }
7260ade8cd8SKonstantin Porotchkin
7270ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
7280ade8cd8SKonstantin Porotchkin data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
7290ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
7300ade8cd8SKonstantin Porotchkin data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
7310ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
7320ade8cd8SKonstantin Porotchkin data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
7330ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
7340ade8cd8SKonstantin Porotchkin
7350ade8cd8SKonstantin Porotchkin /* Set hard reset */
7360ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
7370ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
7380ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
7390ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
7400ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
7410ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
7420ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
7430ade8cd8SKonstantin Porotchkin
7440ade8cd8SKonstantin Porotchkin /* Release hard reset */
7450ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
7460ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
7470ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
7480ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
7490ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
7500ade8cd8SKonstantin Porotchkin
7510ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
7520ade8cd8SKonstantin Porotchkin mdelay(1);
7530ade8cd8SKonstantin Porotchkin
7540ade8cd8SKonstantin Porotchkin /* Make sure that 40 data bits is disabled
7550ade8cd8SKonstantin Porotchkin * This bit is not cleared by reset
7560ade8cd8SKonstantin Porotchkin */
7570ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG6_IF_40_SEL_MASK;
7580ade8cd8SKonstantin Porotchkin data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET;
7590ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask);
7600ade8cd8SKonstantin Porotchkin
7610ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
7620ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
7630ade8cd8SKonstantin Porotchkin /* set reference clock */
7640ade8cd8SKonstantin Porotchkin mask = HPIPE_MISC_REFCLK_SEL_MASK;
7650ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
7660ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
7670ade8cd8SKonstantin Porotchkin /* Power and PLL Control */
7680ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
7690ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
7700ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
7710ade8cd8SKonstantin Porotchkin data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
7720ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
7730ade8cd8SKonstantin Porotchkin /* Loopback register */
7740ade8cd8SKonstantin Porotchkin mask = HPIPE_LOOPBACK_SEL_MASK;
7750ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
7760ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
7770ade8cd8SKonstantin Porotchkin /* rx control 1 */
7780ade8cd8SKonstantin Porotchkin mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
7790ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
7800ade8cd8SKonstantin Porotchkin mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
7810ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
7820ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
7830ade8cd8SKonstantin Porotchkin /* DTL Control */
7840ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
7850ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
7860ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
7870ade8cd8SKonstantin Porotchkin
78842a29337SGrzegorz Jaszczyk /* Set analog parameters from ETP(HW) - for now use the default data */
7890ade8cd8SKonstantin Porotchkin debug("stage: Analog parameters from ETP(HW)\n");
7900ade8cd8SKonstantin Porotchkin
7910ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
7920ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
7930ade8cd8SKonstantin Porotchkin HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
7940ade8cd8SKonstantin Porotchkin
7950ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
7960ade8cd8SKonstantin Porotchkin /* SERDES External Configuration */
7970ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
7980ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
7990ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
8000ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
8010ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
8020ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
8030ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
8040ade8cd8SKonstantin Porotchkin
8050ade8cd8SKonstantin Porotchkin ret = mvebu_cp110_comphy_is_pll_locked(comphy_base, comphy_index);
8060ade8cd8SKonstantin Porotchkin if (ret)
8070ade8cd8SKonstantin Porotchkin return ret;
8080ade8cd8SKonstantin Porotchkin
8090ade8cd8SKonstantin Porotchkin /* RX init */
8100ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
8110ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
8120ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
8130ade8cd8SKonstantin Porotchkin
8140ade8cd8SKonstantin Porotchkin /* check that RX init done */
8150ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
8160ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
8170ade8cd8SKonstantin Porotchkin mask = data;
8180ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
8190ade8cd8SKonstantin Porotchkin if (data != 0) {
8200ade8cd8SKonstantin Porotchkin ERROR("RX init failed\n");
8210ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
8220ade8cd8SKonstantin Porotchkin }
8230ade8cd8SKonstantin Porotchkin
8240ade8cd8SKonstantin Porotchkin debug("stage: RF Reset\n");
8250ade8cd8SKonstantin Porotchkin /* RF Reset */
8260ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
8270ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
8280ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
8290ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
8300ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
8310ade8cd8SKonstantin Porotchkin
8320ade8cd8SKonstantin Porotchkin debug_exit();
8330ade8cd8SKonstantin Porotchkin
8340ade8cd8SKonstantin Porotchkin return ret;
8350ade8cd8SKonstantin Porotchkin }
8360ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode,uint64_t comphy_train_base)8370ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base,
8380ade8cd8SKonstantin Porotchkin uint8_t comphy_index,
839550a06dfSAlex Evraev uint32_t comphy_mode,
840550a06dfSAlex Evraev uint64_t comphy_train_base)
8410ade8cd8SKonstantin Porotchkin {
8420ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
8430ade8cd8SKonstantin Porotchkin uint32_t mask, data, speed = COMPHY_GET_SPEED(comphy_mode);
8440ade8cd8SKonstantin Porotchkin int ret = 0;
84542a29337SGrzegorz Jaszczyk uint8_t ap_nr, cp_nr;
8460ade8cd8SKonstantin Porotchkin
8470ade8cd8SKonstantin Porotchkin debug_enter();
84842a29337SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
84942a29337SGrzegorz Jaszczyk
85042a29337SGrzegorz Jaszczyk if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
85142a29337SGrzegorz Jaszczyk debug("Skip %s for comphy[%d][%d][%d], due to rx training\n",
85242a29337SGrzegorz Jaszczyk __func__, ap_nr, cp_nr, comphy_index);
85342a29337SGrzegorz Jaszczyk return 0;
85442a29337SGrzegorz Jaszczyk }
85542a29337SGrzegorz Jaszczyk
85642a29337SGrzegorz Jaszczyk const struct xfi_params *xfi_static_values =
85742a29337SGrzegorz Jaszczyk &xfi_static_values_tab[ap_nr][cp_nr][comphy_index];
85842a29337SGrzegorz Jaszczyk
85942a29337SGrzegorz Jaszczyk debug("%s: the ap_nr = %d, cp_nr = %d, comphy_index %d\n",
86042a29337SGrzegorz Jaszczyk __func__, ap_nr, cp_nr, comphy_index);
86142a29337SGrzegorz Jaszczyk
86242a29337SGrzegorz Jaszczyk debug("g1_ffe_cap_sel= 0x%x, g1_ffe_res_sel= 0x%x, g1_dfe_res= 0x%x\n",
86342a29337SGrzegorz Jaszczyk xfi_static_values->g1_ffe_cap_sel,
86442a29337SGrzegorz Jaszczyk xfi_static_values->g1_ffe_res_sel,
86542a29337SGrzegorz Jaszczyk xfi_static_values->g1_dfe_res);
86642a29337SGrzegorz Jaszczyk
86742a29337SGrzegorz Jaszczyk if (!xfi_static_values->valid) {
86842a29337SGrzegorz Jaszczyk ERROR("[ap%d][cp[%d][comphy:%d]: Has no valid static params\n",
86942a29337SGrzegorz Jaszczyk ap_nr, cp_nr, comphy_index);
87042a29337SGrzegorz Jaszczyk ERROR("[ap%d][cp[%d][comphy:%d]: porting layer needs update\n",
87142a29337SGrzegorz Jaszczyk ap_nr, cp_nr, comphy_index);
87242a29337SGrzegorz Jaszczyk return -EINVAL;
87342a29337SGrzegorz Jaszczyk }
87442a29337SGrzegorz Jaszczyk
8750ade8cd8SKonstantin Porotchkin if ((speed != COMPHY_SPEED_5_15625G) &&
8760ade8cd8SKonstantin Porotchkin (speed != COMPHY_SPEED_10_3125G) &&
8770ade8cd8SKonstantin Porotchkin (speed != COMPHY_SPEED_DEFAULT)) {
8780ade8cd8SKonstantin Porotchkin ERROR("comphy:%d: unsupported sfi/xfi speed\n", comphy_index);
8790ade8cd8SKonstantin Porotchkin return -EINVAL;
8800ade8cd8SKonstantin Porotchkin }
8810ade8cd8SKonstantin Porotchkin
8820ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
8830ade8cd8SKonstantin Porotchkin comphy_index);
8840ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
8850ade8cd8SKonstantin Porotchkin comphy_index);
8860ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
8870ade8cd8SKonstantin Porotchkin
8880ade8cd8SKonstantin Porotchkin /* configure phy selector for XFI/SFI */
8890ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
8900ade8cd8SKonstantin Porotchkin comphy_mode);
8910ade8cd8SKonstantin Porotchkin
8920ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
8930ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
8940ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
8950ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
8960ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
8970ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
8980ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
8990ade8cd8SKonstantin Porotchkin
9000ade8cd8SKonstantin Porotchkin /* Make sure that 40 data bits is disabled
9010ade8cd8SKonstantin Porotchkin * This bit is not cleared by reset
9020ade8cd8SKonstantin Porotchkin */
9030ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG6_IF_40_SEL_MASK;
9040ade8cd8SKonstantin Porotchkin data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET;
9050ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask);
9060ade8cd8SKonstantin Porotchkin
9070ade8cd8SKonstantin Porotchkin /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
9080ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
9090ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
9100ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
9110ade8cd8SKonstantin Porotchkin data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
9120ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
9130ade8cd8SKonstantin Porotchkin data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
9140ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
9150ade8cd8SKonstantin Porotchkin data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
9160ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
9170ade8cd8SKonstantin Porotchkin data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
9180ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
9190ade8cd8SKonstantin Porotchkin data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
9200ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
9210ade8cd8SKonstantin Porotchkin
9220ade8cd8SKonstantin Porotchkin /* release from hard reset */
9230ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
9240ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
9250ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
9260ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
9270ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
9280ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
9290ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
9300ade8cd8SKonstantin Porotchkin
9310ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
9320ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
9330ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
9340ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
9358fa13408SMarcin Wojtas mask |= SD_EXTERNAL_CONFIG1_TX_IDLE_MASK;
9368fa13408SMarcin Wojtas data |= 0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET;
9370ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
9380ade8cd8SKonstantin Porotchkin
9390ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
9400ade8cd8SKonstantin Porotchkin mdelay(1);
9410ade8cd8SKonstantin Porotchkin
9428fa13408SMarcin Wojtas /*
9438fa13408SMarcin Wojtas * Erratum IPCE_COMPHY-1353: toggle TX_IDLE bit in
9448fa13408SMarcin Wojtas * addition to the PHY reset
9458fa13408SMarcin Wojtas */
9468fa13408SMarcin Wojtas mask = SD_EXTERNAL_CONFIG1_TX_IDLE_MASK;
9478fa13408SMarcin Wojtas data = 0x0U;
9488fa13408SMarcin Wojtas reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
9498fa13408SMarcin Wojtas
9500ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
9510ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
9520ade8cd8SKonstantin Porotchkin /* set reference clock */
9530ade8cd8SKonstantin Porotchkin mask = HPIPE_MISC_ICP_FORCE_MASK;
9540ade8cd8SKonstantin Porotchkin data = (speed == COMPHY_SPEED_5_15625G) ?
9550ade8cd8SKonstantin Porotchkin (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) :
9560ade8cd8SKonstantin Porotchkin (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET);
9570ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_REFCLK_SEL_MASK;
9580ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
9590ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
9600ade8cd8SKonstantin Porotchkin /* Power and PLL Control */
9610ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
9620ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
9630ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
9640ade8cd8SKonstantin Porotchkin data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
9650ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
9660ade8cd8SKonstantin Porotchkin /* Loopback register */
9670ade8cd8SKonstantin Porotchkin mask = HPIPE_LOOPBACK_SEL_MASK;
9680ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
9690ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
9700ade8cd8SKonstantin Porotchkin /* rx control 1 */
9710ade8cd8SKonstantin Porotchkin mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
9720ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
9730ade8cd8SKonstantin Porotchkin mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
9740ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
9750ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
9760ade8cd8SKonstantin Porotchkin /* DTL Control */
9770ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
9780ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
9790ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
9800ade8cd8SKonstantin Porotchkin
9810ade8cd8SKonstantin Porotchkin /* Transmitter/Receiver Speed Divider Force */
9820ade8cd8SKonstantin Porotchkin if (speed == COMPHY_SPEED_5_15625G) {
9830ade8cd8SKonstantin Porotchkin mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK;
9840ade8cd8SKonstantin Porotchkin data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET;
9850ade8cd8SKonstantin Porotchkin mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK;
9860ade8cd8SKonstantin Porotchkin data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET;
9870ade8cd8SKonstantin Porotchkin mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK;
9880ade8cd8SKonstantin Porotchkin data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET;
9890ade8cd8SKonstantin Porotchkin mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK;
9900ade8cd8SKonstantin Porotchkin data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET;
9910ade8cd8SKonstantin Porotchkin } else {
9920ade8cd8SKonstantin Porotchkin mask = HPIPE_TXDIGCK_DIV_FORCE_MASK;
9930ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET;
9940ade8cd8SKonstantin Porotchkin }
9950ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask);
9960ade8cd8SKonstantin Porotchkin
9970ade8cd8SKonstantin Porotchkin /* Set analog parameters from ETP(HW) */
9980ade8cd8SKonstantin Porotchkin debug("stage: Analog parameters from ETP(HW)\n");
9990ade8cd8SKonstantin Porotchkin /* SERDES External Configuration 2 */
10000ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK;
10010ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET;
10020ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
10030ade8cd8SKonstantin Porotchkin /* 0x7-DFE Resolution control */
10040ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_RES_FORCE_MASK;
10050ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
10060ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
10070ade8cd8SKonstantin Porotchkin /* 0xd-G1_Setting_0 */
10080ade8cd8SKonstantin Porotchkin if (speed == COMPHY_SPEED_5_15625G) {
10090ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
10100ade8cd8SKonstantin Porotchkin data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
10110ade8cd8SKonstantin Porotchkin } else {
10120ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
101342a29337SGrzegorz Jaszczyk data = xfi_static_values->g1_amp <<
101442a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
10150ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
101642a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_emph <<
101742a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
101842a29337SGrzegorz Jaszczyk
101942a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK;
102042a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_emph_en <<
102142a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET;
102242a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK;
102342a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_tx_amp_adj <<
102442a29337SGrzegorz Jaszczyk HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET;
10250ade8cd8SKonstantin Porotchkin }
10260ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
10270ade8cd8SKonstantin Porotchkin /* Genration 1 setting 2 (G1_Setting_2) */
10280ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
102942a29337SGrzegorz Jaszczyk data = xfi_static_values->g1_tx_emph <<
103042a29337SGrzegorz Jaszczyk HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
10310ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
103242a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_tx_emph_en <<
103342a29337SGrzegorz Jaszczyk HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
10340ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
10350ade8cd8SKonstantin Porotchkin /* Transmitter Slew Rate Control register (tx_reg1) */
10360ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK;
10370ade8cd8SKonstantin Porotchkin data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET;
10380ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_REG1_SLC_EN_MASK;
10390ade8cd8SKonstantin Porotchkin data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET;
10400ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask);
10410ade8cd8SKonstantin Porotchkin /* Impedance Calibration Control register (cal_reg1) */
10420ade8cd8SKonstantin Porotchkin mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK;
10430ade8cd8SKonstantin Porotchkin data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
10440ade8cd8SKonstantin Porotchkin mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK;
10450ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET;
10460ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask);
10470ade8cd8SKonstantin Porotchkin /* Generation 1 Setting 5 (g1_setting_5) */
10480ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SETTING_5_G1_ICP_MASK;
10490ade8cd8SKonstantin Porotchkin data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
10500ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask);
10510ade8cd8SKonstantin Porotchkin
10520ade8cd8SKonstantin Porotchkin /* 0xE-G1_Setting_1 */
10530ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
10540ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
10550ade8cd8SKonstantin Porotchkin if (speed == COMPHY_SPEED_5_15625G) {
10560ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
10570ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
10583c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
10593c0024ccSGrzegorz Jaszczyk data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
10600ade8cd8SKonstantin Porotchkin } else {
10610ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
106242a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_rx_selmupi <<
106342a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
10643c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
106542a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_rx_selmupf <<
106642a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
10670ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
106842a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_rx_selmufi <<
106942a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
10700ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
107142a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_rx_selmuff <<
107242a29337SGrzegorz Jaszczyk HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
10730ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
10740ade8cd8SKonstantin Porotchkin data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
10750ade8cd8SKonstantin Porotchkin }
10760ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
10770ade8cd8SKonstantin Porotchkin
10780ade8cd8SKonstantin Porotchkin /* 0xA-DFE_Reg3 */
10790ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
10800ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
10810ade8cd8SKonstantin Porotchkin mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
10820ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
10830ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
10840ade8cd8SKonstantin Porotchkin
10850ade8cd8SKonstantin Porotchkin /* 0x111-G1_Setting_4 */
10860ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
10870ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
10880ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
10890ade8cd8SKonstantin Porotchkin /* Genration 1 setting 3 (G1_Setting_3) */
10900ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK;
10910ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET;
10920ade8cd8SKonstantin Porotchkin if (speed == COMPHY_SPEED_5_15625G) {
10930ade8cd8SKonstantin Porotchkin /* Force FFE (Feed Forward Equalization) to 5G */
10940ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
10950ade8cd8SKonstantin Porotchkin data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
10960ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
10970ade8cd8SKonstantin Porotchkin data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
10980ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
10990ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
11000ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
110142a29337SGrzegorz Jaszczyk } else {
110242a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
110342a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_ffe_cap_sel <<
110442a29337SGrzegorz Jaszczyk HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
110542a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
110642a29337SGrzegorz Jaszczyk data |= xfi_static_values->g1_ffe_res_sel <<
110742a29337SGrzegorz Jaszczyk HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
110842a29337SGrzegorz Jaszczyk mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
110942a29337SGrzegorz Jaszczyk data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
111042a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
111142a29337SGrzegorz Jaszczyk
111242a29337SGrzegorz Jaszczyk /* Use the value from CAL_OS_PH_EXT */
111342a29337SGrzegorz Jaszczyk mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
111442a29337SGrzegorz Jaszczyk data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
111542a29337SGrzegorz Jaszczyk reg_set(hpipe_addr +
111642a29337SGrzegorz Jaszczyk HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
111742a29337SGrzegorz Jaszczyk data, mask);
111842a29337SGrzegorz Jaszczyk
111942a29337SGrzegorz Jaszczyk /* Update align90 */
112042a29337SGrzegorz Jaszczyk mask = HPIPE_CAL_OS_PH_EXT_MASK;
112142a29337SGrzegorz Jaszczyk data = xfi_static_values->align90 << HPIPE_CAL_OS_PH_EXT_OFFSET;
112242a29337SGrzegorz Jaszczyk reg_set(hpipe_addr +
112342a29337SGrzegorz Jaszczyk HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
112442a29337SGrzegorz Jaszczyk data, mask);
112542a29337SGrzegorz Jaszczyk
112642a29337SGrzegorz Jaszczyk /* Force DFE resolution (use gen table value) */
112742a29337SGrzegorz Jaszczyk mask = HPIPE_DFE_RES_FORCE_MASK;
112842a29337SGrzegorz Jaszczyk data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
112942a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
113042a29337SGrzegorz Jaszczyk
113142a29337SGrzegorz Jaszczyk /* 0x111-G1 DFE_Setting_4 */
113242a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
113342a29337SGrzegorz Jaszczyk data = xfi_static_values->g1_dfe_res <<
113442a29337SGrzegorz Jaszczyk HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
113542a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
113642a29337SGrzegorz Jaszczyk }
11370ade8cd8SKonstantin Porotchkin
11380ade8cd8SKonstantin Porotchkin /* Connfigure RX training timer */
11390ade8cd8SKonstantin Porotchkin mask = HPIPE_RX_TRAIN_TIMER_MASK;
11400ade8cd8SKonstantin Porotchkin data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET;
11410ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
11420ade8cd8SKonstantin Porotchkin
11430ade8cd8SKonstantin Porotchkin /* Enable TX train peak to peak hold */
11440ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
11450ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
11460ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
11470ade8cd8SKonstantin Porotchkin
11480ade8cd8SKonstantin Porotchkin /* Configure TX preset index */
11490ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_PRESET_INDEX_MASK;
11500ade8cd8SKonstantin Porotchkin data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET;
11510ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask);
11520ade8cd8SKonstantin Porotchkin
11530ade8cd8SKonstantin Porotchkin /* Disable pattern lock lost timeout */
11540ade8cd8SKonstantin Porotchkin mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
11550ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
11560ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
11570ade8cd8SKonstantin Porotchkin
11580ade8cd8SKonstantin Porotchkin /* Configure TX training pattern and TX training 16bit auto */
11590ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK;
11600ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET;
11610ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK;
11620ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET;
11630ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
11640ade8cd8SKonstantin Porotchkin
11650ade8cd8SKonstantin Porotchkin /* Configure Training patten number */
11660ade8cd8SKonstantin Porotchkin mask = HPIPE_TRAIN_PAT_NUM_MASK;
11670ade8cd8SKonstantin Porotchkin data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET;
11680ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask);
11690ade8cd8SKonstantin Porotchkin
11700ade8cd8SKonstantin Porotchkin /* Configure differencial manchester encoter to ethernet mode */
11710ade8cd8SKonstantin Porotchkin mask = HPIPE_DME_ETHERNET_MODE_MASK;
11720ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET;
11730ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DME_REG, data, mask);
11740ade8cd8SKonstantin Porotchkin
11750ade8cd8SKonstantin Porotchkin /* Configure VDD Continuous Calibration */
11760ade8cd8SKonstantin Porotchkin mask = HPIPE_CAL_VDD_CONT_MODE_MASK;
11770ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET;
11780ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask);
11790ade8cd8SKonstantin Porotchkin
11800ade8cd8SKonstantin Porotchkin /* Trigger sampler enable pulse (by toggleing the bit) */
11810ade8cd8SKonstantin Porotchkin mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK;
11820ade8cd8SKonstantin Porotchkin data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET;
11830ade8cd8SKonstantin Porotchkin mask |= HPIPE_SMAPLER_MASK;
11840ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_SMAPLER_OFFSET;
11850ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
11860ade8cd8SKonstantin Porotchkin mask = HPIPE_SMAPLER_MASK;
11870ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_SMAPLER_OFFSET;
11880ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
11890ade8cd8SKonstantin Porotchkin
11900ade8cd8SKonstantin Porotchkin /* Set External RX Regulator Control */
11910ade8cd8SKonstantin Porotchkin mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
11920ade8cd8SKonstantin Porotchkin data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
11930ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
11940ade8cd8SKonstantin Porotchkin
11950ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
11960ade8cd8SKonstantin Porotchkin /* SERDES External Configuration */
11970ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
11980ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
11990ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
12000ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
12010ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
12020ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
12030ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
12040ade8cd8SKonstantin Porotchkin
12050ade8cd8SKonstantin Porotchkin /* check PLL rx & tx ready */
12060ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
12070ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
12080ade8cd8SKonstantin Porotchkin SD_EXTERNAL_STATUS0_PLL_TX_MASK;
12090ade8cd8SKonstantin Porotchkin mask = data;
12100ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask,
12110ade8cd8SKonstantin Porotchkin PLL_LOCK_TIMEOUT, REG_32BIT);
12120ade8cd8SKonstantin Porotchkin if (data != 0) {
12130ade8cd8SKonstantin Porotchkin if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)
12140ade8cd8SKonstantin Porotchkin ERROR("RX PLL is not locked\n");
12150ade8cd8SKonstantin Porotchkin if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)
12160ade8cd8SKonstantin Porotchkin ERROR("TX PLL is not locked\n");
12170ade8cd8SKonstantin Porotchkin
12180ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
12190ade8cd8SKonstantin Porotchkin }
12200ade8cd8SKonstantin Porotchkin
12210ade8cd8SKonstantin Porotchkin /* RX init */
12220ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
12230ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
12240ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
12250ade8cd8SKonstantin Porotchkin
12260ade8cd8SKonstantin Porotchkin /* check that RX init done */
12270ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
12280ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
12290ade8cd8SKonstantin Porotchkin mask = data;
12300ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
12310ade8cd8SKonstantin Porotchkin if (data != 0) {
12320ade8cd8SKonstantin Porotchkin ERROR("RX init failed\n");
12330ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
12340ade8cd8SKonstantin Porotchkin }
12350ade8cd8SKonstantin Porotchkin
12360ade8cd8SKonstantin Porotchkin debug("stage: RF Reset\n");
12370ade8cd8SKonstantin Porotchkin /* RF Reset */
12380ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
12390ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
12400ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
12410ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
12420ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
12430ade8cd8SKonstantin Porotchkin
1244550a06dfSAlex Evraev /* Force rx training on 10G port */
1245550a06dfSAlex Evraev data = mmio_read_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index));
1246550a06dfSAlex Evraev data |= COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE;
1247550a06dfSAlex Evraev mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data);
1248550a06dfSAlex Evraev mdelay(200);
1249550a06dfSAlex Evraev data &= ~COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE;
1250550a06dfSAlex Evraev mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data);
1251550a06dfSAlex Evraev
12520ade8cd8SKonstantin Porotchkin debug_exit();
12530ade8cd8SKonstantin Porotchkin
12540ade8cd8SKonstantin Porotchkin return ret;
12550ade8cd8SKonstantin Porotchkin }
12560ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)12570ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base,
12580ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
12590ade8cd8SKonstantin Porotchkin {
12600ade8cd8SKonstantin Porotchkin int ret = 0;
12610ade8cd8SKonstantin Porotchkin uint32_t reg, mask, data, pcie_width;
12620ade8cd8SKonstantin Porotchkin uint32_t clk_dir;
12630ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, comphy_addr, addr;
12640ade8cd8SKonstantin Porotchkin _Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode);
126555df84f9SIgal Liberman _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
126655df84f9SIgal Liberman
126755df84f9SIgal Liberman /* In Armada 8K DB boards, PCIe initialization can be executed
126855df84f9SIgal Liberman * only once (PCIe reset performed during chip power on and
126955df84f9SIgal Liberman * it cannot be executed via GPIO later).
127055df84f9SIgal Liberman * This means that power on can be executed only once, so let's
127155df84f9SIgal Liberman * mark if the caller is bootloader or Linux.
127255df84f9SIgal Liberman * If bootloader -> run power on.
127355df84f9SIgal Liberman * If Linux -> exit.
127455df84f9SIgal Liberman *
127555df84f9SIgal Liberman * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
127655df84f9SIgal Liberman * so after GPIO reset is added to Linux Kernel, it can be
127755df84f9SIgal Liberman * powered-on by Linux.
127855df84f9SIgal Liberman */
127955df84f9SIgal Liberman if (!called_from_uboot)
128055df84f9SIgal Liberman return ret;
12810ade8cd8SKonstantin Porotchkin
12820ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
12830ade8cd8SKonstantin Porotchkin comphy_index);
12840ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
12850ade8cd8SKonstantin Porotchkin pcie_width = COMPHY_GET_PCIE_WIDTH(comphy_mode);
12860ade8cd8SKonstantin Porotchkin
12870ade8cd8SKonstantin Porotchkin debug_enter();
12880ade8cd8SKonstantin Porotchkin
12890ade8cd8SKonstantin Porotchkin spin_lock(&cp110_mac_reset_lock);
12900ade8cd8SKonstantin Porotchkin
12910ade8cd8SKonstantin Porotchkin reg = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
12920ade8cd8SKonstantin Porotchkin SYS_CTRL_UINIT_SOFT_RESET_REG);
12930ade8cd8SKonstantin Porotchkin switch (comphy_index) {
12940ade8cd8SKonstantin Porotchkin case COMPHY_LANE0:
12950ade8cd8SKonstantin Porotchkin reg |= PCIE_MAC_RESET_MASK_PORT0;
12960ade8cd8SKonstantin Porotchkin break;
12970ade8cd8SKonstantin Porotchkin case COMPHY_LANE4:
12980ade8cd8SKonstantin Porotchkin reg |= PCIE_MAC_RESET_MASK_PORT1;
12990ade8cd8SKonstantin Porotchkin break;
13000ade8cd8SKonstantin Porotchkin case COMPHY_LANE5:
13010ade8cd8SKonstantin Porotchkin reg |= PCIE_MAC_RESET_MASK_PORT2;
13020ade8cd8SKonstantin Porotchkin break;
13030ade8cd8SKonstantin Porotchkin }
13040ade8cd8SKonstantin Porotchkin
13050ade8cd8SKonstantin Porotchkin mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
13060ade8cd8SKonstantin Porotchkin SYS_CTRL_UINIT_SOFT_RESET_REG, reg);
13070ade8cd8SKonstantin Porotchkin spin_unlock(&cp110_mac_reset_lock);
13080ade8cd8SKonstantin Porotchkin
13090ade8cd8SKonstantin Porotchkin /* Configure PIPE selector for PCIE */
13100ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index,
13110ade8cd8SKonstantin Porotchkin comphy_mode);
13120ade8cd8SKonstantin Porotchkin
13130ade8cd8SKonstantin Porotchkin /*
13140ade8cd8SKonstantin Porotchkin * Read SAR (Sample-At-Reset) configuration for the PCIe clock
13150ade8cd8SKonstantin Porotchkin * direction.
13160ade8cd8SKonstantin Porotchkin *
13170ade8cd8SKonstantin Porotchkin * SerDes Lane 4/5 got the PCIe ref-clock #1,
13180ade8cd8SKonstantin Porotchkin * and SerDes Lane 0 got PCIe ref-clock #0
13190ade8cd8SKonstantin Porotchkin */
13200ade8cd8SKonstantin Porotchkin reg = mmio_read_32(DFX_FROM_COMPHY_ADDR(comphy_base) +
13210ade8cd8SKonstantin Porotchkin SAR_STATUS_0_REG);
13220ade8cd8SKonstantin Porotchkin if (comphy_index == COMPHY_LANE4 || comphy_index == COMPHY_LANE5)
1323371648e1SGuo Yi clk_dir = (reg & SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK) >>
1324371648e1SGuo Yi SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET;
13250ade8cd8SKonstantin Porotchkin else
1326371648e1SGuo Yi clk_dir = (reg & SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK) >>
1327371648e1SGuo Yi SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET;
13280ade8cd8SKonstantin Porotchkin
13290ade8cd8SKonstantin Porotchkin debug("On lane %d\n", comphy_index);
13300ade8cd8SKonstantin Porotchkin debug("PCIe clock direction = %x\n", clk_dir);
13310ade8cd8SKonstantin Porotchkin debug("PCIe Width = %d\n", pcie_width);
13320ade8cd8SKonstantin Porotchkin
13330ade8cd8SKonstantin Porotchkin /* enable PCIe X4 and X2 */
13340ade8cd8SKonstantin Porotchkin if (comphy_index == COMPHY_LANE0) {
13350ade8cd8SKonstantin Porotchkin if (pcie_width == PCIE_LNK_X4) {
13360ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET;
13370ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK;
13380ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
13390ade8cd8SKonstantin Porotchkin data, mask);
13400ade8cd8SKonstantin Porotchkin } else if (pcie_width == PCIE_LNK_X2) {
13410ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET;
13420ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK;
13430ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask);
13440ade8cd8SKonstantin Porotchkin }
13450ade8cd8SKonstantin Porotchkin }
13460ade8cd8SKonstantin Porotchkin
13470ade8cd8SKonstantin Porotchkin /* If PCIe clock is output and clock source from SerDes lane 5,
13480ade8cd8SKonstantin Porotchkin * need to configure the clock-source MUX.
13490ade8cd8SKonstantin Porotchkin * By default, the clock source is from lane 4
13500ade8cd8SKonstantin Porotchkin */
13510ade8cd8SKonstantin Porotchkin if (clk_dir && clk_src && (comphy_index == COMPHY_LANE5)) {
13520ade8cd8SKonstantin Porotchkin data = DFX_DEV_GEN_PCIE_CLK_SRC_MUX <<
13530ade8cd8SKonstantin Porotchkin DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET;
13540ade8cd8SKonstantin Porotchkin mask = DFX_DEV_GEN_PCIE_CLK_SRC_MASK;
13550ade8cd8SKonstantin Porotchkin reg_set(DFX_FROM_COMPHY_ADDR(comphy_base) +
13560ade8cd8SKonstantin Porotchkin DFX_DEV_GEN_CTRL12_REG, data, mask);
13570ade8cd8SKonstantin Porotchkin }
13580ade8cd8SKonstantin Porotchkin
13590ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
13600ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
13610ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
13620ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
13630ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
13640ade8cd8SKonstantin Porotchkin data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
13650ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
13660ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
13670ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
13680ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
13690ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_PHY_MODE_MASK;
13700ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET;
13710ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
13720ade8cd8SKonstantin Porotchkin
13730ade8cd8SKonstantin Porotchkin /* release from hard reset */
13740ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
13750ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
13760ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
13770ade8cd8SKonstantin Porotchkin data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
13780ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
13790ade8cd8SKonstantin Porotchkin
13800ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
13810ade8cd8SKonstantin Porotchkin mdelay(1);
13820ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
13830ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
13840ade8cd8SKonstantin Porotchkin /* Set PIPE soft reset */
13850ade8cd8SKonstantin Porotchkin mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
13860ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
13870ade8cd8SKonstantin Porotchkin /* Set PHY datapath width mode for V0 */
13880ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
13890ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
13900ade8cd8SKonstantin Porotchkin /* Set Data bus width USB mode for V0 */
13910ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
13920ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
13930ade8cd8SKonstantin Porotchkin /* Set CORE_CLK output frequency for 250Mhz */
13940ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
13950ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
13960ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
13970ade8cd8SKonstantin Porotchkin /* Set PLL ready delay for 0x2 */
13980ade8cd8SKonstantin Porotchkin data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET;
13990ade8cd8SKonstantin Porotchkin mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK;
14000ade8cd8SKonstantin Porotchkin if (pcie_width != PCIE_LNK_X1) {
14010ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET;
14020ade8cd8SKonstantin Porotchkin mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK;
14030ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET;
14040ade8cd8SKonstantin Porotchkin mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK;
14050ade8cd8SKonstantin Porotchkin }
14060ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask);
14070ade8cd8SKonstantin Porotchkin
14080ade8cd8SKonstantin Porotchkin /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */
14090ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET;
14100ade8cd8SKonstantin Porotchkin mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK;
14110ade8cd8SKonstantin Porotchkin if (pcie_width != PCIE_LNK_X1) {
14120ade8cd8SKonstantin Porotchkin mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK;
14130ade8cd8SKonstantin Porotchkin mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK;
14140ade8cd8SKonstantin Porotchkin mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK;
14150ade8cd8SKonstantin Porotchkin if (comphy_index == 0) {
14160ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET;
14170ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET;
14180ade8cd8SKonstantin Porotchkin } else if (comphy_index == (pcie_width - 1)) {
14190ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET;
14200ade8cd8SKonstantin Porotchkin }
14210ade8cd8SKonstantin Porotchkin }
14220ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask);
14230ade8cd8SKonstantin Porotchkin /* Config update polarity equalization */
14240ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET;
14250ade8cd8SKonstantin Porotchkin mask = HPIPE_CFG_UPDATE_POLARITY_MASK;
14260ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, data, mask);
14270ade8cd8SKonstantin Porotchkin /* Set PIPE version 4 to mode enable */
14280ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET;
14290ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_CTRL_28_PIPE4_MASK;
14300ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, data, mask);
14310ade8cd8SKonstantin Porotchkin /* TODO: check if pcie clock is output/input - for bringup use input*/
14320ade8cd8SKonstantin Porotchkin /* Enable PIN clock 100M_125M */
14330ade8cd8SKonstantin Porotchkin mask = 0;
14340ade8cd8SKonstantin Porotchkin data = 0;
14350ade8cd8SKonstantin Porotchkin /* Only if clock is output, configure the clock-source mux */
14360ade8cd8SKonstantin Porotchkin if (clk_dir) {
14370ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_CLK100M_125M_MASK;
14380ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET;
14390ade8cd8SKonstantin Porotchkin }
14400ade8cd8SKonstantin Porotchkin /* Set PIN_TXDCLK_2X Clock Freq. Selection for outputs 500MHz clock */
14410ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_TXDCLK_2X_MASK;
14420ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET;
14430ade8cd8SKonstantin Porotchkin /* Enable 500MHz Clock */
14440ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_CLK500_EN_MASK;
14450ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET;
14460ade8cd8SKonstantin Porotchkin if (clk_dir) { /* output */
14470ade8cd8SKonstantin Porotchkin /* Set reference clock comes from group 1 */
14480ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_REFCLK_SEL_MASK;
14490ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
14500ade8cd8SKonstantin Porotchkin } else {
14510ade8cd8SKonstantin Porotchkin /* Set reference clock comes from group 2 */
14520ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_REFCLK_SEL_MASK;
14530ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET;
14540ade8cd8SKonstantin Porotchkin }
14550ade8cd8SKonstantin Porotchkin mask |= HPIPE_MISC_ICP_FORCE_MASK;
14560ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET;
14570ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
14580ade8cd8SKonstantin Porotchkin if (clk_dir) { /* output */
14590ade8cd8SKonstantin Porotchkin /* Set reference frequcency select - 0x2 for 25MHz*/
14600ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
14610ade8cd8SKonstantin Porotchkin data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
14620ade8cd8SKonstantin Porotchkin } else {
14630ade8cd8SKonstantin Porotchkin /* Set reference frequcency select - 0x0 for 100MHz*/
14640ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
14650ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
14660ade8cd8SKonstantin Porotchkin }
14670ade8cd8SKonstantin Porotchkin /* Set PHY mode to PCIe */
14680ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
14690ade8cd8SKonstantin Porotchkin data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
14700ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
14710ade8cd8SKonstantin Porotchkin
14720ade8cd8SKonstantin Porotchkin /* ref clock alignment */
14730ade8cd8SKonstantin Porotchkin if (pcie_width != PCIE_LNK_X1) {
14740ade8cd8SKonstantin Porotchkin mask = HPIPE_LANE_ALIGN_OFF_MASK;
14750ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET;
14760ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask);
14770ade8cd8SKonstantin Porotchkin }
14780ade8cd8SKonstantin Porotchkin
14790ade8cd8SKonstantin Porotchkin /* Set the amount of time spent in the LoZ state - set for 0x7 only if
14800ade8cd8SKonstantin Porotchkin * the PCIe clock is output
14810ade8cd8SKonstantin Porotchkin */
14820ade8cd8SKonstantin Porotchkin if (clk_dir)
14830ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
14840ade8cd8SKonstantin Porotchkin 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
14850ade8cd8SKonstantin Porotchkin HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
14860ade8cd8SKonstantin Porotchkin
14870ade8cd8SKonstantin Porotchkin /* Set Maximal PHY Generation Setting(8Gbps) */
14880ade8cd8SKonstantin Porotchkin mask = HPIPE_INTERFACE_GEN_MAX_MASK;
14890ade8cd8SKonstantin Porotchkin data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET;
14900ade8cd8SKonstantin Porotchkin /* Bypass frame detection and sync detection for RX DATA */
14910ade8cd8SKonstantin Porotchkin mask |= HPIPE_INTERFACE_DET_BYPASS_MASK;
14920ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET;
14930ade8cd8SKonstantin Porotchkin /* Set Link Train Mode (Tx training control pins are used) */
14940ade8cd8SKonstantin Porotchkin mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK;
14950ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET;
14960ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask);
14970ade8cd8SKonstantin Porotchkin
14980ade8cd8SKonstantin Porotchkin /* Set Idle_sync enable */
14990ade8cd8SKonstantin Porotchkin mask = HPIPE_PCIE_IDLE_SYNC_MASK;
15000ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET;
15010ade8cd8SKonstantin Porotchkin /* Select bits for PCIE Gen3(32bit) */
15020ade8cd8SKonstantin Porotchkin mask |= HPIPE_PCIE_SEL_BITS_MASK;
15030ade8cd8SKonstantin Porotchkin data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET;
15040ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask);
15050ade8cd8SKonstantin Porotchkin
15060ade8cd8SKonstantin Porotchkin /* Enable Tx_adapt_g1 */
15070ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_CTRL_G1_MASK;
15080ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET;
15090ade8cd8SKonstantin Porotchkin /* Enable Tx_adapt_gn1 */
15100ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK;
15110ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET;
15120ade8cd8SKonstantin Porotchkin /* Disable Tx_adapt_g0 */
15130ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK;
15140ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
15150ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
15160ade8cd8SKonstantin Porotchkin
15170ade8cd8SKonstantin Porotchkin /* Set reg_tx_train_chk_init */
15180ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_CHK_INIT_MASK;
15190ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET;
15200ade8cd8SKonstantin Porotchkin /* Enable TX_COE_FM_PIN_PCIE3_EN */
15210ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK;
15220ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET;
15230ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
15240ade8cd8SKonstantin Porotchkin
15250ade8cd8SKonstantin Porotchkin debug("stage: TRx training parameters\n");
15260ade8cd8SKonstantin Porotchkin /* Set Preset sweep configurations */
15270ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK;
15280ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET;
15290ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_NUM_OF_PRESET_MASK;
15300ade8cd8SKonstantin Porotchkin data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET;
15310ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK;
15320ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET;
15330ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask);
15340ade8cd8SKonstantin Porotchkin
15350ade8cd8SKonstantin Porotchkin /* Tx train start configuration */
15360ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK;
15370ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET;
15380ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK;
15390ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET;
15400ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK;
15410ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET;
15420ade8cd8SKonstantin Porotchkin mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK;
15430ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET;
15440ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
15450ade8cd8SKonstantin Porotchkin
15460ade8cd8SKonstantin Porotchkin /* Enable Tx train P2P */
15470ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
15480ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
15490ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
15500ade8cd8SKonstantin Porotchkin
15510ade8cd8SKonstantin Porotchkin /* Configure Tx train timeout */
15520ade8cd8SKonstantin Porotchkin mask = HPIPE_TRX_TRAIN_TIMER_MASK;
15530ade8cd8SKonstantin Porotchkin data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET;
15540ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask);
15550ade8cd8SKonstantin Porotchkin
15560ade8cd8SKonstantin Porotchkin /* Disable G0/G1/GN1 adaptation */
15570ade8cd8SKonstantin Porotchkin mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK
15580ade8cd8SKonstantin Porotchkin | HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
15590ade8cd8SKonstantin Porotchkin data = 0;
15600ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
15610ade8cd8SKonstantin Porotchkin
15620ade8cd8SKonstantin Porotchkin /* Disable DTL frequency loop */
15630ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
15640ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
15650ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
15660ade8cd8SKonstantin Porotchkin
15670ade8cd8SKonstantin Porotchkin /* Configure G3 DFE */
15680ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_DFE_RES_MASK;
15690ade8cd8SKonstantin Porotchkin data = 0x3 << HPIPE_G3_DFE_RES_OFFSET;
15700ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
15710ade8cd8SKonstantin Porotchkin
15720ade8cd8SKonstantin Porotchkin /* Use TX/RX training result for DFE */
15730ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_RES_FORCE_MASK;
15740ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
15750ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
15760ade8cd8SKonstantin Porotchkin
15770ade8cd8SKonstantin Porotchkin /* Configure initial and final coefficient value for receiver */
15780ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
15790ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
15800ade8cd8SKonstantin Porotchkin
15810ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
15820ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
15830ade8cd8SKonstantin Porotchkin
15840ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
15850ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
15860ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask);
15870ade8cd8SKonstantin Porotchkin
15880ade8cd8SKonstantin Porotchkin /* Trigger sampler enable pulse */
15890ade8cd8SKonstantin Porotchkin mask = HPIPE_SMAPLER_MASK;
15900ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_SMAPLER_OFFSET;
15910ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
15920ade8cd8SKonstantin Porotchkin udelay(5);
15930ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask);
15940ade8cd8SKonstantin Porotchkin
15950ade8cd8SKonstantin Porotchkin /* FFE resistor tuning for different bandwidth */
15960ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
15970ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
15980ade8cd8SKonstantin Porotchkin mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
15990ade8cd8SKonstantin Porotchkin data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
16000ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
16010ade8cd8SKonstantin Porotchkin
16020ade8cd8SKonstantin Porotchkin /* Pattern lock lost timeout disable */
16030ade8cd8SKonstantin Porotchkin mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
16040ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
16050ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
16060ade8cd8SKonstantin Porotchkin
16070ade8cd8SKonstantin Porotchkin /* Configure DFE adaptations */
16080ade8cd8SKonstantin Porotchkin mask = HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK;
16090ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET;
16100ade8cd8SKonstantin Porotchkin mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK;
16110ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET;
16120ade8cd8SKonstantin Porotchkin mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK;
16130ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET;
16140ade8cd8SKonstantin Porotchkin mask |= HPIPE_CDR_MAX_DFE_ADAPT_1_MASK;
16150ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET;
16160ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
16170ade8cd8SKonstantin Porotchkin
16180ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK;
16190ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET;
16200ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask);
16210ade8cd8SKonstantin Porotchkin
16220ade8cd8SKonstantin Porotchkin /* Genration 2 setting 1*/
16230ade8cd8SKonstantin Porotchkin mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
16240ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
16253c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK;
16263c0024ccSGrzegorz Jaszczyk data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET;
16270ade8cd8SKonstantin Porotchkin mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
16280ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
16290ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
16300ade8cd8SKonstantin Porotchkin
16310ade8cd8SKonstantin Porotchkin /* DFE enable */
16320ade8cd8SKonstantin Porotchkin mask = HPIPE_G2_DFE_RES_MASK;
16330ade8cd8SKonstantin Porotchkin data = 0x3 << HPIPE_G2_DFE_RES_OFFSET;
16340ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask);
16350ade8cd8SKonstantin Porotchkin
16360ade8cd8SKonstantin Porotchkin /* Configure DFE Resolution */
16370ade8cd8SKonstantin Porotchkin mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK;
16380ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET;
16390ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
16400ade8cd8SKonstantin Porotchkin
16410ade8cd8SKonstantin Porotchkin /* VDD calibration control */
16420ade8cd8SKonstantin Porotchkin mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
16430ade8cd8SKonstantin Porotchkin data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
16440ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
16450ade8cd8SKonstantin Porotchkin
16460ade8cd8SKonstantin Porotchkin /* Set PLL Charge-pump Current Control */
16470ade8cd8SKonstantin Porotchkin mask = HPIPE_G3_SETTING_5_G3_ICP_MASK;
16480ade8cd8SKonstantin Porotchkin data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET;
16490ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask);
16500ade8cd8SKonstantin Porotchkin
16510ade8cd8SKonstantin Porotchkin /* Set lane rqualization remote setting */
16520ade8cd8SKonstantin Porotchkin mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK;
16530ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET;
16540ade8cd8SKonstantin Porotchkin mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK;
16550ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET;
16560ade8cd8SKonstantin Porotchkin mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK;
16570ade8cd8SKonstantin Porotchkin data |= 0x6 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET;
16580ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask);
16590ade8cd8SKonstantin Porotchkin
16600ade8cd8SKonstantin Porotchkin mask = HPIPE_CFG_EQ_BUNDLE_DIS_MASK;
16610ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET;
16620ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG2_REG, data, mask);
16630ade8cd8SKonstantin Porotchkin
16640ade8cd8SKonstantin Porotchkin debug("stage: Comphy power up\n");
16650ade8cd8SKonstantin Porotchkin
16660ade8cd8SKonstantin Porotchkin /* For PCIe X4 or X2:
16670ade8cd8SKonstantin Porotchkin * release from reset only after finish to configure all lanes
16680ade8cd8SKonstantin Porotchkin */
16690ade8cd8SKonstantin Porotchkin if ((pcie_width == PCIE_LNK_X1) || (comphy_index == (pcie_width - 1))) {
16700ade8cd8SKonstantin Porotchkin uint32_t i, start_lane, end_lane;
16710ade8cd8SKonstantin Porotchkin
16720ade8cd8SKonstantin Porotchkin if (pcie_width != PCIE_LNK_X1) {
16730ade8cd8SKonstantin Porotchkin /* allows writing to all lanes in one write */
16740ade8cd8SKonstantin Porotchkin data = 0x0;
16750ade8cd8SKonstantin Porotchkin if (pcie_width == PCIE_LNK_X2)
16760ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK;
16770ade8cd8SKonstantin Porotchkin else if (pcie_width == PCIE_LNK_X4)
16780ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK;
16790ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask);
16800ade8cd8SKonstantin Porotchkin start_lane = 0;
16810ade8cd8SKonstantin Porotchkin end_lane = pcie_width;
16820ade8cd8SKonstantin Porotchkin
16830ade8cd8SKonstantin Porotchkin /* Release from PIPE soft reset
16840ade8cd8SKonstantin Porotchkin * For PCIe by4 or by2:
16850ade8cd8SKonstantin Porotchkin * release from soft reset all lanes - can't use
16860ade8cd8SKonstantin Porotchkin * read modify write
16870ade8cd8SKonstantin Porotchkin */
16880ade8cd8SKonstantin Porotchkin reg_set(HPIPE_ADDR(
16890ade8cd8SKonstantin Porotchkin COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), 0) +
16900ade8cd8SKonstantin Porotchkin HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff);
16910ade8cd8SKonstantin Porotchkin } else {
16920ade8cd8SKonstantin Porotchkin start_lane = comphy_index;
16930ade8cd8SKonstantin Porotchkin end_lane = comphy_index + 1;
16940ade8cd8SKonstantin Porotchkin
16950ade8cd8SKonstantin Porotchkin /* Release from PIPE soft reset
16960ade8cd8SKonstantin Porotchkin * for PCIe by4 or by2:
16970ade8cd8SKonstantin Porotchkin * release from soft reset all lanes
16980ade8cd8SKonstantin Porotchkin */
16990ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
17000ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
17010ade8cd8SKonstantin Porotchkin HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
17020ade8cd8SKonstantin Porotchkin }
17030ade8cd8SKonstantin Porotchkin
17040ade8cd8SKonstantin Porotchkin if (pcie_width != PCIE_LNK_X1) {
17050ade8cd8SKonstantin Porotchkin /* disable writing to all lanes with one write */
17060ade8cd8SKonstantin Porotchkin if (pcie_width == PCIE_LNK_X2) {
17070ade8cd8SKonstantin Porotchkin data = (COMPHY_LANE0 <<
17080ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) |
17090ade8cd8SKonstantin Porotchkin (COMPHY_LANE1 <<
17100ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET);
17110ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK;
17120ade8cd8SKonstantin Porotchkin } else if (pcie_width == PCIE_LNK_X4) {
17130ade8cd8SKonstantin Porotchkin data = (COMPHY_LANE0 <<
17140ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) |
17150ade8cd8SKonstantin Porotchkin (COMPHY_LANE1 <<
17160ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET) |
17170ade8cd8SKonstantin Porotchkin (COMPHY_LANE2 <<
17180ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET) |
17190ade8cd8SKonstantin Porotchkin (COMPHY_LANE3 <<
17200ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET);
17210ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK;
17220ade8cd8SKonstantin Porotchkin }
17230ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
17240ade8cd8SKonstantin Porotchkin data, mask);
17250ade8cd8SKonstantin Porotchkin }
17260ade8cd8SKonstantin Porotchkin
17270ade8cd8SKonstantin Porotchkin debug("stage: Check PLL\n");
17280ade8cd8SKonstantin Porotchkin /* Read lane status */
17290ade8cd8SKonstantin Porotchkin for (i = start_lane; i < end_lane; i++) {
17300ade8cd8SKonstantin Porotchkin addr = HPIPE_ADDR(
17310ade8cd8SKonstantin Porotchkin COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), i) +
17320ade8cd8SKonstantin Porotchkin HPIPE_LANE_STATUS1_REG;
17330ade8cd8SKonstantin Porotchkin data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
17340ade8cd8SKonstantin Porotchkin mask = data;
1735c0a909cdSPali Rohár data = polling_with_timeout(addr, data, mask,
17360ade8cd8SKonstantin Porotchkin PLL_LOCK_TIMEOUT,
17370ade8cd8SKonstantin Porotchkin REG_32BIT);
1738c0a909cdSPali Rohár if (data) {
17390ade8cd8SKonstantin Porotchkin ERROR("Failed to lock PCIE PLL\n");
1740c0a909cdSPali Rohár ret = -ETIMEDOUT;
1741c0a909cdSPali Rohár }
17420ade8cd8SKonstantin Porotchkin }
17430ade8cd8SKonstantin Porotchkin }
17440ade8cd8SKonstantin Porotchkin
17450ade8cd8SKonstantin Porotchkin debug_exit();
17460ade8cd8SKonstantin Porotchkin
17470ade8cd8SKonstantin Porotchkin return ret;
17480ade8cd8SKonstantin Porotchkin }
17490ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)17500ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base,
17510ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
17520ade8cd8SKonstantin Porotchkin {
17530ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr;
17540ade8cd8SKonstantin Porotchkin uint32_t mask, data;
17550ade8cd8SKonstantin Porotchkin int ret = 0;
17560ade8cd8SKonstantin Porotchkin
17570ade8cd8SKonstantin Porotchkin debug_enter();
17580ade8cd8SKonstantin Porotchkin
17590ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
17600ade8cd8SKonstantin Porotchkin comphy_index);
17610ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
17620ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
17630ade8cd8SKonstantin Porotchkin comphy_index);
17640ade8cd8SKonstantin Porotchkin
17650ade8cd8SKonstantin Porotchkin /* configure phy selector for RXAUI */
17660ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
17670ade8cd8SKonstantin Porotchkin comphy_mode);
17680ade8cd8SKonstantin Porotchkin
17690ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
17700ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
17710ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
17720ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
17730ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
17740ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
17750ade8cd8SKonstantin Porotchkin
17760ade8cd8SKonstantin Porotchkin if (comphy_index == 2) {
17770ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
17780ade8cd8SKonstantin Porotchkin 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET,
17790ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_RXAUI0_MASK);
17800ade8cd8SKonstantin Porotchkin }
17810ade8cd8SKonstantin Porotchkin if (comphy_index == 4) {
17820ade8cd8SKonstantin Porotchkin reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
17830ade8cd8SKonstantin Porotchkin 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET,
17840ade8cd8SKonstantin Porotchkin COMMON_PHY_SD_CTRL1_RXAUI1_MASK);
17850ade8cd8SKonstantin Porotchkin }
17860ade8cd8SKonstantin Porotchkin
17870ade8cd8SKonstantin Porotchkin /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
17880ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
17890ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
17900ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
17910ade8cd8SKonstantin Porotchkin data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
17920ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
17930ade8cd8SKonstantin Porotchkin data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
17940ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
17950ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
17960ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
17970ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
17980ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
17990ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
18000ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK;
18010ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET;
18020ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
18030ade8cd8SKonstantin Porotchkin
18040ade8cd8SKonstantin Porotchkin /* release from hard reset */
18050ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
18060ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
18070ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
18080ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
18090ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
18100ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
18110ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
18120ade8cd8SKonstantin Porotchkin
18130ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
18140ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
18150ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
18160ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
18170ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
18180ade8cd8SKonstantin Porotchkin
18190ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
18200ade8cd8SKonstantin Porotchkin mdelay(1);
18210ade8cd8SKonstantin Porotchkin
18220ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
18230ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
18240ade8cd8SKonstantin Porotchkin /* set reference clock */
18250ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG,
18260ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
18270ade8cd8SKonstantin Porotchkin HPIPE_MISC_REFCLK_SEL_MASK);
18280ade8cd8SKonstantin Porotchkin /* Power and PLL Control */
18290ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
18300ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
18310ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
18320ade8cd8SKonstantin Porotchkin data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
18330ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
18340ade8cd8SKonstantin Porotchkin /* Loopback register */
18350ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
18360ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
18370ade8cd8SKonstantin Porotchkin /* rx control 1 */
18380ade8cd8SKonstantin Porotchkin mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
18390ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
18400ade8cd8SKonstantin Porotchkin mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
18410ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
18420ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
18430ade8cd8SKonstantin Porotchkin /* DTL Control */
18440ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG,
18450ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET,
18460ade8cd8SKonstantin Porotchkin HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK);
18470ade8cd8SKonstantin Porotchkin
18480ade8cd8SKonstantin Porotchkin /* Set analog parameters from ETP(HW) */
18490ade8cd8SKonstantin Porotchkin debug("stage: Analog parameters from ETP(HW)\n");
18500ade8cd8SKonstantin Porotchkin /* SERDES External Configuration 2 */
18510ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG,
18520ade8cd8SKonstantin Porotchkin 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET,
18530ade8cd8SKonstantin Porotchkin SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK);
18540ade8cd8SKonstantin Porotchkin /* 0x7-DFE Resolution control */
18550ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET,
18560ade8cd8SKonstantin Porotchkin HPIPE_DFE_RES_FORCE_MASK);
18570ade8cd8SKonstantin Porotchkin /* 0xd-G1_Setting_0 */
18580ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
18590ade8cd8SKonstantin Porotchkin 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
18600ade8cd8SKonstantin Porotchkin HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
18610ade8cd8SKonstantin Porotchkin /* 0xE-G1_Setting_1 */
18620ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
18630ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
18643c0024ccSGrzegorz Jaszczyk mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK;
18653c0024ccSGrzegorz Jaszczyk data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET;
18660ade8cd8SKonstantin Porotchkin mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
18670ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
18680ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
18690ade8cd8SKonstantin Porotchkin /* 0xA-DFE_Reg3 */
18700ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
18710ade8cd8SKonstantin Porotchkin data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
18720ade8cd8SKonstantin Porotchkin mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
18730ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
18740ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
18750ade8cd8SKonstantin Porotchkin
18760ade8cd8SKonstantin Porotchkin /* 0x111-G1_Setting_4 */
18770ade8cd8SKonstantin Porotchkin mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
18780ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
18790ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
18800ade8cd8SKonstantin Porotchkin
18810ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
18820ade8cd8SKonstantin Porotchkin /* SERDES External Configuration */
18830ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
18840ade8cd8SKonstantin Porotchkin data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
18850ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
18860ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
18870ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
18880ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
18890ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
18900ade8cd8SKonstantin Porotchkin
18910ade8cd8SKonstantin Porotchkin
18920ade8cd8SKonstantin Porotchkin /* check PLL rx & tx ready */
18930ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
18940ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
18950ade8cd8SKonstantin Porotchkin SD_EXTERNAL_STATUS0_PLL_TX_MASK;
18960ade8cd8SKonstantin Porotchkin mask = data;
18970ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT);
18980ade8cd8SKonstantin Porotchkin if (data != 0) {
18990ade8cd8SKonstantin Porotchkin debug("Read from reg = %lx - value = 0x%x\n",
19000ade8cd8SKonstantin Porotchkin sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
19010ade8cd8SKonstantin Porotchkin ERROR("SD_EXTERNAL_STATUS0_PLL_RX is %d, -\"-_PLL_TX is %d\n",
19020ade8cd8SKonstantin Porotchkin (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
19030ade8cd8SKonstantin Porotchkin (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
19040ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
19050ade8cd8SKonstantin Porotchkin }
19060ade8cd8SKonstantin Porotchkin
19070ade8cd8SKonstantin Porotchkin /* RX init */
19080ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG,
19090ade8cd8SKonstantin Porotchkin 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET,
19100ade8cd8SKonstantin Porotchkin SD_EXTERNAL_CONFIG1_RX_INIT_MASK);
19110ade8cd8SKonstantin Porotchkin
19120ade8cd8SKonstantin Porotchkin /* check that RX init done */
19130ade8cd8SKonstantin Porotchkin addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
19140ade8cd8SKonstantin Porotchkin data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
19150ade8cd8SKonstantin Porotchkin mask = data;
19160ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask, 100, REG_32BIT);
19170ade8cd8SKonstantin Porotchkin if (data != 0) {
19180ade8cd8SKonstantin Porotchkin debug("Read from reg = %lx - value = 0x%x\n",
19190ade8cd8SKonstantin Porotchkin sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
19200ade8cd8SKonstantin Porotchkin ERROR("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
19210ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
19220ade8cd8SKonstantin Porotchkin }
19230ade8cd8SKonstantin Porotchkin
19240ade8cd8SKonstantin Porotchkin debug("stage: RF Reset\n");
19250ade8cd8SKonstantin Porotchkin /* RF Reset */
19260ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
19270ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
19280ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
19290ade8cd8SKonstantin Porotchkin data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
19300ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
19310ade8cd8SKonstantin Porotchkin
19320ade8cd8SKonstantin Porotchkin debug_exit();
19330ade8cd8SKonstantin Porotchkin
19340ade8cd8SKonstantin Porotchkin return ret;
19350ade8cd8SKonstantin Porotchkin }
19360ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)19370ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base,
19380ade8cd8SKonstantin Porotchkin uint8_t comphy_index, uint32_t comphy_mode)
19390ade8cd8SKonstantin Porotchkin {
19400ade8cd8SKonstantin Porotchkin uintptr_t hpipe_addr, comphy_addr, addr;
19410ade8cd8SKonstantin Porotchkin uint32_t mask, data;
1942ff9cfdc0SGrzegorz Jaszczyk uint8_t ap_nr, cp_nr, phy_polarity_invert;
19430ade8cd8SKonstantin Porotchkin int ret = 0;
19440ade8cd8SKonstantin Porotchkin
19450ade8cd8SKonstantin Porotchkin debug_enter();
19460ade8cd8SKonstantin Porotchkin
19470ade8cd8SKonstantin Porotchkin /* Configure PIPE selector for USB3 */
19480ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index,
19490ade8cd8SKonstantin Porotchkin comphy_mode);
19500ade8cd8SKonstantin Porotchkin
1951ff9cfdc0SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
1952ff9cfdc0SGrzegorz Jaszczyk
1953ff9cfdc0SGrzegorz Jaszczyk const struct usb_params *usb_static_values =
1954ff9cfdc0SGrzegorz Jaszczyk &usb_static_values_tab[ap_nr][cp_nr][comphy_index];
1955ff9cfdc0SGrzegorz Jaszczyk
1956ff9cfdc0SGrzegorz Jaszczyk phy_polarity_invert = usb_static_values->polarity_invert;
1957ff9cfdc0SGrzegorz Jaszczyk
19580ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
19590ade8cd8SKonstantin Porotchkin comphy_index);
19600ade8cd8SKonstantin Porotchkin comphy_addr = COMPHY_ADDR(comphy_base, comphy_index);
19610ade8cd8SKonstantin Porotchkin
19620ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
19630ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
19640ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
19650ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
19660ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
19670ade8cd8SKonstantin Porotchkin data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
19680ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
19690ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
19700ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
19710ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
19720ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_PHY_MODE_MASK;
19730ade8cd8SKonstantin Porotchkin data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET;
19740ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
19750ade8cd8SKonstantin Porotchkin
19760ade8cd8SKonstantin Porotchkin /* release from hard reset */
19770ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
19780ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
19790ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
19800ade8cd8SKonstantin Porotchkin data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
19810ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
19820ade8cd8SKonstantin Porotchkin
19830ade8cd8SKonstantin Porotchkin /* Wait 1ms - until band gap and ref clock ready */
19840ade8cd8SKonstantin Porotchkin mdelay(1);
19850ade8cd8SKonstantin Porotchkin
19860ade8cd8SKonstantin Porotchkin /* Start comphy Configuration */
19870ade8cd8SKonstantin Porotchkin debug("stage: Comphy configuration\n");
19880ade8cd8SKonstantin Porotchkin /* Set PIPE soft reset */
19890ade8cd8SKonstantin Porotchkin mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
19900ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
19910ade8cd8SKonstantin Porotchkin /* Set PHY datapath width mode for V0 */
19920ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
19930ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
19940ade8cd8SKonstantin Porotchkin /* Set Data bus width USB mode for V0 */
19950ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
19960ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
19970ade8cd8SKonstantin Porotchkin /* Set CORE_CLK output frequency for 250Mhz */
19980ade8cd8SKonstantin Porotchkin mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
19990ade8cd8SKonstantin Porotchkin data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
20000ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
20010ade8cd8SKonstantin Porotchkin /* Set PLL ready delay for 0x2 */
20020ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG,
20030ade8cd8SKonstantin Porotchkin 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET,
20040ade8cd8SKonstantin Porotchkin HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK);
20050ade8cd8SKonstantin Porotchkin /* Set reference clock to come from group 1 - 25Mhz */
20060ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_MISC_REG,
20070ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
20080ade8cd8SKonstantin Porotchkin HPIPE_MISC_REFCLK_SEL_MASK);
20090ade8cd8SKonstantin Porotchkin /* Set reference frequcency select - 0x2 */
20100ade8cd8SKonstantin Porotchkin mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
20110ade8cd8SKonstantin Porotchkin data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
20120ade8cd8SKonstantin Porotchkin /* Set PHY mode to USB - 0x5 */
20130ade8cd8SKonstantin Porotchkin mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
20140ade8cd8SKonstantin Porotchkin data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
20150ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
20160ade8cd8SKonstantin Porotchkin /* Set the amount of time spent in the LoZ state - set for 0x7 */
20170ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
20180ade8cd8SKonstantin Porotchkin 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
20190ade8cd8SKonstantin Porotchkin HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
20200ade8cd8SKonstantin Porotchkin /* Set max PHY generation setting - 5Gbps */
20210ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
20220ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
20230ade8cd8SKonstantin Porotchkin HPIPE_INTERFACE_GEN_MAX_MASK);
20240ade8cd8SKonstantin Porotchkin /* Set select data width 20Bit (SEL_BITS[2:0]) */
20250ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
20260ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_LOOPBACK_SEL_OFFSET,
20270ade8cd8SKonstantin Porotchkin HPIPE_LOOPBACK_SEL_MASK);
20280ade8cd8SKonstantin Porotchkin /* select de-emphasize 3.5db */
20290ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG,
20300ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET,
20310ade8cd8SKonstantin Porotchkin HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK);
20320ade8cd8SKonstantin Porotchkin /* override tx margining from the MAC */
20330ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG,
20340ade8cd8SKonstantin Porotchkin 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET,
20350ade8cd8SKonstantin Porotchkin HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK);
20360ade8cd8SKonstantin Porotchkin
2037ff9cfdc0SGrzegorz Jaszczyk /* The polarity inversion for USB was not tested due to lack of hw
2038ff9cfdc0SGrzegorz Jaszczyk * design which requires it. Support is added for customer needs.
2039ff9cfdc0SGrzegorz Jaszczyk */
2040ff9cfdc0SGrzegorz Jaszczyk if (phy_polarity_invert)
2041ff9cfdc0SGrzegorz Jaszczyk mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG,
2042ff9cfdc0SGrzegorz Jaszczyk phy_polarity_invert);
2043ff9cfdc0SGrzegorz Jaszczyk
20440ade8cd8SKonstantin Porotchkin /* Start analog parameters from ETP(HW) */
20450ade8cd8SKonstantin Porotchkin debug("stage: Analog parameters from ETP(HW)\n");
20460ade8cd8SKonstantin Porotchkin /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */
20470ade8cd8SKonstantin Porotchkin mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK;
20480ade8cd8SKonstantin Porotchkin data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET;
20490ade8cd8SKonstantin Porotchkin /* Set Override PHY DFE control pins for 0x1 */
20500ade8cd8SKonstantin Porotchkin mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK;
20510ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET;
20520ade8cd8SKonstantin Porotchkin /* Set Spread Spectrum Clock Enable fot 0x1 */
20530ade8cd8SKonstantin Porotchkin mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK;
20540ade8cd8SKonstantin Porotchkin data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET;
20550ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
2056*1b491eeaSElyes Haouas /* Configure SSC amplitude */
20570ade8cd8SKonstantin Porotchkin mask = HPIPE_G2_TX_SSC_AMP_MASK;
20580ade8cd8SKonstantin Porotchkin data = 0x1f << HPIPE_G2_TX_SSC_AMP_OFFSET;
20590ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask);
20600ade8cd8SKonstantin Porotchkin /* End of analog parameters */
20610ade8cd8SKonstantin Porotchkin
20620ade8cd8SKonstantin Porotchkin debug("stage: Comphy power up\n");
20630ade8cd8SKonstantin Porotchkin /* Release from PIPE soft reset */
20640ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
20650ade8cd8SKonstantin Porotchkin 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
20660ade8cd8SKonstantin Porotchkin HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
20670ade8cd8SKonstantin Porotchkin
20680ade8cd8SKonstantin Porotchkin /* wait 15ms - for comphy calibration done */
20690ade8cd8SKonstantin Porotchkin debug("stage: Check PLL\n");
20700ade8cd8SKonstantin Porotchkin /* Read lane status */
20710ade8cd8SKonstantin Porotchkin addr = hpipe_addr + HPIPE_LANE_STATUS1_REG;
20720ade8cd8SKonstantin Porotchkin data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
20730ade8cd8SKonstantin Porotchkin mask = data;
20740ade8cd8SKonstantin Porotchkin data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT);
20750ade8cd8SKonstantin Porotchkin if (data != 0) {
20760ade8cd8SKonstantin Porotchkin debug("Read from reg = %lx - value = 0x%x\n",
20770ade8cd8SKonstantin Porotchkin hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
20780ade8cd8SKonstantin Porotchkin ERROR("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
20790ade8cd8SKonstantin Porotchkin ret = -ETIMEDOUT;
20800ade8cd8SKonstantin Porotchkin }
20810ade8cd8SKonstantin Porotchkin
20820ade8cd8SKonstantin Porotchkin debug_exit();
20830ade8cd8SKonstantin Porotchkin
20840ade8cd8SKonstantin Porotchkin return ret;
20850ade8cd8SKonstantin Porotchkin }
20860ade8cd8SKonstantin Porotchkin
rx_pre_train(uint64_t comphy_base,uint8_t comphy_index)20878e8ec8cfSGrzegorz Jaszczyk static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index)
20888e8ec8cfSGrzegorz Jaszczyk {
20898e8ec8cfSGrzegorz Jaszczyk uintptr_t hpipe_addr;
20908e8ec8cfSGrzegorz Jaszczyk uint32_t mask, data;
20918e8ec8cfSGrzegorz Jaszczyk
20928e8ec8cfSGrzegorz Jaszczyk hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
20938e8ec8cfSGrzegorz Jaszczyk comphy_index);
20948e8ec8cfSGrzegorz Jaszczyk
20958e8ec8cfSGrzegorz Jaszczyk debug("rx_training preparation\n\n");
20968e8ec8cfSGrzegorz Jaszczyk
20978e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK;
20988e8ec8cfSGrzegorz Jaszczyk data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF);
20998e8ec8cfSGrzegorz Jaszczyk mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK;
21008e8ec8cfSGrzegorz Jaszczyk data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF);
21018e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask);
21028e8ec8cfSGrzegorz Jaszczyk
21038e8ec8cfSGrzegorz Jaszczyk
21048e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
21058e8ec8cfSGrzegorz Jaszczyk data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
21068e8ec8cfSGrzegorz Jaszczyk mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK;
21078e8ec8cfSGrzegorz Jaszczyk data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF);
21088e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask);
21098e8ec8cfSGrzegorz Jaszczyk
21108e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK;
21118e8ec8cfSGrzegorz Jaszczyk data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF);
21128e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
21138e8ec8cfSGrzegorz Jaszczyk
21148e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK;
21158e8ec8cfSGrzegorz Jaszczyk data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF);
21168e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask);
21178e8ec8cfSGrzegorz Jaszczyk
21188e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK;
21198e8ec8cfSGrzegorz Jaszczyk data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF);
21208e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask);
21218e8ec8cfSGrzegorz Jaszczyk
21228e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK;
21238e8ec8cfSGrzegorz Jaszczyk data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET);
21248e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
21258e8ec8cfSGrzegorz Jaszczyk
21268e8ec8cfSGrzegorz Jaszczyk mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK;
21278e8ec8cfSGrzegorz Jaszczyk data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF);
21288e8ec8cfSGrzegorz Jaszczyk mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
21298e8ec8cfSGrzegorz Jaszczyk data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
21308e8ec8cfSGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
21318e8ec8cfSGrzegorz Jaszczyk }
21328e8ec8cfSGrzegorz Jaszczyk
mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,uint8_t comphy_index)213342a29337SGrzegorz Jaszczyk int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
213442a29337SGrzegorz Jaszczyk uint8_t comphy_index)
21350ade8cd8SKonstantin Porotchkin {
21360ade8cd8SKonstantin Porotchkin uint32_t mask, data, timeout;
213742a29337SGrzegorz Jaszczyk uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res;
21388e8ec8cfSGrzegorz Jaszczyk uintptr_t hpipe_addr;
21390ade8cd8SKonstantin Porotchkin
214042a29337SGrzegorz Jaszczyk uint8_t ap_nr, cp_nr;
214142a29337SGrzegorz Jaszczyk
214242a29337SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
214342a29337SGrzegorz Jaszczyk
21440ade8cd8SKonstantin Porotchkin hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
21450ade8cd8SKonstantin Porotchkin comphy_index);
21460ade8cd8SKonstantin Porotchkin
214742a29337SGrzegorz Jaszczyk debug_enter();
214842a29337SGrzegorz Jaszczyk
21498e8ec8cfSGrzegorz Jaszczyk rx_pre_train(comphy_base, comphy_index);
215042a29337SGrzegorz Jaszczyk
215142a29337SGrzegorz Jaszczyk debug("Preparation for rx_training\n\n");
215242a29337SGrzegorz Jaszczyk
215342a29337SGrzegorz Jaszczyk /* Use the FFE table */
215442a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
215542a29337SGrzegorz Jaszczyk data = 0 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
215642a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
215742a29337SGrzegorz Jaszczyk
215842a29337SGrzegorz Jaszczyk /* Use auto-calibration value */
215942a29337SGrzegorz Jaszczyk mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
216042a29337SGrzegorz Jaszczyk data = 0 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
216142a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
216242a29337SGrzegorz Jaszczyk data, mask);
216342a29337SGrzegorz Jaszczyk
216442a29337SGrzegorz Jaszczyk /* Use Tx/Rx training results */
216542a29337SGrzegorz Jaszczyk mask = HPIPE_DFE_RES_FORCE_MASK;
216642a29337SGrzegorz Jaszczyk data = 0 << HPIPE_DFE_RES_FORCE_OFFSET;
216742a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
216842a29337SGrzegorz Jaszczyk
21698e8ec8cfSGrzegorz Jaszczyk debug("Enable RX training\n\n");
21700ade8cd8SKonstantin Porotchkin
217142a29337SGrzegorz Jaszczyk mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
217242a29337SGrzegorz Jaszczyk data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
217342a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
21740ade8cd8SKonstantin Porotchkin
21750ade8cd8SKonstantin Porotchkin /* Check the result of RX training */
21760ade8cd8SKonstantin Porotchkin timeout = RX_TRAINING_TIMEOUT;
217742a29337SGrzegorz Jaszczyk mask = HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET |
217842a29337SGrzegorz Jaszczyk HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET |
217942a29337SGrzegorz Jaszczyk HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK;
21800ade8cd8SKonstantin Porotchkin while (timeout) {
218142a29337SGrzegorz Jaszczyk data = mmio_read_32(hpipe_addr + HPIPE_INTERRUPT_1_REGISTER);
218242a29337SGrzegorz Jaszczyk if (data & mask)
21830ade8cd8SKonstantin Porotchkin break;
21840ade8cd8SKonstantin Porotchkin mdelay(1);
21850ade8cd8SKonstantin Porotchkin timeout--;
21860ade8cd8SKonstantin Porotchkin }
21870ade8cd8SKonstantin Porotchkin
218842a29337SGrzegorz Jaszczyk debug("RX training result: interrupt reg 0x%lx = 0x%x\n\n",
218942a29337SGrzegorz Jaszczyk hpipe_addr + HPIPE_INTERRUPT_1_REGISTER, data);
219042a29337SGrzegorz Jaszczyk
219142a29337SGrzegorz Jaszczyk if (timeout == 0 || data & HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK) {
219242a29337SGrzegorz Jaszczyk ERROR("Rx training timeout...\n");
21930ade8cd8SKonstantin Porotchkin return -ETIMEDOUT;
21940ade8cd8SKonstantin Porotchkin }
21950ade8cd8SKonstantin Porotchkin
219642a29337SGrzegorz Jaszczyk if (data & HPIPE_TRX_TRAIN_FAILED_MASK) {
219742a29337SGrzegorz Jaszczyk ERROR("Rx training failed...\n");
219842a29337SGrzegorz Jaszczyk return -EINVAL;
219942a29337SGrzegorz Jaszczyk }
220042a29337SGrzegorz Jaszczyk
220142a29337SGrzegorz Jaszczyk mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
220242a29337SGrzegorz Jaszczyk data = 0x0 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
220342a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
220442a29337SGrzegorz Jaszczyk
220542a29337SGrzegorz Jaszczyk debug("Training done, reading results...\n\n");
220642a29337SGrzegorz Jaszczyk
220742a29337SGrzegorz Jaszczyk mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK;
220842a29337SGrzegorz Jaszczyk g1_ffe_res_sel = ((mmio_read_32(hpipe_addr +
220942a29337SGrzegorz Jaszczyk HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
221042a29337SGrzegorz Jaszczyk & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET);
221142a29337SGrzegorz Jaszczyk
221242a29337SGrzegorz Jaszczyk mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK;
221342a29337SGrzegorz Jaszczyk g1_ffe_cap_sel = ((mmio_read_32(hpipe_addr +
221442a29337SGrzegorz Jaszczyk HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
221542a29337SGrzegorz Jaszczyk & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET);
221642a29337SGrzegorz Jaszczyk
221742a29337SGrzegorz Jaszczyk mask = HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK;
221842a29337SGrzegorz Jaszczyk align90 = ((mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG)
221942a29337SGrzegorz Jaszczyk & mask) >> HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET);
222042a29337SGrzegorz Jaszczyk
222142a29337SGrzegorz Jaszczyk mask = HPIPE_ADAPTED_DFE_RES_MASK;
222242a29337SGrzegorz Jaszczyk g1_dfe_res = ((mmio_read_32(hpipe_addr +
222342a29337SGrzegorz Jaszczyk HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG)
222442a29337SGrzegorz Jaszczyk & mask) >> HPIPE_ADAPTED_DFE_RES_OFFSET);
222542a29337SGrzegorz Jaszczyk
222642a29337SGrzegorz Jaszczyk debug("================================================\n");
222742a29337SGrzegorz Jaszczyk debug("Switching to static configuration:\n");
222842a29337SGrzegorz Jaszczyk debug("FFE_RES = 0x%x FFE_CAP = 0x%x align90 = 0x%x g1_dfe_res 0x%x\n",
222942a29337SGrzegorz Jaszczyk g1_ffe_res_sel, g1_ffe_cap_sel, align90, g1_dfe_res);
223042a29337SGrzegorz Jaszczyk debug("Result after training: 0x%lx= 0x%x, 0x%lx= 0x%x, 0x%lx = 0x%x\n",
223142a29337SGrzegorz Jaszczyk (hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
223242a29337SGrzegorz Jaszczyk mmio_read_32(hpipe_addr +
223342a29337SGrzegorz Jaszczyk HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
223442a29337SGrzegorz Jaszczyk (hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
223542a29337SGrzegorz Jaszczyk mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
223642a29337SGrzegorz Jaszczyk (hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG),
223742a29337SGrzegorz Jaszczyk mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG));
223842a29337SGrzegorz Jaszczyk debug("================================================\n");
223942a29337SGrzegorz Jaszczyk
224042a29337SGrzegorz Jaszczyk /* Update FFE_RES */
224142a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
224242a29337SGrzegorz Jaszczyk data = g1_ffe_res_sel << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
224342a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
224442a29337SGrzegorz Jaszczyk
224542a29337SGrzegorz Jaszczyk /* Update FFE_CAP */
224642a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
224742a29337SGrzegorz Jaszczyk data = g1_ffe_cap_sel << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
224842a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
224942a29337SGrzegorz Jaszczyk
225042a29337SGrzegorz Jaszczyk /* Bypass the FFE table settings and use the FFE settings directly from
225142a29337SGrzegorz Jaszczyk * registers FFE_RES_SEL and FFE_CAP_SEL
22520ade8cd8SKonstantin Porotchkin */
225342a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
225442a29337SGrzegorz Jaszczyk data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
225542a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
22560ade8cd8SKonstantin Porotchkin
225742a29337SGrzegorz Jaszczyk /* Force DFE resolution (use gen table value) */
22580ade8cd8SKonstantin Porotchkin mask = HPIPE_DFE_RES_FORCE_MASK;
22598e8ec8cfSGrzegorz Jaszczyk data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
22600ade8cd8SKonstantin Porotchkin reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
22610ade8cd8SKonstantin Porotchkin
226242a29337SGrzegorz Jaszczyk /* 0x111-G1 DFE_Setting_4 */
226342a29337SGrzegorz Jaszczyk mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
226442a29337SGrzegorz Jaszczyk data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
226542a29337SGrzegorz Jaszczyk reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
22660ade8cd8SKonstantin Porotchkin
226742a29337SGrzegorz Jaszczyk printf("########################################################\n");
226842a29337SGrzegorz Jaszczyk printf("# To use trained values update the ATF sources:\n");
2269a2847172SGrzegorz Jaszczyk printf("# plat/marvell/armada/a8k/<board_type>/board/phy-porting-layer.h ");
227042a29337SGrzegorz Jaszczyk printf("file\n# with new values as below (for appropriate AP nr %d",
227142a29337SGrzegorz Jaszczyk ap_nr);
227242a29337SGrzegorz Jaszczyk printf("and CP nr: %d comphy_index %d\n\n",
227342a29337SGrzegorz Jaszczyk cp_nr, comphy_index);
227442a29337SGrzegorz Jaszczyk printf("static struct xfi_params xfi_static_values_tab[AP_NUM]");
227542a29337SGrzegorz Jaszczyk printf("[CP_NUM][MAX_LANE_NR] = {\n");
227642a29337SGrzegorz Jaszczyk printf("\t...\n");
227742a29337SGrzegorz Jaszczyk printf("\t.g1_ffe_res_sel = 0x%x,\n", g1_ffe_res_sel);
227842a29337SGrzegorz Jaszczyk printf("\t.g1_ffe_cap_sel = 0x%x,\n", g1_ffe_cap_sel);
227942a29337SGrzegorz Jaszczyk printf("\t.align90 = 0x%x,\n", align90);
228042a29337SGrzegorz Jaszczyk printf("\t.g1_dfe_res = 0x%x\n", g1_dfe_res);
228142a29337SGrzegorz Jaszczyk printf("\t...\n");
228242a29337SGrzegorz Jaszczyk printf("};\n\n");
228342a29337SGrzegorz Jaszczyk printf("########################################################\n");
228442a29337SGrzegorz Jaszczyk
228542a29337SGrzegorz Jaszczyk rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1;
228642a29337SGrzegorz Jaszczyk
228742a29337SGrzegorz Jaszczyk return 0;
22880ade8cd8SKonstantin Porotchkin }
22890ade8cd8SKonstantin Porotchkin
22900ade8cd8SKonstantin Porotchkin /* During AP the proper mode is auto-negotiated and the mac, pcs and serdes
22910ade8cd8SKonstantin Porotchkin * configuration are done by the firmware loaded to the MG's CM3 for appropriate
22920ade8cd8SKonstantin Porotchkin * negotiated mode. Therefore there is no need to configure the mac, pcs and
22930ade8cd8SKonstantin Porotchkin * serdes from u-boot. The only thing that need to be setup is powering up
22940ade8cd8SKonstantin Porotchkin * the comphy, which is done through Common PHY<n> Configuration 1 Register
22950ade8cd8SKonstantin Porotchkin * (CP0: 0xF2441000, CP1: 0xF4441000). This step can't be done by MG's CM3,
22960ade8cd8SKonstantin Porotchkin * since it doesn't have an access to this register-set (but it has access to
22970ade8cd8SKonstantin Porotchkin * the network registers like: MG, AP, MAC, PCS, Serdes etc.)
22980ade8cd8SKonstantin Porotchkin */
mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode)22990ade8cd8SKonstantin Porotchkin static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,
2300050eb19cSGrzegorz Jaszczyk uint8_t comphy_index,
2301050eb19cSGrzegorz Jaszczyk uint32_t comphy_mode)
23020ade8cd8SKonstantin Porotchkin {
23030ade8cd8SKonstantin Porotchkin uint32_t mask, data;
23040ade8cd8SKonstantin Porotchkin uintptr_t comphy_addr = comphy_addr =
23050ade8cd8SKonstantin Porotchkin COMPHY_ADDR(comphy_base, comphy_index);
23060ade8cd8SKonstantin Porotchkin
2307050eb19cSGrzegorz Jaszczyk /* configure phy selector for XFI/SFI */
2308050eb19cSGrzegorz Jaszczyk mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
2309050eb19cSGrzegorz Jaszczyk comphy_mode);
23100ade8cd8SKonstantin Porotchkin debug_enter();
23110ade8cd8SKonstantin Porotchkin debug("stage: RFU configurations - hard reset comphy\n");
23120ade8cd8SKonstantin Porotchkin /* RFU configurations - hard reset comphy */
23130ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_UP_MASK;
23140ade8cd8SKonstantin Porotchkin data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
23150ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
23160ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
23170ade8cd8SKonstantin Porotchkin reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
23180ade8cd8SKonstantin Porotchkin debug_exit();
23190ade8cd8SKonstantin Porotchkin
2320718dbcacSKonstantin Porotchkin #if MSS_SUPPORT
2321718dbcacSKonstantin Porotchkin do {
2322718dbcacSKonstantin Porotchkin uint8_t ap_nr, cp_nr;
2323718dbcacSKonstantin Porotchkin
2324718dbcacSKonstantin Porotchkin /* start ap fw */
23255a9e46e6SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
23262cae4a85SGrzegorz Jaszczyk mg_start_ap_fw(cp_nr, comphy_index);
23275a9e46e6SGrzegorz Jaszczyk
2328718dbcacSKonstantin Porotchkin } while (0);
2329718dbcacSKonstantin Porotchkin #endif
23300ade8cd8SKonstantin Porotchkin return 0;
23310ade8cd8SKonstantin Porotchkin }
23320ade8cd8SKonstantin Porotchkin
23330ade8cd8SKonstantin Porotchkin /*
23340ade8cd8SKonstantin Porotchkin * This function allows to reset the digital synchronizers between
23350ade8cd8SKonstantin Porotchkin * the MAC and the PHY, it is required when the MAC changes its state.
23360ade8cd8SKonstantin Porotchkin */
mvebu_cp110_comphy_digital_reset(uint64_t comphy_base,uint8_t comphy_index,uint32_t comphy_mode,uint32_t command)23370ade8cd8SKonstantin Porotchkin int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base,
23380ade8cd8SKonstantin Porotchkin uint8_t comphy_index,
23390ade8cd8SKonstantin Porotchkin uint32_t comphy_mode, uint32_t command)
23400ade8cd8SKonstantin Porotchkin {
23410ade8cd8SKonstantin Porotchkin int mode = COMPHY_GET_MODE(comphy_mode);
23420ade8cd8SKonstantin Porotchkin uintptr_t sd_ip_addr;
23430ade8cd8SKonstantin Porotchkin uint32_t mask, data;
23440ade8cd8SKonstantin Porotchkin
23450ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
23460ade8cd8SKonstantin Porotchkin comphy_index);
23470ade8cd8SKonstantin Porotchkin
23480ade8cd8SKonstantin Porotchkin switch (mode) {
23490ade8cd8SKonstantin Porotchkin case (COMPHY_SGMII_MODE):
2350a669983cSPali Rohár case (COMPHY_2500BASEX_MODE):
23510ade8cd8SKonstantin Porotchkin case (COMPHY_XFI_MODE):
23520ade8cd8SKonstantin Porotchkin case (COMPHY_SFI_MODE):
23530ade8cd8SKonstantin Porotchkin case (COMPHY_RXAUI_MODE):
23540ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
23550ade8cd8SKonstantin Porotchkin data = ((command == COMPHY_COMMAND_DIGITAL_PWR_OFF) ?
23560ade8cd8SKonstantin Porotchkin 0x0 : 0x1) << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
23570ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
23580ade8cd8SKonstantin Porotchkin break;
23590ade8cd8SKonstantin Porotchkin default:
23600ade8cd8SKonstantin Porotchkin ERROR("comphy%d: Digital PWR ON/OFF is not supported\n",
23610ade8cd8SKonstantin Porotchkin comphy_index);
23620ade8cd8SKonstantin Porotchkin return -EINVAL;
23630ade8cd8SKonstantin Porotchkin }
23640ade8cd8SKonstantin Porotchkin
23650ade8cd8SKonstantin Porotchkin return 0;
23660ade8cd8SKonstantin Porotchkin }
23670ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_power_on(uint64_t comphy_base,uint8_t comphy_index,uint64_t comphy_mode,uint64_t comphy_train_base)2368550a06dfSAlex Evraev int mvebu_cp110_comphy_power_on(uint64_t comphy_base,
2369550a06dfSAlex Evraev uint8_t comphy_index,
2370550a06dfSAlex Evraev uint64_t comphy_mode,
2371550a06dfSAlex Evraev uint64_t comphy_train_base)
23720ade8cd8SKonstantin Porotchkin {
23730ade8cd8SKonstantin Porotchkin int mode = COMPHY_GET_MODE(comphy_mode);
23740ade8cd8SKonstantin Porotchkin int err = 0;
23750ade8cd8SKonstantin Porotchkin
23760ade8cd8SKonstantin Porotchkin debug_enter();
23770ade8cd8SKonstantin Porotchkin
23780ade8cd8SKonstantin Porotchkin switch (mode) {
23790ade8cd8SKonstantin Porotchkin case(COMPHY_SATA_MODE):
23800ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_sata_power_on(comphy_base,
23810ade8cd8SKonstantin Porotchkin comphy_index,
23820ade8cd8SKonstantin Porotchkin comphy_mode);
23830ade8cd8SKonstantin Porotchkin break;
23840ade8cd8SKonstantin Porotchkin case(COMPHY_SGMII_MODE):
2385a669983cSPali Rohár case(COMPHY_2500BASEX_MODE):
23860ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_sgmii_power_on(comphy_base,
23870ade8cd8SKonstantin Porotchkin comphy_index,
23880ade8cd8SKonstantin Porotchkin comphy_mode);
23890ade8cd8SKonstantin Porotchkin break;
23900ade8cd8SKonstantin Porotchkin /* From comphy perspective, XFI and SFI are the same */
23910ade8cd8SKonstantin Porotchkin case (COMPHY_XFI_MODE):
23920ade8cd8SKonstantin Porotchkin case (COMPHY_SFI_MODE):
23930ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_xfi_power_on(comphy_base,
23940ade8cd8SKonstantin Porotchkin comphy_index,
2395550a06dfSAlex Evraev comphy_mode,
2396550a06dfSAlex Evraev comphy_train_base);
23970ade8cd8SKonstantin Porotchkin break;
23980ade8cd8SKonstantin Porotchkin case (COMPHY_PCIE_MODE):
23990ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_pcie_power_on(comphy_base,
24000ade8cd8SKonstantin Porotchkin comphy_index,
24010ade8cd8SKonstantin Porotchkin comphy_mode);
24020ade8cd8SKonstantin Porotchkin break;
24030ade8cd8SKonstantin Porotchkin case (COMPHY_RXAUI_MODE):
24040ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_rxaui_power_on(comphy_base,
24050ade8cd8SKonstantin Porotchkin comphy_index,
24060ade8cd8SKonstantin Porotchkin comphy_mode);
240742a29337SGrzegorz Jaszczyk break;
24080ade8cd8SKonstantin Porotchkin case (COMPHY_USB3H_MODE):
24090ade8cd8SKonstantin Porotchkin case (COMPHY_USB3D_MODE):
24100ade8cd8SKonstantin Porotchkin err = mvebu_cp110_comphy_usb3_power_on(comphy_base,
24110ade8cd8SKonstantin Porotchkin comphy_index,
24120ade8cd8SKonstantin Porotchkin comphy_mode);
24130ade8cd8SKonstantin Porotchkin break;
24140ade8cd8SKonstantin Porotchkin case (COMPHY_AP_MODE):
2415050eb19cSGrzegorz Jaszczyk err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index,
2416050eb19cSGrzegorz Jaszczyk comphy_mode);
24170ade8cd8SKonstantin Porotchkin break;
24180ade8cd8SKonstantin Porotchkin default:
2419f858e989SGrzegorz Jaszczyk ERROR("comphy%d: unsupported comphy mode\n", comphy_index);
24200ade8cd8SKonstantin Porotchkin err = -EINVAL;
24210ade8cd8SKonstantin Porotchkin break;
24220ade8cd8SKonstantin Porotchkin }
24230ade8cd8SKonstantin Porotchkin
24240ade8cd8SKonstantin Porotchkin debug_exit();
24250ade8cd8SKonstantin Porotchkin
24260ade8cd8SKonstantin Porotchkin return err;
24270ade8cd8SKonstantin Porotchkin }
24280ade8cd8SKonstantin Porotchkin
mvebu_cp110_comphy_power_off(uint64_t comphy_base,uint8_t comphy_index,uint64_t comphy_mode)242955df84f9SIgal Liberman int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index,
243055df84f9SIgal Liberman uint64_t comphy_mode)
24310ade8cd8SKonstantin Porotchkin {
24320ade8cd8SKonstantin Porotchkin uintptr_t sd_ip_addr, comphy_ip_addr;
24330ade8cd8SKonstantin Porotchkin uint32_t mask, data;
243442a29337SGrzegorz Jaszczyk uint8_t ap_nr, cp_nr;
243555df84f9SIgal Liberman _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
24360ade8cd8SKonstantin Porotchkin
24370ade8cd8SKonstantin Porotchkin debug_enter();
24380ade8cd8SKonstantin Porotchkin
243955df84f9SIgal Liberman /* Power-off might happen because of 2 things:
244055df84f9SIgal Liberman * 1. Bootloader turns off unconnected lanes
244155df84f9SIgal Liberman * 2. Linux turns off all lanes during boot
244255df84f9SIgal Liberman * (and then reconfigure it).
244355df84f9SIgal Liberman *
244455df84f9SIgal Liberman * For PCIe, there's a problem:
244555df84f9SIgal Liberman * In Armada 8K DB boards, PCIe initialization can be executed
244655df84f9SIgal Liberman * only once (PCIe reset performed during chip power on and
244755df84f9SIgal Liberman * it cannot be executed via GPIO later) so a lane configured to
244855df84f9SIgal Liberman * PCIe should not be powered off by Linux.
244955df84f9SIgal Liberman *
245055df84f9SIgal Liberman * So, check 2 things:
245155df84f9SIgal Liberman * 1. Is Linux called for power-off?
245255df84f9SIgal Liberman * 2. Is the comphy configured to PCIe?
245355df84f9SIgal Liberman * If the answer is YES for both 1 and 2, skip the power-off.
245455df84f9SIgal Liberman *
245555df84f9SIgal Liberman * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
245655df84f9SIgal Liberman * so after GPIO reset is added to Linux Kernel, it can be
245755df84f9SIgal Liberman * powered-off.
245855df84f9SIgal Liberman */
245955df84f9SIgal Liberman if (!called_from_uboot) {
246055df84f9SIgal Liberman data = mmio_read_32(comphy_base +
246155df84f9SIgal Liberman COMMON_SELECTOR_PIPE_REG_OFFSET);
246255df84f9SIgal Liberman data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index);
246355df84f9SIgal Liberman data &= COMMON_SELECTOR_COMPHY_MASK;
246455df84f9SIgal Liberman if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE)
246555df84f9SIgal Liberman return 0;
246655df84f9SIgal Liberman }
246755df84f9SIgal Liberman
246842a29337SGrzegorz Jaszczyk mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
246942a29337SGrzegorz Jaszczyk
247042a29337SGrzegorz Jaszczyk if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
247142a29337SGrzegorz Jaszczyk debug("Skip %s for comphy[%d][%d][%d], due to rx training\n",
247242a29337SGrzegorz Jaszczyk __func__, ap_nr, cp_nr, comphy_index);
247342a29337SGrzegorz Jaszczyk return 0;
247442a29337SGrzegorz Jaszczyk }
247542a29337SGrzegorz Jaszczyk
24760ade8cd8SKonstantin Porotchkin sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
24770ade8cd8SKonstantin Porotchkin comphy_index);
24780ade8cd8SKonstantin Porotchkin comphy_ip_addr = COMPHY_ADDR(comphy_base, comphy_index);
24790ade8cd8SKonstantin Porotchkin
24800ade8cd8SKonstantin Porotchkin /* Hard reset the comphy, for Ethernet modes and Sata */
24810ade8cd8SKonstantin Porotchkin mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
24820ade8cd8SKonstantin Porotchkin data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
24830ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
24840ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
24850ade8cd8SKonstantin Porotchkin mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
24860ade8cd8SKonstantin Porotchkin data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
24870ade8cd8SKonstantin Porotchkin reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
24880ade8cd8SKonstantin Porotchkin
24890ade8cd8SKonstantin Porotchkin /* PCIe reset */
24900ade8cd8SKonstantin Porotchkin spin_lock(&cp110_mac_reset_lock);
24910ade8cd8SKonstantin Porotchkin
24920ade8cd8SKonstantin Porotchkin /* The mvebu_cp110_comphy_power_off will be called only from Linux (to
24930ade8cd8SKonstantin Porotchkin * override settings done by bootloader) and it will be relevant only
24940ade8cd8SKonstantin Porotchkin * to PCIe (called before check if to skip pcie power off or not).
24950ade8cd8SKonstantin Porotchkin */
24960ade8cd8SKonstantin Porotchkin data = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
24970ade8cd8SKonstantin Porotchkin SYS_CTRL_UINIT_SOFT_RESET_REG);
24980ade8cd8SKonstantin Porotchkin switch (comphy_index) {
24990ade8cd8SKonstantin Porotchkin case COMPHY_LANE0:
25000ade8cd8SKonstantin Porotchkin data &= ~PCIE_MAC_RESET_MASK_PORT0;
25010ade8cd8SKonstantin Porotchkin break;
25020ade8cd8SKonstantin Porotchkin case COMPHY_LANE4:
25030ade8cd8SKonstantin Porotchkin data &= ~PCIE_MAC_RESET_MASK_PORT1;
25040ade8cd8SKonstantin Porotchkin break;
25050ade8cd8SKonstantin Porotchkin case COMPHY_LANE5:
25060ade8cd8SKonstantin Porotchkin data &= ~PCIE_MAC_RESET_MASK_PORT2;
25070ade8cd8SKonstantin Porotchkin break;
25080ade8cd8SKonstantin Porotchkin }
25090ade8cd8SKonstantin Porotchkin
25100ade8cd8SKonstantin Porotchkin mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) +
25110ade8cd8SKonstantin Porotchkin SYS_CTRL_UINIT_SOFT_RESET_REG, data);
25120ade8cd8SKonstantin Porotchkin spin_unlock(&cp110_mac_reset_lock);
25130ade8cd8SKonstantin Porotchkin
25140ade8cd8SKonstantin Porotchkin /* Hard reset the comphy, for PCIe and usb3 */
25150ade8cd8SKonstantin Porotchkin mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
25160ade8cd8SKonstantin Porotchkin data = 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
25170ade8cd8SKonstantin Porotchkin mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
25180ade8cd8SKonstantin Porotchkin data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
25190ade8cd8SKonstantin Porotchkin reg_set(comphy_ip_addr + COMMON_PHY_CFG1_REG, data, mask);
25200ade8cd8SKonstantin Porotchkin
25210ade8cd8SKonstantin Porotchkin /* Clear comphy PHY and PIPE selector, can't rely on previous config. */
25220ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index);
25230ade8cd8SKonstantin Porotchkin mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index);
25240ade8cd8SKonstantin Porotchkin
25250ade8cd8SKonstantin Porotchkin debug_exit();
25260ade8cd8SKonstantin Porotchkin
25270ade8cd8SKonstantin Porotchkin return 0;
25280ade8cd8SKonstantin Porotchkin }
2529