1*29b103c7SStefan Roese /* 2*29b103c7SStefan Roese * Copyright (C) Marvell International Ltd. and its affiliates 3*29b103c7SStefan Roese * 4*29b103c7SStefan Roese * SPDX-License-Identifier: GPL-2.0 5*29b103c7SStefan Roese */ 6*29b103c7SStefan Roese 7*29b103c7SStefan Roese #include <common.h> 8*29b103c7SStefan Roese #include <i2c.h> 9*29b103c7SStefan Roese #include <spl.h> 10*29b103c7SStefan Roese #include <asm/io.h> 11*29b103c7SStefan Roese #include <asm/arch/cpu.h> 12*29b103c7SStefan Roese #include <asm/arch/soc.h> 13*29b103c7SStefan Roese 14*29b103c7SStefan Roese #include "high_speed_env_spec.h" 15*29b103c7SStefan Roese #include "board_env_spec.h" 16*29b103c7SStefan Roese 17*29b103c7SStefan Roese #define SERDES_VERION "2.1.5" 18*29b103c7SStefan Roese #define ENDED_OK "High speed PHY - Ended Successfully\n" 19*29b103c7SStefan Roese 20*29b103c7SStefan Roese static const u8 serdes_cfg[][SERDES_LAST_UNIT] = BIN_SERDES_CFG; 21*29b103c7SStefan Roese 22*29b103c7SStefan Roese extern MV_BIN_SERDES_CFG *serdes_info_tbl[]; 23*29b103c7SStefan Roese 24*29b103c7SStefan Roese extern u8 rd78460gp_twsi_dev[]; 25*29b103c7SStefan Roese extern u8 db88f78xx0rev2_twsi_dev[]; 26*29b103c7SStefan Roese 27*29b103c7SStefan Roese u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs); 28*29b103c7SStefan Roese int pex_local_bus_num_set(u32 pex_if, u32 bus_num); 29*29b103c7SStefan Roese int pex_local_dev_num_set(u32 pex_if, u32 dev_num); 30*29b103c7SStefan Roese 31*29b103c7SStefan Roese #define MV_BOARD_PEX_MODULE_ADDR 0x23 32*29b103c7SStefan Roese #define MV_BOARD_PEX_MODULE_ID 1 33*29b103c7SStefan Roese #define MV_BOARD_ETM_MODULE_ID 2 34*29b103c7SStefan Roese 35*29b103c7SStefan Roese #define PEX_MODULE_DETECT 1 36*29b103c7SStefan Roese #define ETM_MODULE_DETECT 2 37*29b103c7SStefan Roese 38*29b103c7SStefan Roese #define PEX_MODE_GET(satr) ((satr & 0x6) >> 1) 39*29b103c7SStefan Roese #define PEX_CAPABILITY_GET(satr) (satr & 1) 40*29b103c7SStefan Roese #define MV_PEX_UNIT_TO_IF(pex_unit) ((pex_unit < 3) ? (pex_unit * 4) : 9) 41*29b103c7SStefan Roese 42*29b103c7SStefan Roese /* Static parametes */ 43*29b103c7SStefan Roese static int config_module; 44*29b103c7SStefan Roese static int switch_module; 45*29b103c7SStefan Roese 46*29b103c7SStefan Roese /* Local function */ 47*29b103c7SStefan Roese static u32 board_id_get(void) 48*29b103c7SStefan Roese { 49*29b103c7SStefan Roese #if defined(CONFIG_DB_88F78X60) 50*29b103c7SStefan Roese return DB_88F78XX0_BP_ID; 51*29b103c7SStefan Roese #elif defined(CONFIG_RD_88F78460_SERVER) 52*29b103c7SStefan Roese return RD_78460_SERVER_ID; 53*29b103c7SStefan Roese #elif defined(CONFIG_RD_78460_SERVER_REV2) 54*29b103c7SStefan Roese return RD_78460_SERVER_REV2_ID; 55*29b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_PCAC) 56*29b103c7SStefan Roese return DB_78X60_PCAC_ID; 57*29b103c7SStefan Roese #elif defined(CONFIG_DB_88F78X60_REV2) 58*29b103c7SStefan Roese return DB_88F78XX0_BP_REV2_ID; 59*29b103c7SStefan Roese #elif defined(CONFIG_RD_78460_NAS) 60*29b103c7SStefan Roese return RD_78460_NAS_ID; 61*29b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_AMC) 62*29b103c7SStefan Roese return DB_78X60_AMC_ID; 63*29b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_PCAC_REV2) 64*29b103c7SStefan Roese return DB_78X60_PCAC_REV2_ID; 65*29b103c7SStefan Roese #elif defined(CONFIG_DB_784MP_GP) 66*29b103c7SStefan Roese return DB_784MP_GP_ID; 67*29b103c7SStefan Roese #elif defined(CONFIG_RD_78460_CUSTOMER) 68*29b103c7SStefan Roese return RD_78460_CUSTOMER_ID; 69*29b103c7SStefan Roese #else 70*29b103c7SStefan Roese /* 71*29b103c7SStefan Roese * Return 0 here for custom board as this should not be used 72*29b103c7SStefan Roese * for custom boards. 73*29b103c7SStefan Roese */ 74*29b103c7SStefan Roese return 0; 75*29b103c7SStefan Roese #endif 76*29b103c7SStefan Roese } 77*29b103c7SStefan Roese 78*29b103c7SStefan Roese static u8 board_sat_r_get(u8 dev_num, u8 reg) 79*29b103c7SStefan Roese { 80*29b103c7SStefan Roese u8 data; 81*29b103c7SStefan Roese u8 *dev; 82*29b103c7SStefan Roese u32 board_id = board_id_get(); 83*29b103c7SStefan Roese int ret; 84*29b103c7SStefan Roese 85*29b103c7SStefan Roese i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 86*29b103c7SStefan Roese 87*29b103c7SStefan Roese switch (board_id) { 88*29b103c7SStefan Roese case DB_784MP_GP_ID: 89*29b103c7SStefan Roese dev = rd78460gp_twsi_dev; 90*29b103c7SStefan Roese 91*29b103c7SStefan Roese break; 92*29b103c7SStefan Roese case DB_88F78XX0_BP_ID: 93*29b103c7SStefan Roese case DB_88F78XX0_BP_REV2_ID: 94*29b103c7SStefan Roese dev = db88f78xx0rev2_twsi_dev; 95*29b103c7SStefan Roese break; 96*29b103c7SStefan Roese 97*29b103c7SStefan Roese case DB_78X60_PCAC_ID: 98*29b103c7SStefan Roese case FPGA_88F78XX0_ID: 99*29b103c7SStefan Roese case DB_78X60_PCAC_REV2_ID: 100*29b103c7SStefan Roese case RD_78460_SERVER_REV2_ID: 101*29b103c7SStefan Roese default: 102*29b103c7SStefan Roese return 0; 103*29b103c7SStefan Roese } 104*29b103c7SStefan Roese 105*29b103c7SStefan Roese /* Read MPP module ID */ 106*29b103c7SStefan Roese ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1); 107*29b103c7SStefan Roese if (ret) 108*29b103c7SStefan Roese return MV_ERROR; 109*29b103c7SStefan Roese 110*29b103c7SStefan Roese return data; 111*29b103c7SStefan Roese } 112*29b103c7SStefan Roese 113*29b103c7SStefan Roese static int board_modules_scan(void) 114*29b103c7SStefan Roese { 115*29b103c7SStefan Roese u8 val; 116*29b103c7SStefan Roese u32 board_id = board_id_get(); 117*29b103c7SStefan Roese int ret; 118*29b103c7SStefan Roese 119*29b103c7SStefan Roese /* Perform scan only for DB board */ 120*29b103c7SStefan Roese if ((board_id == DB_88F78XX0_BP_ID) || 121*29b103c7SStefan Roese (board_id == DB_88F78XX0_BP_REV2_ID)) { 122*29b103c7SStefan Roese /* reset modules flags */ 123*29b103c7SStefan Roese config_module = 0; 124*29b103c7SStefan Roese 125*29b103c7SStefan Roese i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 126*29b103c7SStefan Roese 127*29b103c7SStefan Roese /* SERDES module (only PEX model is supported now) */ 128*29b103c7SStefan Roese ret = i2c_read(MV_BOARD_PEX_MODULE_ADDR, 0, 1, (u8 *)&val, 1); 129*29b103c7SStefan Roese if (ret) 130*29b103c7SStefan Roese return MV_ERROR; 131*29b103c7SStefan Roese 132*29b103c7SStefan Roese if (val == MV_BOARD_PEX_MODULE_ID) 133*29b103c7SStefan Roese config_module = PEX_MODULE_DETECT; 134*29b103c7SStefan Roese if (val == MV_BOARD_ETM_MODULE_ID) 135*29b103c7SStefan Roese config_module = ETM_MODULE_DETECT; 136*29b103c7SStefan Roese } else if (board_id == RD_78460_NAS_ID) { 137*29b103c7SStefan Roese switch_module = 0; 138*29b103c7SStefan Roese if ((reg_read(GPP_DATA_IN_REG(2)) & MV_GPP66) == 0x0) 139*29b103c7SStefan Roese switch_module = 1; 140*29b103c7SStefan Roese } 141*29b103c7SStefan Roese 142*29b103c7SStefan Roese return MV_OK; 143*29b103c7SStefan Roese } 144*29b103c7SStefan Roese 145*29b103c7SStefan Roese u32 pex_max_unit_get(void) 146*29b103c7SStefan Roese { 147*29b103c7SStefan Roese /* 148*29b103c7SStefan Roese * TODO: 149*29b103c7SStefan Roese * Right now only MV78460 is supported. Other SoC's might need 150*29b103c7SStefan Roese * a different value here. 151*29b103c7SStefan Roese */ 152*29b103c7SStefan Roese return MV_PEX_MAX_UNIT; 153*29b103c7SStefan Roese } 154*29b103c7SStefan Roese 155*29b103c7SStefan Roese u32 pex_max_if_get(void) 156*29b103c7SStefan Roese { 157*29b103c7SStefan Roese /* 158*29b103c7SStefan Roese * TODO: 159*29b103c7SStefan Roese * Right now only MV78460 is supported. Other SoC's might need 160*29b103c7SStefan Roese * a different value here. 161*29b103c7SStefan Roese */ 162*29b103c7SStefan Roese return MV_PEX_MAX_IF; 163*29b103c7SStefan Roese } 164*29b103c7SStefan Roese 165*29b103c7SStefan Roese u8 board_cpu_freq_get(void) 166*29b103c7SStefan Roese { 167*29b103c7SStefan Roese u32 sar; 168*29b103c7SStefan Roese u32 sar_msb; 169*29b103c7SStefan Roese 170*29b103c7SStefan Roese sar = reg_read(MPP_SAMPLE_AT_RESET(0)); 171*29b103c7SStefan Roese sar_msb = reg_read(MPP_SAMPLE_AT_RESET(1)); 172*29b103c7SStefan Roese return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21); 173*29b103c7SStefan Roese } 174*29b103c7SStefan Roese 175*29b103c7SStefan Roese __weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) 176*29b103c7SStefan Roese { 177*29b103c7SStefan Roese u32 board_id; 178*29b103c7SStefan Roese u32 serdes_cfg_val = 0; /* default */ 179*29b103c7SStefan Roese 180*29b103c7SStefan Roese board_id = board_id_get(); 181*29b103c7SStefan Roese 182*29b103c7SStefan Roese switch (board_id) { 183*29b103c7SStefan Roese case DB_784MP_GP_ID: 184*29b103c7SStefan Roese serdes_cfg_val = 0; 185*29b103c7SStefan Roese break; 186*29b103c7SStefan Roese } 187*29b103c7SStefan Roese 188*29b103c7SStefan Roese return &serdes_info_tbl[board_id - BOARD_ID_BASE][serdes_cfg_val]; 189*29b103c7SStefan Roese } 190*29b103c7SStefan Roese 191*29b103c7SStefan Roese u16 ctrl_model_get(void) 192*29b103c7SStefan Roese { 193*29b103c7SStefan Roese /* Right now only MV78460 supported */ 194*29b103c7SStefan Roese return MV_78460_DEV_ID; 195*29b103c7SStefan Roese } 196*29b103c7SStefan Roese 197*29b103c7SStefan Roese u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info) 198*29b103c7SStefan Roese { 199*29b103c7SStefan Roese if (line_num < 8) 200*29b103c7SStefan Roese return (info->line0_7 >> (line_num << 2)) & 0xF; 201*29b103c7SStefan Roese else 202*29b103c7SStefan Roese return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF; 203*29b103c7SStefan Roese } 204*29b103c7SStefan Roese 205*29b103c7SStefan Roese int serdes_phy_config(void) 206*29b103c7SStefan Roese { 207*29b103c7SStefan Roese int status = MV_OK; 208*29b103c7SStefan Roese u32 line_cfg; 209*29b103c7SStefan Roese u8 line_num; 210*29b103c7SStefan Roese /* addr/value for each line @ every setup step */ 211*29b103c7SStefan Roese u32 addr[16][11], val[16][11]; 212*29b103c7SStefan Roese u8 pex_unit, pex_line_num; 213*29b103c7SStefan Roese u8 sgmii_port = 0; 214*29b103c7SStefan Roese u32 tmp; 215*29b103c7SStefan Roese u32 in_direct; 216*29b103c7SStefan Roese u8 max_serdes_lines; 217*29b103c7SStefan Roese MV_BIN_SERDES_CFG *info; 218*29b103c7SStefan Roese u8 satr11; 219*29b103c7SStefan Roese u8 sata_port; 220*29b103c7SStefan Roese u8 freq; 221*29b103c7SStefan Roese u8 device_rev; 222*29b103c7SStefan Roese u32 rx_high_imp_mode; 223*29b103c7SStefan Roese u16 ctrl_mode; 224*29b103c7SStefan Roese u32 board_id = board_id_get(); 225*29b103c7SStefan Roese u32 pex_if; 226*29b103c7SStefan Roese u32 pex_if_num; 227*29b103c7SStefan Roese 228*29b103c7SStefan Roese /* 229*29b103c7SStefan Roese * TODO: 230*29b103c7SStefan Roese * Right now we only support the MV78460 with 16 serdes lines 231*29b103c7SStefan Roese */ 232*29b103c7SStefan Roese max_serdes_lines = 16; 233*29b103c7SStefan Roese if (max_serdes_lines == 0) 234*29b103c7SStefan Roese return MV_OK; 235*29b103c7SStefan Roese 236*29b103c7SStefan Roese switch (board_id) { 237*29b103c7SStefan Roese case DB_78X60_AMC_ID: 238*29b103c7SStefan Roese case DB_78X60_PCAC_REV2_ID: 239*29b103c7SStefan Roese case RD_78460_CUSTOMER_ID: 240*29b103c7SStefan Roese case RD_78460_SERVER_ID: 241*29b103c7SStefan Roese case RD_78460_SERVER_REV2_ID: 242*29b103c7SStefan Roese case DB_78X60_PCAC_ID: 243*29b103c7SStefan Roese satr11 = (0x1 << 1) | 1; 244*29b103c7SStefan Roese break; 245*29b103c7SStefan Roese case FPGA_88F78XX0_ID: 246*29b103c7SStefan Roese case RD_78460_NAS_ID: 247*29b103c7SStefan Roese satr11 = (0x0 << 1) | 1; 248*29b103c7SStefan Roese break; 249*29b103c7SStefan Roese case DB_88F78XX0_BP_REV2_ID: 250*29b103c7SStefan Roese case DB_784MP_GP_ID: 251*29b103c7SStefan Roese case DB_88F78XX0_BP_ID: 252*29b103c7SStefan Roese satr11 = board_sat_r_get(1, 1); 253*29b103c7SStefan Roese if ((u8) MV_ERROR == (u8) satr11) 254*29b103c7SStefan Roese return MV_ERROR; 255*29b103c7SStefan Roese break; 256*29b103c7SStefan Roese } 257*29b103c7SStefan Roese 258*29b103c7SStefan Roese board_modules_scan(); 259*29b103c7SStefan Roese memset(addr, 0, sizeof(addr)); 260*29b103c7SStefan Roese memset(val, 0, sizeof(val)); 261*29b103c7SStefan Roese 262*29b103c7SStefan Roese /* Check if DRAM is already initialized */ 263*29b103c7SStefan Roese if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & 264*29b103c7SStefan Roese (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { 265*29b103c7SStefan Roese DEBUG_INIT_S("High speed PHY - Version: "); 266*29b103c7SStefan Roese DEBUG_INIT_S(SERDES_VERION); 267*29b103c7SStefan Roese DEBUG_INIT_S(" - 2nd boot - Skip\n"); 268*29b103c7SStefan Roese return MV_OK; 269*29b103c7SStefan Roese } 270*29b103c7SStefan Roese DEBUG_INIT_S("High speed PHY - Version: "); 271*29b103c7SStefan Roese DEBUG_INIT_S(SERDES_VERION); 272*29b103c7SStefan Roese DEBUG_INIT_S(" (COM-PHY-V20)\n"); 273*29b103c7SStefan Roese 274*29b103c7SStefan Roese /* 275*29b103c7SStefan Roese * AVS : disable AVS for frequency less than 1333 276*29b103c7SStefan Roese */ 277*29b103c7SStefan Roese freq = board_cpu_freq_get(); 278*29b103c7SStefan Roese device_rev = mv_ctrl_rev_get(); 279*29b103c7SStefan Roese 280*29b103c7SStefan Roese if (device_rev == 2) { /* for B0 only */ 281*29b103c7SStefan Roese u32 cpu_avs; 282*29b103c7SStefan Roese u8 fabric_freq; 283*29b103c7SStefan Roese cpu_avs = reg_read(CPU_AVS_CONTROL2_REG); 284*29b103c7SStefan Roese DEBUG_RD_REG(CPU_AVS_CONTROL2_REG, cpu_avs); 285*29b103c7SStefan Roese cpu_avs &= ~(1 << 9); 286*29b103c7SStefan Roese 287*29b103c7SStefan Roese if ((0x4 == freq) || (0xB == freq)) { 288*29b103c7SStefan Roese u32 tmp2; 289*29b103c7SStefan Roese 290*29b103c7SStefan Roese tmp2 = reg_read(CPU_AVS_CONTROL0_REG); 291*29b103c7SStefan Roese DEBUG_RD_REG(CPU_AVS_CONTROL0_REG, tmp2); 292*29b103c7SStefan Roese /* cpu upper limit = 1.1V cpu lower limit = 0.9125V */ 293*29b103c7SStefan Roese tmp2 |= 0x0FF; 294*29b103c7SStefan Roese reg_write(CPU_AVS_CONTROL0_REG, tmp2); 295*29b103c7SStefan Roese DEBUG_WR_REG(CPU_AVS_CONTROL0_REG, tmp2); 296*29b103c7SStefan Roese cpu_avs |= (1 << 9); /* cpu avs enable */ 297*29b103c7SStefan Roese cpu_avs |= (1 << 18); /* AvsAvddDetEn enable */ 298*29b103c7SStefan Roese fabric_freq = (reg_read(MPP_SAMPLE_AT_RESET(0)) & 299*29b103c7SStefan Roese SAR0_FABRIC_FREQ_MASK) >> SAR0_FABRIC_FREQ_OFFSET; 300*29b103c7SStefan Roese if ((0xB == freq) && (5 == fabric_freq)) { 301*29b103c7SStefan Roese u32 core_avs; 302*29b103c7SStefan Roese 303*29b103c7SStefan Roese core_avs = reg_read(CORE_AVS_CONTROL_0REG); 304*29b103c7SStefan Roese DEBUG_RD_REG(CORE_AVS_CONTROL_0REG, core_avs); 305*29b103c7SStefan Roese 306*29b103c7SStefan Roese /* 307*29b103c7SStefan Roese * Set core lower limit = 0.9V & 308*29b103c7SStefan Roese * core upper limit = 0.9125V 309*29b103c7SStefan Roese */ 310*29b103c7SStefan Roese core_avs &= ~(0xff); 311*29b103c7SStefan Roese core_avs |= 0x0E; 312*29b103c7SStefan Roese reg_write(CORE_AVS_CONTROL_0REG, core_avs); 313*29b103c7SStefan Roese DEBUG_WR_REG(CORE_AVS_CONTROL_0REG, core_avs); 314*29b103c7SStefan Roese 315*29b103c7SStefan Roese core_avs = reg_read(CORE_AVS_CONTROL_2REG); 316*29b103c7SStefan Roese DEBUG_RD_REG(CORE_AVS_CONTROL_2REG, core_avs); 317*29b103c7SStefan Roese core_avs |= (1 << 9); /* core AVS enable */ 318*29b103c7SStefan Roese reg_write(CORE_AVS_CONTROL_2REG, core_avs); 319*29b103c7SStefan Roese DEBUG_WR_REG(CORE_AVS_CONTROL_2REG, core_avs); 320*29b103c7SStefan Roese 321*29b103c7SStefan Roese tmp2 = reg_read(GENERAL_PURPOSE_RESERVED0_REG); 322*29b103c7SStefan Roese DEBUG_RD_REG(GENERAL_PURPOSE_RESERVED0_REG, 323*29b103c7SStefan Roese tmp2); 324*29b103c7SStefan Roese tmp2 |= 0x1; /* AvsCoreAvddDetEn enable */ 325*29b103c7SStefan Roese reg_write(GENERAL_PURPOSE_RESERVED0_REG, tmp2); 326*29b103c7SStefan Roese DEBUG_WR_REG(GENERAL_PURPOSE_RESERVED0_REG, 327*29b103c7SStefan Roese tmp2); 328*29b103c7SStefan Roese } 329*29b103c7SStefan Roese } 330*29b103c7SStefan Roese reg_write(CPU_AVS_CONTROL2_REG, cpu_avs); 331*29b103c7SStefan Roese DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs); 332*29b103c7SStefan Roese } 333*29b103c7SStefan Roese 334*29b103c7SStefan Roese info = board_serdes_cfg_get(PEX_MODE_GET(satr11)); 335*29b103c7SStefan Roese DEBUG_INIT_FULL_S("info->line0_7= 0x"); 336*29b103c7SStefan Roese DEBUG_INIT_FULL_D(info->line0_7, 8); 337*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" info->line8_15= 0x"); 338*29b103c7SStefan Roese DEBUG_INIT_FULL_D(info->line8_15, 8); 339*29b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 340*29b103c7SStefan Roese 341*29b103c7SStefan Roese if (info == NULL) { 342*29b103c7SStefan Roese DEBUG_INIT_S("Hight speed PHY Error #1\n"); 343*29b103c7SStefan Roese return MV_ERROR; 344*29b103c7SStefan Roese } 345*29b103c7SStefan Roese 346*29b103c7SStefan Roese if (config_module & ETM_MODULE_DETECT) { /* step 0.9 ETM */ 347*29b103c7SStefan Roese DEBUG_INIT_FULL_S("ETM module detect Step 0.9:\n"); 348*29b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, 0x11111111); 349*29b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x11111111); 350*29b103c7SStefan Roese info->pex_mode[1] = PEX_BUS_DISABLED; /* pex unit 1 is configure for ETM */ 351*29b103c7SStefan Roese mdelay(100); 352*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d); /* SETM0 - start calibration */ 353*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d); /* SETM0 - start calibration */ 354*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d); /* SETM1 - start calibration */ 355*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d); /* SETM1 - start calibration */ 356*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801); /* SETM0 - SATA mode & 25MHz ref clk */ 357*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801); /* SETM0 - SATA mode & 25MHz ref clk */ 358*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801); /* SETM1 - SATA mode & 25MHz ref clk */ 359*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801); /* SETM1 - SATA mode & 25MHz ref clk */ 360*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF); /* SETM0 - G3 full swing AMP */ 361*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF); /* SETM0 - G3 full swing AMP */ 362*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF); /* SETM1 - G3 full swing AMP */ 363*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF); /* SETM1 - G3 full swing AMP */ 364*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800); /* SETM0 - 40 data bit width */ 365*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800); /* SETM0 - 40 data bit width */ 366*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800); /* SETM1 - 40 data bit width */ 367*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800); /* SETM1 - 40 data bit width */ 368*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400); /* lane0(serdes4) */ 369*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400); /* lane0(serdes4) */ 370*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400); /* lane3(serdes7) */ 371*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400); /* lane3(serdes7) */ 372*29b103c7SStefan Roese } 373*29b103c7SStefan Roese 374*29b103c7SStefan Roese /* STEP -1 [PEX-Only] First phase of PEX-PIPE Configuration: */ 375*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 1: First phase of PEX-PIPE Configuration\n"); 376*29b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 377*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 378*29b103c7SStefan Roese continue; 379*29b103c7SStefan Roese 380*29b103c7SStefan Roese /* 1. GLOB_CLK_CTRL Reset and Clock Control */ 381*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25); 382*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25); 383*29b103c7SStefan Roese 384*29b103c7SStefan Roese /* 2. GLOB_TEST_CTRL Test Mode Control */ 385*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) { 386*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 387*29b103c7SStefan Roese (0xC2 << 16) | 0x200); 388*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 389*29b103c7SStefan Roese (0xC2 << 16) | 0x200); 390*29b103c7SStefan Roese } 391*29b103c7SStefan Roese 392*29b103c7SStefan Roese /* 3. GLOB_CLK_SRC_LO Clock Source Low */ 393*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) { 394*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 395*29b103c7SStefan Roese (0xC3 << 16) | 0x0F); 396*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 397*29b103c7SStefan Roese (0xC3 << 16) | 0x0F); 398*29b103c7SStefan Roese } 399*29b103c7SStefan Roese 400*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC5 << 16) | 0x11F); 401*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 402*29b103c7SStefan Roese (0xC5 << 16) | 0x11F); 403*29b103c7SStefan Roese } 404*29b103c7SStefan Roese 405*29b103c7SStefan Roese /* 406*29b103c7SStefan Roese * 2 Configure the desire PIN_PHY_GEN and do power down to the PU_PLL, 407*29b103c7SStefan Roese * PU_RX,PU_TX. (bits[12:5]) 408*29b103c7SStefan Roese */ 409*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 2: Configure the desire PIN_PHY_GEN\n"); 410*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 411*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 412*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 413*29b103c7SStefan Roese continue; 414*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) 415*29b103c7SStefan Roese continue; 416*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 417*29b103c7SStefan Roese switch (line_num) { 418*29b103c7SStefan Roese case 4: 419*29b103c7SStefan Roese case 6: 420*29b103c7SStefan Roese sata_port = 0; 421*29b103c7SStefan Roese break; 422*29b103c7SStefan Roese case 5: 423*29b103c7SStefan Roese sata_port = 1; 424*29b103c7SStefan Roese break; 425*29b103c7SStefan Roese default: 426*29b103c7SStefan Roese DEBUG_INIT_C 427*29b103c7SStefan Roese ("SATA port error for serdes line: ", 428*29b103c7SStefan Roese line_num, 2); 429*29b103c7SStefan Roese return MV_ERROR; 430*29b103c7SStefan Roese } 431*29b103c7SStefan Roese tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port)); 432*29b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 433*29b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 434*29b103c7SStefan Roese tmp |= ((info->bus_speed & (1 << line_num)) != 0) ? 435*29b103c7SStefan Roese (0x11 << 5) : 0x0; 436*29b103c7SStefan Roese 437*29b103c7SStefan Roese reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 438*29b103c7SStefan Roese DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 439*29b103c7SStefan Roese } 440*29b103c7SStefan Roese 441*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 442*29b103c7SStefan Roese /* 443*29b103c7SStefan Roese * 4) Configure the desire PIN_PHY_GEN and do power 444*29b103c7SStefan Roese * down to the PU_PLL,PU_RX,PU_TX. (bits[12:5]) 445*29b103c7SStefan Roese */ 446*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(0)); 447*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp); 448*29b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 449*29b103c7SStefan Roese tmp |= 0x660; 450*29b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(0), tmp); 451*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp); 452*29b103c7SStefan Roese continue; 453*29b103c7SStefan Roese } 454*29b103c7SStefan Roese 455*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 456*29b103c7SStefan Roese sgmii_port = 0; 457*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 458*29b103c7SStefan Roese sgmii_port = 1; 459*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 460*29b103c7SStefan Roese sgmii_port = 2; 461*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 462*29b103c7SStefan Roese sgmii_port = 3; 463*29b103c7SStefan Roese else 464*29b103c7SStefan Roese continue; 465*29b103c7SStefan Roese 466*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port)); 467*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 468*29b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 469*29b103c7SStefan Roese tmp |= (((info->bus_speed & (1 << line_num)) != 0) ? 470*29b103c7SStefan Roese (0x88 << 5) : (0x66 << 5)); 471*29b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 472*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 473*29b103c7SStefan Roese } 474*29b103c7SStefan Roese 475*29b103c7SStefan Roese /* Step 3 - QSGMII enable */ 476*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 3 QSGMII enable\n"); 477*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 478*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 479*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 480*29b103c7SStefan Roese /* QSGMII Active bit set to true */ 481*29b103c7SStefan Roese tmp = reg_read(QSGMII_CONTROL_1_REG); 482*29b103c7SStefan Roese DEBUG_RD_REG(QSGMII_CONTROL_1_REG, tmp); 483*29b103c7SStefan Roese tmp |= (1 << 30); 484*29b103c7SStefan Roese #ifdef ERRATA_GL_6572255 485*29b103c7SStefan Roese tmp |= (1 << 27); 486*29b103c7SStefan Roese #endif 487*29b103c7SStefan Roese reg_write(QSGMII_CONTROL_1_REG, tmp); 488*29b103c7SStefan Roese DEBUG_WR_REG(QSGMII_CONTROL_1_REG, tmp); 489*29b103c7SStefan Roese } 490*29b103c7SStefan Roese } 491*29b103c7SStefan Roese 492*29b103c7SStefan Roese /* Step 4 - configure SERDES MUXes */ 493*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 4: Configure SERDES MUXes\n"); 494*29b103c7SStefan Roese if (config_module & ETM_MODULE_DETECT) { 495*29b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, 0x40041111); 496*29b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x40041111); 497*29b103c7SStefan Roese } else { 498*29b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, info->line0_7); 499*29b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, info->line0_7); 500*29b103c7SStefan Roese } 501*29b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_8_15, info->line8_15); 502*29b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_8_15, info->line8_15); 503*29b103c7SStefan Roese 504*29b103c7SStefan Roese /* Step 5: Activate the RX High Impedance Mode */ 505*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 5: Activate the RX High Impedance Mode\n"); 506*29b103c7SStefan Roese rx_high_imp_mode = 0x8080; 507*29b103c7SStefan Roese if (device_rev == 2) /* for B0 only */ 508*29b103c7SStefan Roese rx_high_imp_mode |= 4; 509*29b103c7SStefan Roese 510*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 511*29b103c7SStefan Roese /* for each serdes lane */ 512*29b103c7SStefan Roese DEBUG_INIT_FULL_S("SERDES "); 513*29b103c7SStefan Roese DEBUG_INIT_FULL_D_10(line_num, 2); 514*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 515*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) { 516*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" unconnected ***\n"); 517*29b103c7SStefan Roese continue; 518*29b103c7SStefan Roese } 519*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 520*29b103c7SStefan Roese pex_unit = line_num >> 2; 521*29b103c7SStefan Roese pex_line_num = line_num % 4; 522*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" - PEX unit "); 523*29b103c7SStefan Roese DEBUG_INIT_FULL_D_10(pex_unit, 1); 524*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" line= "); 525*29b103c7SStefan Roese DEBUG_INIT_FULL_D_10(pex_line_num, 1); 526*29b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 527*29b103c7SStefan Roese 528*29b103c7SStefan Roese /* Needed for PEX_PHY_ACCESS_REG macro */ 529*29b103c7SStefan Roese if ((line_num > 7) && 530*29b103c7SStefan Roese (info->pex_mode[3] == PEX_BUS_MODE_X8)) 531*29b103c7SStefan Roese /* lines 8 - 15 are belong to PEX3 in x8 mode */ 532*29b103c7SStefan Roese pex_unit = 3; 533*29b103c7SStefan Roese 534*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 535*29b103c7SStefan Roese continue; 536*29b103c7SStefan Roese 537*29b103c7SStefan Roese /* 538*29b103c7SStefan Roese * 8) Activate the RX High Impedance Mode field 539*29b103c7SStefan Roese * (bit [2]) in register /PCIe_USB Control (Each MAC 540*29b103c7SStefan Roese * contain different Access to reach its 541*29b103c7SStefan Roese * Serdes-Regfile). 542*29b103c7SStefan Roese * [PEX-Only] Set bit[12]: The analog part latches idle 543*29b103c7SStefan Roese * if PU_TX = 1 and PU_PLL =1. 544*29b103c7SStefan Roese */ 545*29b103c7SStefan Roese 546*29b103c7SStefan Roese /* Termination enable */ 547*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) { 548*29b103c7SStefan Roese in_direct = (0x48 << 16) | (pex_line_num << 24) | 549*29b103c7SStefan Roese 0x1000 | rx_high_imp_mode; /* x1 */ 550*29b103c7SStefan Roese } else if ((info->pex_mode[pex_unit] == 551*29b103c7SStefan Roese PEX_BUS_MODE_X4) && (pex_line_num == 0)) 552*29b103c7SStefan Roese in_direct = (0x48 << 16) | (pex_line_num << 24) | 553*29b103c7SStefan Roese 0x1000 | (rx_high_imp_mode & 0xff); /* x4 */ 554*29b103c7SStefan Roese else 555*29b103c7SStefan Roese in_direct = 0; 556*29b103c7SStefan Roese 557*29b103c7SStefan Roese if (in_direct) { 558*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 559*29b103c7SStefan Roese in_direct); 560*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 561*29b103c7SStefan Roese in_direct); 562*29b103c7SStefan Roese } 563*29b103c7SStefan Roese 564*29b103c7SStefan Roese continue; 565*29b103c7SStefan Roese } 566*29b103c7SStefan Roese 567*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 568*29b103c7SStefan Roese /* 569*29b103c7SStefan Roese * port 0 for serdes lines 4,6, and port 1 for 570*29b103c7SStefan Roese * serdes lines 5 571*29b103c7SStefan Roese */ 572*29b103c7SStefan Roese sata_port = line_num & 1; 573*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" - SATA port "); 574*29b103c7SStefan Roese DEBUG_INIT_FULL_D_10(sata_port, 2); 575*29b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 576*29b103c7SStefan Roese reg_write(SATA_COMPHY_CTRL_REG(sata_port), 577*29b103c7SStefan Roese rx_high_imp_mode); 578*29b103c7SStefan Roese DEBUG_WR_REG(SATA_COMPHY_CTRL_REG(sata_port), 579*29b103c7SStefan Roese rx_high_imp_mode); 580*29b103c7SStefan Roese continue; 581*29b103c7SStefan Roese } 582*29b103c7SStefan Roese 583*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 584*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" - QSGMII\n"); 585*29b103c7SStefan Roese reg_write(SGMII_COMPHY_CTRL_REG(0), rx_high_imp_mode); 586*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(0), 587*29b103c7SStefan Roese rx_high_imp_mode); 588*29b103c7SStefan Roese continue; 589*29b103c7SStefan Roese } 590*29b103c7SStefan Roese 591*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 592*29b103c7SStefan Roese sgmii_port = 0; 593*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 594*29b103c7SStefan Roese sgmii_port = 1; 595*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 596*29b103c7SStefan Roese sgmii_port = 2; 597*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 598*29b103c7SStefan Roese sgmii_port = 3; 599*29b103c7SStefan Roese else 600*29b103c7SStefan Roese continue; 601*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" - SGMII port "); 602*29b103c7SStefan Roese DEBUG_INIT_FULL_D_10(sgmii_port, 2); 603*29b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 604*29b103c7SStefan Roese reg_write(SGMII_COMPHY_CTRL_REG(sgmii_port), rx_high_imp_mode); 605*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(sgmii_port), 606*29b103c7SStefan Roese rx_high_imp_mode); 607*29b103c7SStefan Roese } /* for each serdes lane */ 608*29b103c7SStefan Roese 609*29b103c7SStefan Roese /* Step 6 [PEX-Only] PEX-Main configuration (X4 or X1): */ 610*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6: [PEX-Only] PEX-Main configuration (X4 or X1)\n"); 611*29b103c7SStefan Roese tmp = reg_read(SOC_CTRL_REG); 612*29b103c7SStefan Roese DEBUG_RD_REG(SOC_CTRL_REG, tmp); 613*29b103c7SStefan Roese tmp &= 0x200; 614*29b103c7SStefan Roese if (info->pex_mode[0] == PEX_BUS_MODE_X1) 615*29b103c7SStefan Roese tmp |= PCIE0_QUADX1_EN; 616*29b103c7SStefan Roese if (info->pex_mode[1] == PEX_BUS_MODE_X1) 617*29b103c7SStefan Roese tmp |= PCIE1_QUADX1_EN; 618*29b103c7SStefan Roese if (((reg_read(MPP_SAMPLE_AT_RESET(0)) & PEX_CLK_100MHZ_MASK) >> 619*29b103c7SStefan Roese PEX_CLK_100MHZ_OFFSET) == 0x1) 620*29b103c7SStefan Roese tmp |= (PCIE0_CLK_OUT_EN_MASK | PCIE1_CLK_OUT_EN_MASK); 621*29b103c7SStefan Roese 622*29b103c7SStefan Roese reg_write(SOC_CTRL_REG, tmp); 623*29b103c7SStefan Roese DEBUG_WR_REG(SOC_CTRL_REG, tmp); 624*29b103c7SStefan Roese 625*29b103c7SStefan Roese /* 6.2 PCI Express Link Capabilities */ 626*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6.2: [PEX-Only] PCI Express Link Capabilities\n"); 627*29b103c7SStefan Roese 628*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 629*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 630*29b103c7SStefan Roese 631*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 632*29b103c7SStefan Roese /* 633*29b103c7SStefan Roese * PCI Express Control 634*29b103c7SStefan Roese * 0xX1A00 [0]: 635*29b103c7SStefan Roese * 0x0 X4-Link. 636*29b103c7SStefan Roese * 0x1 X1-Link 637*29b103c7SStefan Roese */ 638*29b103c7SStefan Roese pex_unit = line_num >> 2; 639*29b103c7SStefan Roese pex_if = MV_SERDES_NUM_TO_PEX_NUM(line_num); 640*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 641*29b103c7SStefan Roese continue; 642*29b103c7SStefan Roese 643*29b103c7SStefan Roese /* set Common Clock Configuration */ 644*29b103c7SStefan Roese tmp = reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if)); 645*29b103c7SStefan Roese DEBUG_RD_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 646*29b103c7SStefan Roese tmp |= (1 << 6); 647*29b103c7SStefan Roese reg_write(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 648*29b103c7SStefan Roese DEBUG_WR_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 649*29b103c7SStefan Roese 650*29b103c7SStefan Roese tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if)); 651*29b103c7SStefan Roese DEBUG_RD_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 652*29b103c7SStefan Roese tmp &= ~(0x3FF); 653*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) 654*29b103c7SStefan Roese tmp |= (0x1 << 4); 655*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) 656*29b103c7SStefan Roese tmp |= (0x4 << 4); 657*29b103c7SStefan Roese if (0 == PEX_CAPABILITY_GET(satr11)) 658*29b103c7SStefan Roese tmp |= 0x1; 659*29b103c7SStefan Roese else 660*29b103c7SStefan Roese tmp |= 0x2; 661*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6.2: PEX "); 662*29b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 663*29b103c7SStefan Roese DEBUG_INIT_FULL_C(" set GEN", (tmp & 3), 1); 664*29b103c7SStefan Roese reg_write(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 665*29b103c7SStefan Roese DEBUG_WR_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 666*29b103c7SStefan Roese 667*29b103c7SStefan Roese /* 668*29b103c7SStefan Roese * If pex is X4, no need to pass thru the other 669*29b103c7SStefan Roese * 3X1 serdes lines 670*29b103c7SStefan Roese */ 671*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) 672*29b103c7SStefan Roese line_num += 3; 673*29b103c7SStefan Roese } 674*29b103c7SStefan Roese } 675*29b103c7SStefan Roese 676*29b103c7SStefan Roese /* 677*29b103c7SStefan Roese * Step 7 [PEX-X4 Only] To create PEX-Link that contain 4-lanes you 678*29b103c7SStefan Roese * need to config the register SOC_Misc/General Purpose2 679*29b103c7SStefan Roese * (Address= 182F8) 680*29b103c7SStefan Roese */ 681*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 7: [PEX-X4 Only] To create PEX-Link\n"); 682*29b103c7SStefan Roese tmp = reg_read(GEN_PURP_RES_2_REG); 683*29b103c7SStefan Roese DEBUG_RD_REG(GEN_PURP_RES_2_REG, tmp); 684*29b103c7SStefan Roese 685*29b103c7SStefan Roese tmp &= 0xFFFF0000; 686*29b103c7SStefan Roese if (info->pex_mode[0] == PEX_BUS_MODE_X4) 687*29b103c7SStefan Roese tmp |= 0x0000000F; 688*29b103c7SStefan Roese 689*29b103c7SStefan Roese if (info->pex_mode[1] == PEX_BUS_MODE_X4) 690*29b103c7SStefan Roese tmp |= 0x000000F0; 691*29b103c7SStefan Roese 692*29b103c7SStefan Roese if (info->pex_mode[2] == PEX_BUS_MODE_X4) 693*29b103c7SStefan Roese tmp |= 0x00000F00; 694*29b103c7SStefan Roese 695*29b103c7SStefan Roese if (info->pex_mode[3] == PEX_BUS_MODE_X4) 696*29b103c7SStefan Roese tmp |= 0x0000F000; 697*29b103c7SStefan Roese 698*29b103c7SStefan Roese reg_write(GEN_PURP_RES_2_REG, tmp); 699*29b103c7SStefan Roese DEBUG_WR_REG(GEN_PURP_RES_2_REG, tmp); 700*29b103c7SStefan Roese 701*29b103c7SStefan Roese /* Steps 8 , 9 ,10 - use prepared REG addresses and values */ 702*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 7,8,9,10 and 11\n"); 703*29b103c7SStefan Roese 704*29b103c7SStefan Roese /* Prepare PHY parameters for each step according to MUX selection */ 705*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 706*29b103c7SStefan Roese /* for each serdes lane */ 707*29b103c7SStefan Roese 708*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 709*29b103c7SStefan Roese 710*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 711*29b103c7SStefan Roese continue; 712*29b103c7SStefan Roese 713*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 714*29b103c7SStefan Roese pex_unit = line_num >> 2; 715*29b103c7SStefan Roese pex_line_num = line_num % 4; 716*29b103c7SStefan Roese 717*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 718*29b103c7SStefan Roese continue; 719*29b103c7SStefan Roese /* 720*29b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) 721*29b103c7SStefan Roese * and REF_FREF_SEL (bits[4:0]) in the register Power 722*29b103c7SStefan Roese * and PLL Control (Each MAC contain different Access 723*29b103c7SStefan Roese * to reach its Serdes-Regfile). 724*29b103c7SStefan Roese */ 725*29b103c7SStefan Roese if (((info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) && 726*29b103c7SStefan Roese (0 == pex_line_num)) 727*29b103c7SStefan Roese || ((info->pex_mode[pex_unit] == PEX_BUS_MODE_X1))) { 728*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 729*29b103c7SStefan Roese (0x01 << 16) | (pex_line_num << 24) | 730*29b103c7SStefan Roese 0xFC60); 731*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 732*29b103c7SStefan Roese (0x01 << 16) | (pex_line_num << 24) 733*29b103c7SStefan Roese | 0xFC60); 734*29b103c7SStefan Roese /* 735*29b103c7SStefan Roese * Step 8.1: [PEX-Only] Configure Max PLL Rate 736*29b103c7SStefan Roese * (bit 8 in KVCO Calibration Control and 737*29b103c7SStefan Roese * bits[10:9] in 738*29b103c7SStefan Roese */ 739*29b103c7SStefan Roese /* Use Maximum PLL Rate(Bit 8) */ 740*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 741*29b103c7SStefan Roese (0x02 << 16) | (1 << 31) | 742*29b103c7SStefan Roese (pex_line_num << 24)); /* read command */ 743*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 744*29b103c7SStefan Roese (0x02 << 16) | (1 << 31) | 745*29b103c7SStefan Roese (pex_line_num << 24)); 746*29b103c7SStefan Roese tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit)); 747*29b103c7SStefan Roese DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 748*29b103c7SStefan Roese tmp &= ~(1 << 31); 749*29b103c7SStefan Roese tmp |= (1 << 8); 750*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp); 751*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 752*29b103c7SStefan Roese 753*29b103c7SStefan Roese /* Use Maximum PLL Rate(Bits [10:9]) */ 754*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 755*29b103c7SStefan Roese (0x81 << 16) | (1 << 31) | 756*29b103c7SStefan Roese (pex_line_num << 24)); /* read command */ 757*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 758*29b103c7SStefan Roese (0x81 << 16) | (1 << 31) | 759*29b103c7SStefan Roese (pex_line_num << 24)); 760*29b103c7SStefan Roese tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit)); 761*29b103c7SStefan Roese DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 762*29b103c7SStefan Roese tmp &= ~(1 << 31); 763*29b103c7SStefan Roese tmp |= (3 << 9); 764*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp); 765*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 766*29b103c7SStefan Roese } 767*29b103c7SStefan Roese 768*29b103c7SStefan Roese continue; 769*29b103c7SStefan Roese } 770*29b103c7SStefan Roese 771*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 772*29b103c7SStefan Roese /* 773*29b103c7SStefan Roese * Port 0 for serdes lines 4,6, and port 1 for serdes 774*29b103c7SStefan Roese * lines 5 775*29b103c7SStefan Roese */ 776*29b103c7SStefan Roese sata_port = line_num & 1; 777*29b103c7SStefan Roese 778*29b103c7SStefan Roese /* 779*29b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) and 780*29b103c7SStefan Roese * REF_FREF_SEL (bits[4:0]) in the register Power 781*29b103c7SStefan Roese * and PLL Control (Each MAC contain different Access 782*29b103c7SStefan Roese * to reach its Serdes-Regfile). 783*29b103c7SStefan Roese */ 784*29b103c7SStefan Roese reg_write(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801); 785*29b103c7SStefan Roese DEBUG_WR_REG(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801); 786*29b103c7SStefan Roese 787*29b103c7SStefan Roese /* 9) Configure the desire SEL_BITS */ 788*29b103c7SStefan Roese reg_write(SATA_DIG_LP_ENA_REG(sata_port), 0x400); 789*29b103c7SStefan Roese DEBUG_WR_REG(SATA_DIG_LP_ENA_REG(sata_port), 0x400); 790*29b103c7SStefan Roese 791*29b103c7SStefan Roese /* 10) Configure the desire REFCLK_SEL */ 792*29b103c7SStefan Roese 793*29b103c7SStefan Roese reg_write(SATA_REF_CLK_SEL_REG(sata_port), 0x400); 794*29b103c7SStefan Roese DEBUG_WR_REG(SATA_REF_CLK_SEL_REG(sata_port), 0x400); 795*29b103c7SStefan Roese 796*29b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 797*29b103c7SStefan Roese tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port)); 798*29b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 799*29b103c7SStefan Roese tmp |= 7; 800*29b103c7SStefan Roese reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 801*29b103c7SStefan Roese DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 802*29b103c7SStefan Roese 803*29b103c7SStefan Roese continue; 804*29b103c7SStefan Roese } 805*29b103c7SStefan Roese 806*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 807*29b103c7SStefan Roese /* 808*29b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) 809*29b103c7SStefan Roese * and REF_FREF_SEL (bits[4:0]) in the register 810*29b103c7SStefan Roese */ 811*29b103c7SStefan Roese reg_write(SGMII_PWR_PLL_CTRL_REG(0), 0xF881); 812*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(0), 0xF881); 813*29b103c7SStefan Roese 814*29b103c7SStefan Roese /* 815*29b103c7SStefan Roese * 9) Configure the desire SEL_BITS (bits [11:0] 816*29b103c7SStefan Roese * in register 817*29b103c7SStefan Roese */ 818*29b103c7SStefan Roese reg_write(SGMII_DIG_LP_ENA_REG(0), 0x400); 819*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(0), 0x400); 820*29b103c7SStefan Roese 821*29b103c7SStefan Roese /* 822*29b103c7SStefan Roese * 10) Configure the desire REFCLK_SEL (bit [10]) 823*29b103c7SStefan Roese * in register 824*29b103c7SStefan Roese */ 825*29b103c7SStefan Roese reg_write(SGMII_REF_CLK_SEL_REG(0), 0x400); 826*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(0), 0x400); 827*29b103c7SStefan Roese 828*29b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 829*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(0)); 830*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp); 831*29b103c7SStefan Roese tmp |= 7; 832*29b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(0), tmp); 833*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp); 834*29b103c7SStefan Roese continue; 835*29b103c7SStefan Roese } 836*29b103c7SStefan Roese 837*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 838*29b103c7SStefan Roese sgmii_port = 0; 839*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 840*29b103c7SStefan Roese sgmii_port = 1; 841*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 842*29b103c7SStefan Roese sgmii_port = 2; 843*29b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 844*29b103c7SStefan Roese sgmii_port = 3; 845*29b103c7SStefan Roese else 846*29b103c7SStefan Roese continue; 847*29b103c7SStefan Roese 848*29b103c7SStefan Roese /* 849*29b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) and 850*29b103c7SStefan Roese * REF_FREF_SEL (bits[4:0]) in the register 851*29b103c7SStefan Roese */ 852*29b103c7SStefan Roese reg_write(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881); 853*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881); 854*29b103c7SStefan Roese 855*29b103c7SStefan Roese /* 9) Configure the desire SEL_BITS (bits [11:0] in register */ 856*29b103c7SStefan Roese reg_write(SGMII_DIG_LP_ENA_REG(sgmii_port), 0); 857*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(sgmii_port), 0); 858*29b103c7SStefan Roese 859*29b103c7SStefan Roese /* 10) Configure the desire REFCLK_SEL (bit [10]) in register */ 860*29b103c7SStefan Roese reg_write(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400); 861*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400); 862*29b103c7SStefan Roese 863*29b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 864*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port)); 865*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 866*29b103c7SStefan Roese tmp |= 7; 867*29b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 868*29b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 869*29b103c7SStefan Roese 870*29b103c7SStefan Roese } /* for each serdes lane */ 871*29b103c7SStefan Roese 872*29b103c7SStefan Roese /* Step 12 [PEX-Only] Last phase of PEX-PIPE Configuration */ 873*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 12: [PEX-Only] Last phase of PEX-PIPE Configuration\n"); 874*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 875*29b103c7SStefan Roese /* for each serdes lane */ 876*29b103c7SStefan Roese 877*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 878*29b103c7SStefan Roese 879*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 880*29b103c7SStefan Roese continue; 881*29b103c7SStefan Roese 882*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 883*29b103c7SStefan Roese pex_unit = line_num >> 2; 884*29b103c7SStefan Roese pex_line_num = line_num % 4; 885*29b103c7SStefan Roese if (0 == pex_line_num) { 886*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 887*29b103c7SStefan Roese (0xC1 << 16) | 0x24); 888*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 889*29b103c7SStefan Roese (0xC1 << 16) | 0x24); 890*29b103c7SStefan Roese } 891*29b103c7SStefan Roese } 892*29b103c7SStefan Roese } 893*29b103c7SStefan Roese 894*29b103c7SStefan Roese /*--------------------------------------------------------------*/ 895*29b103c7SStefan Roese /* Step 13: Wait 15ms before checking results */ 896*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 13: Wait 15ms before checking results"); 897*29b103c7SStefan Roese mdelay(15); 898*29b103c7SStefan Roese tmp = 20; 899*29b103c7SStefan Roese while (tmp) { 900*29b103c7SStefan Roese status = MV_OK; 901*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 902*29b103c7SStefan Roese u32 tmp; 903*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 904*29b103c7SStefan Roese if (line_cfg == 905*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 906*29b103c7SStefan Roese continue; 907*29b103c7SStefan Roese 908*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) 909*29b103c7SStefan Roese continue; 910*29b103c7SStefan Roese 911*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 912*29b103c7SStefan Roese /* 913*29b103c7SStefan Roese * Port 0 for serdes lines 4,6, and port 1 914*29b103c7SStefan Roese * for serdes lines 5 915*29b103c7SStefan Roese */ 916*29b103c7SStefan Roese sata_port = line_num & 1; 917*29b103c7SStefan Roese 918*29b103c7SStefan Roese tmp = 919*29b103c7SStefan Roese reg_read(SATA_LP_PHY_EXT_STAT_REG 920*29b103c7SStefan Roese (sata_port)); 921*29b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_STAT_REG 922*29b103c7SStefan Roese (sata_port), tmp); 923*29b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 924*29b103c7SStefan Roese status = MV_ERROR; 925*29b103c7SStefan Roese continue; 926*29b103c7SStefan Roese } 927*29b103c7SStefan Roese 928*29b103c7SStefan Roese if (line_cfg == 929*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 930*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_STAT_REG(0)); 931*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_STAT_REG(0), tmp); 932*29b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 933*29b103c7SStefan Roese status = MV_ERROR; 934*29b103c7SStefan Roese continue; 935*29b103c7SStefan Roese } 936*29b103c7SStefan Roese 937*29b103c7SStefan Roese if (line_cfg == 938*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 939*29b103c7SStefan Roese sgmii_port = 0; 940*29b103c7SStefan Roese else if (line_cfg == 941*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 942*29b103c7SStefan Roese sgmii_port = 1; 943*29b103c7SStefan Roese else if (line_cfg == 944*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 945*29b103c7SStefan Roese sgmii_port = 2; 946*29b103c7SStefan Roese else if (line_cfg == 947*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 948*29b103c7SStefan Roese sgmii_port = 3; 949*29b103c7SStefan Roese else 950*29b103c7SStefan Roese continue; 951*29b103c7SStefan Roese 952*29b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_STAT_REG(sgmii_port)); 953*29b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_STAT_REG(sgmii_port), tmp); 954*29b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 955*29b103c7SStefan Roese status = MV_ERROR; 956*29b103c7SStefan Roese } 957*29b103c7SStefan Roese 958*29b103c7SStefan Roese if (status == MV_OK) 959*29b103c7SStefan Roese break; 960*29b103c7SStefan Roese mdelay(5); 961*29b103c7SStefan Roese tmp--; 962*29b103c7SStefan Roese } 963*29b103c7SStefan Roese 964*29b103c7SStefan Roese /* 965*29b103c7SStefan Roese * Step14 [PEX-Only] In order to configure RC/EP mode please write 966*29b103c7SStefan Roese * to register 0x0060 bits 967*29b103c7SStefan Roese */ 968*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 14: [PEX-Only] In order to configure\n"); 969*29b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 970*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 971*29b103c7SStefan Roese continue; 972*29b103c7SStefan Roese tmp = 973*29b103c7SStefan Roese reg_read(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit))); 974*29b103c7SStefan Roese DEBUG_RD_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 975*29b103c7SStefan Roese tmp); 976*29b103c7SStefan Roese tmp &= ~(0xf << 20); 977*29b103c7SStefan Roese if (info->pex_type == MV_PEX_ROOT_COMPLEX) 978*29b103c7SStefan Roese tmp |= (0x4 << 20); 979*29b103c7SStefan Roese else 980*29b103c7SStefan Roese tmp |= (0x1 << 20); 981*29b103c7SStefan Roese reg_write(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 982*29b103c7SStefan Roese tmp); 983*29b103c7SStefan Roese DEBUG_WR_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 984*29b103c7SStefan Roese tmp); 985*29b103c7SStefan Roese } 986*29b103c7SStefan Roese 987*29b103c7SStefan Roese /* 988*29b103c7SStefan Roese * Step 15 [PEX-Only] Only for EP mode set to Zero bits 19 and 16 of 989*29b103c7SStefan Roese * register 0x1a60 990*29b103c7SStefan Roese */ 991*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 15: [PEX-Only] In order to configure\n"); 992*29b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 993*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 994*29b103c7SStefan Roese continue; 995*29b103c7SStefan Roese if (info->pex_type == MV_PEX_END_POINT) { 996*29b103c7SStefan Roese tmp = 997*29b103c7SStefan Roese reg_read(PEX_DBG_CTRL_REG 998*29b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit))); 999*29b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_CTRL_REG 1000*29b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit)), tmp); 1001*29b103c7SStefan Roese tmp &= 0xfff6ffff; 1002*29b103c7SStefan Roese reg_write(PEX_DBG_CTRL_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 1003*29b103c7SStefan Roese tmp); 1004*29b103c7SStefan Roese DEBUG_WR_REG(PEX_DBG_CTRL_REG 1005*29b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit)), tmp); 1006*29b103c7SStefan Roese } 1007*29b103c7SStefan Roese } 1008*29b103c7SStefan Roese 1009*29b103c7SStefan Roese if (info->serdes_m_phy_change) { 1010*29b103c7SStefan Roese MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change; 1011*29b103c7SStefan Roese u32 bus_speed; 1012*29b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 1013*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 1014*29b103c7SStefan Roese if (line_cfg == 1015*29b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 1016*29b103c7SStefan Roese continue; 1017*29b103c7SStefan Roese serdes_m_phy_change = info->serdes_m_phy_change; 1018*29b103c7SStefan Roese bus_speed = info->bus_speed & (1 << line_num); 1019*29b103c7SStefan Roese while (serdes_m_phy_change->type != 1020*29b103c7SStefan Roese SERDES_UNIT_UNCONNECTED) { 1021*29b103c7SStefan Roese switch (serdes_m_phy_change->type) { 1022*29b103c7SStefan Roese case SERDES_UNIT_PEX: 1023*29b103c7SStefan Roese if (line_cfg != SERDES_UNIT_PEX) 1024*29b103c7SStefan Roese break; 1025*29b103c7SStefan Roese pex_unit = line_num >> 2; 1026*29b103c7SStefan Roese pex_line_num = line_num % 4; 1027*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == 1028*29b103c7SStefan Roese PEX_BUS_DISABLED) 1029*29b103c7SStefan Roese break; 1030*29b103c7SStefan Roese if ((info->pex_mode[pex_unit] == 1031*29b103c7SStefan Roese PEX_BUS_MODE_X4) && pex_line_num) 1032*29b103c7SStefan Roese break; 1033*29b103c7SStefan Roese 1034*29b103c7SStefan Roese if (bus_speed) { 1035*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG 1036*29b103c7SStefan Roese (pex_unit), 1037*29b103c7SStefan Roese (pex_line_num << 24) | 1038*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1039*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG 1040*29b103c7SStefan Roese (pex_unit), 1041*29b103c7SStefan Roese (pex_line_num << 1042*29b103c7SStefan Roese 24) | 1043*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1044*29b103c7SStefan Roese } else { 1045*29b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG 1046*29b103c7SStefan Roese (pex_unit), 1047*29b103c7SStefan Roese (pex_line_num << 24) | 1048*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1049*29b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG 1050*29b103c7SStefan Roese (pex_unit), 1051*29b103c7SStefan Roese (pex_line_num << 1052*29b103c7SStefan Roese 24) | 1053*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1054*29b103c7SStefan Roese } 1055*29b103c7SStefan Roese break; 1056*29b103c7SStefan Roese case SERDES_UNIT_SATA: 1057*29b103c7SStefan Roese if (line_cfg != SERDES_UNIT_SATA) 1058*29b103c7SStefan Roese break; 1059*29b103c7SStefan Roese /* 1060*29b103c7SStefan Roese * Port 0 for serdes lines 4,6, and 1061*29b103c7SStefan Roese * port 1 for serdes lines 5 1062*29b103c7SStefan Roese */ 1063*29b103c7SStefan Roese sata_port = line_num & 1; 1064*29b103c7SStefan Roese if (bus_speed) { 1065*29b103c7SStefan Roese reg_write(SATA_BASE_REG 1066*29b103c7SStefan Roese (sata_port) | 1067*29b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 1068*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1069*29b103c7SStefan Roese DEBUG_WR_REG(SATA_BASE_REG 1070*29b103c7SStefan Roese (sata_port) | 1071*29b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 1072*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1073*29b103c7SStefan Roese } else { 1074*29b103c7SStefan Roese reg_write(SATA_BASE_REG 1075*29b103c7SStefan Roese (sata_port) | 1076*29b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 1077*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1078*29b103c7SStefan Roese DEBUG_WR_REG(SATA_BASE_REG 1079*29b103c7SStefan Roese (sata_port) | 1080*29b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 1081*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1082*29b103c7SStefan Roese } 1083*29b103c7SStefan Roese break; 1084*29b103c7SStefan Roese case SERDES_UNIT_SGMII0: 1085*29b103c7SStefan Roese case SERDES_UNIT_SGMII1: 1086*29b103c7SStefan Roese case SERDES_UNIT_SGMII2: 1087*29b103c7SStefan Roese case SERDES_UNIT_SGMII3: 1088*29b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num] 1089*29b103c7SStefan Roese [SERDES_UNIT_SGMII0]) 1090*29b103c7SStefan Roese sgmii_port = 0; 1091*29b103c7SStefan Roese else if (line_cfg == 1092*29b103c7SStefan Roese serdes_cfg[line_num] 1093*29b103c7SStefan Roese [SERDES_UNIT_SGMII1]) 1094*29b103c7SStefan Roese sgmii_port = 1; 1095*29b103c7SStefan Roese else if (line_cfg == 1096*29b103c7SStefan Roese serdes_cfg[line_num] 1097*29b103c7SStefan Roese [SERDES_UNIT_SGMII2]) 1098*29b103c7SStefan Roese sgmii_port = 2; 1099*29b103c7SStefan Roese else if (line_cfg == 1100*29b103c7SStefan Roese serdes_cfg[line_num] 1101*29b103c7SStefan Roese [SERDES_UNIT_SGMII3]) 1102*29b103c7SStefan Roese sgmii_port = 3; 1103*29b103c7SStefan Roese else 1104*29b103c7SStefan Roese break; 1105*29b103c7SStefan Roese if (bus_speed) { 1106*29b103c7SStefan Roese reg_write(MV_ETH_REGS_BASE 1107*29b103c7SStefan Roese (sgmii_port) | 1108*29b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 1109*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1110*29b103c7SStefan Roese DEBUG_WR_REG(MV_ETH_REGS_BASE 1111*29b103c7SStefan Roese (sgmii_port) | 1112*29b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 1113*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1114*29b103c7SStefan Roese } else { 1115*29b103c7SStefan Roese reg_write(MV_ETH_REGS_BASE 1116*29b103c7SStefan Roese (sgmii_port) | 1117*29b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 1118*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1119*29b103c7SStefan Roese DEBUG_WR_REG(MV_ETH_REGS_BASE 1120*29b103c7SStefan Roese (sgmii_port) | 1121*29b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 1122*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1123*29b103c7SStefan Roese } 1124*29b103c7SStefan Roese break; 1125*29b103c7SStefan Roese case SERDES_UNIT_QSGMII: 1126*29b103c7SStefan Roese if (line_cfg != SERDES_UNIT_QSGMII) 1127*29b103c7SStefan Roese break; 1128*29b103c7SStefan Roese if (bus_speed) { 1129*29b103c7SStefan Roese reg_write 1130*29b103c7SStefan Roese (serdes_m_phy_change->reg_hi_speed, 1131*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1132*29b103c7SStefan Roese DEBUG_WR_REG 1133*29b103c7SStefan Roese (serdes_m_phy_change->reg_hi_speed, 1134*29b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 1135*29b103c7SStefan Roese } else { 1136*29b103c7SStefan Roese reg_write 1137*29b103c7SStefan Roese (serdes_m_phy_change->reg_low_speed, 1138*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1139*29b103c7SStefan Roese DEBUG_WR_REG 1140*29b103c7SStefan Roese (serdes_m_phy_change->reg_low_speed, 1141*29b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 1142*29b103c7SStefan Roese } 1143*29b103c7SStefan Roese break; 1144*29b103c7SStefan Roese default: 1145*29b103c7SStefan Roese break; 1146*29b103c7SStefan Roese } 1147*29b103c7SStefan Roese serdes_m_phy_change++; 1148*29b103c7SStefan Roese } 1149*29b103c7SStefan Roese } 1150*29b103c7SStefan Roese } 1151*29b103c7SStefan Roese 1152*29b103c7SStefan Roese /* Step 16 [PEX-Only] Training Enable */ 1153*29b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 16: [PEX-Only] Training Enable"); 1154*29b103c7SStefan Roese tmp = reg_read(SOC_CTRL_REG); 1155*29b103c7SStefan Roese DEBUG_RD_REG(SOC_CTRL_REG, tmp); 1156*29b103c7SStefan Roese tmp &= ~(0x0F); 1157*29b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 1158*29b103c7SStefan Roese reg_write(PEX_CAUSE_REG(pex_unit), 0); 1159*29b103c7SStefan Roese DEBUG_WR_REG(PEX_CAUSE_REG(pex_unit), 0); 1160*29b103c7SStefan Roese if (info->pex_mode[pex_unit] != PEX_BUS_DISABLED) 1161*29b103c7SStefan Roese tmp |= (0x1 << pex_unit); 1162*29b103c7SStefan Roese } 1163*29b103c7SStefan Roese reg_write(SOC_CTRL_REG, tmp); 1164*29b103c7SStefan Roese DEBUG_WR_REG(SOC_CTRL_REG, tmp); 1165*29b103c7SStefan Roese 1166*29b103c7SStefan Roese /* Step 17: Speed change to target speed and width */ 1167*29b103c7SStefan Roese { 1168*29b103c7SStefan Roese u32 tmp_reg, tmp_pex_reg; 1169*29b103c7SStefan Roese u32 addr; 1170*29b103c7SStefan Roese u32 first_busno, next_busno; 1171*29b103c7SStefan Roese u32 max_link_width = 0; 1172*29b103c7SStefan Roese u32 neg_link_width = 0; 1173*29b103c7SStefan Roese pex_if_num = pex_max_if_get(); 1174*29b103c7SStefan Roese mdelay(150); 1175*29b103c7SStefan Roese DEBUG_INIT_FULL_C("step 17: max_if= 0x", pex_if_num, 1); 1176*29b103c7SStefan Roese next_busno = 0; 1177*29b103c7SStefan Roese for (pex_if = 0; pex_if < pex_if_num; pex_if++) { 1178*29b103c7SStefan Roese line_num = (pex_if <= 8) ? pex_if : 12; 1179*29b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 1180*29b103c7SStefan Roese if (line_cfg != serdes_cfg[line_num][SERDES_UNIT_PEX]) 1181*29b103c7SStefan Roese continue; 1182*29b103c7SStefan Roese pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3; 1183*29b103c7SStefan Roese DEBUG_INIT_FULL_S("step 17: PEX"); 1184*29b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 1185*29b103c7SStefan Roese DEBUG_INIT_FULL_C(" pex_unit= ", pex_unit, 1); 1186*29b103c7SStefan Roese 1187*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) { 1188*29b103c7SStefan Roese DEBUG_INIT_FULL_C("PEX disabled interface ", 1189*29b103c7SStefan Roese pex_if, 1); 1190*29b103c7SStefan Roese if (pex_if < 8) 1191*29b103c7SStefan Roese pex_if += 3; 1192*29b103c7SStefan Roese continue; 1193*29b103c7SStefan Roese } 1194*29b103c7SStefan Roese first_busno = next_busno; 1195*29b103c7SStefan Roese if ((info->pex_type == MV_PEX_END_POINT) && 1196*29b103c7SStefan Roese (0 == pex_if)) { 1197*29b103c7SStefan Roese if ((pex_if < 8) && (info->pex_mode[pex_unit] == 1198*29b103c7SStefan Roese PEX_BUS_MODE_X4)) 1199*29b103c7SStefan Roese pex_if += 3; 1200*29b103c7SStefan Roese continue; 1201*29b103c7SStefan Roese } 1202*29b103c7SStefan Roese 1203*29b103c7SStefan Roese tmp = reg_read(PEX_DBG_STATUS_REG(pex_if)); 1204*29b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_STATUS_REG(pex_if), tmp); 1205*29b103c7SStefan Roese if ((tmp & 0x7f) == 0x7e) { 1206*29b103c7SStefan Roese next_busno++; 1207*29b103c7SStefan Roese tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if)); 1208*29b103c7SStefan Roese max_link_width = tmp; 1209*29b103c7SStefan Roese DEBUG_RD_REG((PEX_LINK_CAPABILITIES_REG 1210*29b103c7SStefan Roese (pex_if)), tmp); 1211*29b103c7SStefan Roese max_link_width = ((max_link_width >> 4) & 0x3F); 1212*29b103c7SStefan Roese neg_link_width = 1213*29b103c7SStefan Roese reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if)); 1214*29b103c7SStefan Roese DEBUG_RD_REG((PEX_LINK_CTRL_STATUS_REG(pex_if)), 1215*29b103c7SStefan Roese neg_link_width); 1216*29b103c7SStefan Roese neg_link_width = ((neg_link_width >> 20) & 0x3F); 1217*29b103c7SStefan Roese if (max_link_width > neg_link_width) { 1218*29b103c7SStefan Roese tmp &= ~(0x3F << 4); 1219*29b103c7SStefan Roese tmp |= (neg_link_width << 4); 1220*29b103c7SStefan Roese reg_write(PEX_LINK_CAPABILITIES_REG 1221*29b103c7SStefan Roese (pex_if), tmp); 1222*29b103c7SStefan Roese DEBUG_WR_REG((PEX_LINK_CAPABILITIES_REG 1223*29b103c7SStefan Roese (pex_if)), tmp); 1224*29b103c7SStefan Roese mdelay(1); /* wait 1ms before reading capability for speed */ 1225*29b103c7SStefan Roese DEBUG_INIT_S("PEX"); 1226*29b103c7SStefan Roese DEBUG_INIT_D(pex_if, 1); 1227*29b103c7SStefan Roese DEBUG_INIT_C(": change width to X", 1228*29b103c7SStefan Roese neg_link_width, 1); 1229*29b103c7SStefan Roese } 1230*29b103c7SStefan Roese tmp_pex_reg = 1231*29b103c7SStefan Roese reg_read((PEX_CFG_DIRECT_ACCESS 1232*29b103c7SStefan Roese (pex_if, 1233*29b103c7SStefan Roese PEX_LINK_CAPABILITY_REG))); 1234*29b103c7SStefan Roese DEBUG_RD_REG((PEX_CFG_DIRECT_ACCESS 1235*29b103c7SStefan Roese (pex_if, 1236*29b103c7SStefan Roese PEX_LINK_CAPABILITY_REG)), 1237*29b103c7SStefan Roese tmp_pex_reg); 1238*29b103c7SStefan Roese tmp_pex_reg &= (0xF); 1239*29b103c7SStefan Roese if (tmp_pex_reg == 0x2) { 1240*29b103c7SStefan Roese tmp_reg = 1241*29b103c7SStefan Roese (reg_read 1242*29b103c7SStefan Roese (PEX_CFG_DIRECT_ACCESS 1243*29b103c7SStefan Roese (pex_if, 1244*29b103c7SStefan Roese PEX_LINK_CTRL_STAT_REG)) & 1245*29b103c7SStefan Roese 0xF0000) >> 16; 1246*29b103c7SStefan Roese DEBUG_RD_REG(PEX_CFG_DIRECT_ACCESS 1247*29b103c7SStefan Roese (pex_if, 1248*29b103c7SStefan Roese PEX_LINK_CTRL_STAT_REG), 1249*29b103c7SStefan Roese tmp_pex_reg); 1250*29b103c7SStefan Roese /* check if the link established is GEN1 */ 1251*29b103c7SStefan Roese if (tmp_reg == 0x1) { 1252*29b103c7SStefan Roese pex_local_bus_num_set(pex_if, 1253*29b103c7SStefan Roese first_busno); 1254*29b103c7SStefan Roese pex_local_dev_num_set(pex_if, 1255*29b103c7SStefan Roese 1); 1256*29b103c7SStefan Roese 1257*29b103c7SStefan Roese DEBUG_INIT_FULL_S("** Link is Gen1, check the EP capability\n"); 1258*29b103c7SStefan Roese /* link is Gen1, check the EP capability */ 1259*29b103c7SStefan Roese addr = 1260*29b103c7SStefan Roese pex_cfg_read(pex_if, 1261*29b103c7SStefan Roese first_busno, 0, 1262*29b103c7SStefan Roese 0, 1263*29b103c7SStefan Roese 0x34) & 0xFF; 1264*29b103c7SStefan Roese DEBUG_INIT_FULL_C("pex_cfg_read: return addr=0x%x", 1265*29b103c7SStefan Roese addr, 4); 1266*29b103c7SStefan Roese if (addr == 0xff) { 1267*29b103c7SStefan Roese DEBUG_INIT_FULL_C("pex_cfg_read: return 0xff -->PEX (%d): Detected No Link.", 1268*29b103c7SStefan Roese pex_if, 1); 1269*29b103c7SStefan Roese continue; 1270*29b103c7SStefan Roese } 1271*29b103c7SStefan Roese while ((pex_cfg_read 1272*29b103c7SStefan Roese (pex_if, first_busno, 0, 1273*29b103c7SStefan Roese 0, 1274*29b103c7SStefan Roese addr) & 0xFF) != 1275*29b103c7SStefan Roese 0x10) { 1276*29b103c7SStefan Roese addr = 1277*29b103c7SStefan Roese (pex_cfg_read 1278*29b103c7SStefan Roese (pex_if, 1279*29b103c7SStefan Roese first_busno, 0, 0, 1280*29b103c7SStefan Roese addr) & 0xFF00) >> 1281*29b103c7SStefan Roese 8; 1282*29b103c7SStefan Roese } 1283*29b103c7SStefan Roese if ((pex_cfg_read 1284*29b103c7SStefan Roese (pex_if, first_busno, 0, 0, 1285*29b103c7SStefan Roese addr + 0xC) & 0xF) >= 1286*29b103c7SStefan Roese 0x2) { 1287*29b103c7SStefan Roese tmp = 1288*29b103c7SStefan Roese reg_read 1289*29b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 1290*29b103c7SStefan Roese (pex_if)); 1291*29b103c7SStefan Roese DEBUG_RD_REG 1292*29b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 1293*29b103c7SStefan Roese (pex_if), tmp); 1294*29b103c7SStefan Roese tmp &= ~(0x1 | 1 << 1); 1295*29b103c7SStefan Roese tmp |= (1 << 1); 1296*29b103c7SStefan Roese reg_write 1297*29b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 1298*29b103c7SStefan Roese (pex_if), tmp); 1299*29b103c7SStefan Roese DEBUG_WR_REG 1300*29b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 1301*29b103c7SStefan Roese (pex_if), tmp); 1302*29b103c7SStefan Roese 1303*29b103c7SStefan Roese tmp = 1304*29b103c7SStefan Roese reg_read 1305*29b103c7SStefan Roese (PEX_CTRL_REG 1306*29b103c7SStefan Roese (pex_if)); 1307*29b103c7SStefan Roese DEBUG_RD_REG 1308*29b103c7SStefan Roese (PEX_CTRL_REG 1309*29b103c7SStefan Roese (pex_if), tmp); 1310*29b103c7SStefan Roese tmp |= (1 << 10); 1311*29b103c7SStefan Roese reg_write(PEX_CTRL_REG 1312*29b103c7SStefan Roese (pex_if), 1313*29b103c7SStefan Roese tmp); 1314*29b103c7SStefan Roese DEBUG_WR_REG 1315*29b103c7SStefan Roese (PEX_CTRL_REG 1316*29b103c7SStefan Roese (pex_if), tmp); 1317*29b103c7SStefan Roese mdelay(10); /* We need to wait 10ms before reading the PEX_DBG_STATUS_REG in order not to read the status of the former state */ 1318*29b103c7SStefan Roese DEBUG_INIT_FULL_S 1319*29b103c7SStefan Roese ("Gen2 client!\n"); 1320*29b103c7SStefan Roese } else { 1321*29b103c7SStefan Roese DEBUG_INIT_FULL_S 1322*29b103c7SStefan Roese ("GEN1 client!\n"); 1323*29b103c7SStefan Roese } 1324*29b103c7SStefan Roese } 1325*29b103c7SStefan Roese } 1326*29b103c7SStefan Roese } else { 1327*29b103c7SStefan Roese DEBUG_INIT_FULL_S("PEX"); 1328*29b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 1329*29b103c7SStefan Roese DEBUG_INIT_FULL_S(" : Detected No Link. Status Reg(0x"); 1330*29b103c7SStefan Roese DEBUG_INIT_FULL_D(PEX_DBG_STATUS_REG(pex_if), 1331*29b103c7SStefan Roese 8); 1332*29b103c7SStefan Roese DEBUG_INIT_FULL_C(") = 0x", tmp, 8); 1333*29b103c7SStefan Roese } 1334*29b103c7SStefan Roese 1335*29b103c7SStefan Roese if ((pex_if < 8) && 1336*29b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 1337*29b103c7SStefan Roese pex_if += 3; 1338*29b103c7SStefan Roese } 1339*29b103c7SStefan Roese } 1340*29b103c7SStefan Roese 1341*29b103c7SStefan Roese /* Step 18: update pex DEVICE ID */ 1342*29b103c7SStefan Roese { 1343*29b103c7SStefan Roese u32 devId; 1344*29b103c7SStefan Roese pex_if_num = pex_max_if_get(); 1345*29b103c7SStefan Roese ctrl_mode = ctrl_model_get(); 1346*29b103c7SStefan Roese for (pex_if = 0; pex_if < pex_if_num; pex_if++) { 1347*29b103c7SStefan Roese pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3; 1348*29b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) { 1349*29b103c7SStefan Roese if ((pex_if < 8) && 1350*29b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 1351*29b103c7SStefan Roese pex_if += 3; 1352*29b103c7SStefan Roese continue; 1353*29b103c7SStefan Roese } 1354*29b103c7SStefan Roese 1355*29b103c7SStefan Roese devId = reg_read(PEX_CFG_DIRECT_ACCESS( 1356*29b103c7SStefan Roese pex_if, PEX_DEVICE_AND_VENDOR_ID)); 1357*29b103c7SStefan Roese devId &= 0xFFFF; 1358*29b103c7SStefan Roese devId |= ((ctrl_mode << 16) & 0xffff0000); 1359*29b103c7SStefan Roese DEBUG_INIT_S("Update Device ID PEX"); 1360*29b103c7SStefan Roese DEBUG_INIT_D(pex_if, 1); 1361*29b103c7SStefan Roese DEBUG_INIT_D(devId, 8); 1362*29b103c7SStefan Roese DEBUG_INIT_S("\n"); 1363*29b103c7SStefan Roese reg_write(PEX_CFG_DIRECT_ACCESS 1364*29b103c7SStefan Roese (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId); 1365*29b103c7SStefan Roese if ((pex_if < 8) && 1366*29b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 1367*29b103c7SStefan Roese pex_if += 3; 1368*29b103c7SStefan Roese } 1369*29b103c7SStefan Roese DEBUG_INIT_S("Update PEX Device ID 0x"); 1370*29b103c7SStefan Roese DEBUG_INIT_D(ctrl_mode, 4); 1371*29b103c7SStefan Roese DEBUG_INIT_S("0\n"); 1372*29b103c7SStefan Roese } 1373*29b103c7SStefan Roese tmp = reg_read(PEX_DBG_STATUS_REG(0)); 1374*29b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp); 1375*29b103c7SStefan Roese 1376*29b103c7SStefan Roese DEBUG_INIT_S(ENDED_OK); 1377*29b103c7SStefan Roese return MV_OK; 1378*29b103c7SStefan Roese } 1379*29b103c7SStefan Roese 1380*29b103c7SStefan Roese /* PEX configuration space read write */ 1381*29b103c7SStefan Roese 1382*29b103c7SStefan Roese /* 1383*29b103c7SStefan Roese * pex_cfg_read - Read from configuration space 1384*29b103c7SStefan Roese * 1385*29b103c7SStefan Roese * DESCRIPTION: 1386*29b103c7SStefan Roese * This function performs a 32 bit read from PEX configuration space. 1387*29b103c7SStefan Roese * It supports both type 0 and type 1 of Configuration Transactions 1388*29b103c7SStefan Roese * (local and over bridge). In order to read from local bus segment, use 1389*29b103c7SStefan Roese * bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers 1390*29b103c7SStefan Roese * will result configuration transaction of type 1 (over bridge). 1391*29b103c7SStefan Roese * 1392*29b103c7SStefan Roese * INPUT: 1393*29b103c7SStefan Roese * pex_if - PEX interface number. 1394*29b103c7SStefan Roese * bus - PEX segment bus number. 1395*29b103c7SStefan Roese * dev - PEX device number. 1396*29b103c7SStefan Roese * func - Function number. 1397*29b103c7SStefan Roese * offss - Register offset. 1398*29b103c7SStefan Roese * 1399*29b103c7SStefan Roese * OUTPUT: 1400*29b103c7SStefan Roese * None. 1401*29b103c7SStefan Roese * 1402*29b103c7SStefan Roese * RETURN: 1403*29b103c7SStefan Roese * 32bit register data, 0xffffffff on error 1404*29b103c7SStefan Roese * 1405*29b103c7SStefan Roese */ 1406*29b103c7SStefan Roese u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs) 1407*29b103c7SStefan Roese { 1408*29b103c7SStefan Roese u32 pex_data = 0; 1409*29b103c7SStefan Roese u32 local_dev, local_bus; 1410*29b103c7SStefan Roese u32 val; 1411*29b103c7SStefan Roese 1412*29b103c7SStefan Roese if (pex_if >= MV_PEX_MAX_IF) 1413*29b103c7SStefan Roese return 0xFFFFFFFF; 1414*29b103c7SStefan Roese 1415*29b103c7SStefan Roese if (dev >= MAX_PEX_DEVICES) { 1416*29b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. device number illigal ", dev, 1417*29b103c7SStefan Roese 1); 1418*29b103c7SStefan Roese return 0xFFFFFFFF; 1419*29b103c7SStefan Roese } 1420*29b103c7SStefan Roese 1421*29b103c7SStefan Roese if (func >= MAX_PEX_FUNCS) { 1422*29b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. function num illigal ", func, 1423*29b103c7SStefan Roese 1); 1424*29b103c7SStefan Roese return 0xFFFFFFFF; 1425*29b103c7SStefan Roese } 1426*29b103c7SStefan Roese 1427*29b103c7SStefan Roese if (bus >= MAX_PEX_BUSSES) { 1428*29b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. bus number illigal ", bus, 1); 1429*29b103c7SStefan Roese return MV_ERROR; 1430*29b103c7SStefan Roese } 1431*29b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 1432*29b103c7SStefan Roese 1433*29b103c7SStefan Roese local_dev = 1434*29b103c7SStefan Roese ((val & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS); 1435*29b103c7SStefan Roese local_bus = 1436*29b103c7SStefan Roese ((val & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS); 1437*29b103c7SStefan Roese 1438*29b103c7SStefan Roese /* Speed up the process. In case on no link, return MV_ERROR */ 1439*29b103c7SStefan Roese if ((dev != local_dev) || (bus != local_bus)) { 1440*29b103c7SStefan Roese pex_data = reg_read(PEX_STATUS_REG(pex_if)); 1441*29b103c7SStefan Roese 1442*29b103c7SStefan Roese if ((pex_data & PXSR_DL_DOWN)) 1443*29b103c7SStefan Roese return MV_ERROR; 1444*29b103c7SStefan Roese } 1445*29b103c7SStefan Roese 1446*29b103c7SStefan Roese /* 1447*29b103c7SStefan Roese * In PCI Express we have only one device number 1448*29b103c7SStefan Roese * and this number is the first number we encounter else that the 1449*29b103c7SStefan Roese * local_dev spec pex define return on config read/write on any device 1450*29b103c7SStefan Roese */ 1451*29b103c7SStefan Roese if (bus == local_bus) { 1452*29b103c7SStefan Roese if (local_dev == 0) { 1453*29b103c7SStefan Roese /* 1454*29b103c7SStefan Roese * If local dev is 0 then the first number we encounter 1455*29b103c7SStefan Roese * after 0 is 1 1456*29b103c7SStefan Roese */ 1457*29b103c7SStefan Roese if ((dev != 1) && (dev != local_dev)) 1458*29b103c7SStefan Roese return MV_ERROR; 1459*29b103c7SStefan Roese } else { 1460*29b103c7SStefan Roese /* 1461*29b103c7SStefan Roese * If local dev is not 0 then the first number we 1462*29b103c7SStefan Roese * encounter is 0 1463*29b103c7SStefan Roese */ 1464*29b103c7SStefan Roese if ((dev != 0) && (dev != local_dev)) 1465*29b103c7SStefan Roese return MV_ERROR; 1466*29b103c7SStefan Roese } 1467*29b103c7SStefan Roese } 1468*29b103c7SStefan Roese 1469*29b103c7SStefan Roese /* Creating PEX address to be passed */ 1470*29b103c7SStefan Roese pex_data = (bus << PXCAR_BUS_NUM_OFFS); 1471*29b103c7SStefan Roese pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS); 1472*29b103c7SStefan Roese pex_data |= (func << PXCAR_FUNC_NUM_OFFS); 1473*29b103c7SStefan Roese pex_data |= (offs & PXCAR_REG_NUM_MASK); /* lgacy register space */ 1474*29b103c7SStefan Roese /* extended register space */ 1475*29b103c7SStefan Roese pex_data |= (((offs & PXCAR_REAL_EXT_REG_NUM_MASK) >> 1476*29b103c7SStefan Roese PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); 1477*29b103c7SStefan Roese 1478*29b103c7SStefan Roese pex_data |= PXCAR_CONFIG_EN; 1479*29b103c7SStefan Roese 1480*29b103c7SStefan Roese /* Write the address to the PEX configuration address register */ 1481*29b103c7SStefan Roese reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data); 1482*29b103c7SStefan Roese 1483*29b103c7SStefan Roese /* 1484*29b103c7SStefan Roese * In order to let the PEX controller absorbed the address of the read 1485*29b103c7SStefan Roese * transaction we perform a validity check that the address was written 1486*29b103c7SStefan Roese */ 1487*29b103c7SStefan Roese if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if))) 1488*29b103c7SStefan Roese return MV_ERROR; 1489*29b103c7SStefan Roese 1490*29b103c7SStefan Roese /* cleaning Master Abort */ 1491*29b103c7SStefan Roese reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND), 1492*29b103c7SStefan Roese PXSAC_MABORT); 1493*29b103c7SStefan Roese /* Read the Data returned in the PEX Data register */ 1494*29b103c7SStefan Roese pex_data = reg_read(PEX_CFG_DATA_REG(pex_if)); 1495*29b103c7SStefan Roese 1496*29b103c7SStefan Roese DEBUG_INIT_FULL_C(" --> ", pex_data, 4); 1497*29b103c7SStefan Roese 1498*29b103c7SStefan Roese return pex_data; 1499*29b103c7SStefan Roese } 1500*29b103c7SStefan Roese 1501*29b103c7SStefan Roese /* 1502*29b103c7SStefan Roese * pex_local_bus_num_set - Set PEX interface local bus number. 1503*29b103c7SStefan Roese * 1504*29b103c7SStefan Roese * DESCRIPTION: 1505*29b103c7SStefan Roese * This function sets given PEX interface its local bus number. 1506*29b103c7SStefan Roese * Note: In case the PEX interface is PEX-X, the information is read-only. 1507*29b103c7SStefan Roese * 1508*29b103c7SStefan Roese * INPUT: 1509*29b103c7SStefan Roese * pex_if - PEX interface number. 1510*29b103c7SStefan Roese * bus_num - Bus number. 1511*29b103c7SStefan Roese * 1512*29b103c7SStefan Roese * OUTPUT: 1513*29b103c7SStefan Roese * None. 1514*29b103c7SStefan Roese * 1515*29b103c7SStefan Roese * RETURN: 1516*29b103c7SStefan Roese * MV_NOT_ALLOWED in case PEX interface is PEX-X. 1517*29b103c7SStefan Roese * MV_BAD_PARAM on bad parameters , 1518*29b103c7SStefan Roese * otherwise MV_OK 1519*29b103c7SStefan Roese * 1520*29b103c7SStefan Roese */ 1521*29b103c7SStefan Roese int pex_local_bus_num_set(u32 pex_if, u32 bus_num) 1522*29b103c7SStefan Roese { 1523*29b103c7SStefan Roese u32 val; 1524*29b103c7SStefan Roese 1525*29b103c7SStefan Roese if (bus_num >= MAX_PEX_BUSSES) { 1526*29b103c7SStefan Roese DEBUG_INIT_C("pex_local_bus_num_set: ERR. bus number illigal %d\n", 1527*29b103c7SStefan Roese bus_num, 4); 1528*29b103c7SStefan Roese return MV_ERROR; 1529*29b103c7SStefan Roese } 1530*29b103c7SStefan Roese 1531*29b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 1532*29b103c7SStefan Roese val &= ~PXSR_PEX_BUS_NUM_MASK; 1533*29b103c7SStefan Roese val |= (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK; 1534*29b103c7SStefan Roese reg_write(PEX_STATUS_REG(pex_if), val); 1535*29b103c7SStefan Roese 1536*29b103c7SStefan Roese return MV_OK; 1537*29b103c7SStefan Roese } 1538*29b103c7SStefan Roese 1539*29b103c7SStefan Roese /* 1540*29b103c7SStefan Roese * pex_local_dev_num_set - Set PEX interface local device number. 1541*29b103c7SStefan Roese * 1542*29b103c7SStefan Roese * DESCRIPTION: 1543*29b103c7SStefan Roese * This function sets given PEX interface its local device number. 1544*29b103c7SStefan Roese * Note: In case the PEX interface is PEX-X, the information is read-only. 1545*29b103c7SStefan Roese * 1546*29b103c7SStefan Roese * INPUT: 1547*29b103c7SStefan Roese * pex_if - PEX interface number. 1548*29b103c7SStefan Roese * dev_num - Device number. 1549*29b103c7SStefan Roese * 1550*29b103c7SStefan Roese * OUTPUT: 1551*29b103c7SStefan Roese * None. 1552*29b103c7SStefan Roese * 1553*29b103c7SStefan Roese * RETURN: 1554*29b103c7SStefan Roese * MV_NOT_ALLOWED in case PEX interface is PEX-X. 1555*29b103c7SStefan Roese * MV_BAD_PARAM on bad parameters , 1556*29b103c7SStefan Roese * otherwise MV_OK 1557*29b103c7SStefan Roese * 1558*29b103c7SStefan Roese */ 1559*29b103c7SStefan Roese int pex_local_dev_num_set(u32 pex_if, u32 dev_num) 1560*29b103c7SStefan Roese { 1561*29b103c7SStefan Roese u32 val; 1562*29b103c7SStefan Roese 1563*29b103c7SStefan Roese if (pex_if >= MV_PEX_MAX_IF) 1564*29b103c7SStefan Roese return MV_BAD_PARAM; 1565*29b103c7SStefan Roese 1566*29b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 1567*29b103c7SStefan Roese val &= ~PXSR_PEX_DEV_NUM_MASK; 1568*29b103c7SStefan Roese val |= (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK; 1569*29b103c7SStefan Roese reg_write(PEX_STATUS_REG(pex_if), val); 1570*29b103c7SStefan Roese 1571*29b103c7SStefan Roese return MV_OK; 1572*29b103c7SStefan Roese } 1573