X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fdavinci_emac.c;h=5e7ebc8a99f3cb7b458b6e973947759cf47a4a61;hb=46fe9eb08812cc27a0d5cd97d97373c14d578fe9;hp=476039059126fc0895f0ca4a25407335d4982fd9;hpb=2aa8720257beadde8f798bd30096ca4c9007c8e0;p=oweals%2Fu-boot.git diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 4760390591..5e7ebc8a99 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -16,31 +16,18 @@ * * ---------------------------------------------------------------------------- * - * 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. + * SPDX-License-Identifier: GPL-2.0+ * - * 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 #include #include #include #include +#include #include #include #include @@ -121,26 +108,6 @@ 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; @@ -220,7 +187,7 @@ static int davinci_eth_phy_detect(void) for (i = 0, j = 0; i < 32; i++) if (phy_act_state & (1 << i)) { count++; - if (count < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) { + if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) { active_phy_addr[j++] = i; } else { printf("%s: to many PHYs detected.\n", @@ -256,11 +223,10 @@ int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) if (tmp & MDIO_USERACCESS0_ACK) { *data = tmp & 0xffff; - return(1); + return 1; } - *data = -1; - return(0); + return 0; } /* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ @@ -281,7 +247,7 @@ int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) ; - return(1); + return 1; } /* PHY functions for a generic PHY */ @@ -403,14 +369,19 @@ static int gen_auto_negotiate(int phy_addr) #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) +static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad, + int reg) { - return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1); + unsigned short value = 0; + int retval = davinci_eth_phy_read(addr, reg, &value); + + return retval ? value : -EIO; } -static int davinci_mii_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value) +static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad, + int reg, u16 value) { - return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1); + return davinci_eth_phy_write(addr, reg, value) ? 0 : 1; } #endif @@ -472,11 +443,11 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis) /* Set DMA 8 TX / 8 RX Head pointers to 0 */ addr = &adap_emac->TX0HDP; - for(cnt = 0; cnt < 16; cnt++) + for (cnt = 0; cnt < 8; cnt++) writel(0, addr++); addr = &adap_emac->RX0HDP; - for(cnt = 0; cnt < 16; cnt++) + for (cnt = 0; cnt < 8; cnt++) writel(0, addr++); /* Clear Statistics (do this before setting MacControl register) */ @@ -504,8 +475,6 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis) 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); @@ -520,7 +489,8 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis) writel(1, &adap_emac->RXUNICASTSET); /* Enable MII interface and Full duplex mode */ -#ifdef CONFIG_SOC_DA8XX +#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), @@ -610,7 +580,8 @@ static void davinci_eth_close(struct eth_device *dev) debug_emac("+ emac_close\n"); davinci_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ - davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ + if (readl(&adap_emac->RXCONTROL) & 1) + davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ /* Reset EMAC module and disable interrupts in wrapper */ writel(1, &adap_emac->SOFTRESET); @@ -636,7 +607,7 @@ static int tx_send_loop = 0; * 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) + void *packet, int length) { int ret_status = -1; int index; @@ -665,8 +636,7 @@ static int davinci_eth_send_packet (struct eth_device *dev, EMAC_CPPI_EOP_BIT); flush_dcache_range((unsigned long)packet, - (unsigned long)packet + length); - davinci_flush_desc(emac_tx_desc); + (unsigned long)packet + ALIGN(length, PKTALIGN)); /* Send the packet */ writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP); @@ -700,21 +670,22 @@ static int davinci_eth_rcv_packet (struct eth_device *dev) volatile emac_desc *tail_desc; int status, ret = -1; - davinci_invalidate_rx_descs(); - rx_curr_desc = emac_rx_active_head; + if (!rx_curr_desc) + return 0; status = rx_curr_desc->pkt_flag_len; - if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { + if ((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; + unsigned short len = + rx_curr_desc->buff_off_len & 0xffff; - 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; + invalidate_dcache_range(tmp, tmp + ALIGN(len, PKTALIGN)); + net_process_received_packet(rx_curr_desc->buffer, len); + ret = len; } /* Ack received packet descriptor */ @@ -737,7 +708,6 @@ static int davinci_eth_rcv_packet (struct eth_device *dev) 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"); @@ -755,13 +725,11 @@ static int davinci_eth_rcv_packet (struct eth_device *dev) 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); } return (ret); } @@ -787,7 +755,7 @@ int davinci_emac_initialize(void) return -1; memset(dev, 0, sizeof *dev); - sprintf(dev->name, "DaVinci-EMAC"); + strcpy(dev->name, "DaVinci-EMAC"); dev->iobase = 0; dev->init = davinci_eth_open; @@ -891,8 +859,26 @@ int davinci_emac_initialize(void) debug("Ethernet PHY: %s\n", phy[i].name); - miiphy_register(phy[i].name, davinci_mii_phy_read, - davinci_mii_phy_write); + int retval; + struct mii_dev *mdiodev = mdio_alloc(); + if (!mdiodev) + return -ENOMEM; + strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN); + mdiodev->read = davinci_mii_phy_read; + mdiodev->write = davinci_mii_phy_write; + + retval = mdio_register(mdiodev); + if (retval < 0) + return retval; + } + +#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \ + defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \ + !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE) + for (i = 0; i < num_phy; i++) { + if (phy[i].is_phy_connected(i)) + phy[i].auto_negotiate(i); } +#endif return(1); }