From bcb60cb9c42eaef9292c02c60742654a3151883e Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 24 Oct 2014 16:49:02 +0200 Subject: Freescale t104x: Do not exclude SGMII fman_port_enet_if() tests if FM1_DTSEC2 or FM1_DTSEC4 uses RGMII or MII and if not returns PHY_INTERFACE_MODE_NONE. This excludes testing for SGMII further down. Remove the unconditional "else return PHY_INTERFACE_MODE_NONE" so SGMII can be tested too. Signed-off-by: Joakim Tjernlund Reviewed-by: York Sun --- drivers/net/fm/t1040.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/t1040.c b/drivers/net/fm/t1040.c index 4cce46d..d2a097e 100644 --- a/drivers/net/fm/t1040.c +++ b/drivers/net/fm/t1040.c @@ -25,8 +25,6 @@ phy_interface_t fman_port_enet_if(enum fm_port port) else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) return PHY_INTERFACE_MODE_MII; - else - return PHY_INTERFACE_MODE_NONE; } if ((port == FM1_DTSEC4) && @@ -38,8 +36,6 @@ phy_interface_t fman_port_enet_if(enum fm_port port) else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) return PHY_INTERFACE_MODE_MII; - else - return PHY_INTERFACE_MODE_NONE; } if (port == FM1_DTSEC5) { -- cgit v1.1 From 84baed2a2bdde3b2bf876d36cc966bd41ac67a6d Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 7 Nov 2014 12:14:36 -0800 Subject: driver/ddr/fsl: Adjust timing_cfg_0 to better support two DDR slots Increase write-to-write and read-to-read turnaround time for two-slot DDR configurations. Previously only quad-rank and two dual-rank configurations have this additional turnaround time. A recent test on two single-rank DIMMs shows the shorter additional turnaround time is also needed. Signed-off-by: York Sun --- drivers/ddr/fsl/ctrl_regs.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 9e2a4d2..fe8aa98 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -253,22 +253,30 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ #if !defined(CONFIG_SYS_FSL_DDR1) +/* + * Check DIMM configuration, return 2 if quad-rank or two dual-rank + * Return 1 if other two slots configuration. Return 0 if single slot. + */ static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) { #if CONFIG_DIMM_SLOTS_PER_CTLR == 1 if (dimm_params[0].n_ranks == 4) - return 1; + return 2; #endif #if CONFIG_DIMM_SLOTS_PER_CTLR == 2 if ((dimm_params[0].n_ranks == 2) && (dimm_params[1].n_ranks == 2)) - return 1; + return 2; #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE if (dimm_params[0].n_ranks == 4) - return 1; + return 2; #endif + + if ((dimm_params[0].n_ranks != 0) && + (dimm_params[2].n_ranks != 0)) + return 1; #endif return 0; } @@ -316,6 +324,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, #elif defined(CONFIG_SYS_FSL_DDR3) unsigned int data_rate = get_ddr_freq(0); int txp; + int odt_overlap; /* * (tXARD and tXARDS). Empirical? * The DDR3 spec has not tXARD, @@ -331,13 +340,23 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, /* set the turnaround time */ /* - * for single quad-rank DIMM and two dual-rank DIMMs + * for single quad-rank DIMM and two-slot DIMMs * to avoid ODT overlap */ - if (avoid_odt_overlap(dimm_params)) { + odt_overlap = avoid_odt_overlap(dimm_params); + switch (odt_overlap) { + case 2: twwt_mclk = 2; trrt_mclk = 1; + break; + case 1: + twwt_mclk = 1; + trrt_mclk = 0; + break; + default: + break; } + /* for faster clock, need more time for data setup */ trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1; @@ -383,7 +402,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, ); debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); } -#endif /* defined(CONFIG_SYS_FSL_DDR2) */ +#endif /* !defined(CONFIG_SYS_FSL_DDR1) */ /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, -- cgit v1.1 From 9b18e5199ec42f9dc62c0da7f4fe7554e199980d Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Mon, 10 Nov 2014 18:32:29 +0800 Subject: net/phy: Add support for CS4315/CS4340 PHY Add support for Cortina CS4315/CS4340 10G PHY. - This driver loads CS43xx firmware from NOR/NAND/SPI/SD device to initialize Cortina PHY. - Cortina PHY has non-standard offset of PHY ID registers, thus we define own get_phy_id() to override default get_phy_id(). - To define macro CONFIG_PHY_CORTINA will enable this driver. Signed-off-by: Shengzhou Liu Reviewed-by: York Sun --- drivers/net/phy/Makefile | 1 + drivers/net/phy/cortina.c | 333 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/phy/phy.c | 3 + 3 files changed, 337 insertions(+) create mode 100644 drivers/net/phy/cortina.c (limited to 'drivers') diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 9556536..f46bf00 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PHYLIB) += phy.o obj-$(CONFIG_PHYLIB_10G) += generic_10g.o obj-$(CONFIG_PHY_ATHEROS) += atheros.o obj-$(CONFIG_PHY_BROADCOM) += broadcom.o +obj-$(CONFIG_PHY_CORTINA) += cortina.o obj-$(CONFIG_PHY_DAVICOM) += davicom.o obj-$(CONFIG_PHY_ET1011C) += et1011c.o obj-$(CONFIG_PHY_LXT) += lxt.o diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c new file mode 100644 index 0000000..254f056 --- /dev/null +++ b/drivers/net/phy/cortina.c @@ -0,0 +1,333 @@ +/* + * Cortina CS4315/CS4340 10G PHY drivers + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Copyright 2014 Freescale Semiconductor, Inc. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SYS_CORTINA_FW_IN_NAND +#include +#elif defined(CONFIG_SYS_CORTINA_FW_IN_SPIFLASH) +#include +#elif defined(CONFIG_SYS_CORTINA_FW_IN_MMC) +#include +#endif + +#ifndef CONFIG_PHYLIB_10G +#error The Cortina PHY needs 10G support +#endif + +struct cortina_reg_config cortina_reg_cfg[] = { + /* CS4315_enable_sr_mode */ + {VILLA_GLOBAL_MSEQCLKCTRL, 0x8004}, + {VILLA_MSEQ_OPTIONS, 0xf}, + {VILLA_MSEQ_PC, 0x0}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_CPA, 0x55}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_LOOP_FILTER, 0x30}, + {VILLA_DSP_SDS_SERDES_SRX_DFE0_SELECT, 0x1}, + {VILLA_DSP_SDS_DSP_COEF_DFE0_SELECT, 0x2}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_CPB, 0x2003}, + {VILLA_DSP_SDS_SERDES_SRX_FFE_DELAY_CTRL, 0xF047}, + {VILLA_MSEQ_ENABLE_MSB, 0x0000}, + {VILLA_MSEQ_SPARE21_LSB, 0x6}, + {VILLA_MSEQ_RESET_COUNT_LSB, 0x0}, + {VILLA_MSEQ_SPARE12_MSB, 0x0000}, + /* + * to invert the receiver path, uncomment the next line + * write (VILLA_MSEQ_SPARE12_MSB, 0x4000) + * + * SPARE2_LSB is used to configure the device while in sr mode to + * enable power savings and to use the optical module LOS signal. + * in power savings mode, the internal prbs checker can not be used. + * if the optical module LOS signal is used as an input to the micro + * code, then the micro code will wait until the optical module + * LOS = 0 before turning on the adaptive equalizer. + * Setting SPARE2_LSB bit 0 to 1 places the devie in power savings mode + * while setting bit 0 to 0 disables power savings mode. + * Setting SPARE2_LSB bit 2 to 0 configures the device to use the + * optical module LOS signal while setting bit 2 to 1 configures the + * device so that it will ignore the optical module LOS SPARE2_LSB = 0 + */ + + /* enable power savings, ignore optical module LOS */ + {VILLA_MSEQ_SPARE2_LSB, 0x5}, + + {VILLA_MSEQ_SPARE7_LSB, 0x1e}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_MSEQ_SPARE9_LSB, 0x2}, + {VILLA_MSEQ_SPARE3_LSB, 0x0F53}, + {VILLA_MSEQ_SPARE3_MSB, 0x2006}, + {VILLA_MSEQ_SPARE8_LSB, 0x3FF7}, + {VILLA_MSEQ_SPARE8_MSB, 0x0A46}, + {VILLA_MSEQ_COEF8_FFE0_LSB, 0xD500}, + {VILLA_MSEQ_COEF8_FFE1_LSB, 0x0200}, + {VILLA_MSEQ_COEF8_FFE2_LSB, 0xBA00}, + {VILLA_MSEQ_COEF8_FFE3_LSB, 0x0100}, + {VILLA_MSEQ_COEF8_FFE4_LSB, 0x0300}, + {VILLA_MSEQ_COEF8_FFE5_LSB, 0x0300}, + {VILLA_MSEQ_COEF8_DFE0_LSB, 0x0700}, + {VILLA_MSEQ_COEF8_DFE0N_LSB, 0x0E00}, + {VILLA_MSEQ_COEF8_DFE1_LSB, 0x0B00}, + {VILLA_DSP_SDS_DSP_COEF_LARGE_LEAK, 0x2}, + {VILLA_DSP_SDS_SERDES_SRX_DAC_ENABLEB_LSB, 0xD000}, + {VILLA_MSEQ_POWER_DOWN_LSB, 0xFFFF}, + {VILLA_MSEQ_POWER_DOWN_MSB, 0x0}, + {VILLA_MSEQ_CAL_RX_SLICER, 0x80}, + {VILLA_DSP_SDS_SERDES_SRX_DAC_BIAS_SELECT1_MSB, 0x3f}, + {VILLA_GLOBAL_MSEQCLKCTRL, 0x4}, + {VILLA_MSEQ_OPTIONS, 0x7}, + + /* set up min value for ffe1 */ + {VILLA_MSEQ_COEF_INIT_SEL, 0x2}, + {VILLA_DSP_SDS_DSP_PRECODEDINITFFE21, 0x41}, + + /* CS4315_sr_rx_pre_eq_set_4in */ + {VILLA_GLOBAL_MSEQCLKCTRL, 0x8004}, + {VILLA_MSEQ_OPTIONS, 0xf}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_MSEQ_PC, 0x0}, + + /* for lengths from 3.5 to 4.5inches */ + {VILLA_MSEQ_SERDES_PARAM_LSB, 0x0306}, + {VILLA_MSEQ_SPARE25_LSB, 0x0306}, + {VILLA_MSEQ_SPARE21_LSB, 0x2}, + {VILLA_MSEQ_SPARE23_LSB, 0x2}, + {VILLA_MSEQ_CAL_RX_DFE_EQ, 0x0}, + + {VILLA_GLOBAL_MSEQCLKCTRL, 0x4}, + {VILLA_MSEQ_OPTIONS, 0x7}, + + /* CS4315_rx_drive_4inch */ + /* for length 4inches */ + {VILLA_GLOBAL_VILLA2_COMPATIBLE, 0x0000}, + {VILLA_HOST_SDS_COMMON_STX0_TX_OUTPUT_CTRLA, 0x3023}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLB, 0xc01E}, + + /* CS4315_tx_drive_4inch */ + /* for length 4inches */ + {VILLA_GLOBAL_VILLA2_COMPATIBLE, 0x0000}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLA, 0x3023}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLB, 0xc01E}, +}; + +void cs4340_upload_firmware(struct phy_device *phydev) +{ + char line_temp[0x50] = {0}; + char reg_addr[0x50] = {0}; + char reg_data[0x50] = {0}; + int i, line_cnt = 0, column_cnt = 0; + struct cortina_reg_config fw_temp; + char *addr = NULL; + +#if defined(CONFIG_SYS_CORTINA_FW_IN_NOR) || \ + defined(CONFIG_SYS_CORTINA_FW_IN_REMOTE) + + addr = (char *)CONFIG_CORTINA_FW_ADDR; +#elif defined(CONFIG_SYS_CORTINA_FW_IN_NAND) + int ret; + size_t fw_length = CONFIG_CORTINA_FW_LENGTH; + + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + ret = nand_read(&nand_info[0], (loff_t)CONFIG_CORTINA_FW_ADDR, + &fw_length, (u_char *)addr); + if (ret == -EUCLEAN) { + printf("NAND read of Cortina firmware at 0x%x failed %d\n", + CONFIG_CORTINA_FW_ADDR, ret); + } +#elif defined(CONFIG_SYS_CORTINA_FW_IN_SPIFLASH) + int ret; + struct spi_flash *ucode_flash; + + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); + if (!ucode_flash) { + puts("SF: probe for Cortina ucode failed\n"); + } else { + ret = spi_flash_read(ucode_flash, CONFIG_CORTINA_FW_ADDR, + CONFIG_CORTINA_FW_LENGTH, addr); + if (ret) + puts("SF: read for Cortina ucode failed\n"); + spi_flash_free(ucode_flash); + } +#elif defined(CONFIG_SYS_CORTINA_FW_IN_MMC) + int dev = CONFIG_SYS_MMC_ENV_DEV; + u32 cnt = CONFIG_CORTINA_FW_LENGTH / 512; + u32 blk = CONFIG_CORTINA_FW_ADDR / 512; + struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); + + if (!mmc) { + puts("Failed to find MMC device for Cortina ucode\n"); + } else { + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + printf("MMC read: dev # %u, block # %u, count %u ...\n", + dev, blk, cnt); + mmc_init(mmc); + (void)mmc->block_dev.block_read(dev, blk, cnt, addr); + /* flush cache after read */ + flush_cache((ulong)addr, cnt * 512); + } +#endif + + while (*addr != 'Q') { + i = 0; + + while (*addr != 0x0a) { + line_temp[i++] = *addr++; + if (0x50 < i) { + printf("Not found Cortina PHY ucode at 0x%x\n", + CONFIG_CORTINA_FW_ADDR); + return; + } + } + + addr++; /* skip '\n' */ + line_cnt++; + column_cnt = i; + line_temp[column_cnt] = '\0'; + + if (CONFIG_CORTINA_FW_LENGTH < line_cnt) + return; + + for (i = 0; i < column_cnt; i++) { + if (isspace(line_temp[i++])) + break; + } + + memcpy(reg_addr, line_temp, i); + memcpy(reg_data, &line_temp[i], column_cnt - i); + strim(reg_addr); + strim(reg_data); + fw_temp.reg_addr = (simple_strtoul(reg_addr, NULL, 0)) & 0xffff; + fw_temp.reg_value = (simple_strtoul(reg_data, NULL, 0)) & + 0xffff; + phy_write(phydev, 0x00, fw_temp.reg_addr, fw_temp.reg_value); + } +} + +int cs4340_phy_init(struct phy_device *phydev) +{ + int timeout = 100; /* 100ms */ + int reg_value; + + /* step1: BIST test */ + phy_write(phydev, 0x00, VILLA_GLOBAL_MSEQCLKCTRL, 0x0004); + phy_write(phydev, 0x00, VILLA_GLOBAL_LINE_SOFT_RESET, 0x0000); + phy_write(phydev, 0x00, VILLA_GLOBAL_BIST_CONTROL, 0x0001); + while (--timeout) { + reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_BIST_STATUS); + if (reg_value & mseq_edc_bist_done) { + if (0 == (reg_value & mseq_edc_bist_fail)) + break; + } + udelay(1000); + } + + if (!timeout) { + printf("%s BIST mseq_edc_bist_done timeout!\n", __func__); + return -1; + } + + /* setp2: upload ucode */ + cs4340_upload_firmware(phydev); + reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_DWNLD_CHECKSUM_STATUS); + if (reg_value) { + debug("%s checksum status failed.\n", __func__); + return -1; + } + + return 0; +} + +int cs4340_config(struct phy_device *phydev) +{ + cs4340_phy_init(phydev); + return 0; +} + +int cs4340_startup(struct phy_device *phydev) +{ + phydev->link = 1; + + /* For now just lie and say it's 10G all the time */ + phydev->speed = SPEED_10000; + phydev->duplex = DUPLEX_FULL; + return 0; +} + +struct phy_driver cs4340_driver = { + .name = "Cortina CS4315/CS4340", + .uid = PHY_UID_CS4340, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS | MDIO_DEVS_AN | + MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2), + .config = &cs4340_config, + .startup = &cs4340_startup, + .shutdown = &gen10g_shutdown, +}; + +int phy_cortina_init(void) +{ + phy_register(&cs4340_driver); + return 0; +} + +int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) +{ + int phy_reg; + bool is_cortina_phy = false; + + switch (addr) { +#ifdef CORTINA_PHY_ADDR1 + case CORTINA_PHY_ADDR1: +#endif +#ifdef CORTINA_PHY_ADDR2 + case CORTINA_PHY_ADDR2: +#endif +#ifdef CORTINA_PHY_ADDR3 + case CORTINA_PHY_ADDR3: +#endif +#ifdef CORTINA_PHY_ADDR4 + case CORTINA_PHY_ADDR4: +#endif + is_cortina_phy = true; + break; + default: + break; + } + + /* Cortina PHY has non-standard offset of PHY ID registers */ + if (is_cortina_phy) + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB); + else + phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); + + if (phy_reg < 0) + return -EIO; + + *phy_id = (phy_reg & 0xffff) << 16; + if (is_cortina_phy) + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB); + else + phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); + + if (phy_reg < 0) + return -EIO; + + *phy_id |= (phy_reg & 0xffff); + + return 0; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 467c972..5b04c85 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -448,6 +448,9 @@ int phy_init(void) #ifdef CONFIG_PHY_BROADCOM phy_broadcom_init(); #endif +#ifdef CONFIG_PHY_CORTINA + phy_cortina_init(); +#endif #ifdef CONFIG_PHY_DAVICOM phy_davicom_init(); #endif -- cgit v1.1 From 89b94d851d683308e731e3ceae1a12f616d1f2f7 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Thu, 13 Nov 2014 11:26:19 +0800 Subject: powerpc/b4860qds: add xfi support We need following changes to make xfi work on B4: 1. set cross-point switch VSC3308 to use sfp config when running xfi; 2. add 10G interface check for xfi; 3. set phy address for xfi so the 10G ports can be registered by mdio; Signed-off-by: Shaohui Xie Reviewed-by: York Sun --- drivers/net/fm/b4860.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fm/b4860.c b/drivers/net/fm/b4860.c index 373cc4f..71285a8 100644 --- a/drivers/net/fm/b4860.c +++ b/drivers/net/fm/b4860.c @@ -52,7 +52,9 @@ phy_interface_t fman_port_enet_if(enum fm_port port) /*B4860 has two 10Gig Mac*/ if ((port == FM1_10GEC1 || port == FM1_10GEC2) && ((is_serdes_configured(XAUI_FM1_MAC9)) || - (is_serdes_configured(XAUI_FM1_MAC10)))) + (is_serdes_configured(XAUI_FM1_MAC10)) || + (is_serdes_configured(XFI_FM1_MAC9)) || + (is_serdes_configured(XFI_FM1_MAC10)))) return PHY_INTERFACE_MODE_XGMII; /* Fix me need to handle RGMII here first */ -- cgit v1.1 From e2544e7a5459b7ad5efd8c99d54e71c2535281d1 Mon Sep 17 00:00:00 2001 From: Suresh Gupta Date: Thu, 13 Nov 2014 11:28:09 +0800 Subject: B4860QDS: Enable enet port as per fsl_b4860_serdes2 string in hwconfig In B4860QDS board SerDes2 lanes EFGH either go to SFP or AMC riser card slot2 so either DTSEC3/DTSEC4 or TGEC1/TGEC2 should be accessible. This Patch enables DTSEC3/DTSEC4 or TGEC1/TGEC2 on bases of user specified string fsl_b4860_serdes2:sfp_amc=amc or fsl_b4860_serdes2:sfp_amc=sfp respectively in hwconfig. Signed-off-by: Suresh Gupta Signed-off-by: Shaohui Xie Reviewed-by: York Sun --- drivers/net/fm/b4860.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/b4860.c b/drivers/net/fm/b4860.c index 71285a8..eb058c9 100644 --- a/drivers/net/fm/b4860.c +++ b/drivers/net/fm/b4860.c @@ -10,6 +10,7 @@ #include #include #include +#include u32 port_to_devdisr[] = { [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1, @@ -46,17 +47,76 @@ void fman_enable_port(enum fm_port port) phy_interface_t fman_port_enet_if(enum fm_port port) { +#if defined(CONFIG_B4860QDS) + u32 serdes2_prtcl; + char buffer[HWCONFIG_BUFFER_SIZE]; + char *buf = NULL; + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#endif + if (is_device_disabled(port)) return PHY_INTERFACE_MODE_NONE; /*B4860 has two 10Gig Mac*/ if ((port == FM1_10GEC1 || port == FM1_10GEC2) && ((is_serdes_configured(XAUI_FM1_MAC9)) || - (is_serdes_configured(XAUI_FM1_MAC10)) || + #if !defined(CONFIG_B4860QDS) (is_serdes_configured(XFI_FM1_MAC9)) || - (is_serdes_configured(XFI_FM1_MAC10)))) + (is_serdes_configured(XFI_FM1_MAC10)) || + #endif + (is_serdes_configured(XAUI_FM1_MAC10)) + )) return PHY_INTERFACE_MODE_XGMII; +#if defined(CONFIG_B4860QDS) + serdes2_prtcl = in_be32(&gur->rcwsr[4]) & + FSL_CORENET2_RCWSR4_SRDS2_PRTCL; + + if (serdes2_prtcl) { + serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; + switch (serdes2_prtcl) { + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0xb1: + case 0xb2: + /* + * Extract hwconfig from environment since environment + * is not setup yet + */ + getenv_f("hwconfig", buffer, sizeof(buffer)); + buf = buffer; + + /* check if XFI interface enable in hwconfig for 10g */ + if (hwconfig_subarg_cmp_f("fsl_b4860_serdes2", + "sfp_amc", "sfp", buf)) { + if ((port == FM1_10GEC1 || + port == FM1_10GEC2) && + ((is_serdes_configured(XFI_FM1_MAC9)) || + (is_serdes_configured(XFI_FM1_MAC10)))) + return PHY_INTERFACE_MODE_XGMII; + else if ((port == FM1_DTSEC1) || + (port == FM1_DTSEC2) || + (port == FM1_DTSEC3) || + (port == FM1_DTSEC4)) + return PHY_INTERFACE_MODE_NONE; + } + } + } +#endif + /* Fix me need to handle RGMII here first */ switch (port) { -- cgit v1.1 From 789b3447c0c02fd0eec839f694446c0dd4eb3718 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 14 Nov 2014 17:17:50 -0800 Subject: driver/ddr/fsl: Add workaround for faulty SPD Some UDIMMs have faulty SPD with wrong mapping for DQ[36-39]. Using raw card spec in case this error is detected. Signed-off-by: York Sun --- drivers/ddr/fsl/ddr4_dimm_params.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 2418dca..aaddc8f 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -126,6 +126,12 @@ ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd, { unsigned int retval; int i; + const u8 udimm_rc_e_dq[18] = { + 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15, + 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36 + }; + int spd_error = 0; + u8 *ptr; if (spd->mem_type) { if (spd->mem_type != SPD_MEMTYPE_DDR4) { @@ -179,6 +185,22 @@ ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd, /* Unbuffered DIMMs */ if (spd->mod_section.unbuffered.addr_mapping & 0x1) pdimm->mirrored_dimm = 1; + if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 && + (spd->mod_section.unbuffered.ref_raw_card == 0x04)) { + /* Fix SPD error found on DIMMs with raw card E0 */ + for (i = 0; i < 18; i++) { + if (spd->mapping[i] == udimm_rc_e_dq[i]) + continue; + spd_error = 1; + debug("SPD byte %d: 0x%x, should be 0x%x\n", + 60 + i, spd->mapping[i], + udimm_rc_e_dq[i]); + ptr = (u8 *)&spd->mapping[i]; + *ptr = udimm_rc_e_dq[i]; + } + if (spd_error) + puts("SPD DQ mapping error fixed\n"); + } break; default: -- cgit v1.1 From f605079041079cb4e84693110e26086f8d1a8bcd Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Mon, 24 Nov 2014 17:11:54 +0800 Subject: powerpc/mpc85xx: Add T1024/T1023 SoC support Add support for Freescale T1024/T1023 SoC. The T1024 SoC includes the following function and features: - Two 64-bit Power architecture e5500 cores, up to 1.4GHz - private 256KB L2 cache each core and shared 256KB CoreNet platform cache (CPC) - 32-/64-bit DDR3L/DDR4 SDRAM memory controller with ECC and interleaving support - Data Path Acceleration Architecture (DPAA) incorporating acceleration - Four MAC for 1G/2.5G/10G network interfaces (RGMII, SGMII, QSGMII, XFI) - High-speed peripheral interfaces - Three PCI Express 2.0 controllers - Additional peripheral interfaces - One SATA 2.0 controller - Two USB 2.0 controllers with integrated PHY - Enhanced secure digital host controller (SD/eSDHC/eMMC) - Enhanced serial peripheral interface (eSPI) - Four I2C controllers - Four 2-pin UARTs or two 4-pin UARTs - Integrated Flash Controller supporting NAND and NOR flash - Two 8-channel DMA engines - Multicore programmable interrupt controller (PIC) - LCD interface (DIU) with 12 bit dual data rate - QUICC Engine block supporting TDM, HDLC, and UART - Deep Sleep power implementaion (wakeup from GPIO/Timer/Ethernet/USB) - Support for hardware virtualization and partitioning enforcement - QorIQ Platform's Trust Architecture 2.0 Differences between T1024 and T1023: Feature T1024 T1023 QUICC Engine: yes no DIU: yes no Deep Sleep: yes no I2C controller: 4 3 DDR: 64-bit 32-bit IFC: 32-bit 28-bit Signed-off-by: Shengzhou Liu Reviewed-by: York Sun --- drivers/net/fm/Makefile | 2 ++ drivers/net/fm/t1024.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 drivers/net/fm/t1024.c (limited to 'drivers') diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile index 5ae3b16..d052fcb 100644 --- a/drivers/net/fm/Makefile +++ b/drivers/net/fm/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_PPC_T1040) += t1040.o obj-$(CONFIG_PPC_T1042) += t1040.o obj-$(CONFIG_PPC_T1020) += t1040.o obj-$(CONFIG_PPC_T1022) += t1040.o +obj-$(CONFIG_PPC_T1023) += t1024.o +obj-$(CONFIG_PPC_T1024) += t1024.o obj-$(CONFIG_PPC_T2080) += t2080.o obj-$(CONFIG_PPC_T2081) += t2080.o obj-$(CONFIG_PPC_T4240) += t4240.o diff --git a/drivers/net/fm/t1024.c b/drivers/net/fm/t1024.c new file mode 100644 index 0000000..9b31173 --- /dev/null +++ b/drivers/net/fm/t1024.c @@ -0,0 +1,88 @@ +/* Copyright 2014 Freescale Semiconductor, Inc. + * + * Shengzhou Liu + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +u32 port_to_devdisr[] = { + [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1, + [FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2, + [FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3, + [FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4, + [FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1_1, /* MAC1 */ +}; + +static int is_device_disabled(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 devdisr2 = in_be32(&gur->devdisr2); + + return port_to_devdisr[port] & devdisr2; +} + +void fman_disable_port(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + + setbits_be32(&gur->devdisr2, port_to_devdisr[port]); +} + +phy_interface_t fman_port_enet_if(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 rcwsr13 = in_be32(&gur->rcwsr[13]); + + if (is_device_disabled(port)) + return PHY_INTERFACE_MODE_NONE; + + if ((port == FM1_10GEC1) && (is_serdes_configured(XFI_FM1_MAC1))) + return PHY_INTERFACE_MODE_XGMII; + + if ((port == FM1_DTSEC3) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) == + FSL_CORENET_RCWSR13_EC2_RGMII) && + (!is_serdes_configured(QSGMII_FM1_A))) + return PHY_INTERFACE_MODE_RGMII; + + if ((port == FM1_DTSEC4) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_RGMII) && + (!is_serdes_configured(QSGMII_FM1_A))) + return PHY_INTERFACE_MODE_RGMII; + + /* handle SGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + case FM1_DTSEC3: + if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII; + else if (is_serdes_configured(SGMII_2500_FM1_DTSEC1 + + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII_2500; + break; + default: + break; + } + + /* handle QSGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + case FM1_DTSEC3: + case FM1_DTSEC4: + /* check lane A on SerDes1 */ + if (is_serdes_configured(QSGMII_FM1_A)) + return PHY_INTERFACE_MODE_QSGMII; + break; + default: + break; + } + + return PHY_INTERFACE_MODE_NONE; +} -- cgit v1.1 From cc19c25e2752bb8b446463eb627e258e659d73d9 Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Mon, 24 Nov 2014 17:11:57 +0800 Subject: net/fman: update 10GEC to fit new SoC fm_standard_init() initializes each 10G port by FM_TGEC_INFO_INITIALIZER. but it needs different implementation of FM_TGEC_INFO_INITIALIZER on different SoCs. on SoCs earlier(e.g. T4240, T2080), the notation between 10GEC and MAC as below: 10GEC1->MAC9, 10GEC2->MAC10, 10GEC3->MAC1, 10GEC4->MAC2 on SoCs later(e.g. T1024, etc), the notation between 10GEC and MAC as below: 10GEC1->MAC1, 10GEC2->MAC2 so we introduce CONFIG_FSL_FM_10GEC_REGULAR_NOTATION to fit the new SoCs on which 10GEC enumeration is consistent with MAC enumeration. Signed-off-by: Shengzhou Liu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 7 +++++-- drivers/net/fm/init.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 137886c..f1e39b9 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -565,9 +565,11 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) num = fm_eth->num; #ifdef CONFIG_SYS_FMAN_V3 +#ifndef CONFIG_FSL_FM_10GEC_REGULAR_NOTATION if (fm_eth->type == FM_ETH_10G_E) { - /* 10GEC1/10GEC2 use mEMAC9/mEMAC10 - * 10GEC3/10GEC4 use mEMAC1/mEMAC2 + /* 10GEC1/10GEC2 use mEMAC9/mEMAC10 on T2080/T4240. + * 10GEC3/10GEC4 use mEMAC1/mEMAC2 on T2080. + * 10GEC1 uses mEMAC1 on T1024. * so it needs to change the num. */ if (fm_eth->num >= 2) @@ -575,6 +577,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) else num += 8; } +#endif base = ®->memac[num].fm_memac; phyregs = ®->memac[num].fm_memac_mdio; #else diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index 6cf21c6..5d82f29 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -254,8 +254,10 @@ static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) */ if (((info->port == FM1_DTSEC9) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC10) && (PORT_IS_ENABLED(FM1_10GEC2))) || + ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC3))) || ((info->port == FM1_DTSEC2) && (PORT_IS_ENABLED(FM1_10GEC4))) || + ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC1))) || ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC9))) || ((info->port == FM1_10GEC2) && (PORT_IS_ENABLED(FM1_DTSEC10))) || ((info->port == FM1_10GEC3) && (PORT_IS_ENABLED(FM1_DTSEC1))) || -- cgit v1.1 From c18fc2c960708d85e5ef77fe7c5eead7d41d2231 Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Mon, 24 Nov 2014 17:11:59 +0800 Subject: net/phy: enable serdes auto-negotiation for vsc8514 phy VSC8514 QSGMII PHY requires enabling auto-negotiation, otherwise it wouldn't work. Signed-off-by: Shengzhou Liu Reviewed-by: York Sun --- drivers/net/phy/vitesse.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 2b29cd8..20a6746 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -1,8 +1,8 @@ /* * Vitesse PHY drivers * - * Copyright 2010-2012 Freescale Semiconductor, Inc. - * Author: Andy Fleming + * Copyright 2010-2014 Freescale Semiconductor, Inc. + * Original Author: Andy Fleming * Add vsc8662 phy support - Priyanka Jain * SPDX-License-Identifier: GPL-2.0+ */ @@ -50,6 +50,7 @@ #define MIIM_VSC8574_18G_CMDSTAT 0x8000 /* Vitesse VSC8514 control register */ +#define MIIM_VSC8514_MAC_SERDES_CON 0x10 #define MIIM_VSC8514_GENERAL18 0x12 #define MIIM_VSC8514_GENERAL19 0x13 #define MIIM_VSC8514_GENERAL23 0x17 @@ -246,6 +247,14 @@ static int vsc8514_config(struct phy_device *phydev) val = (val & 0xf8ff); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val); + /* Enable Serdes Auto-negotiation */ + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_EXTENDED3); + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON); + val = val | MIIM_VSC8574_MAC_SERDES_ANEG; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val); + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + genphy_config_aneg(phydev); return 0; -- cgit v1.1