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