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