//========================================================================== // // devs_eth_arm_tx27.inl // // Board ethernet I/O definitions. // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that 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 eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //=========================================================================== #include // CYGNUM_HAL_INTERRUPT_ETHR #include #ifdef CYGPKG_REDBOOT #include #ifdef CYGSEM_REDBOOT_FLASH_CONFIG #include #include #endif #endif #ifdef __WANT_DEVS #ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0 #ifdef CYGPKG_DEVS_ETH_PHY static char mxc_fec_name[] = "mxc_fec"; #define OCR_SHIFT(bit) (((bit) * 2) % 32) #define OCR_MASK(bit) (3 << (OCR_SHIFT(bit))) #define OCR_VAL(bit,val) (((val) << (OCR_SHIFT(bit))) & (OCR_MASK(bit))) #define GPR_SHIFT(bit) (bit) #define GPR_MASK(bit) (1 << (GPR_SHIFT(bit))) #define GPR_VAL(bit,val) (((val) << (GPR_SHIFT(bit))) & (GPR_MASK(bit))) #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE // // Verify that the given ESA is valid for this platform // static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX27KARO_OUI; bool cyg_plf_redboot_esa_validate(unsigned char *val) { return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]); } #endif extern int tx27_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]); static inline void tx27_set_reg(unsigned long addr, CYG_WORD32 set, CYG_WORD32 clr) { CYG_WORD32 val; HAL_READ_UINT32(addr, val); //diag_printf("Changing reg %08lx from %08x to %08x\n", addr, val, (val & ~clr) | set); val = (val & ~clr) | set; HAL_WRITE_UINT32(addr, val); } static inline void tx27_phy_power_off(void) { if (net_debug) diag_printf("Switching PHY POWER off\n"); // deassert PD0-15 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0xffffffff, 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, 0xffff); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0xffff, 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0xffff, 0); // deassert PD16 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, OCR_MASK(16), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, GPR_MASK(16)); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, GPR_MASK(16), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, GPR_MASK(16), 0); // deassert PF23 tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, OCR_MASK(23), 0); tx27_set_reg(SOC_GPIOF_BASE + GPIO_DR, 0, GPR_MASK(23)); tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0); tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0); tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, 0, GPR_MASK(27) | GPR_MASK(30)); } static bool mxc_fec_init(struct cyg_netdevtab_entry *tab); static bool tx27_fec_init(struct cyg_netdevtab_entry *tab) { cyg_bool esa_set; int ok; /* Check, whether MAC address is enabled */ ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa", &esa_set, CONFIG_BOOL); if (!(ok && esa_set)) { diag_printf("FEC disabled; set fec_esa=true to enable networking\n"); return false; } return mxc_fec_init(tab); } static void tx27_fec_phy_init(void) { int ok; cyg_bool esa_set; int phy_reset_delay = 100; ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa", &esa_set, CONFIG_BOOL); if (!(ok && esa_set)) { tx27_phy_power_off(); return; } /* * make sure the ETH PHY strap pins are pulled to the right voltage * before deasserting the PHY reset GPIO * REGOFF: PD14 * RMII: PD15 * nINTSEL: PD7 * MODE0: PD12 * MODE1: PD5 * MODE2: PD6 * PHYAD0: - * PHYAD1: GND * PHYAD2: GND * PHYAD3: - * PHYAD4: PD10 */ // assert FEC PHY Reset (PB30) and switch PHY power on /* PB22, PB27, PB30 => GPIO out */ if (!gpio_tst_bit(1, 27)) { if (net_debug) diag_printf("Switching PHY POWER on\n"); tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, GPR_MASK(27), GPR_MASK(30)); /* wait for 22ms for LAN8700 to power up */ phy_reset_delay = 22000; } else { if (net_debug) diag_printf("Asserting PHY RESET\n"); tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, 0, GPR_MASK(30)); } const unsigned int phy_mode_mask = 0x10e0; // deassert PD0-15 (except 5,6,7,12 => PHY MODE[0..2], INTSEL) tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0xffffffff, 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, phy_mode_mask, ~phy_mode_mask); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0xffff, 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0xffff, 0); // deassert PD16 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, OCR_MASK(16), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, GPR_MASK(16)); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, GPR_MASK(16), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, GPR_MASK(16), 0); // deassert PF23 tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, OCR_MASK(23), 0); tx27_set_reg(SOC_GPIOF_BASE + GPIO_DR, 0, GPR_MASK(23)); tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0); tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0); /* wait for 100us according to LAN8700 spec. before ... */ HAL_DELAY_US(phy_reset_delay); /* ... deasserting FEC PHY reset */ if (net_debug) diag_printf("Releasing PHY RESET\n"); tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, GPR_MASK(30), 0); // program PF23 as FEC_TXEN tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, 0, OCR_MASK(23)); tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0); tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, 0, OCR_MASK(16)); tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0, 0x000C00FF); tx27_set_reg(SOC_GPIOD_BASE + GPIO_ICONFA1, 0, 0xFFF0FF00); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GPR, GPR_MASK(8), 0); tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0x0001020F, 0x0001FFFF); tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0x0001FEFF, 0x0001FFFF); } ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy, tx27_fec_phy_init, mxc_fec_phy_reset, mxc_fec_phy_write, mxc_fec_phy_read); cyg_bool _tx27_provide_fec_esa(unsigned char *addr) { cyg_bool enabled; int ok; ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa", &enabled, CONFIG_BOOL); if (ok && enabled) { #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE cyg_uint8 addr2[ETHER_ADDR_LEN]; addr[0] = readl(SOC_FEC_MAC_BASE2 + 0x0); addr[1] = readl(SOC_FEC_MAC_BASE2 + 0x4); addr[2] = readl(SOC_FEC_MAC_BASE2 + 0x8); addr[3] = readl(SOC_FEC_MAC_BASE2 + 0xC); addr[4] = readl(SOC_FEC_MAC_BASE2 + 0x10); addr[5] = readl(SOC_FEC_MAC_BASE2 + 0x14); if (cyg_plf_redboot_esa_validate(addr)) { diag_printf("Ethernet FEC MAC address from fuse bank: "); diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa_data", addr2, CONFIG_ESA); if (memcmp(addr, addr2, sizeof(addr)) != 0) { CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_SET, "fec_esa_data", addr, CONFIG_ESA); } #ifdef SOC_MAC_ADDR_LOCK if ((readl(SOC_FEC_MAC_BASE2 - 0x14) & SOC_MAC_ADDR_LOCK) == 0) { tx27_mac_addr_program(addr); } #endif // SOC_MAC_ADDR_LOCK return true; } #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa_data", addr, CONFIG_ESA); diag_printf("Ethernet FEC MAC address from fconfig: "); diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE if (cyg_plf_redboot_esa_validate(addr)) { tx27_mac_addr_program(addr); return true; } diag_printf("** Error: Invalid MAC address: "); diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); #ifdef SOC_MAC_ADDR_LOCK if ((readl(SOC_FEC_MAC_BASE2 - 0x14) & SOC_MAC_ADDR_LOCK) == 0) { diag_printf("Use 'fconfig fec_esa_data' to set the MAC address\n"); return false; } else { diag_printf("Using MAC address from fconfig\n"); } #else diag_printf("Using MAC address from fconfig\n"); #endif // SOC_MAC_ADDR_LOCK #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE return true; } return false; } static mxc_fec_priv_t mxc_fec_private = { .phy = ð0_phy, // PHY access routines .provide_esa = _tx27_provide_fec_esa, }; ETH_DRV_SC(mxc_fec_sc, &mxc_fec_private, // Driver specific data mxc_fec_name, mxc_fec_start, mxc_fec_stop, mxc_fec_control, mxc_fec_can_send, mxc_fec_send, mxc_fec_recv, mxc_fec_deliver, // "pseudoDSR" called from fast net thread mxc_fec_poll, // poll function, encapsulates ISR and DSR mxc_fec_int_vector); NETDEVTAB_ENTRY(mxc_fec_netdev, mxc_fec_name, tx27_fec_init, &mxc_fec_sc); #endif #if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG) RedBoot_config_option("Set FEC network hardware address [MAC]", fec_esa, ALWAYS_ENABLED, true, CONFIG_BOOL, true ); RedBoot_config_option("FEC network hardware address [MAC]", fec_esa_data, "fec_esa", true, CONFIG_ESA, 0 ); #endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // Note that this section *is* active in an application, outside RedBoot, // where the above section is not included. #endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT #endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0 #endif // __WANT_DEVS