This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I'm using UBOOT provided by MCSDK_1_01_00_02 for omapl138. I'd want to connect EMAC of omapl138 directly with another EMAC switch into FPGA by MII.
My target is like omapl138_lcdk provided by TI (da850evm).
I did that with linux and it works. But I can't do it with UBOOT after to have done some changes:
- PING from OMAP to PC works (with uboot shell)
- PING from PC to omapl138 doesn't work (with PC shell)
- PING from omapl to omapl doesn't work (with uboot shell)
- PING from PC to omapl138 works (with PC shell) while I do a PING from omapl to omapl (with uboot shell). After it doesn't work anymore.
When it doesn't work, I obtains message "ping failed; host 192.168.1.4 is not alive".
ip PC : 192.168.1.1
mask PC : 255.255.255.0
ip omapl uboot : 192.168.1.4
I set these environment variables :
ethaddr=00:00:00:fc:fa:c3
gatewayip=192.168.1.1
ipaddr=192.168.1.4
netdev=eth0
netmask=255.255.255.0
serverip=192.168.1.1
Perhaps something is missing?
I send you files I have modified...
Thanks a lot
Best regards
/* * Ethernet driver for TI TMS320DM644x (DaVinci) chips. * * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> * * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright * follows: * * ---------------------------------------------------------------------------- * * dm644x_emac.c * * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM * * Copyright (C) 2005 Texas Instruments. * * ---------------------------------------------------------------------------- * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ---------------------------------------------------------------------------- * Modifications: * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot. * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors * */ #include <common.h> #include <command.h> #include <net.h> #include <miiphy.h> #include <malloc.h> #include <linux/compiler.h> #include <asm/arch/emac_defs.h> #include <asm/io.h> #include "davinci_emac.h" unsigned int emac_dbg = 0; #define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args) #ifdef EMAC_HW_RAM_ADDR static inline unsigned long BD_TO_HW(unsigned long x) { if (x == 0) return 0; return x - EMAC_WRAPPER_RAM_ADDR + EMAC_HW_RAM_ADDR; } static inline unsigned long HW_TO_BD(unsigned long x) { if (x == 0) return 0; return x - EMAC_HW_RAM_ADDR + EMAC_WRAPPER_RAM_ADDR; } #else #define BD_TO_HW(x) (x) #define HW_TO_BD(x) (x) #endif #ifdef DAVINCI_EMAC_GIG_ENABLE #define emac_gigabit_enable(phy_addr) davinci_eth_gigabit_enable(phy_addr) #else #define emac_gigabit_enable(phy_addr) /* no gigabit to enable */ #endif #if !defined(CONFIG_SYS_EMAC_TI_CLKDIV) #define CONFIG_SYS_EMAC_TI_CLKDIV ((EMAC_MDIO_BUS_FREQ / \ EMAC_MDIO_CLOCK_FREQ) - 1) #endif static void davinci_eth_mdio_enable(void); static int gen_init_phy(int phy_addr); static int gen_is_phy_connected(int phy_addr); static int gen_get_link_speed(int phy_addr); static int gen_auto_negotiate(int phy_addr); static int gen_init_phy_wo_phy(int phy_addr); static int gen_is_phy_connected_wo_phy(int phy_addr); static int gen_get_link_speed_wo_phy(int phy_addr); static int gen_auto_negotiate_wo_phy(int phy_addr); void eth_mdio_enable(void) { davinci_eth_mdio_enable(); } /* EMAC Addresses */ static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR; static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR; static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR; /* EMAC descriptors */ static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE); static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); static volatile emac_desc *emac_rx_active_head = 0; static volatile emac_desc *emac_rx_active_tail = 0; static int emac_rx_queue_active = 0; /* Receive packet buffers */ static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE] __aligned(ARCH_DMA_MINALIGN); #ifndef CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT #define CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT 1 //3 /*seb*/ #endif /* PHY address for a discovered PHY (0xff - not found) */ static u_int8_t active_phy_addr[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT]; /* number of PHY found active */ static u_int8_t num_phy; phy_t phy[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT]; static inline void davinci_flush_rx_descs(void) { /* flush the whole RX descs area */ flush_dcache_range(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE, EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); } static inline void davinci_invalidate_rx_descs(void) { /* invalidate the whole RX descs area */ invalidate_dcache_range(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE, EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); } static inline void davinci_flush_desc(emac_desc *desc) { flush_dcache_range((unsigned long)desc, (unsigned long)desc + sizeof(*desc)); } static int davinci_eth_set_mac_addr(struct eth_device *dev) { unsigned long mac_hi; unsigned long mac_lo; /* * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast * receive) * Using channel 0 only - other channels are disabled * */ writel(0, &adap_emac->MACINDEX); mac_hi = (dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) | (dev->enetaddr[1] << 8) | (dev->enetaddr[0]); mac_lo = (dev->enetaddr[5] << 8) | (dev->enetaddr[4]); writel(mac_hi, &adap_emac->MACADDRHI); #if defined(DAVINCI_EMAC_VERSION2) writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH, &adap_emac->MACADDRLO); #else writel(mac_lo, &adap_emac->MACADDRLO); #endif writel(0, &adap_emac->MACHASH1); writel(0, &adap_emac->MACHASH2); /* Set source MAC address - REQUIRED */ writel(mac_hi, &adap_emac->MACSRCADDRHI); writel(mac_lo, &adap_emac->MACSRCADDRLO); return 0; } static void davinci_eth_mdio_enable(void) { u_int32_t clkdiv; clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV; writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE, &adap_mdio->CONTROL); while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE) ; } /* * Tries to find an active connected PHY. Returns 1 if address if found. * If no active PHY (or more than one PHY) found returns 0. * Sets active_phy_addr variable. */ static int davinci_eth_phy_detect(void) { u_int32_t phy_act_state; int i; int j; unsigned int count = 0; for (i = 0; i < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT; i++) active_phy_addr[i] = 0xff; udelay(1000); phy_act_state = readl(&adap_mdio->ALIVE); if (phy_act_state == 0) return 0; /* No active PHYs */ debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); for (i = 0, j = 0; i < 32; i++) if (phy_act_state & (1 << i)) { count++; if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) { active_phy_addr[j++] = i; } else { printf("%s: to many PHYs detected.\n", __func__); count = 0; break; } } num_phy = count; return count; } /* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) { int tmp; printf("davinci_eth_phy_read :%d,%d\n",phy_addr,reg_num); while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) ; writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | ((reg_num & 0x1f) << 21) | ((phy_addr & 0x1f) << 16), &adap_mdio->USERACCESS0); /* Wait for command to complete */ while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO) ; if (tmp & MDIO_USERACCESS0_ACK) { printf("davinci_eth_phy_read ok: %d",*data); *data = tmp & 0xffff; return(1); } *data = -1; return(0); } /* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) { printf("davinci_eth_phy_write :%d,%d,%d\n",phy_addr,reg_num,data); while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) ; writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE | ((reg_num & 0x1f) << 21) | ((phy_addr & 0x1f) << 16) | (data & 0xffff), &adap_mdio->USERACCESS0); /* Wait for command to complete */ while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) ; printf("davinci_eth_phy_write ok"); return(1); } /* PHY functions for a generic PHY */ static int gen_init_phy(int phy_addr) { int ret = 1; if (gen_get_link_speed(phy_addr)) { /* Try another time */ ret = gen_get_link_speed(phy_addr); } return(ret); } static int gen_is_phy_connected(int phy_addr) { u_int16_t dummy; return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy); } static int get_active_phy(void) { int i; for (i = 0; i < num_phy; i++) if (phy[i].get_link_speed(active_phy_addr[i])) return i; return -1; /* Return error if no link */ } static int gen_get_link_speed(int phy_addr) { u_int16_t tmp; if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04)) { #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \ defined(CONFIG_MACH_DAVINCI_DA850_EVM) davinci_eth_phy_read(phy_addr, MII_LPA, &tmp); /* Speed doesn't matter, there is no setting for it in EMAC. */ if (tmp & (LPA_100FULL | LPA_10FULL)) { /* set EMAC for Full Duplex */ writel(EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE, &adap_emac->MACCONTROL); } else { /*set EMAC for Half Duplex */ writel(EMAC_MACCONTROL_MIIEN_ENABLE, &adap_emac->MACCONTROL); } if (tmp & (LPA_100FULL | LPA_100HALF)) writel(readl(&adap_emac->MACCONTROL) | EMAC_MACCONTROL_RMIISPEED_100, &adap_emac->MACCONTROL); else writel(readl(&adap_emac->MACCONTROL) & ~EMAC_MACCONTROL_RMIISPEED_100, &adap_emac->MACCONTROL); #endif return(1); } return(0); } static int gen_auto_negotiate(int phy_addr) { u_int16_t tmp; u_int16_t val; unsigned long cntr = 0; if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp)) return 0; val = tmp | BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_SPEED100; davinci_eth_phy_write(phy_addr, MII_BMCR, val); if (!davinci_eth_phy_read(phy_addr, MII_ADVERTISE, &val)) return 0; val |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF); davinci_eth_phy_write(phy_addr, MII_ADVERTISE, val); if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp)) return(0); /* Restart Auto_negotiation */ tmp |= BMCR_ANRESTART; davinci_eth_phy_write(phy_addr, MII_BMCR, tmp); /*check AutoNegotiate complete */ do { udelay(40000); if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp)) return 0; if (tmp & BMSR_ANEGCOMPLETE) break; cntr++; } while (cntr < 200); if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp)) return(0); if (!(tmp & BMSR_ANEGCOMPLETE)) return(0); return(gen_get_link_speed(phy_addr)); } /* End of generic PHY functions */ #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) static int davinci_mii_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1); } static int davinci_mii_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value) { return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1); } #endif static void __attribute__((unused)) davinci_eth_gigabit_enable(int phy_addr) { u_int16_t data; if (davinci_eth_phy_read(phy_addr, 0, &data)) { if (data & (1 << 6)) { /* speed selection MSB */ /* * Check if link detected is giga-bit * If Gigabit mode detected, enable gigbit in MAC */ writel(readl(&adap_emac->MACCONTROL) | EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, &adap_emac->MACCONTROL); } } } /* Eth device open */ static int davinci_eth_open(struct eth_device *dev, bd_t *bis) { dv_reg_p addr; u_int32_t clkdiv, cnt; volatile emac_desc *rx_desc; int index; printf("+ emac_open\n"); debug_emac("+ emac_open\n"); /* Reset EMAC module and disable interrupts in wrapper */ writel(1, &adap_emac->SOFTRESET); while (readl(&adap_emac->SOFTRESET) != 0) ; #if defined(DAVINCI_EMAC_VERSION2) writel(1, &adap_ewrap->softrst); while (readl(&adap_ewrap->softrst) != 0) ; #else writel(0, &adap_ewrap->EWCTL); for (cnt = 0; cnt < 5; cnt++) { clkdiv = readl(&adap_ewrap->EWCTL); } #endif #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \ defined(CONFIG_MACH_DAVINCI_DA850_EVM) adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0; adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0; adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0; #endif rx_desc = emac_rx_desc; writel(1, &adap_emac->TXCONTROL); writel(1, &adap_emac->RXCONTROL); davinci_eth_set_mac_addr(dev); /* Set DMA 8 TX / 8 RX Head pointers to 0 */ addr = &adap_emac->TX0HDP; for(cnt = 0; cnt < 16; cnt++) writel(0, addr++); addr = &adap_emac->RX0HDP; for(cnt = 0; cnt < 16; cnt++) writel(0, addr++); /* Clear Statistics (do this before setting MacControl register) */ addr = &adap_emac->RXGOODFRAMES; for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++) writel(0, addr++); /* No multicast addressing */ writel(0, &adap_emac->MACHASH1); writel(0, &adap_emac->MACHASH2); /* Create RX queue and set receive process in place */ emac_rx_active_head = emac_rx_desc; for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) { rx_desc->next = BD_TO_HW((u_int32_t)(rx_desc + 1)); rx_desc->buffer = &emac_rx_buffers[cnt * EMAC_RXBUF_SIZE]; rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; rx_desc++; } /* Finalize the rx desc list */ rx_desc--; rx_desc->next = 0; emac_rx_active_tail = rx_desc; emac_rx_queue_active = 1; davinci_flush_rx_descs(); /* Enable TX/RX */ writel(EMAC_MAX_ETHERNET_PKT_SIZE, &adap_emac->RXMAXLEN); writel(0, &adap_emac->RXBUFFEROFFSET); /* * No fancy configs - Use this for promiscous debug * - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */ writel(EMAC_RXMBPENABLE_RXBROADEN, &adap_emac->RXMBPENABLE); /* Enable ch 0 only */ writel(1, &adap_emac->RXUNICASTSET); /* Enable MII interface and Full duplex mode */ #if defined(CONFIG_SOC_DA8XX) || \ (defined(CONFIG_OMAP34XX) && defined(CONFIG_DRIVER_TI_EMAC_USE_RMII)) writel((EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE | EMAC_MACCONTROL_RMIISPEED_100), &adap_emac->MACCONTROL); #else writel((EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE), &adap_emac->MACCONTROL); #endif /* Init MDIO & get link state */ clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV; writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT, &adap_mdio->CONTROL); /* We need to wait for MDIO to start */ udelay(1000); index = get_active_phy(); if (index == -1) return(0); emac_gigabit_enable(active_phy_addr[index]); /* Start receive process */ writel(BD_TO_HW((u_int32_t)emac_rx_desc), &adap_emac->RX0HDP); debug_emac("- emac_open\n"); return(1); } /* EMAC Channel Teardown */ static void davinci_eth_ch_teardown(int ch) { dv_reg dly = 0xff; dv_reg cnt; debug_emac("+ emac_ch_teardown\n"); debug_emac("+ emac_ch_teardown\n"); if (ch == EMAC_CH_TX) { /* Init TX channel teardown */ writel(0, &adap_emac->TXTEARDOWN); do { /* * Wait here for Tx teardown completion interrupt to * occur. Note: A task delay can be called here to pend * rather than occupying CPU cycles - anyway it has * been found that teardown takes very few cpu cycles * and does not affect functionality */ dly--; udelay(1); if (dly == 0) break; cnt = readl(&adap_emac->TX0CP); } while (cnt != 0xfffffffc); writel(cnt, &adap_emac->TX0CP); writel(0, &adap_emac->TX0HDP); } else { /* Init RX channel teardown */ writel(0, &adap_emac->RXTEARDOWN); do { /* * Wait here for Rx teardown completion interrupt to * occur. Note: A task delay can be called here to pend * rather than occupying CPU cycles - anyway it has * been found that teardown takes very few cpu cycles * and does not affect functionality */ dly--; udelay(1); if (dly == 0) break; cnt = readl(&adap_emac->RX0CP); } while (cnt != 0xfffffffc); writel(cnt, &adap_emac->RX0CP); writel(0, &adap_emac->RX0HDP); } debug_emac("- emac_ch_teardown\n"); debug_emac("- emac_ch_teardown\n"); } /* Eth device close */ static void davinci_eth_close(struct eth_device *dev) { debug_emac("+ emac_close\n"); printf("+ emac_close\n"); davinci_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ /* Reset EMAC module and disable interrupts in wrapper */ writel(1, &adap_emac->SOFTRESET); #if defined(DAVINCI_EMAC_VERSION2) writel(1, &adap_ewrap->softrst); #else writel(0, &adap_ewrap->EWCTL); #endif #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \ defined(CONFIG_MACH_DAVINCI_DA850_EVM) adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0; adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0; adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0; #endif debug_emac("- emac_close\n"); printf("- emac_close\n"); } static int tx_send_loop = 0; /* * This function sends a single packet on the network and returns * positive number (number of bytes transmitted) or negative for error */ static int davinci_eth_send_packet (struct eth_device *dev, volatile void *packet, int length) { int ret_status = -1; int index; tx_send_loop = 0; printf("davinci_eth_send_packet start\n"); index = get_active_phy(); if (index == -1) { printf(" WARN: emac_send_packet: No link\n"); return (ret_status); } emac_gigabit_enable(active_phy_addr[index]); /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */ if (length < EMAC_MIN_ETHERNET_PKT_SIZE) { length = EMAC_MIN_ETHERNET_PKT_SIZE; } /* Populate the TX descriptor */ emac_tx_desc->next = 0; emac_tx_desc->buffer = (u_int8_t *) packet; emac_tx_desc->buff_off_len = (length & 0xffff); emac_tx_desc->pkt_flag_len = ((length & 0xffff) | EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | EMAC_CPPI_EOP_BIT); flush_dcache_range((unsigned long)packet, (unsigned long)packet + length); davinci_flush_desc(emac_tx_desc); /* Send the packet */ writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP); /* Wait for packet to complete or link down */ while (1) { #ifndef CONFIG_DRIVER_TI_EMAC_USE_RMII if (!phy[index].get_link_speed(active_phy_addr[index])) { davinci_eth_ch_teardown (EMAC_CH_TX); return (ret_status); } #endif emac_gigabit_enable(active_phy_addr[index]); if (readl(&adap_emac->TXINTSTATRAW) & 0x01) { ret_status = length; break; } tx_send_loop++; } printf("davinci_eth_send_packet end\n"); return (ret_status); } /* * This function handles receipt of a packet from the network */ static int davinci_eth_rcv_packet (struct eth_device *dev) { volatile emac_desc *rx_curr_desc; volatile emac_desc *curr_desc; volatile emac_desc *tail_desc; int status, ret = -1; printf("davinci_eth_rcv_packet start\n"); davinci_invalidate_rx_descs(); rx_curr_desc = emac_rx_active_head; status = rx_curr_desc->pkt_flag_len; if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { if (status & EMAC_CPPI_RX_ERROR_FRAME) { /* Error in packet - discard it and requeue desc */ printf ("WARN: emac_rcv_pkt: Error in packet\n"); } else { unsigned long tmp = (unsigned long)rx_curr_desc->buffer; invalidate_dcache_range(tmp, tmp + EMAC_RXBUF_SIZE); NetReceive (rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); ret = rx_curr_desc->buff_off_len & 0xffff; } /* Ack received packet descriptor */ writel(BD_TO_HW((ulong)rx_curr_desc), &adap_emac->RX0CP); curr_desc = rx_curr_desc; emac_rx_active_head = (volatile emac_desc *) (HW_TO_BD(rx_curr_desc->next)); if (status & EMAC_CPPI_EOQ_BIT) { if (emac_rx_active_head) { writel(BD_TO_HW((ulong)emac_rx_active_head), &adap_emac->RX0HDP); } else { emac_rx_queue_active = 0; printf ("INFO:emac_rcv_packet: RX Queue not active\n"); } } /* Recycle RX descriptor */ rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; rx_curr_desc->next = 0; davinci_flush_desc(rx_curr_desc); if (emac_rx_active_head == 0) { printf ("INFO: emac_rcv_pkt: active queue head = 0\n"); emac_rx_active_head = curr_desc; emac_rx_active_tail = curr_desc; if (emac_rx_queue_active != 0) { writel(BD_TO_HW((ulong)emac_rx_active_head), &adap_emac->RX0HDP); printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n"); emac_rx_queue_active = 1; } } else { tail_desc = emac_rx_active_tail; emac_rx_active_tail = curr_desc; tail_desc->next = BD_TO_HW((ulong) curr_desc); status = tail_desc->pkt_flag_len; if (status & EMAC_CPPI_EOQ_BIT) { davinci_flush_desc(tail_desc); writel(BD_TO_HW((ulong)curr_desc), &adap_emac->RX0HDP); status &= ~EMAC_CPPI_EOQ_BIT; tail_desc->pkt_flag_len = status; } davinci_flush_desc(tail_desc); } printf("davinci_eth_rcv_packet ok\n"); return (ret); } printf("davinci_eth_rcv_packet ko\n"); return (0); } /* * This function initializes the emac hardware. It does NOT initialize * EMAC modules power or pin multiplexors, that is done by board_init() * much earlier in bootup process. Returns 1 on success, 0 otherwise. */ #if 0 int davinci_emac_initialize(void) { u_int32_t phy_id; u_int16_t tmp; int i; int ret; struct eth_device *dev; dev = malloc(sizeof *dev); if (dev == NULL) return -1; memset(dev, 0, sizeof *dev); sprintf(dev->name, "DaVinci-EMAC"); dev->iobase = 0; dev->init = davinci_eth_open; dev->halt = davinci_eth_close; dev->send = davinci_eth_send_packet; dev->recv = davinci_eth_rcv_packet; dev->write_hwaddr = davinci_eth_set_mac_addr; eth_register(dev); davinci_eth_mdio_enable(); /* let the EMAC detect the PHYs */ udelay(5000); for (i = 0; i < 256; i++) { if (readl(&adap_mdio->ALIVE)) break; udelay(1000); } if (i >= 256) { printf("No ETH PHY detected!!!\n"); return(0); } /* Find if PHY(s) is/are connected */ ret = davinci_eth_phy_detect(); if (!ret) return(0); else debug_emac(" %d ETH PHY detected\n", ret); /* Get PHY ID and initialize phy_ops for a detected PHY */ for (i = 0; i < num_phy; i++) { if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID1, &tmp)) { active_phy_addr[i] = 0xff; continue; } phy_id = (tmp << 16) & 0xffff0000; if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID2, &tmp)) { active_phy_addr[i] = 0xff; continue; } phy_id |= tmp & 0x0000ffff; switch (phy_id) { #ifdef PHY_KSZ8873 case PHY_KSZ8873: sprintf(phy[i].name, "KSZ8873 @ 0x%02x", active_phy_addr[i]); phy[i].init = ksz8873_init_phy; phy[i].is_phy_connected = ksz8873_is_phy_connected; phy[i].get_link_speed = ksz8873_get_link_speed; phy[i].auto_negotiate = ksz8873_auto_negotiate; break; #endif #ifdef PHY_LXT972 case PHY_LXT972: sprintf(phy[i].name, "LXT972 @ 0x%02x", active_phy_addr[i]); phy[i].init = lxt972_init_phy; phy[i].is_phy_connected = lxt972_is_phy_connected; phy[i].get_link_speed = lxt972_get_link_speed; phy[i].auto_negotiate = lxt972_auto_negotiate; break; #endif #ifdef PHY_DP83848 case PHY_DP83848: sprintf(phy[i].name, "DP83848 @ 0x%02x", active_phy_addr[i]); phy[i].init = dp83848_init_phy; phy[i].is_phy_connected = dp83848_is_phy_connected; phy[i].get_link_speed = dp83848_get_link_speed; phy[i].auto_negotiate = dp83848_auto_negotiate; break; #endif #ifdef PHY_ET1011C case PHY_ET1011C: sprintf(phy[i].name, "ET1011C @ 0x%02x", active_phy_addr[i]); phy[i].init = gen_init_phy; phy[i].is_phy_connected = gen_is_phy_connected; phy[i].get_link_speed = et1011c_get_link_speed; phy[i].auto_negotiate = gen_auto_negotiate; break; #endif default: sprintf(phy[i].name, "GENERIC @ 0x%02x", active_phy_addr[i]); phy[i].init = gen_init_phy; phy[i].is_phy_connected = gen_is_phy_connected; phy[i].get_link_speed = gen_get_link_speed; phy[i].auto_negotiate = gen_auto_negotiate; } debug("Ethernet PHY: %s\n", phy[i].name); miiphy_register(phy[i].name, davinci_mii_phy_read, davinci_mii_phy_write); } #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \ defined(CONFIG_MACH_DAVINCI_DA850_EVM) for (i = 0; i < num_phy; i++) { if (phy[i].is_phy_connected(i)) phy[i].auto_negotiate(i); } #endif return(1); } #endif /* PHY functions for a generic PHY */ static int gen_init_phy_wo_phy(int phy_addr) { printf("gen_init_phy_wo_phy :%d\n",phy_addr); return 1; } static int gen_is_phy_connected_wo_phy(int phy_addr) { printf("gen_is_phy_connected_wo_phy :%d\n",phy_addr); return 1; } static int gen_get_link_speed_wo_phy(int phy_addr) { printf("gen_get_link_speed_wo_phy :%d\n",phy_addr); return 1; } static int gen_auto_negotiate_wo_phy(int phy_addr) { printf("gen_auto_negotiate_wo_phy :%d\n",phy_addr); return 1; } int davinci_emac_initialize(void) { u_int32_t phy_id; u_int16_t tmp; int i; int ret; struct eth_device *dev; dev = malloc(sizeof *dev); if (dev == NULL) return -1; memset(dev, 0, sizeof *dev); sprintf(dev->name, "DaVinci-EMAC"); dev->iobase = 0; dev->init = davinci_eth_open; dev->halt = davinci_eth_close; dev->send = davinci_eth_send_packet; dev->recv = davinci_eth_rcv_packet; dev->write_hwaddr = davinci_eth_set_mac_addr; eth_register(dev); davinci_eth_mdio_enable(); num_phy = 1; for (i = 0; i < num_phy; i++) { active_phy_addr[i] = 0; phy[i].init = gen_init_phy_wo_phy; phy[i].is_phy_connected = gen_is_phy_connected_wo_phy; phy[i].get_link_speed = gen_get_link_speed_wo_phy; phy[i].auto_negotiate = gen_auto_negotiate_wo_phy; sprintf(phy[i].name, "Working without Ethernet PHY"); miiphy_register(phy[i].name, davinci_mii_phy_read, davinci_mii_phy_write); printf("%s at 100Mb/s\n",phy[i].name); } return(1); }
/* * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ * * Based on da850evm.c. Original Copyrights follow: * * Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. <nick.thompson@gefanuc.com> * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <common.h> #include <i2c.h> #include <net.h> #include <netdev.h> #include <spi.h> #include <spi_flash.h> #include <asm/arch/hardware.h> #include <asm/arch/emif_defs.h> #include <asm/arch/emac_defs.h> #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/davinci_misc.h> #ifdef CONFIG_DAVINCI_MMC #include <mmc.h> #include <asm/arch/sdmmc_defs.h> #endif DECLARE_GLOBAL_DATA_PTR; #define pinmux(x) (&davinci_syscfg_regs->pinmux[x]) #ifdef CONFIG_DAVINCI_MMC /* MMC0 pin muxer settings */ const struct pinmux_config mmc0_pins[] = { /* GP0[11] is required for SD to work on Rev 3 EVMs */ { pinmux(0), 8, 4 }, /* GP0[11] */ { pinmux(10), 2, 0 }, /* MMCSD0_CLK */ { pinmux(10), 2, 1 }, /* MMCSD0_CMD */ { pinmux(10), 2, 2 }, /* MMCSD0_DAT_0 */ { pinmux(10), 2, 3 }, /* MMCSD0_DAT_1 */ { pinmux(10), 2, 4 }, /* MMCSD0_DAT_2 */ { pinmux(10), 2, 5 }, /* MMCSD0_DAT_3 */ /* LCDK supports only 4-bit mode, remaining pins are not configured */ }; #endif /* UART pin muxer settings */ static const struct pinmux_config uart_pins[] = { { pinmux(0), 4, 6 }, { pinmux(0), 4, 7 }, { pinmux(4), 2, 4 }, { pinmux(4), 2, 5 } }; #ifdef CONFIG_DRIVER_TI_EMAC static const struct pinmux_config emac_pins[] = { { pinmux(2), 8, 1 }, { pinmux(2), 8, 2 }, { pinmux(2), 8, 3 }, { pinmux(2), 8, 4 }, { pinmux(2), 8, 5 }, { pinmux(2), 8, 6 }, { pinmux(2), 8, 7 }, { pinmux(3), 8, 0 }, { pinmux(3), 8, 1 }, { pinmux(3), 8, 2 }, { pinmux(3), 8, 3 }, { pinmux(3), 8, 4 }, { pinmux(3), 8, 5 }, { pinmux(3), 8, 6 }, { pinmux(3), 8, 7 }, { pinmux(4), 8, 0 }, { pinmux(4), 8, 1 } }; #endif /* CONFIG_DRIVER_TI_EMAC */ /* I2C pin muxer settings */ static const struct pinmux_config i2c_pins[] = { { pinmux(4), 2, 2 }, { pinmux(4), 2, 3 } }; #ifdef CONFIG_NAND_DAVINCI const struct pinmux_config nand_pins[] = { { pinmux(7), 1, 1 }, { pinmux(7), 1, 2 }, { pinmux(7), 1, 4 }, { pinmux(7), 1, 5 }, { pinmux(8), 1, 0 }, { pinmux(8), 1, 1 }, { pinmux(8), 1, 2 }, { pinmux(8), 1, 3 }, { pinmux(8), 1, 4 }, { pinmux(8), 1, 5 }, { pinmux(8), 1, 6 }, { pinmux(8), 1, 7 }, { pinmux(9), 1, 0 }, { pinmux(9), 1, 1 }, { pinmux(9), 1, 2 }, { pinmux(9), 1, 3 }, { pinmux(9), 1, 4 }, { pinmux(9), 1, 5 }, { pinmux(9), 1, 6 }, { pinmux(9), 1, 7 }, { pinmux(12), 1, 5 }, { pinmux(12), 1, 6 } }; #endif #ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII #define HAS_RMII 1 #else #define HAS_RMII 0 #endif static const struct pinmux_resource pinmuxes[] = { PINMUX_ITEM(uart_pins), PINMUX_ITEM(i2c_pins), #ifdef CONFIG_NAND_DAVINCI PINMUX_ITEM(nand_pins), #endif }; static const struct lpsc_resource lpsc[] = { { DAVINCI_LPSC_AEMIF }, /* NAND, NOR */ { DAVINCI_LPSC_SPI1 }, /* Serial Flash */ { DAVINCI_LPSC_EMAC }, /* image download */ { DAVINCI_LPSC_UART1/*DAVINCI_LPSC_UART2*/ }, /* console */ //SEB { DAVINCI_LPSC_GPIO }, #ifdef CONFIG_DAVINCI_MMC { DAVINCI_LPSC_MMC_SD }, #endif }; #ifndef CONFIG_DA850_EVM_MAX_CPU_CLK #define CONFIG_DA850_EVM_MAX_CPU_CLK 456000000 #endif /* * get_board_rev() - setup to pass kernel board revision information * Returns: * bit[0-3] Maximum cpu clock rate supported by onboard SoC * 0000b - 300 MHz * 0001b - 372 MHz * 0010b - 408 MHz * 0011b - 456 MHz */ u32 get_board_rev(void) { return 0; } int board_early_init_f(void) { /* * Power on required peripherals * ARM does not have access by default to PSC0 and PSC1 * assuming here that the DSP bootloader has set the IOPU * such that PSC access is available to ARM */ if (da8xx_configure_lpsc_items(lpsc, ARRAY_SIZE(lpsc))) return 1; return 0; } int board_init(void) { unsigned int temp; #ifndef CONFIG_USE_IRQ irq_init(); #endif /* arch number of the board */ gd->bd->bi_arch_number = MACH_TYPE_OMAPL138_LCDK; /* address of boot parameters */ gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; /*gd->bd->bi_dram[0].start = PHYS_SDRAM_1; gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; gd->bd->bi_dram[1].start = PHYS_SDRAM_2; gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; gd->bd->bi_dram[2].start = PHYS_SDRAM_3; gd->bd->bi_dram[2].size = PHYS_SDRAM_3_SIZE; gd->bd->bi_dram[3].start = PHYS_SDRAM_4; gd->bd->bi_dram[3].size = PHYS_SDRAM_4_SIZE; gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE) + get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE) + get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE) + get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE);*/ /* setup the SUSPSRC for ARM to control emulation suspend */ writel(readl(&davinci_syscfg_regs->suspsrc) & ~(DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C | DAVINCI_SYSCFG_SUSPSRC_SPI1 | DAVINCI_SYSCFG_SUSPSRC_TIMER0 | /*DAVINCI_SYSCFG_SUSPSRC_UART2*/DAVINCI_SYSCFG_SUSPSRC_UART1),//SEB &davinci_syscfg_regs->suspsrc); /* configure pinmux settings */ if (davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes))) return 1; #ifdef CONFIG_NAND_DAVINCI /* * NAND CS setup - cycle counts based on da850evm NAND timings in the * Linux kernel @ 25MHz EMIFA */ writel((DAVINCI_ABCR_WSETUP(15) | DAVINCI_ABCR_WSTROBE(63) | DAVINCI_ABCR_WHOLD(7) | DAVINCI_ABCR_RSETUP(15) | DAVINCI_ABCR_RSTROBE(63) | DAVINCI_ABCR_RHOLD(7) | DAVINCI_ABCR_TA(3) | /*DAVINCI_ABCR_ASIZE_16BIT*/DAVINCI_ABCR_ASIZE_8BIT), &davinci_emif_regs->ab2cr); /* CS3 */ #endif #ifdef CONFIG_DAVINCI_MMC if (davinci_configure_pin_mux(mmc0_pins, ARRAY_SIZE(mmc0_pins)) != 0) return 1; #endif #ifdef CONFIG_DRIVER_TI_EMAC if (davinci_configure_pin_mux(emac_pins, ARRAY_SIZE(emac_pins)) != 0) return 1; davinci_emac_mii_mode_sel(HAS_RMII); #endif /* CONFIG_DRIVER_TI_EMAC */ /* enable the console UART */ writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST | DAVINCI_UART_PWREMU_MGMT_UTRST), /*&davinci_uart2_ctrl_regs->pwremu_mgmt*/&davinci_uart1_ctrl_regs->pwremu_mgmt);//SEB return 0; } #ifdef CONFIG_DRIVER_TI_EMAC /* * Initializes on-board ethernet controllers. */ int board_eth_init(bd_t *bis) { if (!davinci_emac_initialize()) { printf("Error: Ethernet init failed!\n"); return -1; } return 0; } #endif /* CONFIG_DRIVER_TI_EMAC */ #define CFG_MAC_ADDR_SPI_BUS 0 #define CFG_MAC_ADDR_SPI_CS 0 #define CFG_MAC_ADDR_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED #define CFG_MAC_ADDR_SPI_MODE SPI_MODE_3 #define CFG_MAC_ADDR_OFFSET (flash->size - SZ_64K) static int get_mac_addr(u8 *addr) { /* Need to find a way to get MAC ADDRESS */ return 0; } void dsp_lpsc_on(unsigned domain, unsigned int id) { dv_reg_p mdstat, mdctl, ptstat, ptcmd; struct davinci_psc_regs *psc_regs; psc_regs = davinci_psc0_regs; mdstat = &psc_regs->psc0.mdstat[id]; mdctl = &psc_regs->psc0.mdctl[id]; ptstat = &psc_regs->ptstat; ptcmd = &psc_regs->ptcmd; while (*ptstat & (0x1 << domain)) ; if ((*mdstat & 0x1f) == 0x03) return; /* Already on and enabled */ *mdctl |= 0x03; *ptcmd = 0x1 << domain; while (*ptstat & (0x1 << domain)) ; while ((*mdstat & 0x1f) != 0x03) ; /* Probably an overkill... */ } static void dspwake(void) { unsigned *resetvect = (unsigned *)DAVINCI_L3CBARAM_BASE; /* if the device is ARM only, return */ if ((REG(CHIP_REV_ID_REG) & 0x3f) == 0x10) return; if (!strcmp(getenv("dspwake"), "no")) return; *resetvect++ = 0x1E000; /* DSP Idle */ /* clear out the next 10 words as NOP */ memset(resetvect, 0, sizeof(unsigned) * 10); /* setup the DSP reset vector */ REG(HOST1CFG) = DAVINCI_L3CBARAM_BASE; dsp_lpsc_on(1, DAVINCI_LPSC_GEM); REG(PSC0_MDCTL + (15 * 4)) |= 0x100; } #ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII /** * rmii_hw_init * */ int rmii_hw_init(void) { return 0; } #endif /* CONFIG_DRIVER_TI_EMAC_USE_RMII */ int misc_init_r(void) { uint8_t tmp[20], addr[10]; if (getenv("ethaddr") == NULL) { /* Read Ethernet MAC address from EEPROM */ if (dvevm_read_mac_address(addr)) { /* Set Ethernet MAC address from EEPROM */ davinci_sync_env_enetaddr(addr); } else { get_mac_addr(addr); } if (is_multicast_ether_addr(addr) || is_zero_ether_addr(addr)) { printf("Invalid MAC address read.\n"); return -EINVAL; } sprintf((char *)tmp, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); setenv("ethaddr", (char *)tmp); } #ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII /* Select RMII fucntion through the expander */ if (rmii_hw_init()) printf("RMII hardware init failed!!!\n"); #endif dspwake(); return 0; } #ifdef CONFIG_DAVINCI_MMC static struct davinci_mmc mmc_sd0 = { .reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE, .host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, .version = MMC_CTLR_VERSION_2, }; int board_mmc_init(bd_t *bis) { mmc_sd0.input_clk = clk_get(DAVINCI_MMCSD_CLKID); /* Add slot-0 to mmc subsystem */ return davinci_mmc_init(bis, &mmc_sd0); } #endif
Sebastien
Hi,
Switch into FPGA doesn't have PHY; it communicates to PC by SFP module with another protocol than MII . But switch communicate to OMAPL by MII protocol fixed to 100Mb/s (25MHz clock).
So on the omapl side, there is not PHY connected.
I'm sure that FPGA connectivity by switch is good PC to OMAPL and OMAPL to PC because with Linux it's working.