/* * Copyright Altera Corporation (C) 2013. All rights reserved * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include #include #include #include #ifndef CONFIG_SPL_BUILD #include #include #include #include #include "../../../drivers/net/designware.h" #endif #include DECLARE_GLOBAL_DATA_PTR; /* * Initialization function which happen at early stage of c code */ int board_early_init_f(void) { #ifdef CONFIG_HW_WATCHDOG /* disable the watchdog when entering U-Boot */ watchdog_disable(); #endif /* calculate the clock frequencies required for drivers */ cm_derive_clocks_for_drivers(); return 0; } /* * Miscellaneous platform dependent initialisations */ int board_init(void) { /* adress of boot parameters for ATAG (if ATAG is used) */ gd->bd->bi_boot_params = 0x00000100; /* * reinitialize the global variable for clock value as after * relocation, the global variable are cleared to zeroes */ cm_derive_clocks_for_drivers(); return 0; } static void setenv_ethaddr_eeprom(void) { uint addr, alen; int linebytes; uchar chip, enetaddr[6], temp; /* configuration based on dev kit EEPROM */ chip = 0x51; /* slave ID for EEPROM */ alen = 2; /* dev kit using 2 byte addressing */ linebytes = 6; /* emac address stored in 6 bytes address */ #if (CONFIG_EMAC_BASE == CONFIG_EMAC0_BASE) addr = 0x16c; #elif (CONFIG_EMAC_BASE == CONFIG_EMAC1_BASE) addr = 0x174; #endif i2c_read(chip, addr, alen, enetaddr, linebytes); /* swapping endian to match board implementation */ temp = enetaddr[0]; enetaddr[0] = enetaddr[5]; enetaddr[5] = temp; temp = enetaddr[1]; enetaddr[1] = enetaddr[4]; enetaddr[4] = temp; temp = enetaddr[2]; enetaddr[2] = enetaddr[3]; enetaddr[3] = temp; if (is_valid_ether_addr(enetaddr)) eth_setenv_enetaddr("ethaddr", enetaddr); else puts("Skipped ethaddr assignment due to invalid " "EMAC address in EEPROM\n"); } #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { uchar enetaddr[6]; setenv_addr("setenv_ethaddr_eeprom", (void *)setenv_ethaddr_eeprom); /* if no ethaddr environment, get it from EEPROM */ if (!eth_getenv_enetaddr("ethaddr", enetaddr)) setenv_ethaddr_eeprom(); return 0; } #endif /* EMAC related setup and only supported in U-Boot */ #if !defined(CONFIG_SOCFPGA_VIRTUAL_TARGET) && \ !defined(CONFIG_SPL_BUILD) /* * DesignWare Ethernet initialization * This function overrides the __weak version in the driver proper. * Our Micrel Phy needs slightly non-conventional setup */ int designware_board_phy_init(struct eth_device *dev, int phy_addr, int (*mii_write)(struct eth_device *, u8, u8, u16), int (*dw_reset_phy)(struct eth_device *)) { struct dw_eth_dev *priv = dev->priv; struct phy_device *phydev; struct mii_dev *bus; if ((*dw_reset_phy)(dev) < 0) return -1; bus = mdio_get_current_dev(); phydev = phy_connect(bus, phy_addr, dev, priv->interface); /* Micrel PHY is connected to EMAC1 */ if (strcasecmp(phydev->drv->name, "Micrel ksz9021") == 0 && ((phydev->drv->uid & phydev->drv->mask) == (phydev->phy_id & phydev->drv->mask))) { printf("Configuring PHY skew timing for %s\n", phydev->drv->name); /* min rx data delay */ if (ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, getenv_ulong(CONFIG_KSZ9021_DATA_SKEW_ENV, 16, CONFIG_KSZ9021_DATA_SKEW_VAL)) < 0) return -1; /* min tx data delay */ if (ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, getenv_ulong(CONFIG_KSZ9021_DATA_SKEW_ENV, 16, CONFIG_KSZ9021_DATA_SKEW_VAL)) < 0) return -1; /* max rx/tx clock delay, min rx/tx control */ if (ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, getenv_ulong(CONFIG_KSZ9021_CLK_SKEW_ENV, 16, CONFIG_KSZ9021_CLK_SKEW_VAL)) < 0) return -1; if (phydev->drv->config) phydev->drv->config(phydev); } return 0; } #endif /* We know all the init functions have been run now */ int board_eth_init(bd_t *bis) { #if !defined(CONFIG_SOCFPGA_VIRTUAL_TARGET) && \ !defined(CONFIG_SPL_BUILD) /* Initialize EMAC */ /* * Putting the EMAC controller to reset when configuring the PHY * interface select at System Manager */ emac0_reset_enable(1); emac1_reset_enable(1); /* Clearing emac0 PHY interface select to 0 */ clrbits_le32(CONFIG_SYSMGR_EMAC_CTRL, (SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << #if (CONFIG_EMAC_BASE == CONFIG_EMAC0_BASE) SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB)); #elif (CONFIG_EMAC_BASE == CONFIG_EMAC1_BASE) SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB)); #endif /* configure to PHY interface select choosed */ setbits_le32(CONFIG_SYSMGR_EMAC_CTRL, #if (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_GMII) (SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII << #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_MII) (SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII << #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_RGMII) (SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_RMII) (SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII << #endif #if (CONFIG_EMAC_BASE == CONFIG_EMAC0_BASE) SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB)); /* Release the EMAC controller from reset */ emac0_reset_enable(0); #elif (CONFIG_EMAC_BASE == CONFIG_EMAC1_BASE) SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB)); /* Release the EMAC controller from reset */ emac1_reset_enable(0); #endif /* initialize and register the emac */ int rval = designware_initialize(0, CONFIG_EMAC_BASE, CONFIG_EPHY_PHY_ADDR, #if (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_GMII) PHY_INTERFACE_MODE_GMII); #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_MII) PHY_INTERFACE_MODE_MII); #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_RGMII) PHY_INTERFACE_MODE_RGMII); #elif (CONFIG_PHY_INTERFACE_MODE == SOCFPGA_PHYSEL_ENUM_RMII) PHY_INTERFACE_MODE_RMII); #endif debug("board_eth_init %d\n", rval); return rval; #else return 0; #endif }