/* * Copyright 2017 Scalys B.V. * opensource@scalys.com * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../../freescale/common/fman.h" #define VILLA_EEPROM_LOADER_STATUS 0xc01 uint8_t sfp_phy_config[][2] = { { 0x1b, 0x90 }, { 0x1b, 0x84 }, { 0x09, 0x0F }, { 0x09, 0x00 }, { 0x00, 0x81 }, { 0x00, 0x40 }, }; int board_eth_init(bd_t *bis) { #ifdef CONFIG_FMAN_ENET struct memac_mdio_info dtsec_mdio_info; struct memac_mdio_info tgec_mdio_info; /*struct phy_driver *cortina_10G_phy;*/ unsigned int i; uint8_t i2c_data; int ret; int phy_addr = 0; /*uint32_t *gpio1_gpdir = (uint32_t *) 0xffe130000; uint32_t *gpio1_gpdat = (uint32_t *) 0xffe130008;*/ uint32_t *gpio2_gpdir = (uint32_t *) 0xffe131000; uint32_t *gpio2_gpdat = (uint32_t *) 0xffe131008; uint32_t *gpio4_gpdir = (uint32_t *) 0xffe133000; uint32_t *gpio4_gpdat = (uint32_t *) 0xffe133008; uint32_t regval; /* Try to read a byte from the carrier eeprom the determine if were on the correct carrier */ ret = i2c_read(0x54, 0, 2, &i2c_data, 1 ); if (ret != 0) { printf("No dragonfruit carrier detected\n"); return 0; } printf("Initializing Fman\n"); dtsec_mdio_info.regs = (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR; dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; /* Register the real 1G MDIO bus */ fm_memac_mdio_init(bis, &dtsec_mdio_info); tgec_mdio_info.regs = (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; /* Register the 10G MDIO bus */ fm_memac_mdio_init(bis, &tgec_mdio_info); /* Marvell 88E1111 Setup * * Remove reset from Ethernet PHY's * * Carrier board v1.x: * IFC_PERR_B : GPIO2_15 : eth1_reset_n * IFC_CS_N2 : GPIO2_11 : eth2_reset_n * * Carrier board v2.x: * IFC_PERR_B : GPIO2_15 : eth1_reset_n * N_DMA2_DDONE0_B : GPIO4_09 : eth2_reset_n * * Note: make sure gpio pins are configured as gpio in RCW! */ #if 0 #define ETH1_RESET_N (0x80000000 >> 15) #define ETH2_RESET_N (0x80000000 >> 11) /* TODO: use EEPROM data to chose carrier board version */ /* Carrier board v1.x */ /* Clear outputs to activate reset */ regval = in_be32(gpio2_gpdat); regval &= ~(ETH1_RESET_N | ETH2_RESET_N); out_be32(gpio2_gpdat, regval); /* Set outputs to output mode */ regval = in_be32(gpio2_gpdir); regval |= (ETH1_RESET_N | ETH2_RESET_N); out_be32(gpio2_gpdir, regval); /* Wait for 10 ms to to meet reset timing */ mdelay(10); /* Set outputs to de-activate reset */ regval = in_be32(gpio2_gpdat); regval |= (ETH1_RESET_N | ETH2_RESET_N); out_be32(gpio2_gpdat, regval); #else #define ETH1_RESET_N (0x80000000 >> 15) #define ETH2_RESET_N (0x80000000 >> 9) /* Carrier board v2.x */ /* Clear outputs to activate reset */ regval = in_be32(gpio2_gpdat); regval &= ~(ETH1_RESET_N); out_be32(gpio2_gpdat, regval); regval = in_be32(gpio4_gpdat); regval &= ~(ETH2_RESET_N); out_be32(gpio4_gpdat, regval); /* Set outputs to output mode */ regval = in_be32(gpio2_gpdir); regval |= (ETH1_RESET_N); out_be32(gpio2_gpdir, regval); regval = in_be32(gpio4_gpdir); regval |= (ETH2_RESET_N); out_be32(gpio4_gpdir, regval); /* Wait for 10 ms to to meet reset timing */ mdelay(10); /* Set outputs to de-activate reset */ regval = in_be32(gpio2_gpdat); regval |= (ETH1_RESET_N); out_be32(gpio2_gpdat, regval); regval = in_be32(gpio4_gpdat); regval |= (ETH2_RESET_N); out_be32(gpio4_gpdat, regval); #endif /* Write 0x4111 to reg 0x18 on both PHYs to change LEDs usage */ miiphy_write("FSL_MDIO0",0,0x18,0x4111); miiphy_write("FSL_MDIO0",1,0x18,0x4111); /* Remove SFP TX_disable */ i2c_set_bus_num(0); ret = i2c_read(0x22, 0x0E, 1, &i2c_data, 1); i2c_data &= ~0x04; ret = i2c_write(0x22, 0x0E, 1, &i2c_data, 1); mdelay(100); i2c_set_bus_num(3); for (phy_addr=0; phy_addr<4; phy_addr++) { i2c_data = (1 << phy_addr); ret = i2c_write(0x70, 0, 1, &i2c_data, 1); if (ret) { printf("Error Setting SFP i2c MUX\n"); break; } for ( i = 0; i < 6; i++) { ret = i2c_write(0x56, sfp_phy_config[i][0], 1, &(sfp_phy_config[i][1]), 1); if (ret) { printf("Error sfp phy(%i:%i):%02x to address %02x\n", phy_addr, i, sfp_phy_config[i][1],sfp_phy_config[i][0]); break; } } } /* Two external pin interfaces * MAC3|MAC4|MAC10 EC1|EC2 RGMII interface */ /* * Program on board RGMII, SGMII PHY addresses. */ for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { int idx = i - FM1_DTSEC1; switch (fm_info_get_enet_if(i)) { case PHY_INTERFACE_MODE_RGMII: if (FM1_DTSEC3 == i) phy_addr = CONFIG_SYS_RGMII1_PHY_ADDR; if (FM1_DTSEC4 == i) phy_addr = CONFIG_SYS_RGMII2_PHY_ADDR; /*if (FM1_DTSEC10 == i) phy_addr = CONFIG_SYS_RGMII2_PHY_ADDR;*/ fm_info_set_phy_address(i, phy_addr); break; /* case PHY_INTERFACE_MODE_QSGMII: fm_info_set_phy_address(i, i+2); break;*/ case PHY_INTERFACE_MODE_NONE: fm_info_set_phy_address(i, 0); break; case PHY_INTERFACE_MODE_SGMII: printf("TODO, add phy interface to SGMII\n"); fm_info_set_phy_address(i, PHY_INTERFACE_MODE_NONE); break; default: printf("Fman1: DTSEC%u set to unknown interface %i\n", idx + 1, fm_info_get_enet_if(i)); //fm_info_set_phy_address(i, 0); break; } fm_info_set_mdio(i, miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME)); } /* 10G XFI interface initialization (TODO)*/ #if 0 /* Reset phy */ /* N_DMA2_DDONE0_B : GPIO1_09 : EDC_RST_N */ #define EDC_RST_N (0x80000000 >> 9) /* Clear outputs to activate reset */ regval = in_be32(gpio1_gpdat); regval &= ~(EDC_RST_N); out_be32(gpio1_gpdat, regval); /* Set outputs to output mode */ regval = in_be32(gpio1_gpdir); regval |= (EDC_RST_N); out_be32(gpio1_gpdir, regval); /* Wait for 10 ms to to meet reset timing */ mdelay(10); /* Set outputs to de-activate reset */ regval = in_be32(gpio1_gpdat); regval |= (EDC_RST_N); out_be32(gpio1_gpdat, regval); /* Wait 10ms to let phy set the load_failed bit */ mdelay(10); /* get cs4315 phy */ cortina_10G_phy = phy_find_by_mask(tgec_mdio_info, 0xfffffff0, PHY_INTERFACE_MODE_XGMII); /* Check load_failed == 1 (else skip initialization) */ mii_data = miiphy_read("FM_TGEC_MDIO",0,VILLA_EEPROM_LOADER_STATUS); if ((mii_data & 0x02) != 0) { /* TODO: upload microcode */ cortina_10G_phy->config(); } /* TODO: insert additional configuration */ /* Start phy */ cortina_10G_phy->startup(); #endif for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) { switch (fm_info_get_enet_if(i)) { case PHY_INTERFACE_MODE_XGMII: fm_info_set_phy_address(FM1_10GEC1, CORTINA_PHY_ADDR1); fm_info_set_phy_address(FM1_10GEC2, CORTINA_PHY_ADDR2); break; case PHY_INTERFACE_MODE_NONE: fm_info_set_phy_address(i, 0); default: break; } fm_info_set_mdio(i, miiphy_get_dev_by_name(DEFAULT_FM_TGEC_MDIO_NAME)); } cpu_eth_init(bis); #endif return pci_eth_init(bis); } void fdt_fixup_board_enet(void *fdt) { return; }