129b103c7SStefan Roese /* 229b103c7SStefan Roese * Copyright (C) Marvell International Ltd. and its affiliates 329b103c7SStefan Roese * 429b103c7SStefan Roese * SPDX-License-Identifier: GPL-2.0 529b103c7SStefan Roese */ 629b103c7SStefan Roese 729b103c7SStefan Roese #include <common.h> 829b103c7SStefan Roese #include <i2c.h> 929b103c7SStefan Roese #include <spl.h> 1029b103c7SStefan Roese #include <asm/io.h> 1129b103c7SStefan Roese #include <asm/arch/cpu.h> 1229b103c7SStefan Roese #include <asm/arch/soc.h> 1329b103c7SStefan Roese 1429b103c7SStefan Roese #include "high_speed_env_spec.h" 1529b103c7SStefan Roese #include "board_env_spec.h" 1629b103c7SStefan Roese 17d374e90bSUwe Kleine-König #define SERDES_VERSION "2.1.5" 1829b103c7SStefan Roese #define ENDED_OK "High speed PHY - Ended Successfully\n" 1929b103c7SStefan Roese 2029b103c7SStefan Roese static const u8 serdes_cfg[][SERDES_LAST_UNIT] = BIN_SERDES_CFG; 2129b103c7SStefan Roese 2229b103c7SStefan Roese extern MV_BIN_SERDES_CFG *serdes_info_tbl[]; 2329b103c7SStefan Roese 2429b103c7SStefan Roese extern u8 rd78460gp_twsi_dev[]; 2529b103c7SStefan Roese extern u8 db88f78xx0rev2_twsi_dev[]; 2629b103c7SStefan Roese 2729b103c7SStefan Roese u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs); 2829b103c7SStefan Roese int pex_local_bus_num_set(u32 pex_if, u32 bus_num); 2929b103c7SStefan Roese int pex_local_dev_num_set(u32 pex_if, u32 dev_num); 3029b103c7SStefan Roese 3129b103c7SStefan Roese #define MV_BOARD_PEX_MODULE_ADDR 0x23 3229b103c7SStefan Roese #define MV_BOARD_PEX_MODULE_ID 1 3329b103c7SStefan Roese #define MV_BOARD_ETM_MODULE_ID 2 3429b103c7SStefan Roese 3529b103c7SStefan Roese #define PEX_MODULE_DETECT 1 3629b103c7SStefan Roese #define ETM_MODULE_DETECT 2 3729b103c7SStefan Roese 3829b103c7SStefan Roese #define PEX_MODE_GET(satr) ((satr & 0x6) >> 1) 3929b103c7SStefan Roese #define PEX_CAPABILITY_GET(satr) (satr & 1) 4029b103c7SStefan Roese #define MV_PEX_UNIT_TO_IF(pex_unit) ((pex_unit < 3) ? (pex_unit * 4) : 9) 4129b103c7SStefan Roese 4229b103c7SStefan Roese /* Static parametes */ 4329b103c7SStefan Roese static int config_module; 4429b103c7SStefan Roese static int switch_module; 4529b103c7SStefan Roese 4629b103c7SStefan Roese /* Local function */ 4729b103c7SStefan Roese static u32 board_id_get(void) 4829b103c7SStefan Roese { 4929b103c7SStefan Roese #if defined(CONFIG_DB_88F78X60) 5029b103c7SStefan Roese return DB_88F78XX0_BP_ID; 5129b103c7SStefan Roese #elif defined(CONFIG_RD_88F78460_SERVER) 5229b103c7SStefan Roese return RD_78460_SERVER_ID; 5329b103c7SStefan Roese #elif defined(CONFIG_RD_78460_SERVER_REV2) 5429b103c7SStefan Roese return RD_78460_SERVER_REV2_ID; 5529b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_PCAC) 5629b103c7SStefan Roese return DB_78X60_PCAC_ID; 5729b103c7SStefan Roese #elif defined(CONFIG_DB_88F78X60_REV2) 5829b103c7SStefan Roese return DB_88F78XX0_BP_REV2_ID; 5929b103c7SStefan Roese #elif defined(CONFIG_RD_78460_NAS) 6029b103c7SStefan Roese return RD_78460_NAS_ID; 6129b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_AMC) 6229b103c7SStefan Roese return DB_78X60_AMC_ID; 6329b103c7SStefan Roese #elif defined(CONFIG_DB_78X60_PCAC_REV2) 6429b103c7SStefan Roese return DB_78X60_PCAC_REV2_ID; 6529b103c7SStefan Roese #elif defined(CONFIG_DB_784MP_GP) 6629b103c7SStefan Roese return DB_784MP_GP_ID; 6729b103c7SStefan Roese #elif defined(CONFIG_RD_78460_CUSTOMER) 6829b103c7SStefan Roese return RD_78460_CUSTOMER_ID; 6929b103c7SStefan Roese #else 7029b103c7SStefan Roese /* 7129b103c7SStefan Roese * Return 0 here for custom board as this should not be used 7229b103c7SStefan Roese * for custom boards. 7329b103c7SStefan Roese */ 7429b103c7SStefan Roese return 0; 7529b103c7SStefan Roese #endif 7629b103c7SStefan Roese } 7729b103c7SStefan Roese 78beadff17SPhil Sutter __weak u8 board_sat_r_get(u8 dev_num, u8 reg) 7929b103c7SStefan Roese { 8029b103c7SStefan Roese u8 data; 8129b103c7SStefan Roese u8 *dev; 8229b103c7SStefan Roese u32 board_id = board_id_get(); 8329b103c7SStefan Roese int ret; 8429b103c7SStefan Roese 8529b103c7SStefan Roese switch (board_id) { 86beadff17SPhil Sutter case DB_78X60_AMC_ID: 87beadff17SPhil Sutter case DB_78X60_PCAC_REV2_ID: 88beadff17SPhil Sutter case RD_78460_CUSTOMER_ID: 89beadff17SPhil Sutter case RD_78460_SERVER_ID: 90beadff17SPhil Sutter case RD_78460_SERVER_REV2_ID: 91beadff17SPhil Sutter case DB_78X60_PCAC_ID: 92beadff17SPhil Sutter return (0x1 << 1) | 1; 93beadff17SPhil Sutter case FPGA_88F78XX0_ID: 94beadff17SPhil Sutter case RD_78460_NAS_ID: 95beadff17SPhil Sutter return (0x0 << 1) | 1; 9629b103c7SStefan Roese case DB_784MP_GP_ID: 9729b103c7SStefan Roese dev = rd78460gp_twsi_dev; 9829b103c7SStefan Roese 9929b103c7SStefan Roese break; 10029b103c7SStefan Roese case DB_88F78XX0_BP_ID: 10129b103c7SStefan Roese case DB_88F78XX0_BP_REV2_ID: 10229b103c7SStefan Roese dev = db88f78xx0rev2_twsi_dev; 10329b103c7SStefan Roese break; 10429b103c7SStefan Roese 10529b103c7SStefan Roese default: 10629b103c7SStefan Roese return 0; 10729b103c7SStefan Roese } 10829b103c7SStefan Roese 10929b103c7SStefan Roese /* Read MPP module ID */ 110beadff17SPhil Sutter i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 11129b103c7SStefan Roese ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1); 11229b103c7SStefan Roese if (ret) 11329b103c7SStefan Roese return MV_ERROR; 11429b103c7SStefan Roese 11529b103c7SStefan Roese return data; 11629b103c7SStefan Roese } 11729b103c7SStefan Roese 11829b103c7SStefan Roese static int board_modules_scan(void) 11929b103c7SStefan Roese { 12029b103c7SStefan Roese u8 val; 12129b103c7SStefan Roese u32 board_id = board_id_get(); 12229b103c7SStefan Roese int ret; 12329b103c7SStefan Roese 12429b103c7SStefan Roese /* Perform scan only for DB board */ 12529b103c7SStefan Roese if ((board_id == DB_88F78XX0_BP_ID) || 12629b103c7SStefan Roese (board_id == DB_88F78XX0_BP_REV2_ID)) { 12729b103c7SStefan Roese /* reset modules flags */ 12829b103c7SStefan Roese config_module = 0; 12929b103c7SStefan Roese 13029b103c7SStefan Roese i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 13129b103c7SStefan Roese 13229b103c7SStefan Roese /* SERDES module (only PEX model is supported now) */ 13329b103c7SStefan Roese ret = i2c_read(MV_BOARD_PEX_MODULE_ADDR, 0, 1, (u8 *)&val, 1); 13429b103c7SStefan Roese if (ret) 13529b103c7SStefan Roese return MV_ERROR; 13629b103c7SStefan Roese 13729b103c7SStefan Roese if (val == MV_BOARD_PEX_MODULE_ID) 13829b103c7SStefan Roese config_module = PEX_MODULE_DETECT; 13929b103c7SStefan Roese if (val == MV_BOARD_ETM_MODULE_ID) 14029b103c7SStefan Roese config_module = ETM_MODULE_DETECT; 14129b103c7SStefan Roese } else if (board_id == RD_78460_NAS_ID) { 14229b103c7SStefan Roese switch_module = 0; 14329b103c7SStefan Roese if ((reg_read(GPP_DATA_IN_REG(2)) & MV_GPP66) == 0x0) 14429b103c7SStefan Roese switch_module = 1; 14529b103c7SStefan Roese } 14629b103c7SStefan Roese 14729b103c7SStefan Roese return MV_OK; 14829b103c7SStefan Roese } 14929b103c7SStefan Roese 15029b103c7SStefan Roese u32 pex_max_unit_get(void) 15129b103c7SStefan Roese { 15229b103c7SStefan Roese /* 15329b103c7SStefan Roese * TODO: 15429b103c7SStefan Roese * Right now only MV78460 is supported. Other SoC's might need 15529b103c7SStefan Roese * a different value here. 15629b103c7SStefan Roese */ 15729b103c7SStefan Roese return MV_PEX_MAX_UNIT; 15829b103c7SStefan Roese } 15929b103c7SStefan Roese 16029b103c7SStefan Roese u32 pex_max_if_get(void) 16129b103c7SStefan Roese { 16229b103c7SStefan Roese /* 16329b103c7SStefan Roese * TODO: 16429b103c7SStefan Roese * Right now only MV78460 is supported. Other SoC's might need 16529b103c7SStefan Roese * a different value here. 16629b103c7SStefan Roese */ 16729b103c7SStefan Roese return MV_PEX_MAX_IF; 16829b103c7SStefan Roese } 16929b103c7SStefan Roese 17029b103c7SStefan Roese u8 board_cpu_freq_get(void) 17129b103c7SStefan Roese { 17229b103c7SStefan Roese u32 sar; 17329b103c7SStefan Roese u32 sar_msb; 17429b103c7SStefan Roese 17529b103c7SStefan Roese sar = reg_read(MPP_SAMPLE_AT_RESET(0)); 17629b103c7SStefan Roese sar_msb = reg_read(MPP_SAMPLE_AT_RESET(1)); 17729b103c7SStefan Roese return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21); 17829b103c7SStefan Roese } 17929b103c7SStefan Roese 18029b103c7SStefan Roese __weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) 18129b103c7SStefan Roese { 18229b103c7SStefan Roese u32 board_id; 18329b103c7SStefan Roese u32 serdes_cfg_val = 0; /* default */ 18429b103c7SStefan Roese 18529b103c7SStefan Roese board_id = board_id_get(); 18629b103c7SStefan Roese 18729b103c7SStefan Roese switch (board_id) { 18829b103c7SStefan Roese case DB_784MP_GP_ID: 18929b103c7SStefan Roese serdes_cfg_val = 0; 19029b103c7SStefan Roese break; 19129b103c7SStefan Roese } 19229b103c7SStefan Roese 19329b103c7SStefan Roese return &serdes_info_tbl[board_id - BOARD_ID_BASE][serdes_cfg_val]; 19429b103c7SStefan Roese } 19529b103c7SStefan Roese 19629b103c7SStefan Roese u16 ctrl_model_get(void) 19729b103c7SStefan Roese { 198bf0db8b8SStefan Roese /* 199bf0db8b8SStefan Roese * SoC version can't be autodetected. So we need to rely on a define 200bf0db8b8SStefan Roese * from the config system here. 201bf0db8b8SStefan Roese */ 2026202953dSPhil Sutter #if defined(CONFIG_MV78230) 2036202953dSPhil Sutter return MV_78230_DEV_ID; 2046202953dSPhil Sutter #elif defined(CONFIG_MV78260) 205bf0db8b8SStefan Roese return MV_78260_DEV_ID; 206bf0db8b8SStefan Roese #else 20729b103c7SStefan Roese return MV_78460_DEV_ID; 208bf0db8b8SStefan Roese #endif 20929b103c7SStefan Roese } 21029b103c7SStefan Roese 21129b103c7SStefan Roese u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info) 21229b103c7SStefan Roese { 21329b103c7SStefan Roese if (line_num < 8) 21429b103c7SStefan Roese return (info->line0_7 >> (line_num << 2)) & 0xF; 21529b103c7SStefan Roese else 21629b103c7SStefan Roese return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF; 21729b103c7SStefan Roese } 21829b103c7SStefan Roese 219bf0db8b8SStefan Roese static int serdes_max_lines_get(void) 220bf0db8b8SStefan Roese { 221bf0db8b8SStefan Roese switch (ctrl_model_get()) { 2226202953dSPhil Sutter case MV_78230_DEV_ID: 2236202953dSPhil Sutter return 7; 224bf0db8b8SStefan Roese case MV_78260_DEV_ID: 225bf0db8b8SStefan Roese return 12; 226bf0db8b8SStefan Roese case MV_78460_DEV_ID: 227bf0db8b8SStefan Roese return 16; 228bf0db8b8SStefan Roese } 229bf0db8b8SStefan Roese 230bf0db8b8SStefan Roese return 0; 231bf0db8b8SStefan Roese } 232bf0db8b8SStefan Roese 2332399e401SStefan Roese /* 2342399e401SStefan Roese * Tests have shown that on some boards the default width of the 2352399e401SStefan Roese * configuration pulse for the PEX link detection might lead to 2362399e401SStefan Roese * non-established PCIe links (link down). Especially under certain 2372399e401SStefan Roese * conditions (higher temperature) and with specific PCIe devices. 2382399e401SStefan Roese * To enable a board-specific detection pulse width this weak 2392399e401SStefan Roese * array "serdes_pex_pulse_width[4]" is introduced which can be 2402399e401SStefan Roese * overwritten if needed by a board-specific version. If the board 2412399e401SStefan Roese * code does not provide a non-weak version of this variable, the 2422399e401SStefan Roese * default value will be used. So nothing is changed from the 2432399e401SStefan Roese * current setup on the supported board. 2442399e401SStefan Roese */ 2452399e401SStefan Roese __weak u8 serdes_pex_pulse_width[4] = { 2, 2, 2, 2 }; 2462399e401SStefan Roese 24729b103c7SStefan Roese int serdes_phy_config(void) 24829b103c7SStefan Roese { 24929b103c7SStefan Roese int status = MV_OK; 25029b103c7SStefan Roese u32 line_cfg; 25129b103c7SStefan Roese u8 line_num; 25229b103c7SStefan Roese /* addr/value for each line @ every setup step */ 25329b103c7SStefan Roese u32 addr[16][11], val[16][11]; 25429b103c7SStefan Roese u8 pex_unit, pex_line_num; 25529b103c7SStefan Roese u8 sgmii_port = 0; 25629b103c7SStefan Roese u32 tmp; 25729b103c7SStefan Roese u32 in_direct; 25829b103c7SStefan Roese u8 max_serdes_lines; 25929b103c7SStefan Roese MV_BIN_SERDES_CFG *info; 26029b103c7SStefan Roese u8 satr11; 26129b103c7SStefan Roese u8 sata_port; 26229b103c7SStefan Roese u8 freq; 26329b103c7SStefan Roese u8 device_rev; 26429b103c7SStefan Roese u32 rx_high_imp_mode; 26529b103c7SStefan Roese u16 ctrl_mode; 26629b103c7SStefan Roese u32 pex_if; 26729b103c7SStefan Roese u32 pex_if_num; 26829b103c7SStefan Roese 26929b103c7SStefan Roese /* 270bf0db8b8SStefan Roese * Get max. serdes lines count 27129b103c7SStefan Roese */ 272bf0db8b8SStefan Roese max_serdes_lines = serdes_max_lines_get(); 27329b103c7SStefan Roese if (max_serdes_lines == 0) 27429b103c7SStefan Roese return MV_OK; 27529b103c7SStefan Roese 27629b103c7SStefan Roese satr11 = board_sat_r_get(1, 1); 27729b103c7SStefan Roese if ((u8) MV_ERROR == (u8) satr11) 27829b103c7SStefan Roese return MV_ERROR; 27929b103c7SStefan Roese 28029b103c7SStefan Roese board_modules_scan(); 28129b103c7SStefan Roese memset(addr, 0, sizeof(addr)); 28229b103c7SStefan Roese memset(val, 0, sizeof(val)); 28329b103c7SStefan Roese 28429b103c7SStefan Roese /* Check if DRAM is already initialized */ 28529b103c7SStefan Roese if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & 28629b103c7SStefan Roese (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { 28729b103c7SStefan Roese DEBUG_INIT_S("High speed PHY - Version: "); 288d374e90bSUwe Kleine-König DEBUG_INIT_S(SERDES_VERSION); 28929b103c7SStefan Roese DEBUG_INIT_S(" - 2nd boot - Skip\n"); 29029b103c7SStefan Roese return MV_OK; 29129b103c7SStefan Roese } 29229b103c7SStefan Roese DEBUG_INIT_S("High speed PHY - Version: "); 293d374e90bSUwe Kleine-König DEBUG_INIT_S(SERDES_VERSION); 29429b103c7SStefan Roese DEBUG_INIT_S(" (COM-PHY-V20)\n"); 29529b103c7SStefan Roese 29629b103c7SStefan Roese /* 29729b103c7SStefan Roese * AVS : disable AVS for frequency less than 1333 29829b103c7SStefan Roese */ 29929b103c7SStefan Roese freq = board_cpu_freq_get(); 30029b103c7SStefan Roese device_rev = mv_ctrl_rev_get(); 30129b103c7SStefan Roese 30229b103c7SStefan Roese if (device_rev == 2) { /* for B0 only */ 30329b103c7SStefan Roese u32 cpu_avs; 30429b103c7SStefan Roese u8 fabric_freq; 30529b103c7SStefan Roese cpu_avs = reg_read(CPU_AVS_CONTROL2_REG); 30629b103c7SStefan Roese DEBUG_RD_REG(CPU_AVS_CONTROL2_REG, cpu_avs); 30729b103c7SStefan Roese cpu_avs &= ~(1 << 9); 30829b103c7SStefan Roese 30929b103c7SStefan Roese if ((0x4 == freq) || (0xB == freq)) { 31029b103c7SStefan Roese u32 tmp2; 31129b103c7SStefan Roese 31229b103c7SStefan Roese tmp2 = reg_read(CPU_AVS_CONTROL0_REG); 31329b103c7SStefan Roese DEBUG_RD_REG(CPU_AVS_CONTROL0_REG, tmp2); 31429b103c7SStefan Roese /* cpu upper limit = 1.1V cpu lower limit = 0.9125V */ 31529b103c7SStefan Roese tmp2 |= 0x0FF; 31629b103c7SStefan Roese reg_write(CPU_AVS_CONTROL0_REG, tmp2); 31729b103c7SStefan Roese DEBUG_WR_REG(CPU_AVS_CONTROL0_REG, tmp2); 31829b103c7SStefan Roese cpu_avs |= (1 << 9); /* cpu avs enable */ 31929b103c7SStefan Roese cpu_avs |= (1 << 18); /* AvsAvddDetEn enable */ 32029b103c7SStefan Roese fabric_freq = (reg_read(MPP_SAMPLE_AT_RESET(0)) & 32129b103c7SStefan Roese SAR0_FABRIC_FREQ_MASK) >> SAR0_FABRIC_FREQ_OFFSET; 32229b103c7SStefan Roese if ((0xB == freq) && (5 == fabric_freq)) { 32329b103c7SStefan Roese u32 core_avs; 32429b103c7SStefan Roese 32529b103c7SStefan Roese core_avs = reg_read(CORE_AVS_CONTROL_0REG); 32629b103c7SStefan Roese DEBUG_RD_REG(CORE_AVS_CONTROL_0REG, core_avs); 32729b103c7SStefan Roese 32829b103c7SStefan Roese /* 32929b103c7SStefan Roese * Set core lower limit = 0.9V & 33029b103c7SStefan Roese * core upper limit = 0.9125V 33129b103c7SStefan Roese */ 33229b103c7SStefan Roese core_avs &= ~(0xff); 33329b103c7SStefan Roese core_avs |= 0x0E; 33429b103c7SStefan Roese reg_write(CORE_AVS_CONTROL_0REG, core_avs); 33529b103c7SStefan Roese DEBUG_WR_REG(CORE_AVS_CONTROL_0REG, core_avs); 33629b103c7SStefan Roese 33729b103c7SStefan Roese core_avs = reg_read(CORE_AVS_CONTROL_2REG); 33829b103c7SStefan Roese DEBUG_RD_REG(CORE_AVS_CONTROL_2REG, core_avs); 33929b103c7SStefan Roese core_avs |= (1 << 9); /* core AVS enable */ 34029b103c7SStefan Roese reg_write(CORE_AVS_CONTROL_2REG, core_avs); 34129b103c7SStefan Roese DEBUG_WR_REG(CORE_AVS_CONTROL_2REG, core_avs); 34229b103c7SStefan Roese 34329b103c7SStefan Roese tmp2 = reg_read(GENERAL_PURPOSE_RESERVED0_REG); 34429b103c7SStefan Roese DEBUG_RD_REG(GENERAL_PURPOSE_RESERVED0_REG, 34529b103c7SStefan Roese tmp2); 34629b103c7SStefan Roese tmp2 |= 0x1; /* AvsCoreAvddDetEn enable */ 34729b103c7SStefan Roese reg_write(GENERAL_PURPOSE_RESERVED0_REG, tmp2); 34829b103c7SStefan Roese DEBUG_WR_REG(GENERAL_PURPOSE_RESERVED0_REG, 34929b103c7SStefan Roese tmp2); 35029b103c7SStefan Roese } 35129b103c7SStefan Roese } 35229b103c7SStefan Roese reg_write(CPU_AVS_CONTROL2_REG, cpu_avs); 35329b103c7SStefan Roese DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs); 35429b103c7SStefan Roese } 35529b103c7SStefan Roese 35629b103c7SStefan Roese info = board_serdes_cfg_get(PEX_MODE_GET(satr11)); 35729b103c7SStefan Roese 35829b103c7SStefan Roese if (info == NULL) { 35929b103c7SStefan Roese DEBUG_INIT_S("Hight speed PHY Error #1\n"); 36029b103c7SStefan Roese return MV_ERROR; 36129b103c7SStefan Roese } 362*a22bbfdaSxypron.glpk@gmx.de DEBUG_INIT_FULL_S("info->line0_7= 0x"); 363*a22bbfdaSxypron.glpk@gmx.de DEBUG_INIT_FULL_D(info->line0_7, 8); 364*a22bbfdaSxypron.glpk@gmx.de DEBUG_INIT_FULL_S(" info->line8_15= 0x"); 365*a22bbfdaSxypron.glpk@gmx.de DEBUG_INIT_FULL_D(info->line8_15, 8); 366*a22bbfdaSxypron.glpk@gmx.de DEBUG_INIT_FULL_S("\n"); 36729b103c7SStefan Roese 36829b103c7SStefan Roese if (config_module & ETM_MODULE_DETECT) { /* step 0.9 ETM */ 36929b103c7SStefan Roese DEBUG_INIT_FULL_S("ETM module detect Step 0.9:\n"); 37029b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, 0x11111111); 37129b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x11111111); 37229b103c7SStefan Roese info->pex_mode[1] = PEX_BUS_DISABLED; /* pex unit 1 is configure for ETM */ 37329b103c7SStefan Roese mdelay(100); 37429b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d); /* SETM0 - start calibration */ 37529b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d); /* SETM0 - start calibration */ 37629b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d); /* SETM1 - start calibration */ 37729b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d); /* SETM1 - start calibration */ 37829b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801); /* SETM0 - SATA mode & 25MHz ref clk */ 37929b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801); /* SETM0 - SATA mode & 25MHz ref clk */ 38029b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801); /* SETM1 - SATA mode & 25MHz ref clk */ 38129b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801); /* SETM1 - SATA mode & 25MHz ref clk */ 38229b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF); /* SETM0 - G3 full swing AMP */ 38329b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF); /* SETM0 - G3 full swing AMP */ 38429b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF); /* SETM1 - G3 full swing AMP */ 38529b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF); /* SETM1 - G3 full swing AMP */ 38629b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800); /* SETM0 - 40 data bit width */ 38729b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800); /* SETM0 - 40 data bit width */ 38829b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800); /* SETM1 - 40 data bit width */ 38929b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800); /* SETM1 - 40 data bit width */ 39029b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400); /* lane0(serdes4) */ 39129b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400); /* lane0(serdes4) */ 39229b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400); /* lane3(serdes7) */ 39329b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400); /* lane3(serdes7) */ 39429b103c7SStefan Roese } 39529b103c7SStefan Roese 39629b103c7SStefan Roese /* STEP -1 [PEX-Only] First phase of PEX-PIPE Configuration: */ 39729b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 1: First phase of PEX-PIPE Configuration\n"); 39829b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 39929b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 40029b103c7SStefan Roese continue; 40129b103c7SStefan Roese 40229b103c7SStefan Roese /* 1. GLOB_CLK_CTRL Reset and Clock Control */ 40329b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25); 40429b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25); 40529b103c7SStefan Roese 40629b103c7SStefan Roese /* 2. GLOB_TEST_CTRL Test Mode Control */ 40729b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) { 40829b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 40929b103c7SStefan Roese (0xC2 << 16) | 0x200); 41029b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 41129b103c7SStefan Roese (0xC2 << 16) | 0x200); 41229b103c7SStefan Roese } 41329b103c7SStefan Roese 41429b103c7SStefan Roese /* 3. GLOB_CLK_SRC_LO Clock Source Low */ 41529b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) { 41629b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 41729b103c7SStefan Roese (0xC3 << 16) | 0x0F); 41829b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 41929b103c7SStefan Roese (0xC3 << 16) | 0x0F); 42029b103c7SStefan Roese } 42129b103c7SStefan Roese 42229b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC5 << 16) | 0x11F); 42329b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 42429b103c7SStefan Roese (0xC5 << 16) | 0x11F); 42529b103c7SStefan Roese } 42629b103c7SStefan Roese 42729b103c7SStefan Roese /* 42829b103c7SStefan Roese * 2 Configure the desire PIN_PHY_GEN and do power down to the PU_PLL, 42929b103c7SStefan Roese * PU_RX,PU_TX. (bits[12:5]) 43029b103c7SStefan Roese */ 43129b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 2: Configure the desire PIN_PHY_GEN\n"); 43229b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 43329b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 43429b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 43529b103c7SStefan Roese continue; 43629b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) 43729b103c7SStefan Roese continue; 43829b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 43929b103c7SStefan Roese switch (line_num) { 44029b103c7SStefan Roese case 4: 44129b103c7SStefan Roese case 6: 44229b103c7SStefan Roese sata_port = 0; 44329b103c7SStefan Roese break; 44429b103c7SStefan Roese case 5: 44529b103c7SStefan Roese sata_port = 1; 44629b103c7SStefan Roese break; 44729b103c7SStefan Roese default: 44829b103c7SStefan Roese DEBUG_INIT_C 44929b103c7SStefan Roese ("SATA port error for serdes line: ", 45029b103c7SStefan Roese line_num, 2); 45129b103c7SStefan Roese return MV_ERROR; 45229b103c7SStefan Roese } 45329b103c7SStefan Roese tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port)); 45429b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 45529b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 45629b103c7SStefan Roese tmp |= ((info->bus_speed & (1 << line_num)) != 0) ? 45729b103c7SStefan Roese (0x11 << 5) : 0x0; 45829b103c7SStefan Roese 45929b103c7SStefan Roese reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 46029b103c7SStefan Roese DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 46129b103c7SStefan Roese } 46229b103c7SStefan Roese 46329b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 46429b103c7SStefan Roese /* 46529b103c7SStefan Roese * 4) Configure the desire PIN_PHY_GEN and do power 46629b103c7SStefan Roese * down to the PU_PLL,PU_RX,PU_TX. (bits[12:5]) 46729b103c7SStefan Roese */ 46829b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(0)); 46929b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp); 47029b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 47129b103c7SStefan Roese tmp |= 0x660; 47229b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(0), tmp); 47329b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp); 47429b103c7SStefan Roese continue; 47529b103c7SStefan Roese } 47629b103c7SStefan Roese 47729b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 47829b103c7SStefan Roese sgmii_port = 0; 47929b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 48029b103c7SStefan Roese sgmii_port = 1; 48129b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 48229b103c7SStefan Roese sgmii_port = 2; 48329b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 48429b103c7SStefan Roese sgmii_port = 3; 48529b103c7SStefan Roese else 48629b103c7SStefan Roese continue; 48729b103c7SStefan Roese 48829b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port)); 48929b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 49029b103c7SStefan Roese tmp &= ~((0x1ff << 5) | 0x7); 49129b103c7SStefan Roese tmp |= (((info->bus_speed & (1 << line_num)) != 0) ? 49229b103c7SStefan Roese (0x88 << 5) : (0x66 << 5)); 49329b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 49429b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 49529b103c7SStefan Roese } 49629b103c7SStefan Roese 49729b103c7SStefan Roese /* Step 3 - QSGMII enable */ 49829b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 3 QSGMII enable\n"); 49929b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 50029b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 50129b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 50229b103c7SStefan Roese /* QSGMII Active bit set to true */ 50329b103c7SStefan Roese tmp = reg_read(QSGMII_CONTROL_1_REG); 50429b103c7SStefan Roese DEBUG_RD_REG(QSGMII_CONTROL_1_REG, tmp); 50529b103c7SStefan Roese tmp |= (1 << 30); 50629b103c7SStefan Roese #ifdef ERRATA_GL_6572255 50729b103c7SStefan Roese tmp |= (1 << 27); 50829b103c7SStefan Roese #endif 50929b103c7SStefan Roese reg_write(QSGMII_CONTROL_1_REG, tmp); 51029b103c7SStefan Roese DEBUG_WR_REG(QSGMII_CONTROL_1_REG, tmp); 51129b103c7SStefan Roese } 51229b103c7SStefan Roese } 51329b103c7SStefan Roese 51429b103c7SStefan Roese /* Step 4 - configure SERDES MUXes */ 51529b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 4: Configure SERDES MUXes\n"); 51629b103c7SStefan Roese if (config_module & ETM_MODULE_DETECT) { 51729b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, 0x40041111); 51829b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x40041111); 51929b103c7SStefan Roese } else { 52029b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_0_7, info->line0_7); 52129b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, info->line0_7); 52229b103c7SStefan Roese } 52329b103c7SStefan Roese reg_write(SERDES_LINE_MUX_REG_8_15, info->line8_15); 52429b103c7SStefan Roese DEBUG_WR_REG(SERDES_LINE_MUX_REG_8_15, info->line8_15); 52529b103c7SStefan Roese 52629b103c7SStefan Roese /* Step 5: Activate the RX High Impedance Mode */ 52729b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 5: Activate the RX High Impedance Mode\n"); 52829b103c7SStefan Roese rx_high_imp_mode = 0x8080; 52929b103c7SStefan Roese if (device_rev == 2) /* for B0 only */ 53029b103c7SStefan Roese rx_high_imp_mode |= 4; 53129b103c7SStefan Roese 53229b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 53329b103c7SStefan Roese /* for each serdes lane */ 53429b103c7SStefan Roese DEBUG_INIT_FULL_S("SERDES "); 53529b103c7SStefan Roese DEBUG_INIT_FULL_D_10(line_num, 2); 53629b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 53729b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) { 53829b103c7SStefan Roese DEBUG_INIT_FULL_S(" unconnected ***\n"); 53929b103c7SStefan Roese continue; 54029b103c7SStefan Roese } 54129b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 54229b103c7SStefan Roese pex_unit = line_num >> 2; 54329b103c7SStefan Roese pex_line_num = line_num % 4; 54429b103c7SStefan Roese DEBUG_INIT_FULL_S(" - PEX unit "); 54529b103c7SStefan Roese DEBUG_INIT_FULL_D_10(pex_unit, 1); 54629b103c7SStefan Roese DEBUG_INIT_FULL_S(" line= "); 54729b103c7SStefan Roese DEBUG_INIT_FULL_D_10(pex_line_num, 1); 54829b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 54929b103c7SStefan Roese 55029b103c7SStefan Roese /* Needed for PEX_PHY_ACCESS_REG macro */ 55129b103c7SStefan Roese if ((line_num > 7) && 55229b103c7SStefan Roese (info->pex_mode[3] == PEX_BUS_MODE_X8)) 55329b103c7SStefan Roese /* lines 8 - 15 are belong to PEX3 in x8 mode */ 55429b103c7SStefan Roese pex_unit = 3; 55529b103c7SStefan Roese 55629b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 55729b103c7SStefan Roese continue; 55829b103c7SStefan Roese 55929b103c7SStefan Roese /* 56029b103c7SStefan Roese * 8) Activate the RX High Impedance Mode field 56129b103c7SStefan Roese * (bit [2]) in register /PCIe_USB Control (Each MAC 56229b103c7SStefan Roese * contain different Access to reach its 56329b103c7SStefan Roese * Serdes-Regfile). 56429b103c7SStefan Roese * [PEX-Only] Set bit[12]: The analog part latches idle 56529b103c7SStefan Roese * if PU_TX = 1 and PU_PLL =1. 56629b103c7SStefan Roese */ 56729b103c7SStefan Roese 56829b103c7SStefan Roese /* Termination enable */ 56929b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) { 57029b103c7SStefan Roese in_direct = (0x48 << 16) | (pex_line_num << 24) | 57129b103c7SStefan Roese 0x1000 | rx_high_imp_mode; /* x1 */ 57229b103c7SStefan Roese } else if ((info->pex_mode[pex_unit] == 57329b103c7SStefan Roese PEX_BUS_MODE_X4) && (pex_line_num == 0)) 57429b103c7SStefan Roese in_direct = (0x48 << 16) | (pex_line_num << 24) | 57529b103c7SStefan Roese 0x1000 | (rx_high_imp_mode & 0xff); /* x4 */ 57629b103c7SStefan Roese else 57729b103c7SStefan Roese in_direct = 0; 57829b103c7SStefan Roese 57929b103c7SStefan Roese if (in_direct) { 58029b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 58129b103c7SStefan Roese in_direct); 58229b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 58329b103c7SStefan Roese in_direct); 58429b103c7SStefan Roese } 58529b103c7SStefan Roese 58629b103c7SStefan Roese continue; 58729b103c7SStefan Roese } 58829b103c7SStefan Roese 58929b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 59029b103c7SStefan Roese /* 59129b103c7SStefan Roese * port 0 for serdes lines 4,6, and port 1 for 59229b103c7SStefan Roese * serdes lines 5 59329b103c7SStefan Roese */ 59429b103c7SStefan Roese sata_port = line_num & 1; 59529b103c7SStefan Roese DEBUG_INIT_FULL_S(" - SATA port "); 59629b103c7SStefan Roese DEBUG_INIT_FULL_D_10(sata_port, 2); 59729b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 59829b103c7SStefan Roese reg_write(SATA_COMPHY_CTRL_REG(sata_port), 59929b103c7SStefan Roese rx_high_imp_mode); 60029b103c7SStefan Roese DEBUG_WR_REG(SATA_COMPHY_CTRL_REG(sata_port), 60129b103c7SStefan Roese rx_high_imp_mode); 60229b103c7SStefan Roese continue; 60329b103c7SStefan Roese } 60429b103c7SStefan Roese 60529b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 60629b103c7SStefan Roese DEBUG_INIT_FULL_S(" - QSGMII\n"); 60729b103c7SStefan Roese reg_write(SGMII_COMPHY_CTRL_REG(0), rx_high_imp_mode); 60829b103c7SStefan Roese DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(0), 60929b103c7SStefan Roese rx_high_imp_mode); 61029b103c7SStefan Roese continue; 61129b103c7SStefan Roese } 61229b103c7SStefan Roese 61329b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 61429b103c7SStefan Roese sgmii_port = 0; 61529b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 61629b103c7SStefan Roese sgmii_port = 1; 61729b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 61829b103c7SStefan Roese sgmii_port = 2; 61929b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 62029b103c7SStefan Roese sgmii_port = 3; 62129b103c7SStefan Roese else 62229b103c7SStefan Roese continue; 62329b103c7SStefan Roese DEBUG_INIT_FULL_S(" - SGMII port "); 62429b103c7SStefan Roese DEBUG_INIT_FULL_D_10(sgmii_port, 2); 62529b103c7SStefan Roese DEBUG_INIT_FULL_S("\n"); 62629b103c7SStefan Roese reg_write(SGMII_COMPHY_CTRL_REG(sgmii_port), rx_high_imp_mode); 62729b103c7SStefan Roese DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(sgmii_port), 62829b103c7SStefan Roese rx_high_imp_mode); 62929b103c7SStefan Roese } /* for each serdes lane */ 63029b103c7SStefan Roese 63129b103c7SStefan Roese /* Step 6 [PEX-Only] PEX-Main configuration (X4 or X1): */ 63229b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6: [PEX-Only] PEX-Main configuration (X4 or X1)\n"); 63329b103c7SStefan Roese tmp = reg_read(SOC_CTRL_REG); 63429b103c7SStefan Roese DEBUG_RD_REG(SOC_CTRL_REG, tmp); 63529b103c7SStefan Roese tmp &= 0x200; 63629b103c7SStefan Roese if (info->pex_mode[0] == PEX_BUS_MODE_X1) 63729b103c7SStefan Roese tmp |= PCIE0_QUADX1_EN; 63829b103c7SStefan Roese if (info->pex_mode[1] == PEX_BUS_MODE_X1) 63929b103c7SStefan Roese tmp |= PCIE1_QUADX1_EN; 64029b103c7SStefan Roese if (((reg_read(MPP_SAMPLE_AT_RESET(0)) & PEX_CLK_100MHZ_MASK) >> 64129b103c7SStefan Roese PEX_CLK_100MHZ_OFFSET) == 0x1) 64229b103c7SStefan Roese tmp |= (PCIE0_CLK_OUT_EN_MASK | PCIE1_CLK_OUT_EN_MASK); 64329b103c7SStefan Roese 64429b103c7SStefan Roese reg_write(SOC_CTRL_REG, tmp); 64529b103c7SStefan Roese DEBUG_WR_REG(SOC_CTRL_REG, tmp); 64629b103c7SStefan Roese 64729b103c7SStefan Roese /* 6.2 PCI Express Link Capabilities */ 64829b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6.2: [PEX-Only] PCI Express Link Capabilities\n"); 64929b103c7SStefan Roese 65029b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 65129b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 65229b103c7SStefan Roese 65329b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 65429b103c7SStefan Roese /* 65529b103c7SStefan Roese * PCI Express Control 65629b103c7SStefan Roese * 0xX1A00 [0]: 65729b103c7SStefan Roese * 0x0 X4-Link. 65829b103c7SStefan Roese * 0x1 X1-Link 65929b103c7SStefan Roese */ 66029b103c7SStefan Roese pex_unit = line_num >> 2; 66129b103c7SStefan Roese pex_if = MV_SERDES_NUM_TO_PEX_NUM(line_num); 66229b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 66329b103c7SStefan Roese continue; 66429b103c7SStefan Roese 66529b103c7SStefan Roese /* set Common Clock Configuration */ 66629b103c7SStefan Roese tmp = reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if)); 66729b103c7SStefan Roese DEBUG_RD_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 66829b103c7SStefan Roese tmp |= (1 << 6); 66929b103c7SStefan Roese reg_write(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 67029b103c7SStefan Roese DEBUG_WR_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp); 67129b103c7SStefan Roese 67229b103c7SStefan Roese tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if)); 67329b103c7SStefan Roese DEBUG_RD_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 67429b103c7SStefan Roese tmp &= ~(0x3FF); 67529b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) 67629b103c7SStefan Roese tmp |= (0x1 << 4); 67729b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) 67829b103c7SStefan Roese tmp |= (0x4 << 4); 67929b103c7SStefan Roese if (0 == PEX_CAPABILITY_GET(satr11)) 68029b103c7SStefan Roese tmp |= 0x1; 68129b103c7SStefan Roese else 68229b103c7SStefan Roese tmp |= 0x2; 68329b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 6.2: PEX "); 68429b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 68529b103c7SStefan Roese DEBUG_INIT_FULL_C(" set GEN", (tmp & 3), 1); 68629b103c7SStefan Roese reg_write(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 68729b103c7SStefan Roese DEBUG_WR_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp); 68829b103c7SStefan Roese 68929b103c7SStefan Roese /* 69029b103c7SStefan Roese * If pex is X4, no need to pass thru the other 69129b103c7SStefan Roese * 3X1 serdes lines 69229b103c7SStefan Roese */ 69329b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) 69429b103c7SStefan Roese line_num += 3; 69529b103c7SStefan Roese } 69629b103c7SStefan Roese } 69729b103c7SStefan Roese 69829b103c7SStefan Roese /* 69929b103c7SStefan Roese * Step 7 [PEX-X4 Only] To create PEX-Link that contain 4-lanes you 70029b103c7SStefan Roese * need to config the register SOC_Misc/General Purpose2 70129b103c7SStefan Roese * (Address= 182F8) 70229b103c7SStefan Roese */ 70329b103c7SStefan Roese DEBUG_INIT_FULL_S("Step 7: [PEX-X4 Only] To create PEX-Link\n"); 70429b103c7SStefan Roese tmp = reg_read(GEN_PURP_RES_2_REG); 70529b103c7SStefan Roese DEBUG_RD_REG(GEN_PURP_RES_2_REG, tmp); 70629b103c7SStefan Roese 70729b103c7SStefan Roese tmp &= 0xFFFF0000; 70829b103c7SStefan Roese if (info->pex_mode[0] == PEX_BUS_MODE_X4) 70929b103c7SStefan Roese tmp |= 0x0000000F; 71029b103c7SStefan Roese 71129b103c7SStefan Roese if (info->pex_mode[1] == PEX_BUS_MODE_X4) 71229b103c7SStefan Roese tmp |= 0x000000F0; 71329b103c7SStefan Roese 71429b103c7SStefan Roese if (info->pex_mode[2] == PEX_BUS_MODE_X4) 71529b103c7SStefan Roese tmp |= 0x00000F00; 71629b103c7SStefan Roese 71729b103c7SStefan Roese if (info->pex_mode[3] == PEX_BUS_MODE_X4) 71829b103c7SStefan Roese tmp |= 0x0000F000; 71929b103c7SStefan Roese 72029b103c7SStefan Roese reg_write(GEN_PURP_RES_2_REG, tmp); 72129b103c7SStefan Roese DEBUG_WR_REG(GEN_PURP_RES_2_REG, tmp); 72229b103c7SStefan Roese 72329b103c7SStefan Roese /* Steps 8 , 9 ,10 - use prepared REG addresses and values */ 72429b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 7,8,9,10 and 11\n"); 72529b103c7SStefan Roese 72629b103c7SStefan Roese /* Prepare PHY parameters for each step according to MUX selection */ 72729b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 72829b103c7SStefan Roese /* for each serdes lane */ 72929b103c7SStefan Roese 73029b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 73129b103c7SStefan Roese 73229b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 73329b103c7SStefan Roese continue; 73429b103c7SStefan Roese 73529b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 73629b103c7SStefan Roese pex_unit = line_num >> 2; 73729b103c7SStefan Roese pex_line_num = line_num % 4; 73829b103c7SStefan Roese 73929b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 74029b103c7SStefan Roese continue; 74129b103c7SStefan Roese /* 74229b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) 74329b103c7SStefan Roese * and REF_FREF_SEL (bits[4:0]) in the register Power 74429b103c7SStefan Roese * and PLL Control (Each MAC contain different Access 74529b103c7SStefan Roese * to reach its Serdes-Regfile). 74629b103c7SStefan Roese */ 74729b103c7SStefan Roese if (((info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) && 74829b103c7SStefan Roese (0 == pex_line_num)) 74929b103c7SStefan Roese || ((info->pex_mode[pex_unit] == PEX_BUS_MODE_X1))) { 75029b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 75129b103c7SStefan Roese (0x01 << 16) | (pex_line_num << 24) | 75229b103c7SStefan Roese 0xFC60); 75329b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 75429b103c7SStefan Roese (0x01 << 16) | (pex_line_num << 24) 75529b103c7SStefan Roese | 0xFC60); 75629b103c7SStefan Roese /* 75729b103c7SStefan Roese * Step 8.1: [PEX-Only] Configure Max PLL Rate 75829b103c7SStefan Roese * (bit 8 in KVCO Calibration Control and 75929b103c7SStefan Roese * bits[10:9] in 76029b103c7SStefan Roese */ 76129b103c7SStefan Roese /* Use Maximum PLL Rate(Bit 8) */ 76229b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 76329b103c7SStefan Roese (0x02 << 16) | (1 << 31) | 76429b103c7SStefan Roese (pex_line_num << 24)); /* read command */ 76529b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 76629b103c7SStefan Roese (0x02 << 16) | (1 << 31) | 76729b103c7SStefan Roese (pex_line_num << 24)); 76829b103c7SStefan Roese tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit)); 76929b103c7SStefan Roese DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 77029b103c7SStefan Roese tmp &= ~(1 << 31); 77129b103c7SStefan Roese tmp |= (1 << 8); 77229b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp); 77329b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 77429b103c7SStefan Roese 77529b103c7SStefan Roese /* Use Maximum PLL Rate(Bits [10:9]) */ 77629b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 77729b103c7SStefan Roese (0x81 << 16) | (1 << 31) | 77829b103c7SStefan Roese (pex_line_num << 24)); /* read command */ 77929b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 78029b103c7SStefan Roese (0x81 << 16) | (1 << 31) | 78129b103c7SStefan Roese (pex_line_num << 24)); 78229b103c7SStefan Roese tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit)); 78329b103c7SStefan Roese DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 78429b103c7SStefan Roese tmp &= ~(1 << 31); 78529b103c7SStefan Roese tmp |= (3 << 9); 78629b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp); 78729b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp); 78829b103c7SStefan Roese } 78929b103c7SStefan Roese 79029b103c7SStefan Roese continue; 79129b103c7SStefan Roese } 79229b103c7SStefan Roese 79329b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 79429b103c7SStefan Roese /* 79529b103c7SStefan Roese * Port 0 for serdes lines 4,6, and port 1 for serdes 79629b103c7SStefan Roese * lines 5 79729b103c7SStefan Roese */ 79829b103c7SStefan Roese sata_port = line_num & 1; 79929b103c7SStefan Roese 80029b103c7SStefan Roese /* 80129b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) and 80229b103c7SStefan Roese * REF_FREF_SEL (bits[4:0]) in the register Power 80329b103c7SStefan Roese * and PLL Control (Each MAC contain different Access 80429b103c7SStefan Roese * to reach its Serdes-Regfile). 80529b103c7SStefan Roese */ 80629b103c7SStefan Roese reg_write(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801); 80729b103c7SStefan Roese DEBUG_WR_REG(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801); 80829b103c7SStefan Roese 80929b103c7SStefan Roese /* 9) Configure the desire SEL_BITS */ 81029b103c7SStefan Roese reg_write(SATA_DIG_LP_ENA_REG(sata_port), 0x400); 81129b103c7SStefan Roese DEBUG_WR_REG(SATA_DIG_LP_ENA_REG(sata_port), 0x400); 81229b103c7SStefan Roese 81329b103c7SStefan Roese /* 10) Configure the desire REFCLK_SEL */ 81429b103c7SStefan Roese 81529b103c7SStefan Roese reg_write(SATA_REF_CLK_SEL_REG(sata_port), 0x400); 81629b103c7SStefan Roese DEBUG_WR_REG(SATA_REF_CLK_SEL_REG(sata_port), 0x400); 81729b103c7SStefan Roese 81829b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 81929b103c7SStefan Roese tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port)); 82029b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 82129b103c7SStefan Roese tmp |= 7; 82229b103c7SStefan Roese reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 82329b103c7SStefan Roese DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp); 82429b103c7SStefan Roese 82529b103c7SStefan Roese continue; 82629b103c7SStefan Roese } 82729b103c7SStefan Roese 82829b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 82929b103c7SStefan Roese /* 83029b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) 83129b103c7SStefan Roese * and REF_FREF_SEL (bits[4:0]) in the register 83229b103c7SStefan Roese */ 83329b103c7SStefan Roese reg_write(SGMII_PWR_PLL_CTRL_REG(0), 0xF881); 83429b103c7SStefan Roese DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(0), 0xF881); 83529b103c7SStefan Roese 83629b103c7SStefan Roese /* 83729b103c7SStefan Roese * 9) Configure the desire SEL_BITS (bits [11:0] 83829b103c7SStefan Roese * in register 83929b103c7SStefan Roese */ 84029b103c7SStefan Roese reg_write(SGMII_DIG_LP_ENA_REG(0), 0x400); 84129b103c7SStefan Roese DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(0), 0x400); 84229b103c7SStefan Roese 84329b103c7SStefan Roese /* 84429b103c7SStefan Roese * 10) Configure the desire REFCLK_SEL (bit [10]) 84529b103c7SStefan Roese * in register 84629b103c7SStefan Roese */ 84729b103c7SStefan Roese reg_write(SGMII_REF_CLK_SEL_REG(0), 0x400); 84829b103c7SStefan Roese DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(0), 0x400); 84929b103c7SStefan Roese 85029b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 85129b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(0)); 85229b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp); 85329b103c7SStefan Roese tmp |= 7; 85429b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(0), tmp); 85529b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp); 85629b103c7SStefan Roese continue; 85729b103c7SStefan Roese } 85829b103c7SStefan Roese 85929b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 86029b103c7SStefan Roese sgmii_port = 0; 86129b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 86229b103c7SStefan Roese sgmii_port = 1; 86329b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 86429b103c7SStefan Roese sgmii_port = 2; 86529b103c7SStefan Roese else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 86629b103c7SStefan Roese sgmii_port = 3; 86729b103c7SStefan Roese else 86829b103c7SStefan Roese continue; 86929b103c7SStefan Roese 87029b103c7SStefan Roese /* 87129b103c7SStefan Roese * 8) Configure the desire PHY_MODE (bits [7:5]) and 87229b103c7SStefan Roese * REF_FREF_SEL (bits[4:0]) in the register 87329b103c7SStefan Roese */ 87429b103c7SStefan Roese reg_write(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881); 87529b103c7SStefan Roese DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881); 87629b103c7SStefan Roese 87729b103c7SStefan Roese /* 9) Configure the desire SEL_BITS (bits [11:0] in register */ 87829b103c7SStefan Roese reg_write(SGMII_DIG_LP_ENA_REG(sgmii_port), 0); 87929b103c7SStefan Roese DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(sgmii_port), 0); 88029b103c7SStefan Roese 88129b103c7SStefan Roese /* 10) Configure the desire REFCLK_SEL (bit [10]) in register */ 88229b103c7SStefan Roese reg_write(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400); 88329b103c7SStefan Roese DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400); 88429b103c7SStefan Roese 88529b103c7SStefan Roese /* 11) Power up to the PU_PLL,PU_RX,PU_TX. */ 88629b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port)); 88729b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 88829b103c7SStefan Roese tmp |= 7; 88929b103c7SStefan Roese reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 89029b103c7SStefan Roese DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp); 89129b103c7SStefan Roese 89229b103c7SStefan Roese } /* for each serdes lane */ 89329b103c7SStefan Roese 89429b103c7SStefan Roese /* Step 12 [PEX-Only] Last phase of PEX-PIPE Configuration */ 89529b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 12: [PEX-Only] Last phase of PEX-PIPE Configuration\n"); 89629b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 89729b103c7SStefan Roese /* for each serdes lane */ 89829b103c7SStefan Roese 89929b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 90029b103c7SStefan Roese 90129b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 90229b103c7SStefan Roese continue; 90329b103c7SStefan Roese 90429b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) { 90529b103c7SStefan Roese pex_unit = line_num >> 2; 90629b103c7SStefan Roese pex_line_num = line_num % 4; 90729b103c7SStefan Roese if (0 == pex_line_num) { 9082399e401SStefan Roese /* 9092399e401SStefan Roese * Configure the detection pulse with before 9102399e401SStefan Roese * the reset is deasserted 9112399e401SStefan Roese */ 9122399e401SStefan Roese 9132399e401SStefan Roese /* Read the old value (indirect access) */ 9142399e401SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 9152399e401SStefan Roese (0x48 << 16) | (1 << 31) | 9162399e401SStefan Roese (pex_line_num << 24)); 9172399e401SStefan Roese tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit)); 9182399e401SStefan Roese tmp &= ~(1 << 31); /* Clear read */ 9192399e401SStefan Roese tmp &= ~(3 << 6); /* Mask width */ 9202399e401SStefan Roese /* Insert new detection pulse width */ 9212399e401SStefan Roese tmp |= serdes_pex_pulse_width[pex_unit] << 6; 9222399e401SStefan Roese /* Write value back */ 9232399e401SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp); 9242399e401SStefan Roese 92529b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG(pex_unit), 92629b103c7SStefan Roese (0xC1 << 16) | 0x24); 92729b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), 92829b103c7SStefan Roese (0xC1 << 16) | 0x24); 92929b103c7SStefan Roese } 93029b103c7SStefan Roese } 93129b103c7SStefan Roese } 93229b103c7SStefan Roese 93329b103c7SStefan Roese /*--------------------------------------------------------------*/ 93429b103c7SStefan Roese /* Step 13: Wait 15ms before checking results */ 93529b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 13: Wait 15ms before checking results"); 93629b103c7SStefan Roese mdelay(15); 93729b103c7SStefan Roese tmp = 20; 93829b103c7SStefan Roese while (tmp) { 93929b103c7SStefan Roese status = MV_OK; 94029b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 94129b103c7SStefan Roese u32 tmp; 94229b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 94329b103c7SStefan Roese if (line_cfg == 94429b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 94529b103c7SStefan Roese continue; 94629b103c7SStefan Roese 94729b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) 94829b103c7SStefan Roese continue; 94929b103c7SStefan Roese 95029b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) { 95129b103c7SStefan Roese /* 95229b103c7SStefan Roese * Port 0 for serdes lines 4,6, and port 1 95329b103c7SStefan Roese * for serdes lines 5 95429b103c7SStefan Roese */ 95529b103c7SStefan Roese sata_port = line_num & 1; 95629b103c7SStefan Roese 95729b103c7SStefan Roese tmp = 95829b103c7SStefan Roese reg_read(SATA_LP_PHY_EXT_STAT_REG 95929b103c7SStefan Roese (sata_port)); 96029b103c7SStefan Roese DEBUG_RD_REG(SATA_LP_PHY_EXT_STAT_REG 96129b103c7SStefan Roese (sata_port), tmp); 96229b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 96329b103c7SStefan Roese status = MV_ERROR; 96429b103c7SStefan Roese continue; 96529b103c7SStefan Roese } 96629b103c7SStefan Roese 96729b103c7SStefan Roese if (line_cfg == 96829b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_QSGMII]) { 96929b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_STAT_REG(0)); 97029b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_STAT_REG(0), tmp); 97129b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 97229b103c7SStefan Roese status = MV_ERROR; 97329b103c7SStefan Roese continue; 97429b103c7SStefan Roese } 97529b103c7SStefan Roese 97629b103c7SStefan Roese if (line_cfg == 97729b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII0]) 97829b103c7SStefan Roese sgmii_port = 0; 97929b103c7SStefan Roese else if (line_cfg == 98029b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII1]) 98129b103c7SStefan Roese sgmii_port = 1; 98229b103c7SStefan Roese else if (line_cfg == 98329b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII2]) 98429b103c7SStefan Roese sgmii_port = 2; 98529b103c7SStefan Roese else if (line_cfg == 98629b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_SGMII3]) 98729b103c7SStefan Roese sgmii_port = 3; 98829b103c7SStefan Roese else 98929b103c7SStefan Roese continue; 99029b103c7SStefan Roese 99129b103c7SStefan Roese tmp = reg_read(SGMII_SERDES_STAT_REG(sgmii_port)); 99229b103c7SStefan Roese DEBUG_RD_REG(SGMII_SERDES_STAT_REG(sgmii_port), tmp); 99329b103c7SStefan Roese if ((tmp & 0x7) != 0x7) 99429b103c7SStefan Roese status = MV_ERROR; 99529b103c7SStefan Roese } 99629b103c7SStefan Roese 99729b103c7SStefan Roese if (status == MV_OK) 99829b103c7SStefan Roese break; 99929b103c7SStefan Roese mdelay(5); 100029b103c7SStefan Roese tmp--; 100129b103c7SStefan Roese } 100229b103c7SStefan Roese 100329b103c7SStefan Roese /* 100429b103c7SStefan Roese * Step14 [PEX-Only] In order to configure RC/EP mode please write 100529b103c7SStefan Roese * to register 0x0060 bits 100629b103c7SStefan Roese */ 100729b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 14: [PEX-Only] In order to configure\n"); 100829b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 100929b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 101029b103c7SStefan Roese continue; 101129b103c7SStefan Roese tmp = 101229b103c7SStefan Roese reg_read(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit))); 101329b103c7SStefan Roese DEBUG_RD_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 101429b103c7SStefan Roese tmp); 101529b103c7SStefan Roese tmp &= ~(0xf << 20); 101629b103c7SStefan Roese if (info->pex_type == MV_PEX_ROOT_COMPLEX) 101729b103c7SStefan Roese tmp |= (0x4 << 20); 101829b103c7SStefan Roese else 101929b103c7SStefan Roese tmp |= (0x1 << 20); 102029b103c7SStefan Roese reg_write(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 102129b103c7SStefan Roese tmp); 102229b103c7SStefan Roese DEBUG_WR_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 102329b103c7SStefan Roese tmp); 102429b103c7SStefan Roese } 102529b103c7SStefan Roese 102629b103c7SStefan Roese /* 102729b103c7SStefan Roese * Step 15 [PEX-Only] Only for EP mode set to Zero bits 19 and 16 of 102829b103c7SStefan Roese * register 0x1a60 102929b103c7SStefan Roese */ 103029b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 15: [PEX-Only] In order to configure\n"); 103129b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 103229b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) 103329b103c7SStefan Roese continue; 103429b103c7SStefan Roese if (info->pex_type == MV_PEX_END_POINT) { 103529b103c7SStefan Roese tmp = 103629b103c7SStefan Roese reg_read(PEX_DBG_CTRL_REG 103729b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit))); 103829b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_CTRL_REG 103929b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit)), tmp); 104029b103c7SStefan Roese tmp &= 0xfff6ffff; 104129b103c7SStefan Roese reg_write(PEX_DBG_CTRL_REG(MV_PEX_UNIT_TO_IF(pex_unit)), 104229b103c7SStefan Roese tmp); 104329b103c7SStefan Roese DEBUG_WR_REG(PEX_DBG_CTRL_REG 104429b103c7SStefan Roese (MV_PEX_UNIT_TO_IF(pex_unit)), tmp); 104529b103c7SStefan Roese } 104629b103c7SStefan Roese } 104729b103c7SStefan Roese 104829b103c7SStefan Roese if (info->serdes_m_phy_change) { 104929b103c7SStefan Roese MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change; 105029b103c7SStefan Roese u32 bus_speed; 105129b103c7SStefan Roese for (line_num = 0; line_num < max_serdes_lines; line_num++) { 105229b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 105329b103c7SStefan Roese if (line_cfg == 105429b103c7SStefan Roese serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) 105529b103c7SStefan Roese continue; 105629b103c7SStefan Roese serdes_m_phy_change = info->serdes_m_phy_change; 105729b103c7SStefan Roese bus_speed = info->bus_speed & (1 << line_num); 105829b103c7SStefan Roese while (serdes_m_phy_change->type != 105929b103c7SStefan Roese SERDES_UNIT_UNCONNECTED) { 106029b103c7SStefan Roese switch (serdes_m_phy_change->type) { 106129b103c7SStefan Roese case SERDES_UNIT_PEX: 106229b103c7SStefan Roese if (line_cfg != SERDES_UNIT_PEX) 106329b103c7SStefan Roese break; 106429b103c7SStefan Roese pex_unit = line_num >> 2; 106529b103c7SStefan Roese pex_line_num = line_num % 4; 106629b103c7SStefan Roese if (info->pex_mode[pex_unit] == 106729b103c7SStefan Roese PEX_BUS_DISABLED) 106829b103c7SStefan Roese break; 106929b103c7SStefan Roese if ((info->pex_mode[pex_unit] == 107029b103c7SStefan Roese PEX_BUS_MODE_X4) && pex_line_num) 107129b103c7SStefan Roese break; 107229b103c7SStefan Roese 107329b103c7SStefan Roese if (bus_speed) { 107429b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG 107529b103c7SStefan Roese (pex_unit), 107629b103c7SStefan Roese (pex_line_num << 24) | 107729b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 107829b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG 107929b103c7SStefan Roese (pex_unit), 108029b103c7SStefan Roese (pex_line_num << 108129b103c7SStefan Roese 24) | 108229b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 108329b103c7SStefan Roese } else { 108429b103c7SStefan Roese reg_write(PEX_PHY_ACCESS_REG 108529b103c7SStefan Roese (pex_unit), 108629b103c7SStefan Roese (pex_line_num << 24) | 108729b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 108829b103c7SStefan Roese DEBUG_WR_REG(PEX_PHY_ACCESS_REG 108929b103c7SStefan Roese (pex_unit), 109029b103c7SStefan Roese (pex_line_num << 109129b103c7SStefan Roese 24) | 109229b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 109329b103c7SStefan Roese } 109429b103c7SStefan Roese break; 109529b103c7SStefan Roese case SERDES_UNIT_SATA: 109629b103c7SStefan Roese if (line_cfg != SERDES_UNIT_SATA) 109729b103c7SStefan Roese break; 109829b103c7SStefan Roese /* 109929b103c7SStefan Roese * Port 0 for serdes lines 4,6, and 110029b103c7SStefan Roese * port 1 for serdes lines 5 110129b103c7SStefan Roese */ 110229b103c7SStefan Roese sata_port = line_num & 1; 110329b103c7SStefan Roese if (bus_speed) { 110429b103c7SStefan Roese reg_write(SATA_BASE_REG 110529b103c7SStefan Roese (sata_port) | 110629b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 110729b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 110829b103c7SStefan Roese DEBUG_WR_REG(SATA_BASE_REG 110929b103c7SStefan Roese (sata_port) | 111029b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 111129b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 111229b103c7SStefan Roese } else { 111329b103c7SStefan Roese reg_write(SATA_BASE_REG 111429b103c7SStefan Roese (sata_port) | 111529b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 111629b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 111729b103c7SStefan Roese DEBUG_WR_REG(SATA_BASE_REG 111829b103c7SStefan Roese (sata_port) | 111929b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 112029b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 112129b103c7SStefan Roese } 112229b103c7SStefan Roese break; 112329b103c7SStefan Roese case SERDES_UNIT_SGMII0: 112429b103c7SStefan Roese case SERDES_UNIT_SGMII1: 112529b103c7SStefan Roese case SERDES_UNIT_SGMII2: 112629b103c7SStefan Roese case SERDES_UNIT_SGMII3: 112729b103c7SStefan Roese if (line_cfg == serdes_cfg[line_num] 112829b103c7SStefan Roese [SERDES_UNIT_SGMII0]) 112929b103c7SStefan Roese sgmii_port = 0; 113029b103c7SStefan Roese else if (line_cfg == 113129b103c7SStefan Roese serdes_cfg[line_num] 113229b103c7SStefan Roese [SERDES_UNIT_SGMII1]) 113329b103c7SStefan Roese sgmii_port = 1; 113429b103c7SStefan Roese else if (line_cfg == 113529b103c7SStefan Roese serdes_cfg[line_num] 113629b103c7SStefan Roese [SERDES_UNIT_SGMII2]) 113729b103c7SStefan Roese sgmii_port = 2; 113829b103c7SStefan Roese else if (line_cfg == 113929b103c7SStefan Roese serdes_cfg[line_num] 114029b103c7SStefan Roese [SERDES_UNIT_SGMII3]) 114129b103c7SStefan Roese sgmii_port = 3; 114229b103c7SStefan Roese else 114329b103c7SStefan Roese break; 114429b103c7SStefan Roese if (bus_speed) { 114529b103c7SStefan Roese reg_write(MV_ETH_REGS_BASE 114629b103c7SStefan Roese (sgmii_port) | 114729b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 114829b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 114929b103c7SStefan Roese DEBUG_WR_REG(MV_ETH_REGS_BASE 115029b103c7SStefan Roese (sgmii_port) | 115129b103c7SStefan Roese serdes_m_phy_change->reg_hi_speed, 115229b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 115329b103c7SStefan Roese } else { 115429b103c7SStefan Roese reg_write(MV_ETH_REGS_BASE 115529b103c7SStefan Roese (sgmii_port) | 115629b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 115729b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 115829b103c7SStefan Roese DEBUG_WR_REG(MV_ETH_REGS_BASE 115929b103c7SStefan Roese (sgmii_port) | 116029b103c7SStefan Roese serdes_m_phy_change->reg_low_speed, 116129b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 116229b103c7SStefan Roese } 116329b103c7SStefan Roese break; 116429b103c7SStefan Roese case SERDES_UNIT_QSGMII: 116529b103c7SStefan Roese if (line_cfg != SERDES_UNIT_QSGMII) 116629b103c7SStefan Roese break; 116729b103c7SStefan Roese if (bus_speed) { 116829b103c7SStefan Roese reg_write 116929b103c7SStefan Roese (serdes_m_phy_change->reg_hi_speed, 117029b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 117129b103c7SStefan Roese DEBUG_WR_REG 117229b103c7SStefan Roese (serdes_m_phy_change->reg_hi_speed, 117329b103c7SStefan Roese serdes_m_phy_change->val_hi_speed); 117429b103c7SStefan Roese } else { 117529b103c7SStefan Roese reg_write 117629b103c7SStefan Roese (serdes_m_phy_change->reg_low_speed, 117729b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 117829b103c7SStefan Roese DEBUG_WR_REG 117929b103c7SStefan Roese (serdes_m_phy_change->reg_low_speed, 118029b103c7SStefan Roese serdes_m_phy_change->val_low_speed); 118129b103c7SStefan Roese } 118229b103c7SStefan Roese break; 118329b103c7SStefan Roese default: 118429b103c7SStefan Roese break; 118529b103c7SStefan Roese } 118629b103c7SStefan Roese serdes_m_phy_change++; 118729b103c7SStefan Roese } 118829b103c7SStefan Roese } 118929b103c7SStefan Roese } 119029b103c7SStefan Roese 119129b103c7SStefan Roese /* Step 16 [PEX-Only] Training Enable */ 119229b103c7SStefan Roese DEBUG_INIT_FULL_S("Steps 16: [PEX-Only] Training Enable"); 119329b103c7SStefan Roese tmp = reg_read(SOC_CTRL_REG); 119429b103c7SStefan Roese DEBUG_RD_REG(SOC_CTRL_REG, tmp); 119529b103c7SStefan Roese tmp &= ~(0x0F); 119629b103c7SStefan Roese for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) { 119729b103c7SStefan Roese reg_write(PEX_CAUSE_REG(pex_unit), 0); 119829b103c7SStefan Roese DEBUG_WR_REG(PEX_CAUSE_REG(pex_unit), 0); 119929b103c7SStefan Roese if (info->pex_mode[pex_unit] != PEX_BUS_DISABLED) 120029b103c7SStefan Roese tmp |= (0x1 << pex_unit); 120129b103c7SStefan Roese } 120229b103c7SStefan Roese reg_write(SOC_CTRL_REG, tmp); 120329b103c7SStefan Roese DEBUG_WR_REG(SOC_CTRL_REG, tmp); 120429b103c7SStefan Roese 120529b103c7SStefan Roese /* Step 17: Speed change to target speed and width */ 120629b103c7SStefan Roese { 120729b103c7SStefan Roese u32 tmp_reg, tmp_pex_reg; 120829b103c7SStefan Roese u32 addr; 120929b103c7SStefan Roese u32 first_busno, next_busno; 121029b103c7SStefan Roese u32 max_link_width = 0; 121129b103c7SStefan Roese u32 neg_link_width = 0; 121229b103c7SStefan Roese pex_if_num = pex_max_if_get(); 121329b103c7SStefan Roese mdelay(150); 121429b103c7SStefan Roese DEBUG_INIT_FULL_C("step 17: max_if= 0x", pex_if_num, 1); 121529b103c7SStefan Roese next_busno = 0; 121629b103c7SStefan Roese for (pex_if = 0; pex_if < pex_if_num; pex_if++) { 121729b103c7SStefan Roese line_num = (pex_if <= 8) ? pex_if : 12; 121829b103c7SStefan Roese line_cfg = get_line_cfg(line_num, info); 121929b103c7SStefan Roese if (line_cfg != serdes_cfg[line_num][SERDES_UNIT_PEX]) 122029b103c7SStefan Roese continue; 122129b103c7SStefan Roese pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3; 122229b103c7SStefan Roese DEBUG_INIT_FULL_S("step 17: PEX"); 122329b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 122429b103c7SStefan Roese DEBUG_INIT_FULL_C(" pex_unit= ", pex_unit, 1); 122529b103c7SStefan Roese 122629b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) { 122729b103c7SStefan Roese DEBUG_INIT_FULL_C("PEX disabled interface ", 122829b103c7SStefan Roese pex_if, 1); 122929b103c7SStefan Roese if (pex_if < 8) 123029b103c7SStefan Roese pex_if += 3; 123129b103c7SStefan Roese continue; 123229b103c7SStefan Roese } 123329b103c7SStefan Roese first_busno = next_busno; 123429b103c7SStefan Roese if ((info->pex_type == MV_PEX_END_POINT) && 123529b103c7SStefan Roese (0 == pex_if)) { 123629b103c7SStefan Roese if ((pex_if < 8) && (info->pex_mode[pex_unit] == 123729b103c7SStefan Roese PEX_BUS_MODE_X4)) 123829b103c7SStefan Roese pex_if += 3; 123929b103c7SStefan Roese continue; 124029b103c7SStefan Roese } 124129b103c7SStefan Roese 124229b103c7SStefan Roese tmp = reg_read(PEX_DBG_STATUS_REG(pex_if)); 124329b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_STATUS_REG(pex_if), tmp); 124429b103c7SStefan Roese if ((tmp & 0x7f) == 0x7e) { 124529b103c7SStefan Roese next_busno++; 124629b103c7SStefan Roese tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if)); 124729b103c7SStefan Roese max_link_width = tmp; 124829b103c7SStefan Roese DEBUG_RD_REG((PEX_LINK_CAPABILITIES_REG 124929b103c7SStefan Roese (pex_if)), tmp); 125029b103c7SStefan Roese max_link_width = ((max_link_width >> 4) & 0x3F); 125129b103c7SStefan Roese neg_link_width = 125229b103c7SStefan Roese reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if)); 125329b103c7SStefan Roese DEBUG_RD_REG((PEX_LINK_CTRL_STATUS_REG(pex_if)), 125429b103c7SStefan Roese neg_link_width); 125529b103c7SStefan Roese neg_link_width = ((neg_link_width >> 20) & 0x3F); 125629b103c7SStefan Roese if (max_link_width > neg_link_width) { 125729b103c7SStefan Roese tmp &= ~(0x3F << 4); 125829b103c7SStefan Roese tmp |= (neg_link_width << 4); 125929b103c7SStefan Roese reg_write(PEX_LINK_CAPABILITIES_REG 126029b103c7SStefan Roese (pex_if), tmp); 126129b103c7SStefan Roese DEBUG_WR_REG((PEX_LINK_CAPABILITIES_REG 126229b103c7SStefan Roese (pex_if)), tmp); 126329b103c7SStefan Roese mdelay(1); /* wait 1ms before reading capability for speed */ 126429b103c7SStefan Roese DEBUG_INIT_S("PEX"); 126529b103c7SStefan Roese DEBUG_INIT_D(pex_if, 1); 126629b103c7SStefan Roese DEBUG_INIT_C(": change width to X", 126729b103c7SStefan Roese neg_link_width, 1); 126829b103c7SStefan Roese } 126929b103c7SStefan Roese tmp_pex_reg = 127029b103c7SStefan Roese reg_read((PEX_CFG_DIRECT_ACCESS 127129b103c7SStefan Roese (pex_if, 127229b103c7SStefan Roese PEX_LINK_CAPABILITY_REG))); 127329b103c7SStefan Roese DEBUG_RD_REG((PEX_CFG_DIRECT_ACCESS 127429b103c7SStefan Roese (pex_if, 127529b103c7SStefan Roese PEX_LINK_CAPABILITY_REG)), 127629b103c7SStefan Roese tmp_pex_reg); 127729b103c7SStefan Roese tmp_pex_reg &= (0xF); 127829b103c7SStefan Roese if (tmp_pex_reg == 0x2) { 127929b103c7SStefan Roese tmp_reg = 128029b103c7SStefan Roese (reg_read 128129b103c7SStefan Roese (PEX_CFG_DIRECT_ACCESS 128229b103c7SStefan Roese (pex_if, 128329b103c7SStefan Roese PEX_LINK_CTRL_STAT_REG)) & 128429b103c7SStefan Roese 0xF0000) >> 16; 128529b103c7SStefan Roese DEBUG_RD_REG(PEX_CFG_DIRECT_ACCESS 128629b103c7SStefan Roese (pex_if, 128729b103c7SStefan Roese PEX_LINK_CTRL_STAT_REG), 128829b103c7SStefan Roese tmp_pex_reg); 128929b103c7SStefan Roese /* check if the link established is GEN1 */ 129029b103c7SStefan Roese if (tmp_reg == 0x1) { 129129b103c7SStefan Roese pex_local_bus_num_set(pex_if, 129229b103c7SStefan Roese first_busno); 129329b103c7SStefan Roese pex_local_dev_num_set(pex_if, 129429b103c7SStefan Roese 1); 129529b103c7SStefan Roese 129629b103c7SStefan Roese DEBUG_INIT_FULL_S("** Link is Gen1, check the EP capability\n"); 129729b103c7SStefan Roese /* link is Gen1, check the EP capability */ 129829b103c7SStefan Roese addr = 129929b103c7SStefan Roese pex_cfg_read(pex_if, 130029b103c7SStefan Roese first_busno, 0, 130129b103c7SStefan Roese 0, 130229b103c7SStefan Roese 0x34) & 0xFF; 130329b103c7SStefan Roese DEBUG_INIT_FULL_C("pex_cfg_read: return addr=0x%x", 130429b103c7SStefan Roese addr, 4); 130529b103c7SStefan Roese if (addr == 0xff) { 130629b103c7SStefan Roese DEBUG_INIT_FULL_C("pex_cfg_read: return 0xff -->PEX (%d): Detected No Link.", 130729b103c7SStefan Roese pex_if, 1); 130829b103c7SStefan Roese continue; 130929b103c7SStefan Roese } 131029b103c7SStefan Roese while ((pex_cfg_read 131129b103c7SStefan Roese (pex_if, first_busno, 0, 131229b103c7SStefan Roese 0, 131329b103c7SStefan Roese addr) & 0xFF) != 131429b103c7SStefan Roese 0x10) { 131529b103c7SStefan Roese addr = 131629b103c7SStefan Roese (pex_cfg_read 131729b103c7SStefan Roese (pex_if, 131829b103c7SStefan Roese first_busno, 0, 0, 131929b103c7SStefan Roese addr) & 0xFF00) >> 132029b103c7SStefan Roese 8; 132129b103c7SStefan Roese } 132229b103c7SStefan Roese if ((pex_cfg_read 132329b103c7SStefan Roese (pex_if, first_busno, 0, 0, 132429b103c7SStefan Roese addr + 0xC) & 0xF) >= 132529b103c7SStefan Roese 0x2) { 132629b103c7SStefan Roese tmp = 132729b103c7SStefan Roese reg_read 132829b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 132929b103c7SStefan Roese (pex_if)); 133029b103c7SStefan Roese DEBUG_RD_REG 133129b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 133229b103c7SStefan Roese (pex_if), tmp); 133329b103c7SStefan Roese tmp &= ~(0x1 | 1 << 1); 133429b103c7SStefan Roese tmp |= (1 << 1); 133529b103c7SStefan Roese reg_write 133629b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 133729b103c7SStefan Roese (pex_if), tmp); 133829b103c7SStefan Roese DEBUG_WR_REG 133929b103c7SStefan Roese (PEX_LINK_CTRL_STATUS2_REG 134029b103c7SStefan Roese (pex_if), tmp); 134129b103c7SStefan Roese 134229b103c7SStefan Roese tmp = 134329b103c7SStefan Roese reg_read 134429b103c7SStefan Roese (PEX_CTRL_REG 134529b103c7SStefan Roese (pex_if)); 134629b103c7SStefan Roese DEBUG_RD_REG 134729b103c7SStefan Roese (PEX_CTRL_REG 134829b103c7SStefan Roese (pex_if), tmp); 134929b103c7SStefan Roese tmp |= (1 << 10); 135029b103c7SStefan Roese reg_write(PEX_CTRL_REG 135129b103c7SStefan Roese (pex_if), 135229b103c7SStefan Roese tmp); 135329b103c7SStefan Roese DEBUG_WR_REG 135429b103c7SStefan Roese (PEX_CTRL_REG 135529b103c7SStefan Roese (pex_if), tmp); 135629b103c7SStefan 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 */ 135729b103c7SStefan Roese DEBUG_INIT_FULL_S 135829b103c7SStefan Roese ("Gen2 client!\n"); 135929b103c7SStefan Roese } else { 136029b103c7SStefan Roese DEBUG_INIT_FULL_S 136129b103c7SStefan Roese ("GEN1 client!\n"); 136229b103c7SStefan Roese } 136329b103c7SStefan Roese } 136429b103c7SStefan Roese } 136529b103c7SStefan Roese } else { 136629b103c7SStefan Roese DEBUG_INIT_FULL_S("PEX"); 136729b103c7SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 136829b103c7SStefan Roese DEBUG_INIT_FULL_S(" : Detected No Link. Status Reg(0x"); 136929b103c7SStefan Roese DEBUG_INIT_FULL_D(PEX_DBG_STATUS_REG(pex_if), 137029b103c7SStefan Roese 8); 137129b103c7SStefan Roese DEBUG_INIT_FULL_C(") = 0x", tmp, 8); 137229b103c7SStefan Roese } 137329b103c7SStefan Roese 137429b103c7SStefan Roese if ((pex_if < 8) && 137529b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 137629b103c7SStefan Roese pex_if += 3; 137729b103c7SStefan Roese } 137829b103c7SStefan Roese } 137929b103c7SStefan Roese 138029b103c7SStefan Roese /* Step 18: update pex DEVICE ID */ 138129b103c7SStefan Roese { 138229b103c7SStefan Roese u32 devId; 138329b103c7SStefan Roese pex_if_num = pex_max_if_get(); 138429b103c7SStefan Roese ctrl_mode = ctrl_model_get(); 138529b103c7SStefan Roese for (pex_if = 0; pex_if < pex_if_num; pex_if++) { 138629b103c7SStefan Roese pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3; 138729b103c7SStefan Roese if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) { 138829b103c7SStefan Roese if ((pex_if < 8) && 138929b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 139029b103c7SStefan Roese pex_if += 3; 139129b103c7SStefan Roese continue; 139229b103c7SStefan Roese } 139329b103c7SStefan Roese 139429b103c7SStefan Roese devId = reg_read(PEX_CFG_DIRECT_ACCESS( 139529b103c7SStefan Roese pex_if, PEX_DEVICE_AND_VENDOR_ID)); 139629b103c7SStefan Roese devId &= 0xFFFF; 139729b103c7SStefan Roese devId |= ((ctrl_mode << 16) & 0xffff0000); 1398e25d5a95SStefan Roese DEBUG_INIT_FULL_S("Update Device ID PEX"); 1399e25d5a95SStefan Roese DEBUG_INIT_FULL_D(pex_if, 1); 1400e25d5a95SStefan Roese DEBUG_INIT_FULL_D(devId, 8); 1401e25d5a95SStefan Roese DEBUG_INIT_FULL_S("\n"); 140229b103c7SStefan Roese reg_write(PEX_CFG_DIRECT_ACCESS 140329b103c7SStefan Roese (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId); 140429b103c7SStefan Roese if ((pex_if < 8) && 140529b103c7SStefan Roese (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) 140629b103c7SStefan Roese pex_if += 3; 140729b103c7SStefan Roese } 1408e25d5a95SStefan Roese DEBUG_INIT_FULL_S("Update PEX Device ID 0x"); 1409e25d5a95SStefan Roese DEBUG_INIT_FULL_D(ctrl_mode, 4); 1410e25d5a95SStefan Roese DEBUG_INIT_FULL_S("0\n"); 141129b103c7SStefan Roese } 141229b103c7SStefan Roese tmp = reg_read(PEX_DBG_STATUS_REG(0)); 141329b103c7SStefan Roese DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp); 141429b103c7SStefan Roese 141529b103c7SStefan Roese DEBUG_INIT_S(ENDED_OK); 141629b103c7SStefan Roese return MV_OK; 141729b103c7SStefan Roese } 141829b103c7SStefan Roese 141929b103c7SStefan Roese /* PEX configuration space read write */ 142029b103c7SStefan Roese 142129b103c7SStefan Roese /* 142229b103c7SStefan Roese * pex_cfg_read - Read from configuration space 142329b103c7SStefan Roese * 142429b103c7SStefan Roese * DESCRIPTION: 142529b103c7SStefan Roese * This function performs a 32 bit read from PEX configuration space. 142629b103c7SStefan Roese * It supports both type 0 and type 1 of Configuration Transactions 142729b103c7SStefan Roese * (local and over bridge). In order to read from local bus segment, use 142829b103c7SStefan Roese * bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers 142929b103c7SStefan Roese * will result configuration transaction of type 1 (over bridge). 143029b103c7SStefan Roese * 143129b103c7SStefan Roese * INPUT: 143229b103c7SStefan Roese * pex_if - PEX interface number. 143329b103c7SStefan Roese * bus - PEX segment bus number. 143429b103c7SStefan Roese * dev - PEX device number. 143529b103c7SStefan Roese * func - Function number. 143629b103c7SStefan Roese * offss - Register offset. 143729b103c7SStefan Roese * 143829b103c7SStefan Roese * OUTPUT: 143929b103c7SStefan Roese * None. 144029b103c7SStefan Roese * 144129b103c7SStefan Roese * RETURN: 144229b103c7SStefan Roese * 32bit register data, 0xffffffff on error 144329b103c7SStefan Roese * 144429b103c7SStefan Roese */ 144529b103c7SStefan Roese u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs) 144629b103c7SStefan Roese { 144729b103c7SStefan Roese u32 pex_data = 0; 144829b103c7SStefan Roese u32 local_dev, local_bus; 144929b103c7SStefan Roese u32 val; 145029b103c7SStefan Roese 145129b103c7SStefan Roese if (pex_if >= MV_PEX_MAX_IF) 145229b103c7SStefan Roese return 0xFFFFFFFF; 145329b103c7SStefan Roese 145429b103c7SStefan Roese if (dev >= MAX_PEX_DEVICES) { 145529b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. device number illigal ", dev, 145629b103c7SStefan Roese 1); 145729b103c7SStefan Roese return 0xFFFFFFFF; 145829b103c7SStefan Roese } 145929b103c7SStefan Roese 146029b103c7SStefan Roese if (func >= MAX_PEX_FUNCS) { 146129b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. function num illigal ", func, 146229b103c7SStefan Roese 1); 146329b103c7SStefan Roese return 0xFFFFFFFF; 146429b103c7SStefan Roese } 146529b103c7SStefan Roese 146629b103c7SStefan Roese if (bus >= MAX_PEX_BUSSES) { 146729b103c7SStefan Roese DEBUG_INIT_C("pex_cfg_read: ERR. bus number illigal ", bus, 1); 146829b103c7SStefan Roese return MV_ERROR; 146929b103c7SStefan Roese } 147029b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 147129b103c7SStefan Roese 147229b103c7SStefan Roese local_dev = 147329b103c7SStefan Roese ((val & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS); 147429b103c7SStefan Roese local_bus = 147529b103c7SStefan Roese ((val & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS); 147629b103c7SStefan Roese 147729b103c7SStefan Roese /* Speed up the process. In case on no link, return MV_ERROR */ 147829b103c7SStefan Roese if ((dev != local_dev) || (bus != local_bus)) { 147929b103c7SStefan Roese pex_data = reg_read(PEX_STATUS_REG(pex_if)); 148029b103c7SStefan Roese 148129b103c7SStefan Roese if ((pex_data & PXSR_DL_DOWN)) 148229b103c7SStefan Roese return MV_ERROR; 148329b103c7SStefan Roese } 148429b103c7SStefan Roese 148529b103c7SStefan Roese /* 148629b103c7SStefan Roese * In PCI Express we have only one device number 148729b103c7SStefan Roese * and this number is the first number we encounter else that the 148829b103c7SStefan Roese * local_dev spec pex define return on config read/write on any device 148929b103c7SStefan Roese */ 149029b103c7SStefan Roese if (bus == local_bus) { 149129b103c7SStefan Roese if (local_dev == 0) { 149229b103c7SStefan Roese /* 149329b103c7SStefan Roese * If local dev is 0 then the first number we encounter 149429b103c7SStefan Roese * after 0 is 1 149529b103c7SStefan Roese */ 149629b103c7SStefan Roese if ((dev != 1) && (dev != local_dev)) 149729b103c7SStefan Roese return MV_ERROR; 149829b103c7SStefan Roese } else { 149929b103c7SStefan Roese /* 150029b103c7SStefan Roese * If local dev is not 0 then the first number we 150129b103c7SStefan Roese * encounter is 0 150229b103c7SStefan Roese */ 150329b103c7SStefan Roese if ((dev != 0) && (dev != local_dev)) 150429b103c7SStefan Roese return MV_ERROR; 150529b103c7SStefan Roese } 150629b103c7SStefan Roese } 150729b103c7SStefan Roese 150829b103c7SStefan Roese /* Creating PEX address to be passed */ 150929b103c7SStefan Roese pex_data = (bus << PXCAR_BUS_NUM_OFFS); 151029b103c7SStefan Roese pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS); 151129b103c7SStefan Roese pex_data |= (func << PXCAR_FUNC_NUM_OFFS); 151229b103c7SStefan Roese pex_data |= (offs & PXCAR_REG_NUM_MASK); /* lgacy register space */ 151329b103c7SStefan Roese /* extended register space */ 151429b103c7SStefan Roese pex_data |= (((offs & PXCAR_REAL_EXT_REG_NUM_MASK) >> 151529b103c7SStefan Roese PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); 151629b103c7SStefan Roese 151729b103c7SStefan Roese pex_data |= PXCAR_CONFIG_EN; 151829b103c7SStefan Roese 151929b103c7SStefan Roese /* Write the address to the PEX configuration address register */ 152029b103c7SStefan Roese reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data); 152129b103c7SStefan Roese 152229b103c7SStefan Roese /* 152329b103c7SStefan Roese * In order to let the PEX controller absorbed the address of the read 152429b103c7SStefan Roese * transaction we perform a validity check that the address was written 152529b103c7SStefan Roese */ 152629b103c7SStefan Roese if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if))) 152729b103c7SStefan Roese return MV_ERROR; 152829b103c7SStefan Roese 152929b103c7SStefan Roese /* cleaning Master Abort */ 153029b103c7SStefan Roese reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND), 153129b103c7SStefan Roese PXSAC_MABORT); 153229b103c7SStefan Roese /* Read the Data returned in the PEX Data register */ 153329b103c7SStefan Roese pex_data = reg_read(PEX_CFG_DATA_REG(pex_if)); 153429b103c7SStefan Roese 153529b103c7SStefan Roese DEBUG_INIT_FULL_C(" --> ", pex_data, 4); 153629b103c7SStefan Roese 153729b103c7SStefan Roese return pex_data; 153829b103c7SStefan Roese } 153929b103c7SStefan Roese 154029b103c7SStefan Roese /* 154129b103c7SStefan Roese * pex_local_bus_num_set - Set PEX interface local bus number. 154229b103c7SStefan Roese * 154329b103c7SStefan Roese * DESCRIPTION: 154429b103c7SStefan Roese * This function sets given PEX interface its local bus number. 154529b103c7SStefan Roese * Note: In case the PEX interface is PEX-X, the information is read-only. 154629b103c7SStefan Roese * 154729b103c7SStefan Roese * INPUT: 154829b103c7SStefan Roese * pex_if - PEX interface number. 154929b103c7SStefan Roese * bus_num - Bus number. 155029b103c7SStefan Roese * 155129b103c7SStefan Roese * OUTPUT: 155229b103c7SStefan Roese * None. 155329b103c7SStefan Roese * 155429b103c7SStefan Roese * RETURN: 155529b103c7SStefan Roese * MV_NOT_ALLOWED in case PEX interface is PEX-X. 155629b103c7SStefan Roese * MV_BAD_PARAM on bad parameters , 155729b103c7SStefan Roese * otherwise MV_OK 155829b103c7SStefan Roese * 155929b103c7SStefan Roese */ 156029b103c7SStefan Roese int pex_local_bus_num_set(u32 pex_if, u32 bus_num) 156129b103c7SStefan Roese { 156229b103c7SStefan Roese u32 val; 156329b103c7SStefan Roese 156429b103c7SStefan Roese if (bus_num >= MAX_PEX_BUSSES) { 156529b103c7SStefan Roese DEBUG_INIT_C("pex_local_bus_num_set: ERR. bus number illigal %d\n", 156629b103c7SStefan Roese bus_num, 4); 156729b103c7SStefan Roese return MV_ERROR; 156829b103c7SStefan Roese } 156929b103c7SStefan Roese 157029b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 157129b103c7SStefan Roese val &= ~PXSR_PEX_BUS_NUM_MASK; 157229b103c7SStefan Roese val |= (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK; 157329b103c7SStefan Roese reg_write(PEX_STATUS_REG(pex_if), val); 157429b103c7SStefan Roese 157529b103c7SStefan Roese return MV_OK; 157629b103c7SStefan Roese } 157729b103c7SStefan Roese 157829b103c7SStefan Roese /* 157929b103c7SStefan Roese * pex_local_dev_num_set - Set PEX interface local device number. 158029b103c7SStefan Roese * 158129b103c7SStefan Roese * DESCRIPTION: 158229b103c7SStefan Roese * This function sets given PEX interface its local device number. 158329b103c7SStefan Roese * Note: In case the PEX interface is PEX-X, the information is read-only. 158429b103c7SStefan Roese * 158529b103c7SStefan Roese * INPUT: 158629b103c7SStefan Roese * pex_if - PEX interface number. 158729b103c7SStefan Roese * dev_num - Device number. 158829b103c7SStefan Roese * 158929b103c7SStefan Roese * OUTPUT: 159029b103c7SStefan Roese * None. 159129b103c7SStefan Roese * 159229b103c7SStefan Roese * RETURN: 159329b103c7SStefan Roese * MV_NOT_ALLOWED in case PEX interface is PEX-X. 159429b103c7SStefan Roese * MV_BAD_PARAM on bad parameters , 159529b103c7SStefan Roese * otherwise MV_OK 159629b103c7SStefan Roese * 159729b103c7SStefan Roese */ 159829b103c7SStefan Roese int pex_local_dev_num_set(u32 pex_if, u32 dev_num) 159929b103c7SStefan Roese { 160029b103c7SStefan Roese u32 val; 160129b103c7SStefan Roese 160229b103c7SStefan Roese if (pex_if >= MV_PEX_MAX_IF) 160329b103c7SStefan Roese return MV_BAD_PARAM; 160429b103c7SStefan Roese 160529b103c7SStefan Roese val = reg_read(PEX_STATUS_REG(pex_if)); 160629b103c7SStefan Roese val &= ~PXSR_PEX_DEV_NUM_MASK; 160729b103c7SStefan Roese val |= (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK; 160829b103c7SStefan Roese reg_write(PEX_STATUS_REG(pex_if), val); 160929b103c7SStefan Roese 161029b103c7SStefan Roese return MV_OK; 161129b103c7SStefan Roese } 1612