From b24bb99df10542bd4ec3cfa310e28b4544fbc847 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Sun, 18 Oct 2020 17:11:11 +0300 Subject: [PATCH 1/9] phy: marvell: cp110: let the firmware configure the comphy Replace all comphy initialization with appropriate smc calls. It will result with triggering synchronous exception that is handled by Secure Monitor code in EL3. Then the Secure Monitor code will dispatch each smc call (by parsing the smc function identifier) and triggers appropriate comphy initialization. This patch reworks serdes handling for: SATA, SGMII, HS-SGMII and SFI interfaces. Signed-off-by: Grzegorz Jaszczyk Reviewed-by: Igal Liberman Signed-off-by: Baruch Siach --- drivers/phy/marvell/comphy_cp110.c | 816 ++++------------------------- 1 file changed, 89 insertions(+), 727 deletions(-) diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 15e80049de..31baa0bb37 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,32 @@ DECLARE_GLOBAL_DATA_PTR; #define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) #define COMPHY_ADDR(base, lane) (base + 0x28 * lane) +/* Firmware related definitions used for SMC calls */ +#define MV_SIP_COMPHY_POWER_ON 0x82000001 +#define MV_SIP_COMPHY_POWER_OFF 0x82000002 +#define MV_SIP_COMPHY_PLL_LOCK 0x82000003 + +#define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) +#define COMPHY_FW_FORMAT(mode, idx, speeds) \ + (((mode) << 12) | ((idx) << 8) | ((speeds) << 2)) +#define COMPHY_SATA_MODE 0x1 +#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ +#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */ +#define COMPHY_USB3H_MODE 0x4 +#define COMPHY_USB3D_MODE 0x5 +#define COMPHY_PCIE_MODE 0x6 +#define COMPHY_RXAUI_MODE 0x7 +#define COMPHY_XFI_MODE 0x8 +#define COMPHY_SFI_MODE 0x9 +#define COMPHY_USB3_MODE 0xa +#define COMPHY_AP_MODE 0xb + +/* Comphy unit index macro */ +#define COMPHY_UNIT_ID0 0 +#define COMPHY_UNIT_ID1 1 +#define COMPHY_UNIT_ID2 2 +#define COMPHY_UNIT_ID3 3 + struct utmi_phy_data { void __iomem *utmi_base_addr; void __iomem *usb_cfg_addr; @@ -642,15 +669,31 @@ static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, return ret; } +static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr, + u32 lane, u32 mode) +{ + struct pt_regs pregs = {0}; + + pregs.regs[0] = function_id; + pregs.regs[1] = (unsigned long)comphy_base_addr; + pregs.regs[2] = lane; + pregs.regs[3] = mode; + + smc_call(&pregs); + + /* + * TODO: Firmware return 0 on success, temporary map it to u-boot + * convention, but after all comphy will be reworked the convention in + * u-boot should be change and this conversion removed + */ + return pregs.regs[0] ? 0 : 1; +} + static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, int cp_index, - u32 invert) + void __iomem *comphy_base_addr, int cp_index, + u32 type) { u32 mask, data, i, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; void __iomem *sata_base = NULL; int sata_node = -1; /* Set to -1 in order to read the first sata node */ @@ -703,255 +746,8 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET; reg_set(sata_base + SATA3_VENDOR_DATA, data, mask); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type); - /* Set select data width 40Bit - SATA mode only */ - reg_set(comphy_addr + COMMON_PHY_CFG6_REG, - 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, - COMMON_PHY_CFG6_IF_40_SEL_MASK); - - /* release from hard reset in SD external */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - debug("stage: Comphy configuration\n"); - /* Start comphy Configuration */ - /* Set reference clock to comes from group 1 - choose 25Mhz */ - reg_set(hpipe_addr + HPIPE_MISC_REG, - 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, - HPIPE_MISC_REFCLK_SEL_MASK); - /* Reference frequency select set 1 (for SATA = 25Mhz) */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - /* PHY mode select (set SATA = 0x0 */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Set max PHY generation setting - 6Gbps */ - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, - 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, - HPIPE_INTERFACE_GEN_MAX_MASK); - /* Set select data width 40Bit (SEL_BITS[2:0]) */ - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, - 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); - - debug("stage: Analog paramters from ETP(HW)\n"); - /* Set analog parameters from ETP(HW) */ - /* G1 settings */ - mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* G2 settings */ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* G3 settings */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET; - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* VDD Calibration Control 3 */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* DFE Resolution Control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* DFE F3-F5 Coefficient Control */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* G3 Setting 3 */ - mask = HPIPE_G3_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G3_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G3_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* G3 Setting 4 */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x2 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Offset Phase Control */ - mask = HPIPE_OS_PH_OFFSET_MASK; - data = 0x5c << HPIPE_OS_PH_OFFSET_OFFSET; - mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK; - data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x1 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x0 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - - /* Set G1 TX amplitude and TX post emphasis value */ - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x8 << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - - /* Set G2 TX amplitude and TX post emphasis value */ - mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK; - data = 0xa << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK; - data |= 0x2 << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask); - - /* Set G3 TX amplitude and TX post emphasis value */ - mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK; - data = 0xe << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK; - data |= 0x6 << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK; - data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask); - - /* SERDES External Configuration 2 register */ - mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - - /* DFE reset sequence */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - - /* Set RX / TX swaps */ - data = mask = 0; - if (invert & PHY_POLARITY_TXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_TXD_SWAP_MASK; - } - if (invert & PHY_POLARITY_RXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_RXD_SWAP_MASK; - } - reg_set(hpipe_addr + HPIPE_SYNC_PATTERN_REG, data, mask); - - /* SW reset for interupt logic */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - - debug("stage: Comphy power up\n"); /* * MAC configuration power up comphy - power up PLL/TX/RX * use indirect address for vendor spesific SATA control register @@ -981,469 +777,7 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, reg_set(sata_base + SATA3_VENDOR_DATA, 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK); - debug("stage: Check PLL\n"); - - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & - SD_EXTERNAL_STATUS0_PLL_RX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)); - ret = 0; - } - - debug_exit(); - return ret; -} - -static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed, - void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - if (sgmii_speed == PHY_SPEED_1_25G) { - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } else { - /* 3.125G */ - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_REFCLK_SEL_MASK; - data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Set analog paramters from ETP(HW) - for now use the default datas */ - debug("stage: Analog paramters from ETP(HW)\n"); - - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, - 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, - HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - debug_exit(); - return ret; -} - -static int comphy_sfi_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, u32 speed) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_ICP_FORCE_MASK; - data = (speed == PHY_SPEED_5_15625G) ? - (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) : - (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET); - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Transmitter/Receiver Speed Divider Force */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK; - data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET; - } else { - mask = HPIPE_TXDIGCK_DIV_FORCE_MASK; - data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask); - - /* Set analog paramters from ETP(HW) */ - debug("stage: Analog paramters from ETP(HW)\n"); - /* SERDES External Configuration 2 */ - mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - /* 0x7-DFE Resolution control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - /* 0xd-G1_Setting_0 */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } else { - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - /* Genration 1 setting 2 (G1_Setting_2) */ - mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; - data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; - mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); - /* Transmitter Slew Rate Control register (tx_reg1) */ - mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; - data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; - mask |= HPIPE_TX_REG1_SLC_EN_MASK; - data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); - /* Impedance Calibration Control register (cal_reg1) */ - mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; - data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; - data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); - /* Generation 1 Setting 5 (g1_setting_5) */ - mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; - data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); - /* 0xE-G1_Setting_1 */ - mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; - data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - } else { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - /* 0xA-DFE_Reg3 */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* 0x111-G1_Setting_4 */ - mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); - /* Genration 1 setting 3 (G1_Setting_3) */ - mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - /* Force FFE (Feed Forward Equalization) to 5G */ - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* Connfigure RX training timer */ - mask = HPIPE_RX_TRAIN_TIMER_MASK; - data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable TX train peak to peak hold */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure TX preset index */ - mask = HPIPE_TX_PRESET_INDEX_MASK; - data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask); - - /* Disable pattern lock lost timeout */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure TX training pattern and TX training 16bit auto */ - mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET; - mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - /* Configure Training patten number */ - mask = HPIPE_TRAIN_PAT_NUM_MASK; - data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask); - - /* Configure differencial manchester encoter to ethernet mode */ - mask = HPIPE_DME_ETHERNET_MODE_MASK; - data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_DME_REG, data, mask); - - /* Configure VDD Continuous Calibration */ - mask = HPIPE_CAL_VDD_CONT_MODE_MASK; - data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK; - data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET; - mask |= HPIPE_SMAPLER_MASK; - data |= 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* Set External RX Regulator Control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type); debug_exit(); return ret; @@ -1973,6 +1307,7 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, void __iomem *comphy_base_addr, *hpipe_base_addr; u32 comphy_max_count, lane, ret = 0; u32 pcie_width = 0; + u32 mode; debug_enter(); @@ -2020,10 +1355,11 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, case PHY_TYPE_SATA1: case PHY_TYPE_SATA2: case PHY_TYPE_SATA3: - ret = comphy_sata_power_up( - lane, hpipe_base_addr, comphy_base_addr, - ptr_chip_cfg->cp_index, - serdes_map[lane].invert); + mode = COMPHY_FW_MODE_FORMAT(COMPHY_SATA_MODE); + ret = comphy_sata_power_up(lane, hpipe_base_addr, + comphy_base_addr, + ptr_chip_cfg->cp_index, + mode); break; case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_HOST1: @@ -2033,6 +1369,25 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, break; case PHY_TYPE_SGMII0: case PHY_TYPE_SGMII1: + if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { + debug("Warning: "); + debug("SGMII PHY speed in lane %d is invalid,", + lane); + debug(" set PHY speed to 1.25G\n"); + ptr_comphy_map->speed = PHY_SPEED_1_25G; + } + + /* + * UINIT_ID not relevant for SGMII0 and SGMII1 - will be + * ignored by firmware + */ + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); + break; case PHY_TYPE_SGMII2: case PHY_TYPE_SGMII3: if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { @@ -2040,14 +1395,21 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, lane); ptr_comphy_map->speed = PHY_SPEED_1_25G; } - ret = comphy_sgmii_power_up( - lane, ptr_comphy_map->speed, hpipe_base_addr, - comphy_base_addr); + + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID2, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SFI: - ret = comphy_sfi_power_up(lane, hpipe_base_addr, - comphy_base_addr, - ptr_comphy_map->speed); + mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_RXAUI0: case PHY_TYPE_RXAUI1: From 0a1a1642aa6674777b8a3ea593c915d742a47dc4 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Sun, 18 Oct 2020 17:11:12 +0300 Subject: [PATCH 2/9] phy: marvell: cp110: let the firmware configure comphy for PCIe Replace the comphy initialization for PCIe with appropriate SMC call, so the firmware will perform appropriate comphy initialization. Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Ken Ma Reviewed-by: Igal Liberman Signed-off-by: Baruch Siach --- drivers/phy/marvell/comphy_cp110.c | 451 +---------------------------- 1 file changed, 12 insertions(+), 439 deletions(-) diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 31baa0bb37..5b6aaa6248 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -31,6 +31,11 @@ DECLARE_GLOBAL_DATA_PTR; #define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) #define COMPHY_FW_FORMAT(mode, idx, speeds) \ (((mode) << 12) | ((idx) << 8) | ((speeds) << 2)) + +#define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \ + (((pcie_width) << 18) | ((clk_src) << 17) | \ + COMPHY_FW_FORMAT(mode, 0, speeds)) + #define COMPHY_SATA_MODE 0x1 #define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ #define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */ @@ -112,441 +117,6 @@ static u32 polling_with_timeout(void __iomem *addr, u32 val, return 0; } -static int comphy_pcie_power_up(u32 lane, u32 pcie_width, bool clk_src, - bool is_end_point, void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - u32 pcie_clk = 0; /* set input by default */ - - debug_enter(); - - /* - * ToDo: - * Add SAR (Sample-At-Reset) configuration for the PCIe clock - * direction. SAR code is currently not ported from Marvell - * U-Boot to mainline version. - * - * SerDes Lane 4/5 got the PCIe ref-clock #1, - * and SerDes Lane 0 got PCIe ref-clock #0 - */ - debug("PCIe clock = %x\n", pcie_clk); - debug("PCIe RC = %d\n", !is_end_point); - debug("PCIe width = %d\n", pcie_width); - - /* enable PCIe by4 and by2 */ - if (lane == 0) { - if (pcie_width == 4) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK); - } else if (pcie_width == 2) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK); - } - } - - /* - * If PCIe clock is output and clock source from SerDes lane 5, - * we need to configure the clock-source MUX. - * By default, the clock source is from lane 4 - */ - if (pcie_clk && clk_src && (lane == 5)) { - reg_set((void __iomem *)DFX_DEV_GEN_CTRL12, - 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET, - DFX_DEV_GEN_PCIE_CLK_SRC_MASK); - } - - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - mask |= COMMON_PHY_PHY_MODE_MASK; - data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* release from hard reset */ - mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* Set PIPE soft reset */ - mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; - data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; - /* Set PHY datapath width mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; - data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; - /* Set Data bus width USB mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; - /* Set CORE_CLK output frequency for 250Mhz */ - mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); - /* Set PLL ready delay for 0x2 */ - data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; - mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; - if (pcie_width != 1) { - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); - - /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ - data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; - mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; - if (pcie_width != 1) { - mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; - if (lane == 0) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; - } else if (lane == (pcie_width - 1)) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; - } - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); - /* Config update polarity equalization */ - reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, - 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET, - HPIPE_CFG_UPDATE_POLARITY_MASK); - /* Set PIPE version 4 to mode enable */ - reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, - 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET, - HPIPE_DFE_CTRL_28_PIPE4_MASK); - /* TODO: check if pcie clock is output/input - for bringup use input*/ - /* Enable PIN clock 100M_125M */ - mask = 0; - data = 0; - /* Only if clock is output, configure the clock-source mux */ - if (pcie_clk) { - mask |= HPIPE_MISC_CLK100M_125M_MASK; - data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; - } - /* - * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz - * clock - */ - mask |= HPIPE_MISC_TXDCLK_2X_MASK; - data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; - /* Enable 500MHz Clock */ - mask |= HPIPE_MISC_CLK500_EN_MASK; - data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; - if (pcie_clk) { /* output */ - /* Set reference clock comes from group 1 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } else { - /* Set reference clock comes from group 2 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } - mask |= HPIPE_MISC_ICP_FORCE_MASK; - data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - if (pcie_clk) { /* output */ - /* Set reference frequcency select - 0x2 for 25MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } else { - /* Set reference frequcency select - 0x0 for 100MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } - /* Set PHY mode to PCIe */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - - /* ref clock alignment */ - if (pcie_width != 1) { - mask = HPIPE_LANE_ALIGN_OFF_MASK; - data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); - } - - /* - * Set the amount of time spent in the LoZ state - set for 0x7 only if - * the PCIe clock is output - */ - if (pcie_clk) { - reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, - 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, - HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); - } - - /* Set Maximal PHY Generation Setting(8Gbps) */ - mask = HPIPE_INTERFACE_GEN_MAX_MASK; - data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; - /* Bypass frame detection and sync detection for RX DATA */ - mask = HPIPE_INTERFACE_DET_BYPASS_MASK; - data = 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET; - /* Set Link Train Mode (Tx training control pins are used) */ - mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; - data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); - - /* Set Idle_sync enable */ - mask = HPIPE_PCIE_IDLE_SYNC_MASK; - data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; - /* Select bits for PCIE Gen3(32bit) */ - mask |= HPIPE_PCIE_SEL_BITS_MASK; - data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; - reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); - - /* Enable Tx_adapt_g1 */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; - data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; - /* Enable Tx_adapt_gn1 */ - mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; - /* Disable Tx_adapt_g0 */ - mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Set reg_tx_train_chk_init */ - mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; - data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; - /* Enable TX_COE_FM_PIN_PCIE3_EN */ - mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - debug("stage: TRx training parameters\n"); - /* Set Preset sweep configurations */ - mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; - data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; - - mask |= HPIPE_TX_NUM_OF_PRESET_MASK; - data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; - - mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; - data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); - - /* Tx train start configuration */ - mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable Tx train P2P */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure Tx train timeout */ - mask = HPIPE_TRX_TRAIN_TIMER_MASK; - data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); - - /* Disable G0/G1/GN1 adaptation */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK - | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - data = 0; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Disable DTL frequency loop */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Configure G3 DFE */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Use TX/RX training result for DFE */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* Configure initial and final coefficient value for receiver */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* Trigger sampler enable pulse */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - udelay(5); - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); - - /* FFE resistor tuning for different bandwidth */ - mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* Pattern lock lost timeout disable */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure DFE adaptations */ - mask = HPIPE_CDR_MAX_DFE_ADAPT_1_MASK; - data = 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET; - mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK; - data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET; - mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK; - data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET; - reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); - mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK; - data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask); - - /* Genration 2 setting 1*/ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* DFE enable */ - mask = HPIPE_G2_DFE_RES_MASK; - data = 0x3 << HPIPE_G2_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask); - - /* Configure DFE Resolution */ - mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK; - data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); - - /* VDD calibration control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* Set PLL Charge-pump Current Control */ - mask = HPIPE_G3_SETTING_5_G3_ICP_MASK; - data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask); - - /* Set lane rqualization remote setting */ - mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK; - data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET; - mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK; - data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET; - mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK; - data |= 0x2 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask); - - if (!is_end_point) { - /* Set phy in root complex mode */ - mask = HPIPE_CFG_PHY_RC_EP_MASK; - data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask); - } - - debug("stage: Comphy power up\n"); - - /* - * For PCIe by4 or by2 - release from reset only after finish to - * configure all lanes - */ - if ((pcie_width == 1) || (lane == (pcie_width - 1))) { - u32 i, start_lane, end_lane; - - if (pcie_width != 1) { - /* allows writing to all lanes in one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x0 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - start_lane = 0; - end_lane = pcie_width; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - can't use read modify write - */ - reg_set(HPIPE_ADDR(hpipe_base, 0) + - HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); - } else { - start_lane = lane; - end_lane = lane + 1; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - */ - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, - 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, - HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); - } - - - if (pcie_width != 1) { - /* disable writing to all lanes with one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x3210 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - } - - debug("stage: Check PLL\n"); - /* Read lane status */ - for (i = start_lane; i < end_lane; i++) { - addr = HPIPE_ADDR(hpipe_base, i) + - HPIPE_LANE_STATUS1_REG; - data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, - data); - pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); - ret = 0; - } - } - } - - debug_exit(); - return ret; -} - static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, void __iomem *comphy_base) { @@ -1346,10 +916,13 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, case PHY_TYPE_PEX1: case PHY_TYPE_PEX2: case PHY_TYPE_PEX3: - ret = comphy_pcie_power_up( - lane, pcie_width, ptr_comphy_map->clk_src, - serdes_map->end_point, - hpipe_base_addr, comphy_base_addr); + mode = COMPHY_FW_PCIE_FORMAT(pcie_width, + ptr_comphy_map->clk_src, + COMPHY_PCIE_MODE, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SATA0: case PHY_TYPE_SATA1: From 3261f6d390f84f38e504eeed9cd2453df932ef24 Mon Sep 17 00:00:00 2001 From: Igal Liberman Date: Sun, 18 Oct 2020 17:11:13 +0300 Subject: [PATCH 3/9] phy: marvell: cp110: update mode parameter for pcie power on calls It helps ATF to determine who called power on function (U-boot/Linux). The corresponding ATF code was added in this commit: mvebu: cp110: avoid pcie power on/off sequence when called from Linux https://github.com/ARM-software/arm-trusted-firmware/commit/55df84f974ea37abbb4f93f000f101f70cda5303 Signed-off-by: Igal Liberman Reviewed-by: Grzegorz Jaszczyk Signed-off-by: Baruch Siach --- drivers/phy/marvell/comphy_cp110.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 5b6aaa6248..b0fcb13f1c 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -28,13 +28,16 @@ DECLARE_GLOBAL_DATA_PTR; #define MV_SIP_COMPHY_POWER_OFF 0x82000002 #define MV_SIP_COMPHY_PLL_LOCK 0x82000003 +/* Used to distinguish between different possible callers (U-boot/Linux) */ +#define COMPHY_CALLER_UBOOT (0x1 << 21) + #define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) #define COMPHY_FW_FORMAT(mode, idx, speeds) \ (((mode) << 12) | ((idx) << 8) | ((speeds) << 2)) #define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \ - (((pcie_width) << 18) | ((clk_src) << 17) | \ - COMPHY_FW_FORMAT(mode, 0, speeds)) + (COMPHY_CALLER_UBOOT | ((pcie_width) << 18) | \ + ((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds)) #define COMPHY_SATA_MODE 0x1 #define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ From ccb350491f105919d0b3ff8baca6a64734e3fece Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 19 Oct 2020 08:02:12 +0200 Subject: [PATCH 4/9] arm: octeontx: Enable network support in supported boards Enable the now included network drivers in the currently supported Marvell Octeon TX & TX2 boards. Signed-off-by: Stefan Roese Cc: Aaron Williams Cc: Suneel Garapati Cc: Chandrakala Chavva --- configs/octeontx2_95xx_defconfig | 2 ++ configs/octeontx2_96xx_defconfig | 2 ++ configs/octeontx_81xx_defconfig | 2 ++ configs/octeontx_83xx_defconfig | 2 ++ 4 files changed, 8 insertions(+) diff --git a/configs/octeontx2_95xx_defconfig b/configs/octeontx2_95xx_defconfig index e37c83742b..591caa7a0d 100644 --- a/configs/octeontx2_95xx_defconfig +++ b/configs/octeontx2_95xx_defconfig @@ -86,6 +86,8 @@ CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y +CONFIG_NET_OCTEONTX2=y +CONFIG_OCTEONTX_SMI=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y diff --git a/configs/octeontx2_96xx_defconfig b/configs/octeontx2_96xx_defconfig index 403ea5121d..0a8888ad0b 100644 --- a/configs/octeontx2_96xx_defconfig +++ b/configs/octeontx2_96xx_defconfig @@ -99,6 +99,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX2=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y diff --git a/configs/octeontx_81xx_defconfig b/configs/octeontx_81xx_defconfig index 78efcf5533..c006a14bdc 100644 --- a/configs/octeontx_81xx_defconfig +++ b/configs/octeontx_81xx_defconfig @@ -100,6 +100,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y diff --git a/configs/octeontx_83xx_defconfig b/configs/octeontx_83xx_defconfig index f5b052871c..86b4bc5190 100644 --- a/configs/octeontx_83xx_defconfig +++ b/configs/octeontx_83xx_defconfig @@ -97,6 +97,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y From e2eafaa18a8834a39251c2edaebd99dc10a2c018 Mon Sep 17 00:00:00 2001 From: Shmuel Hazan Date: Thu, 29 Oct 2020 08:52:16 +0200 Subject: [PATCH 5/9] arm: dts: armada-cp110-slave: add missing cps_nand Align node properties to kernel dts node. Keep U-Boot specific nand-enable-arbiter, and num-cs for compatibility with the current driver. Reviewed-by: Stefan Roese Signed-off-by: Shmuel Hazan Signed-off-by: Baruch Siach --- arch/arm/dts/armada-cp110-slave.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi index b426a4eb69..6cf2177837 100644 --- a/arch/arm/dts/armada-cp110-slave.dtsi +++ b/arch/arm/dts/armada-cp110-slave.dtsi @@ -267,6 +267,22 @@ utmi-port = ; status = "disabled"; }; + + cps_nand: nand@720000 { + compatible = "marvell,armada-8k-nand-controller", + "marvell,armada370-nand-controller"; + reg = <0x720000 0x54>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clock-names = "core", "reg"; + clocks = <&cps_syscon0 1 2>, + <&cps_syscon0 1 17>; + marvell,system-controller = <&cps_syscon0>; + nand-enable-arbiter; + num-cs = <1>; + status = "disabled"; + }; }; cps_pcie0: pcie@f4600000 { From a941226e0060ad207f26ea9203ac6da27febaa62 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 29 Oct 2020 08:52:17 +0200 Subject: [PATCH 6/9] arm: dts: armada-cp110-master: update nand-controller Align node properties to kernel dts node. The change of compatible property does not affect any currently supported board. Keep U-Boot specific nand-enable-arbiter, and num-cs for compatibility with the current driver. Reviewed-by: Stefan Roese Signed-off-by: Baruch Siach --- arch/arm/dts/armada-cp110-master.dtsi | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index cd5c974482..7d0d31da30 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -285,15 +285,18 @@ }; cpm_nand: nand@720000 { - compatible = "marvell,mvebu-pxa3xx-nand"; - reg = <0x720000 0x100>; + compatible = "marvell,armada-8k-nand-controller", + "marvell,armada370-nand-controller"; + reg = <0x720000 0x54>; #address-cells = <1>; - - clocks = <&cpm_syscon0 1 2>; + #size-cells = <0>; + interrupts = ; + clock-names = "core", "reg"; + clocks = <&cpm_syscon0 1 2>, + <&cpm_syscon0 1 17>; + marvell,system-controller = <&cpm_syscon0>; nand-enable-arbiter; num-cs = <1>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; status = "disabled"; }; From 8dddfff4d83e4e29bb6d0eafa348b7b5f6c0e31b Mon Sep 17 00:00:00 2001 From: Shmuel Hazan Date: Thu, 29 Oct 2020 08:52:18 +0200 Subject: [PATCH 7/9] mtd: pxa3xx_nand: port to use driver model Use the generic DT code to find the device compatible property for us. This makes the driver look more like other current drivers. It also make it easier to add support for other variants like Armada 8K in a future commit. Signed-off-by: Shmuel Hazan Signed-off-by: Baruch Siach --- drivers/mtd/nand/raw/Kconfig | 1 + drivers/mtd/nand/raw/pxa3xx_nand.c | 116 +++++++++++++---------------- 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index cd7e598aa8..160b599b34 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -195,6 +195,7 @@ endif config NAND_PXA3XX bool "Support for NAND on PXA3xx and Armada 370/XP/38x" select SYS_NAND_SELF_INIT + select DM_MTD imply CMD_NAND help This enables the driver for the NAND flash device found on diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 5fb3081c83..c9b7a4251b 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "pxa3xx_nand.h" @@ -417,6 +419,14 @@ static struct nand_ecclayout ecc_layout_8KB_bch8bit = { /* convert nano-seconds to nand flash controller clock cycles */ #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) +static const struct udevice_id pxa3xx_nand_dt_ids[] = { + { + .compatible = "marvell,mvebu-pxa3xx-nand", + .data = PXA3XX_NAND_VARIANT_ARMADA370, + }, + {} +}; + static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void) { /* We only support the Armada 370/XP/38x for now */ @@ -1809,74 +1819,52 @@ fail_disable_clk: return ret; } -static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; - const void *blob = gd->fdt_blob; - int node = -1; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - /* Get address decoding nodes from the FDT blob */ - do { - node = fdt_node_offset_by_compatible(blob, node, - "marvell,mvebu-pxa3xx-nand"); - if (node < 0) - break; + info->mmio_base = dev_read_addr_ptr(dev); - /* Bypass disabeld nodes */ - if (!fdtdec_get_is_enabled(blob, node)) - continue; + pdata->num_cs = dev_read_u32_default(dev, "num-cs", 1); + if (pdata->num_cs != 1) { + pr_err("pxa3xx driver supports single CS only\n"); + return -EINVAL; + } - /* Get the first enabled NAND controler base address */ - info->mmio_base = - (void __iomem *)fdtdec_get_addr_size_auto_noparent( - blob, node, "reg", 0, NULL, true); + if (dev_read_bool(dev, "nand-enable-arbiter")) + pdata->enable_arbiter = 1; - pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1); - if (pdata->num_cs != 1) { - pr_err("pxa3xx driver supports single CS only\n"); - break; - } + if (dev_read_bool(dev, "nand-keep-config")) + pdata->keep_config = 1; - if (fdtdec_get_bool(blob, node, "nand-enable-arbiter")) - pdata->enable_arbiter = 1; + /* + * ECC parameters. + * If these are not set, they will be selected according + * to the detected flash type. + */ + /* ECC strength */ + pdata->ecc_strength = dev_read_u32_default(dev, "nand-ecc-strength", 0); - if (fdtdec_get_bool(blob, node, "nand-keep-config")) - pdata->keep_config = 1; + /* ECC step size */ + pdata->ecc_step_size = dev_read_u32_default(dev, "nand-ecc-step-size", + 0); - /* - * ECC parameters. - * If these are not set, they will be selected according - * to the detected flash type. - */ - /* ECC strength */ - pdata->ecc_strength = fdtdec_get_int(blob, node, - "nand-ecc-strength", 0); + info->pdata = pdata; - /* ECC step size */ - pdata->ecc_step_size = fdtdec_get_int(blob, node, - "nand-ecc-step-size", 0); - - info->pdata = pdata; - - /* Currently support only a single NAND controller */ - return 0; - - } while (node >= 0); - - return -EINVAL; + return 0; } -static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe(struct udevice *dev) { - struct mtd_info *mtd = &info->controller.active->mtd; struct pxa3xx_nand_platform_data *pdata; int ret, cs, probe_success; + struct pxa3xx_nand_info *info = dev_get_priv(dev); - ret = pxa3xx_nand_probe_dt(info); + ret = pxa3xx_nand_probe_dt(dev, info); if (ret) return ret; @@ -1884,7 +1872,7 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) ret = alloc_nand_resource(info); if (ret) { - dev_err(mtd->dev, "alloc nand resource failed\n"); + dev_err(dev, "alloc nand resource failed\n"); return ret; } @@ -1918,22 +1906,24 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) return 0; } -/* - * Main initialization routine - */ +U_BOOT_DRIVER(pxa3xx_nand) = { + .name = "pxa3xx-nand", + .id = UCLASS_MTD, + .of_match = pxa3xx_nand_dt_ids, + .probe = pxa3xx_nand_probe, + .priv_auto_alloc_size = sizeof(struct pxa3xx_nand_info) + + sizeof(struct pxa3xx_nand_host) * CONFIG_SYS_MAX_NAND_DEVICE, +}; + void board_nand_init(void) { - struct pxa3xx_nand_info *info; - struct pxa3xx_nand_host *host; + struct udevice *dev; int ret; - info = kzalloc(sizeof(*info) + - sizeof(*host) * CONFIG_SYS_MAX_NAND_DEVICE, - GFP_KERNEL); - if (!info) - return; - - ret = pxa3xx_nand_probe(info); - if (ret) - return; + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(pxa3xx_nand), &dev); + if (ret && ret != -ENODEV) { + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); + } } From 6d1edab44ce261f1500ba20b5587ffa8a6779d39 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 29 Oct 2020 08:52:19 +0200 Subject: [PATCH 8/9] mtd: pxa3xx_nand: remove dead code The kfree() call is unreachable, and is not needed. Remove this call and the fail_disable_clk label. Reviewed-by: Stefan Roese Signed-off-by: Baruch Siach --- drivers/mtd/nand/raw/pxa3xx_nand.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index c9b7a4251b..8481c6e3bf 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -1768,7 +1768,7 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) struct pxa3xx_nand_host *host; struct nand_chip *chip = NULL; struct mtd_info *mtd; - int ret, cs; + int cs; pdata = info->pdata; if (pdata->num_cs <= 0) @@ -1804,19 +1804,13 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) /* Allocate a buffer to allow flash detection */ info->buf_size = INIT_BUFFER_SIZE; info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); - if (info->data_buff == NULL) { - ret = -ENOMEM; - goto fail_disable_clk; - } + if (info->data_buff == NULL) + return -ENOMEM; /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); return 0; - - kfree(info->data_buff); -fail_disable_clk: - return ret; } static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *info) From aaedaaae63921c7edefd0f14ec5f1921a7641454 Mon Sep 17 00:00:00 2001 From: Shmuel Hazan Date: Thu, 29 Oct 2020 08:52:20 +0200 Subject: [PATCH 9/9] mtd: nand: pxa3xx: enable NAND controller if the SoC needs it Based on Linux kernel commit fc256f5789cb ("mtd: nand: pxa3xx: enable NAND controller if the SoC needs it"). This commit adds support for the Armada 8040 nand controller. The kernel commit says this: Marvell recent SoCs like A7k/A8k do not boot with NAND flash controller activated by default. Enabling the controller is a matter of writing in a system controller register that may also be used for other NAND related choices. Reviewed-by: Stefan Roese Signed-off-by: Shmuel Hazan Signed-off-by: Baruch Siach --- drivers/mtd/nand/raw/Kconfig | 2 ++ drivers/mtd/nand/raw/pxa3xx_nand.c | 52 ++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 160b599b34..3cf3b14f05 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -196,6 +196,8 @@ config NAND_PXA3XX bool "Support for NAND on PXA3xx and Armada 370/XP/38x" select SYS_NAND_SELF_INIT select DM_MTD + select REGMAP + select SYSCON imply CMD_NAND help This enables the driver for the NAND flash device found on diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 8481c6e3bf..361a9e3293 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -119,6 +121,10 @@ DECLARE_GLOBAL_DATA_PTR; #define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ #define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ +/* System control register and bit to enable NAND on some SoCs */ +#define GENCONF_SOC_DEVICE_MUX 0x208 +#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0) + /* * This should be large enough to read 'ONFI' and 'JEDEC'. * Let's use 7 bytes, which is the maximum ID count supported @@ -159,6 +165,7 @@ enum { enum pxa3xx_nand_variant { PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_ARMADA370, + PXA3XX_NAND_VARIANT_ARMADA_8K, }; struct pxa3xx_nand_host { @@ -424,13 +431,16 @@ static const struct udevice_id pxa3xx_nand_dt_ids[] = { .compatible = "marvell,mvebu-pxa3xx-nand", .data = PXA3XX_NAND_VARIANT_ARMADA370, }, + { + .compatible = "marvell,armada-8k-nand-controller", + .data = PXA3XX_NAND_VARIANT_ARMADA_8K, + }, {} }; -static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void) +static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(struct udevice *dev) { - /* We only support the Armada 370/XP/38x for now */ - return PXA3XX_NAND_VARIANT_ARMADA370; + return dev_get_driver_data(dev); } static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, @@ -707,7 +717,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) info->retcode = ERR_UNCORERR; if (status & NDSR_CORERR) { info->retcode = ERR_CORERR; - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) && info->ecc_bch) info->ecc_err_cnt = NDSR_ERR_CNT(status); else @@ -762,7 +773,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) nand_writel(info, NDCB0, info->ndcb2); /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDCB0, info->ndcb3); } @@ -1676,7 +1688,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } /* Device detection must be done with ECC disabled */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDECCCTRL, 0x0); if (nand_scan_ident(mtd, 1, NULL)) @@ -1726,7 +1739,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) * (aka split) command handling, */ if (mtd->writesize > info->chunk_size) { - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) { chip->cmdfunc = nand_cmdfunc_extended; } else { dev_err(mtd->dev, @@ -1762,7 +1776,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return nand_scan_tail(mtd); } -static int alloc_nand_resource(struct pxa3xx_nand_info *info) +static int alloc_nand_resource(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_host *host; @@ -1774,7 +1788,7 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) if (pdata->num_cs <= 0) return -ENODEV; - info->variant = pxa3xx_nand_get_variant(); + info->variant = pxa3xx_nand_get_variant(dev); for (cs = 0; cs < pdata->num_cs; cs++) { chip = (struct nand_chip *) ((u8 *)&info[1] + sizeof(*host) * cs); @@ -1810,6 +1824,24 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); + /* + * Some SoCs like A7k/A8k need to enable manually the NAND + * controller to avoid being bootloader dependent. This is done + * through the use of a single bit in the System Functions registers. + */ + if (pxa3xx_nand_get_variant(dev) == PXA3XX_NAND_VARIANT_ARMADA_8K) { + struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle( + dev, "marvell,system-controller"); + u32 reg; + + if (IS_ERR(sysctrl_base)) + return PTR_ERR(sysctrl_base); + + regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, ®); + reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN; + regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); + } + return 0; } @@ -1864,7 +1896,7 @@ static int pxa3xx_nand_probe(struct udevice *dev) pdata = info->pdata; - ret = alloc_nand_resource(info); + ret = alloc_nand_resource(dev, info); if (ret) { dev_err(dev, "alloc nand resource failed\n"); return ret;