19751ee09SNobuhiro Iwamatsu /* 29751ee09SNobuhiro Iwamatsu * sh_eth.c - Driver for Renesas SH7763's ethernet controler. 39751ee09SNobuhiro Iwamatsu * 49751ee09SNobuhiro Iwamatsu * Copyright (C) 2008 Renesas Solutions Corp. 59751ee09SNobuhiro Iwamatsu * Copyright (c) 2008 Nobuhiro Iwamatsu 69751ee09SNobuhiro Iwamatsu * Copyright (c) 2007 Carlos Munoz <carlos@kenati.com> 79751ee09SNobuhiro Iwamatsu * 89751ee09SNobuhiro Iwamatsu * This program is free software; you can redistribute it and/or modify 99751ee09SNobuhiro Iwamatsu * it under the terms of the GNU General Public License as published by 109751ee09SNobuhiro Iwamatsu * the Free Software Foundation; either version 2 of the License, or 119751ee09SNobuhiro Iwamatsu * (at your option) any later version. 129751ee09SNobuhiro Iwamatsu * 139751ee09SNobuhiro Iwamatsu * This program is distributed in the hope that it will be useful, 149751ee09SNobuhiro Iwamatsu * but WITHOUT ANY WARRANTY; without even the implied warranty of 159751ee09SNobuhiro Iwamatsu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 169751ee09SNobuhiro Iwamatsu * GNU General Public License for more details. 179751ee09SNobuhiro Iwamatsu * 189751ee09SNobuhiro Iwamatsu * You should have received a copy of the GNU General Public License 199751ee09SNobuhiro Iwamatsu * along with this program; if not, write to the Free Software 209751ee09SNobuhiro Iwamatsu * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 219751ee09SNobuhiro Iwamatsu */ 229751ee09SNobuhiro Iwamatsu 239751ee09SNobuhiro Iwamatsu #include <config.h> 249751ee09SNobuhiro Iwamatsu #include <common.h> 259751ee09SNobuhiro Iwamatsu #include <malloc.h> 269751ee09SNobuhiro Iwamatsu #include <net.h> 27bd3980ccSNobuhiro Iwamatsu #include <netdev.h> 289751ee09SNobuhiro Iwamatsu #include <asm/errno.h> 299751ee09SNobuhiro Iwamatsu #include <asm/io.h> 309751ee09SNobuhiro Iwamatsu 319751ee09SNobuhiro Iwamatsu #include "sh_eth.h" 329751ee09SNobuhiro Iwamatsu 339751ee09SNobuhiro Iwamatsu #ifndef CONFIG_SH_ETHER_USE_PORT 349751ee09SNobuhiro Iwamatsu # error "Please define CONFIG_SH_ETHER_USE_PORT" 359751ee09SNobuhiro Iwamatsu #endif 369751ee09SNobuhiro Iwamatsu #ifndef CONFIG_SH_ETHER_PHY_ADDR 379751ee09SNobuhiro Iwamatsu # error "Please define CONFIG_SH_ETHER_PHY_ADDR" 389751ee09SNobuhiro Iwamatsu #endif 399751ee09SNobuhiro Iwamatsu 40bd3980ccSNobuhiro Iwamatsu #define SH_ETH_PHY_DELAY 50000 419751ee09SNobuhiro Iwamatsu 429751ee09SNobuhiro Iwamatsu /* 439751ee09SNobuhiro Iwamatsu * Bits are written to the PHY serially using the 449751ee09SNobuhiro Iwamatsu * PIR register, just like a bit banger. 459751ee09SNobuhiro Iwamatsu */ 469751ee09SNobuhiro Iwamatsu static void sh_eth_mii_write_phy_bits(int port, u32 val, int len) 479751ee09SNobuhiro Iwamatsu { 489751ee09SNobuhiro Iwamatsu int i; 499751ee09SNobuhiro Iwamatsu u32 pir; 509751ee09SNobuhiro Iwamatsu 519751ee09SNobuhiro Iwamatsu /* Bit positions is 1 less than the number of bits */ 529751ee09SNobuhiro Iwamatsu for (i = len - 1; i >= 0; i--) { 539751ee09SNobuhiro Iwamatsu /* Write direction, bit to write, clock is low */ 549751ee09SNobuhiro Iwamatsu pir = 2 | ((val & 1 << i) ? 1 << 2 : 0); 559751ee09SNobuhiro Iwamatsu outl(pir, PIR(port)); 569751ee09SNobuhiro Iwamatsu udelay(1); 579751ee09SNobuhiro Iwamatsu /* Write direction, bit to write, clock is high */ 589751ee09SNobuhiro Iwamatsu pir = 3 | ((val & 1 << i) ? 1 << 2 : 0); 599751ee09SNobuhiro Iwamatsu outl(pir, PIR(port)); 609751ee09SNobuhiro Iwamatsu udelay(1); 619751ee09SNobuhiro Iwamatsu /* Write direction, bit to write, clock is low */ 629751ee09SNobuhiro Iwamatsu pir = 2 | ((val & 1 << i) ? 1 << 2 : 0); 639751ee09SNobuhiro Iwamatsu outl(pir, PIR(port)); 649751ee09SNobuhiro Iwamatsu udelay(1); 659751ee09SNobuhiro Iwamatsu } 669751ee09SNobuhiro Iwamatsu } 679751ee09SNobuhiro Iwamatsu 689751ee09SNobuhiro Iwamatsu static void sh_eth_mii_bus_release(int port) 699751ee09SNobuhiro Iwamatsu { 709751ee09SNobuhiro Iwamatsu /* Read direction, clock is low */ 719751ee09SNobuhiro Iwamatsu outl(0, PIR(port)); 729751ee09SNobuhiro Iwamatsu udelay(1); 739751ee09SNobuhiro Iwamatsu /* Read direction, clock is high */ 749751ee09SNobuhiro Iwamatsu outl(1, PIR(port)); 759751ee09SNobuhiro Iwamatsu udelay(1); 769751ee09SNobuhiro Iwamatsu /* Read direction, clock is low */ 779751ee09SNobuhiro Iwamatsu outl(0, PIR(port)); 789751ee09SNobuhiro Iwamatsu udelay(1); 799751ee09SNobuhiro Iwamatsu } 809751ee09SNobuhiro Iwamatsu 819751ee09SNobuhiro Iwamatsu static void sh_eth_mii_ind_bus_release(int port) 829751ee09SNobuhiro Iwamatsu { 839751ee09SNobuhiro Iwamatsu /* Read direction, clock is low */ 849751ee09SNobuhiro Iwamatsu outl(0, PIR(port)); 859751ee09SNobuhiro Iwamatsu udelay(1); 869751ee09SNobuhiro Iwamatsu } 879751ee09SNobuhiro Iwamatsu 88bd3980ccSNobuhiro Iwamatsu static void sh_eth_mii_read_phy_bits(int port, u32 *val, int len) 899751ee09SNobuhiro Iwamatsu { 909751ee09SNobuhiro Iwamatsu int i; 919751ee09SNobuhiro Iwamatsu u32 pir; 929751ee09SNobuhiro Iwamatsu 939751ee09SNobuhiro Iwamatsu *val = 0; 949751ee09SNobuhiro Iwamatsu for (i = len - 1; i >= 0; i--) { 959751ee09SNobuhiro Iwamatsu /* Read direction, clock is high */ 969751ee09SNobuhiro Iwamatsu outl(1, PIR(port)); 979751ee09SNobuhiro Iwamatsu udelay(1); 989751ee09SNobuhiro Iwamatsu /* Read bit */ 999751ee09SNobuhiro Iwamatsu pir = inl(PIR(port)); 1009751ee09SNobuhiro Iwamatsu *val |= (pir & 8) ? 1 << i : 0; 1019751ee09SNobuhiro Iwamatsu /* Read direction, clock is low */ 1029751ee09SNobuhiro Iwamatsu outl(0, PIR(port)); 1039751ee09SNobuhiro Iwamatsu udelay(1); 1049751ee09SNobuhiro Iwamatsu } 1059751ee09SNobuhiro Iwamatsu } 1069751ee09SNobuhiro Iwamatsu 1079751ee09SNobuhiro Iwamatsu #define PHY_INIT 0xFFFFFFFF 1089751ee09SNobuhiro Iwamatsu #define PHY_READ 0x02 1099751ee09SNobuhiro Iwamatsu #define PHY_WRITE 0x01 1109751ee09SNobuhiro Iwamatsu /* 1119751ee09SNobuhiro Iwamatsu * To read a phy register, mii managements frames are sent to the phy. 1129751ee09SNobuhiro Iwamatsu * The frames look like this: 1139751ee09SNobuhiro Iwamatsu * pre (32 bits): 0xffff ffff 1149751ee09SNobuhiro Iwamatsu * st (2 bits): 01 1159751ee09SNobuhiro Iwamatsu * op (2bits): 10: read 01: write 1169751ee09SNobuhiro Iwamatsu * phyad (5 bits): xxxxx 1179751ee09SNobuhiro Iwamatsu * regad (5 bits): xxxxx 1189751ee09SNobuhiro Iwamatsu * ta (Bus release): 1199751ee09SNobuhiro Iwamatsu * data (16 bits): read data 1209751ee09SNobuhiro Iwamatsu */ 1219751ee09SNobuhiro Iwamatsu static u32 sh_eth_mii_read_phy_reg(int port, u8 phy_addr, int reg) 1229751ee09SNobuhiro Iwamatsu { 1239751ee09SNobuhiro Iwamatsu u32 val; 1249751ee09SNobuhiro Iwamatsu 1259751ee09SNobuhiro Iwamatsu /* Sent mii management frame */ 1269751ee09SNobuhiro Iwamatsu /* pre */ 1279751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, PHY_INIT, 32); 1289751ee09SNobuhiro Iwamatsu /* st (start of frame) */ 1299751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, 0x1, 2); 1309751ee09SNobuhiro Iwamatsu /* op (code) */ 1319751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, PHY_READ, 2); 1329751ee09SNobuhiro Iwamatsu /* phy address */ 1339751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, phy_addr, 5); 1349751ee09SNobuhiro Iwamatsu /* Register to read */ 1359751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, reg, 5); 1369751ee09SNobuhiro Iwamatsu 1379751ee09SNobuhiro Iwamatsu /* Bus release */ 1389751ee09SNobuhiro Iwamatsu sh_eth_mii_bus_release(port); 1399751ee09SNobuhiro Iwamatsu 1409751ee09SNobuhiro Iwamatsu /* Read register */ 1419751ee09SNobuhiro Iwamatsu sh_eth_mii_read_phy_bits(port, &val, 16); 1429751ee09SNobuhiro Iwamatsu 1439751ee09SNobuhiro Iwamatsu return val; 1449751ee09SNobuhiro Iwamatsu } 1459751ee09SNobuhiro Iwamatsu 1469751ee09SNobuhiro Iwamatsu /* 1479751ee09SNobuhiro Iwamatsu * To write a phy register, mii managements frames are sent to the phy. 1489751ee09SNobuhiro Iwamatsu * The frames look like this: 1499751ee09SNobuhiro Iwamatsu * pre (32 bits): 0xffff ffff 1509751ee09SNobuhiro Iwamatsu * st (2 bits): 01 1519751ee09SNobuhiro Iwamatsu * op (2bits): 10: read 01: write 1529751ee09SNobuhiro Iwamatsu * phyad (5 bits): xxxxx 1539751ee09SNobuhiro Iwamatsu * regad (5 bits): xxxxx 1549751ee09SNobuhiro Iwamatsu * ta (2 bits): 10 1559751ee09SNobuhiro Iwamatsu * data (16 bits): write data 1569751ee09SNobuhiro Iwamatsu * idle (Independent bus release) 1579751ee09SNobuhiro Iwamatsu */ 1589751ee09SNobuhiro Iwamatsu static void sh_eth_mii_write_phy_reg(int port, u8 phy_addr, int reg, u16 val) 1599751ee09SNobuhiro Iwamatsu { 1609751ee09SNobuhiro Iwamatsu /* Sent mii management frame */ 1619751ee09SNobuhiro Iwamatsu /* pre */ 1629751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, PHY_INIT, 32); 1639751ee09SNobuhiro Iwamatsu /* st (start of frame) */ 1649751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, 0x1, 2); 1659751ee09SNobuhiro Iwamatsu /* op (code) */ 1669751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, PHY_WRITE, 2); 1679751ee09SNobuhiro Iwamatsu /* phy address */ 1689751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, phy_addr, 5); 1699751ee09SNobuhiro Iwamatsu /* Register to read */ 1709751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, reg, 5); 1719751ee09SNobuhiro Iwamatsu /* ta */ 1729751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, PHY_READ, 2); 1739751ee09SNobuhiro Iwamatsu /* Write register data */ 1749751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_bits(port, val, 16); 1759751ee09SNobuhiro Iwamatsu 1769751ee09SNobuhiro Iwamatsu /* Independent bus release */ 1779751ee09SNobuhiro Iwamatsu sh_eth_mii_ind_bus_release(port); 1789751ee09SNobuhiro Iwamatsu } 1799751ee09SNobuhiro Iwamatsu 180bd3980ccSNobuhiro Iwamatsu int sh_eth_send(struct eth_device *dev, volatile void *packet, int len) 1819751ee09SNobuhiro Iwamatsu { 182bd3980ccSNobuhiro Iwamatsu struct sh_eth_dev *eth = dev->priv; 183bd3980ccSNobuhiro Iwamatsu int port = eth->port, ret = 0, timeout; 184bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 1859751ee09SNobuhiro Iwamatsu 1869751ee09SNobuhiro Iwamatsu if (!packet || len > 0xffff) { 187bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": %s: Invalid argument\n", __func__); 188bd3980ccSNobuhiro Iwamatsu ret = -EINVAL; 189bd3980ccSNobuhiro Iwamatsu goto err; 1909751ee09SNobuhiro Iwamatsu } 1919751ee09SNobuhiro Iwamatsu 1929751ee09SNobuhiro Iwamatsu /* packet must be a 4 byte boundary */ 1939751ee09SNobuhiro Iwamatsu if ((int)packet & (4 - 1)) { 194bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n", __func__); 195bd3980ccSNobuhiro Iwamatsu ret = -EFAULT; 196bd3980ccSNobuhiro Iwamatsu goto err; 1979751ee09SNobuhiro Iwamatsu } 1989751ee09SNobuhiro Iwamatsu 1999751ee09SNobuhiro Iwamatsu /* Update tx descriptor */ 2009751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur->td2 = ADDR_TO_PHY(packet); 2019751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur->td1 = len << 16; 2029751ee09SNobuhiro Iwamatsu /* Must preserve the end of descriptor list indication */ 2039751ee09SNobuhiro Iwamatsu if (port_info->tx_desc_cur->td0 & TD_TDLE) 2049751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP | TD_TDLE; 2059751ee09SNobuhiro Iwamatsu else 2069751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP; 2079751ee09SNobuhiro Iwamatsu 2089751ee09SNobuhiro Iwamatsu /* Restart the transmitter if disabled */ 2099751ee09SNobuhiro Iwamatsu if (!(inl(EDTRR(port)) & EDTRR_TRNS)) 2109751ee09SNobuhiro Iwamatsu outl(EDTRR_TRNS, EDTRR(port)); 2119751ee09SNobuhiro Iwamatsu 2129751ee09SNobuhiro Iwamatsu /* Wait until packet is transmitted */ 2139751ee09SNobuhiro Iwamatsu timeout = 1000; 2149751ee09SNobuhiro Iwamatsu while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--) 2159751ee09SNobuhiro Iwamatsu udelay(100); 2169751ee09SNobuhiro Iwamatsu 2179751ee09SNobuhiro Iwamatsu if (timeout < 0) { 218bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": transmit timeout\n"); 219bd3980ccSNobuhiro Iwamatsu ret = -ETIMEDOUT; 2209751ee09SNobuhiro Iwamatsu goto err; 2219751ee09SNobuhiro Iwamatsu } 2229751ee09SNobuhiro Iwamatsu 2239751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur++; 2249751ee09SNobuhiro Iwamatsu if (port_info->tx_desc_cur >= port_info->tx_desc_base + NUM_TX_DESC) 2259751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur = port_info->tx_desc_base; 2269751ee09SNobuhiro Iwamatsu 227bd3980ccSNobuhiro Iwamatsu return ret; 228bd3980ccSNobuhiro Iwamatsu err: 229bd3980ccSNobuhiro Iwamatsu return ret; 2309751ee09SNobuhiro Iwamatsu } 2319751ee09SNobuhiro Iwamatsu 232bd3980ccSNobuhiro Iwamatsu int sh_eth_recv(struct eth_device *dev) 2339751ee09SNobuhiro Iwamatsu { 234bd3980ccSNobuhiro Iwamatsu struct sh_eth_dev *eth = dev->priv; 235bd3980ccSNobuhiro Iwamatsu int port = eth->port, len = 0; 236bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 2379751ee09SNobuhiro Iwamatsu volatile u8 *packet; 2389751ee09SNobuhiro Iwamatsu 2399751ee09SNobuhiro Iwamatsu /* Check if the rx descriptor is ready */ 2409751ee09SNobuhiro Iwamatsu if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) { 2419751ee09SNobuhiro Iwamatsu /* Check for errors */ 2429751ee09SNobuhiro Iwamatsu if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) { 2439751ee09SNobuhiro Iwamatsu len = port_info->rx_desc_cur->rd1 & 0xffff; 2449751ee09SNobuhiro Iwamatsu packet = (volatile u8 *) 2459751ee09SNobuhiro Iwamatsu ADDR_TO_P2(port_info->rx_desc_cur->rd2); 2469751ee09SNobuhiro Iwamatsu NetReceive(packet, len); 2479751ee09SNobuhiro Iwamatsu } 2489751ee09SNobuhiro Iwamatsu 2499751ee09SNobuhiro Iwamatsu /* Make current descriptor available again */ 2509751ee09SNobuhiro Iwamatsu if (port_info->rx_desc_cur->rd0 & RD_RDLE) 2519751ee09SNobuhiro Iwamatsu port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE; 2529751ee09SNobuhiro Iwamatsu else 2539751ee09SNobuhiro Iwamatsu port_info->rx_desc_cur->rd0 = RD_RACT; 2549751ee09SNobuhiro Iwamatsu 2559751ee09SNobuhiro Iwamatsu /* Point to the next descriptor */ 2569751ee09SNobuhiro Iwamatsu port_info->rx_desc_cur++; 2579751ee09SNobuhiro Iwamatsu if (port_info->rx_desc_cur >= 2589751ee09SNobuhiro Iwamatsu port_info->rx_desc_base + NUM_RX_DESC) 2599751ee09SNobuhiro Iwamatsu port_info->rx_desc_cur = port_info->rx_desc_base; 2609751ee09SNobuhiro Iwamatsu } 2619751ee09SNobuhiro Iwamatsu 2629751ee09SNobuhiro Iwamatsu /* Restart the receiver if disabled */ 2639751ee09SNobuhiro Iwamatsu if (!(inl(EDRRR(port)) & EDRRR_R)) 2649751ee09SNobuhiro Iwamatsu outl(EDRRR_R, EDRRR(port)); 2659751ee09SNobuhiro Iwamatsu 2669751ee09SNobuhiro Iwamatsu return len; 2679751ee09SNobuhiro Iwamatsu } 2689751ee09SNobuhiro Iwamatsu 2699751ee09SNobuhiro Iwamatsu #define EDMR_INIT_CNT 1000 270bd3980ccSNobuhiro Iwamatsu static int sh_eth_reset(struct sh_eth_dev *eth) 2719751ee09SNobuhiro Iwamatsu { 272bd3980ccSNobuhiro Iwamatsu int port = eth->port; 273bd3980ccSNobuhiro Iwamatsu int ret = 0, i; 2749751ee09SNobuhiro Iwamatsu 2759751ee09SNobuhiro Iwamatsu /* Start e-dmac transmitter and receiver */ 2769751ee09SNobuhiro Iwamatsu outl(EDSR_ENALL, EDSR(port)); 2779751ee09SNobuhiro Iwamatsu 2789751ee09SNobuhiro Iwamatsu /* Perform a software reset and wait for it to complete */ 2799751ee09SNobuhiro Iwamatsu outl(EDMR_SRST, EDMR(port)); 2809751ee09SNobuhiro Iwamatsu for (i = 0; i < EDMR_INIT_CNT; i++) { 2819751ee09SNobuhiro Iwamatsu if (!(inl(EDMR(port)) & EDMR_SRST)) 2829751ee09SNobuhiro Iwamatsu break; 2839751ee09SNobuhiro Iwamatsu udelay(1000); 2849751ee09SNobuhiro Iwamatsu } 2859751ee09SNobuhiro Iwamatsu 2869751ee09SNobuhiro Iwamatsu if (i == EDMR_INIT_CNT) { 287bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": Software reset timeout\n"); 288bd3980ccSNobuhiro Iwamatsu ret = -EIO; 2899751ee09SNobuhiro Iwamatsu } 2909751ee09SNobuhiro Iwamatsu 291bd3980ccSNobuhiro Iwamatsu return ret; 292bd3980ccSNobuhiro Iwamatsu } 293bd3980ccSNobuhiro Iwamatsu 294bd3980ccSNobuhiro Iwamatsu static int sh_eth_tx_desc_init(struct sh_eth_dev *eth) 2959751ee09SNobuhiro Iwamatsu { 296bd3980ccSNobuhiro Iwamatsu int port = eth->port, i, ret = 0; 2979751ee09SNobuhiro Iwamatsu u32 tmp_addr; 298bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 2999751ee09SNobuhiro Iwamatsu struct tx_desc_s *cur_tx_desc; 3009751ee09SNobuhiro Iwamatsu 301bd3980ccSNobuhiro Iwamatsu /* 302bd3980ccSNobuhiro Iwamatsu * Allocate tx descriptors. They must be TX_DESC_SIZE bytes aligned 303bd3980ccSNobuhiro Iwamatsu */ 304bd3980ccSNobuhiro Iwamatsu port_info->tx_desc_malloc = malloc(NUM_TX_DESC * 3059751ee09SNobuhiro Iwamatsu sizeof(struct tx_desc_s) + 306bd3980ccSNobuhiro Iwamatsu TX_DESC_SIZE - 1); 307bd3980ccSNobuhiro Iwamatsu if (!port_info->tx_desc_malloc) { 308bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": malloc failed\n"); 309bd3980ccSNobuhiro Iwamatsu ret = -ENOMEM; 310bd3980ccSNobuhiro Iwamatsu goto err; 3119751ee09SNobuhiro Iwamatsu } 312bd3980ccSNobuhiro Iwamatsu 3139751ee09SNobuhiro Iwamatsu tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) & 3149751ee09SNobuhiro Iwamatsu ~(TX_DESC_SIZE - 1)); 3159751ee09SNobuhiro Iwamatsu /* Make sure we use a P2 address (non-cacheable) */ 3169751ee09SNobuhiro Iwamatsu port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr); 3179751ee09SNobuhiro Iwamatsu port_info->tx_desc_cur = port_info->tx_desc_base; 3189751ee09SNobuhiro Iwamatsu 3199751ee09SNobuhiro Iwamatsu /* Initialize all descriptors */ 3209751ee09SNobuhiro Iwamatsu for (cur_tx_desc = port_info->tx_desc_base, i = 0; i < NUM_TX_DESC; 3219751ee09SNobuhiro Iwamatsu cur_tx_desc++, i++) { 3229751ee09SNobuhiro Iwamatsu cur_tx_desc->td0 = 0x00; 3239751ee09SNobuhiro Iwamatsu cur_tx_desc->td1 = 0x00; 3249751ee09SNobuhiro Iwamatsu cur_tx_desc->td2 = 0x00; 3259751ee09SNobuhiro Iwamatsu } 3269751ee09SNobuhiro Iwamatsu 3279751ee09SNobuhiro Iwamatsu /* Mark the end of the descriptors */ 3289751ee09SNobuhiro Iwamatsu cur_tx_desc--; 3299751ee09SNobuhiro Iwamatsu cur_tx_desc->td0 |= TD_TDLE; 3309751ee09SNobuhiro Iwamatsu 3319751ee09SNobuhiro Iwamatsu /* Point the controller to the tx descriptor list. Must use physical 3329751ee09SNobuhiro Iwamatsu addresses */ 3339751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(port_info->tx_desc_base), TDLAR(port)); 3349751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(port_info->tx_desc_base), TDFAR(port)); 3359751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(cur_tx_desc), TDFXR(port)); 3369751ee09SNobuhiro Iwamatsu outl(0x01, TDFFR(port));/* Last discriptor bit */ 3379751ee09SNobuhiro Iwamatsu 338bd3980ccSNobuhiro Iwamatsu err: 339bd3980ccSNobuhiro Iwamatsu return ret; 3409751ee09SNobuhiro Iwamatsu } 3419751ee09SNobuhiro Iwamatsu 342bd3980ccSNobuhiro Iwamatsu static int sh_eth_rx_desc_init(struct sh_eth_dev *eth) 3439751ee09SNobuhiro Iwamatsu { 344bd3980ccSNobuhiro Iwamatsu int port = eth->port, i , ret = 0; 345bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 3469751ee09SNobuhiro Iwamatsu struct rx_desc_s *cur_rx_desc; 347bd3980ccSNobuhiro Iwamatsu u32 tmp_addr; 3489751ee09SNobuhiro Iwamatsu u8 *rx_buf; 3499751ee09SNobuhiro Iwamatsu 350bd3980ccSNobuhiro Iwamatsu /* 351bd3980ccSNobuhiro Iwamatsu * Allocate rx descriptors. They must be RX_DESC_SIZE bytes aligned 352bd3980ccSNobuhiro Iwamatsu */ 353bd3980ccSNobuhiro Iwamatsu port_info->rx_desc_malloc = malloc(NUM_RX_DESC * 3549751ee09SNobuhiro Iwamatsu sizeof(struct rx_desc_s) + 355bd3980ccSNobuhiro Iwamatsu RX_DESC_SIZE - 1); 356bd3980ccSNobuhiro Iwamatsu if (!port_info->rx_desc_malloc) { 357bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": malloc failed\n"); 358bd3980ccSNobuhiro Iwamatsu ret = -ENOMEM; 359bd3980ccSNobuhiro Iwamatsu goto err; 3609751ee09SNobuhiro Iwamatsu } 361bd3980ccSNobuhiro Iwamatsu 3629751ee09SNobuhiro Iwamatsu tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) & 3639751ee09SNobuhiro Iwamatsu ~(RX_DESC_SIZE - 1)); 3649751ee09SNobuhiro Iwamatsu /* Make sure we use a P2 address (non-cacheable) */ 3659751ee09SNobuhiro Iwamatsu port_info->rx_desc_base = (struct rx_desc_s *)ADDR_TO_P2(tmp_addr); 3669751ee09SNobuhiro Iwamatsu 3679751ee09SNobuhiro Iwamatsu port_info->rx_desc_cur = port_info->rx_desc_base; 3689751ee09SNobuhiro Iwamatsu 369bd3980ccSNobuhiro Iwamatsu /* 370bd3980ccSNobuhiro Iwamatsu * Allocate rx data buffers. They must be 32 bytes aligned and in 371bd3980ccSNobuhiro Iwamatsu * P2 area 372bd3980ccSNobuhiro Iwamatsu */ 373bd3980ccSNobuhiro Iwamatsu port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31); 374bd3980ccSNobuhiro Iwamatsu if (!port_info->rx_buf_malloc) { 375bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": malloc failed\n"); 376bd3980ccSNobuhiro Iwamatsu ret = -ENOMEM; 377bd3980ccSNobuhiro Iwamatsu goto err_buf_malloc; 3789751ee09SNobuhiro Iwamatsu } 379bd3980ccSNobuhiro Iwamatsu 3809751ee09SNobuhiro Iwamatsu tmp_addr = (u32)(((int)port_info->rx_buf_malloc + (32 - 1)) & 3819751ee09SNobuhiro Iwamatsu ~(32 - 1)); 3829751ee09SNobuhiro Iwamatsu port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr); 3839751ee09SNobuhiro Iwamatsu 3849751ee09SNobuhiro Iwamatsu /* Initialize all descriptors */ 3859751ee09SNobuhiro Iwamatsu for (cur_rx_desc = port_info->rx_desc_base, 3869751ee09SNobuhiro Iwamatsu rx_buf = port_info->rx_buf_base, i = 0; 3879751ee09SNobuhiro Iwamatsu i < NUM_RX_DESC; cur_rx_desc++, rx_buf += MAX_BUF_SIZE, i++) { 3889751ee09SNobuhiro Iwamatsu cur_rx_desc->rd0 = RD_RACT; 3899751ee09SNobuhiro Iwamatsu cur_rx_desc->rd1 = MAX_BUF_SIZE << 16; 3909751ee09SNobuhiro Iwamatsu cur_rx_desc->rd2 = (u32) ADDR_TO_PHY(rx_buf); 3919751ee09SNobuhiro Iwamatsu } 3929751ee09SNobuhiro Iwamatsu 3939751ee09SNobuhiro Iwamatsu /* Mark the end of the descriptors */ 3949751ee09SNobuhiro Iwamatsu cur_rx_desc--; 3959751ee09SNobuhiro Iwamatsu cur_rx_desc->rd0 |= RD_RDLE; 3969751ee09SNobuhiro Iwamatsu 3979751ee09SNobuhiro Iwamatsu /* Point the controller to the rx descriptor list */ 3989751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(port_info->rx_desc_base), RDLAR(port)); 3999751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(port_info->rx_desc_base), RDFAR(port)); 4009751ee09SNobuhiro Iwamatsu outl(ADDR_TO_PHY(cur_rx_desc), RDFXR(port)); 4019751ee09SNobuhiro Iwamatsu outl(RDFFR_RDLF, RDFFR(port)); 4029751ee09SNobuhiro Iwamatsu 403bd3980ccSNobuhiro Iwamatsu return ret; 404bd3980ccSNobuhiro Iwamatsu 405bd3980ccSNobuhiro Iwamatsu err_buf_malloc: 406bd3980ccSNobuhiro Iwamatsu free(port_info->rx_desc_malloc); 407bd3980ccSNobuhiro Iwamatsu port_info->rx_desc_malloc = NULL; 408bd3980ccSNobuhiro Iwamatsu 409bd3980ccSNobuhiro Iwamatsu err: 410bd3980ccSNobuhiro Iwamatsu return ret; 4119751ee09SNobuhiro Iwamatsu } 4129751ee09SNobuhiro Iwamatsu 413bd3980ccSNobuhiro Iwamatsu static void sh_eth_tx_desc_free(struct sh_eth_dev *eth) 4149751ee09SNobuhiro Iwamatsu { 415bd3980ccSNobuhiro Iwamatsu int port = eth->port; 416bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 4179751ee09SNobuhiro Iwamatsu 4189751ee09SNobuhiro Iwamatsu if (port_info->tx_desc_malloc) { 4199751ee09SNobuhiro Iwamatsu free(port_info->tx_desc_malloc); 4209751ee09SNobuhiro Iwamatsu port_info->tx_desc_malloc = NULL; 4219751ee09SNobuhiro Iwamatsu } 422bd3980ccSNobuhiro Iwamatsu } 423bd3980ccSNobuhiro Iwamatsu 424bd3980ccSNobuhiro Iwamatsu static void sh_eth_rx_desc_free(struct sh_eth_dev *eth) 425bd3980ccSNobuhiro Iwamatsu { 426bd3980ccSNobuhiro Iwamatsu int port = eth->port; 427bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 4289751ee09SNobuhiro Iwamatsu 4299751ee09SNobuhiro Iwamatsu if (port_info->rx_desc_malloc) { 4309751ee09SNobuhiro Iwamatsu free(port_info->rx_desc_malloc); 4319751ee09SNobuhiro Iwamatsu port_info->rx_desc_malloc = NULL; 4329751ee09SNobuhiro Iwamatsu } 4339751ee09SNobuhiro Iwamatsu 4349751ee09SNobuhiro Iwamatsu if (port_info->rx_buf_malloc) { 4359751ee09SNobuhiro Iwamatsu free(port_info->rx_buf_malloc); 4369751ee09SNobuhiro Iwamatsu port_info->rx_buf_malloc = NULL; 4379751ee09SNobuhiro Iwamatsu } 4389751ee09SNobuhiro Iwamatsu } 4399751ee09SNobuhiro Iwamatsu 440bd3980ccSNobuhiro Iwamatsu static int sh_eth_desc_init(struct sh_eth_dev *eth) 4419751ee09SNobuhiro Iwamatsu { 442bd3980ccSNobuhiro Iwamatsu int ret = 0; 4439751ee09SNobuhiro Iwamatsu 444bd3980ccSNobuhiro Iwamatsu ret = sh_eth_tx_desc_init(eth); 445bd3980ccSNobuhiro Iwamatsu if (ret) 446bd3980ccSNobuhiro Iwamatsu goto err_tx_init; 447bd3980ccSNobuhiro Iwamatsu 448bd3980ccSNobuhiro Iwamatsu ret = sh_eth_rx_desc_init(eth); 449bd3980ccSNobuhiro Iwamatsu if (ret) 450bd3980ccSNobuhiro Iwamatsu goto err_rx_init; 451bd3980ccSNobuhiro Iwamatsu 452bd3980ccSNobuhiro Iwamatsu return ret; 453bd3980ccSNobuhiro Iwamatsu err_rx_init: 454bd3980ccSNobuhiro Iwamatsu sh_eth_tx_desc_free(eth); 455bd3980ccSNobuhiro Iwamatsu 456bd3980ccSNobuhiro Iwamatsu err_tx_init: 457bd3980ccSNobuhiro Iwamatsu return ret; 4589751ee09SNobuhiro Iwamatsu } 4599751ee09SNobuhiro Iwamatsu 460bd3980ccSNobuhiro Iwamatsu static int sh_eth_phy_config(struct sh_eth_dev *eth) 4619751ee09SNobuhiro Iwamatsu { 462bd3980ccSNobuhiro Iwamatsu int port = eth->port, timeout, ret = 0; 463bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 4649751ee09SNobuhiro Iwamatsu u32 val; 465bd3980ccSNobuhiro Iwamatsu 4669751ee09SNobuhiro Iwamatsu /* Reset phy */ 467bd3980ccSNobuhiro Iwamatsu sh_eth_mii_write_phy_reg 468bd3980ccSNobuhiro Iwamatsu (port, port_info->phy_addr, PHY_CTRL, PHY_C_RESET); 4699751ee09SNobuhiro Iwamatsu timeout = 10; 4709751ee09SNobuhiro Iwamatsu while (timeout--) { 471bd3980ccSNobuhiro Iwamatsu val = sh_eth_mii_read_phy_reg(port, 472bd3980ccSNobuhiro Iwamatsu port_info->phy_addr, PHY_CTRL); 4739751ee09SNobuhiro Iwamatsu if (!(val & PHY_C_RESET)) 4749751ee09SNobuhiro Iwamatsu break; 475bd3980ccSNobuhiro Iwamatsu udelay(SH_ETH_PHY_DELAY); 4769751ee09SNobuhiro Iwamatsu } 477bd3980ccSNobuhiro Iwamatsu 4789751ee09SNobuhiro Iwamatsu if (timeout < 0) { 479bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": phy reset timeout\n"); 480bd3980ccSNobuhiro Iwamatsu ret = -EIO; 481bd3980ccSNobuhiro Iwamatsu goto err_tout; 4829751ee09SNobuhiro Iwamatsu } 4839751ee09SNobuhiro Iwamatsu 4849751ee09SNobuhiro Iwamatsu /* Advertise 100/10 baseT full/half duplex */ 4859751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_reg(port, port_info->phy_addr, PHY_ANA, 4869751ee09SNobuhiro Iwamatsu (PHY_A_FDX|PHY_A_HDX|PHY_A_10FDX|PHY_A_10HDX|PHY_A_EXT)); 4879751ee09SNobuhiro Iwamatsu /* Autonegotiation, normal operation, full duplex, enable tx */ 4889751ee09SNobuhiro Iwamatsu sh_eth_mii_write_phy_reg(port, port_info->phy_addr, PHY_CTRL, 4899751ee09SNobuhiro Iwamatsu (PHY_C_ANEGEN|PHY_C_RANEG)); 4909751ee09SNobuhiro Iwamatsu /* Wait for autonegotiation to complete */ 4919751ee09SNobuhiro Iwamatsu timeout = 100; 4929751ee09SNobuhiro Iwamatsu while (timeout--) { 4939751ee09SNobuhiro Iwamatsu val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1); 4949751ee09SNobuhiro Iwamatsu if (val & PHY_S_ANEGC) 4959751ee09SNobuhiro Iwamatsu break; 496bd3980ccSNobuhiro Iwamatsu 497bd3980ccSNobuhiro Iwamatsu udelay(SH_ETH_PHY_DELAY); 4989751ee09SNobuhiro Iwamatsu } 499bd3980ccSNobuhiro Iwamatsu 5009751ee09SNobuhiro Iwamatsu if (timeout < 0) { 501bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": phy auto-negotiation failed\n"); 502bd3980ccSNobuhiro Iwamatsu ret = -ETIMEDOUT; 503bd3980ccSNobuhiro Iwamatsu goto err_tout; 5049751ee09SNobuhiro Iwamatsu } 5059751ee09SNobuhiro Iwamatsu 506bd3980ccSNobuhiro Iwamatsu return ret; 507bd3980ccSNobuhiro Iwamatsu 508bd3980ccSNobuhiro Iwamatsu err_tout: 509bd3980ccSNobuhiro Iwamatsu return ret; 5109751ee09SNobuhiro Iwamatsu } 5119751ee09SNobuhiro Iwamatsu 512bd3980ccSNobuhiro Iwamatsu static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) 5139751ee09SNobuhiro Iwamatsu { 514bd3980ccSNobuhiro Iwamatsu int port = eth->port, ret = 0; 515bd3980ccSNobuhiro Iwamatsu u32 val, phy_status; 516bd3980ccSNobuhiro Iwamatsu struct sh_eth_info *port_info = ð->port_info[port]; 517c527ce92SMike Frysinger struct eth_device *dev = port_info->dev; 5189751ee09SNobuhiro Iwamatsu 5199751ee09SNobuhiro Iwamatsu /* Configure e-dmac registers */ 5209751ee09SNobuhiro Iwamatsu outl((inl(EDMR(port)) & ~EMDR_DESC_R) | EDMR_EL, EDMR(port)); 5219751ee09SNobuhiro Iwamatsu outl(0, EESIPR(port)); 5229751ee09SNobuhiro Iwamatsu outl(0, TRSCER(port)); 5239751ee09SNobuhiro Iwamatsu outl(0, TFTR(port)); 5249751ee09SNobuhiro Iwamatsu outl((FIFO_SIZE_T | FIFO_SIZE_R), FDR(port)); 5259751ee09SNobuhiro Iwamatsu outl(RMCR_RST, RMCR(port)); 5269751ee09SNobuhiro Iwamatsu outl(0, RPADIR(port)); 5279751ee09SNobuhiro Iwamatsu outl((FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR(port)); 5289751ee09SNobuhiro Iwamatsu 5299751ee09SNobuhiro Iwamatsu /* Configure e-mac registers */ 5309751ee09SNobuhiro Iwamatsu outl(0, ECSIPR(port)); 5319751ee09SNobuhiro Iwamatsu 5329751ee09SNobuhiro Iwamatsu /* Set Mac address */ 533c527ce92SMike Frysinger val = dev->enetaddr[0] << 24 | dev->enetaddr[1] << 16 | 534c527ce92SMike Frysinger dev->enetaddr[2] << 8 | dev->enetaddr[3]; 5359751ee09SNobuhiro Iwamatsu outl(val, MAHR(port)); 5369751ee09SNobuhiro Iwamatsu 537c527ce92SMike Frysinger val = dev->enetaddr[4] << 8 | dev->enetaddr[5]; 5389751ee09SNobuhiro Iwamatsu outl(val, MALR(port)); 5399751ee09SNobuhiro Iwamatsu 5409751ee09SNobuhiro Iwamatsu outl(RFLR_RFL_MIN, RFLR(port)); 5419751ee09SNobuhiro Iwamatsu outl(0, PIPR(port)); 5429751ee09SNobuhiro Iwamatsu outl(APR_AP, APR(port)); 5439751ee09SNobuhiro Iwamatsu outl(MPR_MP, MPR(port)); 5449751ee09SNobuhiro Iwamatsu outl(TPAUSER_TPAUSE, TPAUSER(port)); 5459751ee09SNobuhiro Iwamatsu 5469751ee09SNobuhiro Iwamatsu /* Configure phy */ 547bd3980ccSNobuhiro Iwamatsu ret = sh_eth_phy_config(eth); 548bd3980ccSNobuhiro Iwamatsu if (ret) { 549*88a4c2e7SNobuhiro Iwamatsu printf(SHETHER_NAME ": phy config timeout\n"); 550bd3980ccSNobuhiro Iwamatsu goto err_phy_cfg; 551bd3980ccSNobuhiro Iwamatsu } 5529751ee09SNobuhiro Iwamatsu /* Read phy status to finish configuring the e-mac */ 553bd3980ccSNobuhiro Iwamatsu phy_status = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1); 5549751ee09SNobuhiro Iwamatsu 5559751ee09SNobuhiro Iwamatsu /* Set the transfer speed */ 5569751ee09SNobuhiro Iwamatsu if (phy_status & (PHY_S_100X_F|PHY_S_100X_H)) { 557bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": 100Base/"); 5589751ee09SNobuhiro Iwamatsu outl(GECMR_100B, GECMR(port)); 5599751ee09SNobuhiro Iwamatsu } else { 560bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": 10Base/"); 5619751ee09SNobuhiro Iwamatsu outl(GECMR_10B, GECMR(port)); 5629751ee09SNobuhiro Iwamatsu } 5639751ee09SNobuhiro Iwamatsu 5649751ee09SNobuhiro Iwamatsu /* Check if full duplex mode is supported by the phy */ 5659751ee09SNobuhiro Iwamatsu if (phy_status & (PHY_S_100X_F|PHY_S_10T_F)) { 5669751ee09SNobuhiro Iwamatsu printf("Full\n"); 5679751ee09SNobuhiro Iwamatsu outl((ECMR_CHG_DM|ECMR_RE|ECMR_TE|ECMR_DM), ECMR(port)); 5689751ee09SNobuhiro Iwamatsu } else { 5699751ee09SNobuhiro Iwamatsu printf("Half\n"); 5709751ee09SNobuhiro Iwamatsu outl((ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR(port)); 5719751ee09SNobuhiro Iwamatsu } 572bd3980ccSNobuhiro Iwamatsu 573bd3980ccSNobuhiro Iwamatsu return ret; 574bd3980ccSNobuhiro Iwamatsu 575bd3980ccSNobuhiro Iwamatsu err_phy_cfg: 576bd3980ccSNobuhiro Iwamatsu return ret; 5779751ee09SNobuhiro Iwamatsu } 5789751ee09SNobuhiro Iwamatsu 579bd3980ccSNobuhiro Iwamatsu static void sh_eth_start(struct sh_eth_dev *eth) 5809751ee09SNobuhiro Iwamatsu { 5819751ee09SNobuhiro Iwamatsu /* 5829751ee09SNobuhiro Iwamatsu * Enable the e-dmac receiver only. The transmitter will be enabled when 5839751ee09SNobuhiro Iwamatsu * we have something to transmit 5849751ee09SNobuhiro Iwamatsu */ 585bd3980ccSNobuhiro Iwamatsu outl(EDRRR_R, EDRRR(eth->port)); 586bd3980ccSNobuhiro Iwamatsu } 5879751ee09SNobuhiro Iwamatsu 588bd3980ccSNobuhiro Iwamatsu static void sh_eth_stop(struct sh_eth_dev *eth) 589bd3980ccSNobuhiro Iwamatsu { 590bd3980ccSNobuhiro Iwamatsu outl(~EDRRR_R, EDRRR(eth->port)); 5919751ee09SNobuhiro Iwamatsu } 5929751ee09SNobuhiro Iwamatsu 593bd3980ccSNobuhiro Iwamatsu int sh_eth_init(struct eth_device *dev, bd_t *bd) 5949751ee09SNobuhiro Iwamatsu { 595bd3980ccSNobuhiro Iwamatsu int ret = 0; 596bd3980ccSNobuhiro Iwamatsu struct sh_eth_dev *eth = dev->priv; 597bd3980ccSNobuhiro Iwamatsu 598bd3980ccSNobuhiro Iwamatsu ret = sh_eth_reset(eth); 599bd3980ccSNobuhiro Iwamatsu if (ret) 600bd3980ccSNobuhiro Iwamatsu goto err; 601bd3980ccSNobuhiro Iwamatsu 602bd3980ccSNobuhiro Iwamatsu ret = sh_eth_desc_init(eth); 603bd3980ccSNobuhiro Iwamatsu if (ret) 604bd3980ccSNobuhiro Iwamatsu goto err; 605bd3980ccSNobuhiro Iwamatsu 606bd3980ccSNobuhiro Iwamatsu ret = sh_eth_config(eth, bd); 607bd3980ccSNobuhiro Iwamatsu if (ret) 608bd3980ccSNobuhiro Iwamatsu goto err_config; 609bd3980ccSNobuhiro Iwamatsu 610bd3980ccSNobuhiro Iwamatsu sh_eth_start(eth); 611bd3980ccSNobuhiro Iwamatsu 612bd3980ccSNobuhiro Iwamatsu return ret; 613bd3980ccSNobuhiro Iwamatsu 614bd3980ccSNobuhiro Iwamatsu err_config: 615bd3980ccSNobuhiro Iwamatsu sh_eth_tx_desc_free(eth); 616bd3980ccSNobuhiro Iwamatsu sh_eth_rx_desc_free(eth); 617bd3980ccSNobuhiro Iwamatsu 618bd3980ccSNobuhiro Iwamatsu err: 619bd3980ccSNobuhiro Iwamatsu return ret; 6209751ee09SNobuhiro Iwamatsu } 6219751ee09SNobuhiro Iwamatsu 622bd3980ccSNobuhiro Iwamatsu void sh_eth_halt(struct eth_device *dev) 623bd3980ccSNobuhiro Iwamatsu { 624bd3980ccSNobuhiro Iwamatsu struct sh_eth_dev *eth = dev->priv; 625bd3980ccSNobuhiro Iwamatsu sh_eth_stop(eth); 626bd3980ccSNobuhiro Iwamatsu } 627bd3980ccSNobuhiro Iwamatsu 628bd3980ccSNobuhiro Iwamatsu int sh_eth_initialize(bd_t *bd) 629bd3980ccSNobuhiro Iwamatsu { 630bd3980ccSNobuhiro Iwamatsu int ret = 0; 631bd3980ccSNobuhiro Iwamatsu struct sh_eth_dev *eth = NULL; 632bd3980ccSNobuhiro Iwamatsu struct eth_device *dev = NULL; 633bd3980ccSNobuhiro Iwamatsu 634bd3980ccSNobuhiro Iwamatsu eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev)); 635bd3980ccSNobuhiro Iwamatsu if (!eth) { 636bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": %s: malloc failed\n", __func__); 637bd3980ccSNobuhiro Iwamatsu ret = -ENOMEM; 638bd3980ccSNobuhiro Iwamatsu goto err; 639bd3980ccSNobuhiro Iwamatsu } 640bd3980ccSNobuhiro Iwamatsu 641bd3980ccSNobuhiro Iwamatsu dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 642bd3980ccSNobuhiro Iwamatsu if (!dev) { 643bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": %s: malloc failed\n", __func__); 644bd3980ccSNobuhiro Iwamatsu ret = -ENOMEM; 645bd3980ccSNobuhiro Iwamatsu goto err; 646bd3980ccSNobuhiro Iwamatsu } 647bd3980ccSNobuhiro Iwamatsu memset(dev, 0, sizeof(struct eth_device)); 648bd3980ccSNobuhiro Iwamatsu memset(eth, 0, sizeof(struct sh_eth_dev)); 649bd3980ccSNobuhiro Iwamatsu 650bd3980ccSNobuhiro Iwamatsu eth->port = CONFIG_SH_ETHER_USE_PORT; 651bd3980ccSNobuhiro Iwamatsu eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR; 652bd3980ccSNobuhiro Iwamatsu 653bd3980ccSNobuhiro Iwamatsu dev->priv = (void *)eth; 654bd3980ccSNobuhiro Iwamatsu dev->iobase = 0; 655bd3980ccSNobuhiro Iwamatsu dev->init = sh_eth_init; 656bd3980ccSNobuhiro Iwamatsu dev->halt = sh_eth_halt; 657bd3980ccSNobuhiro Iwamatsu dev->send = sh_eth_send; 658bd3980ccSNobuhiro Iwamatsu dev->recv = sh_eth_recv; 659bd3980ccSNobuhiro Iwamatsu eth->port_info[eth->port].dev = dev; 660bd3980ccSNobuhiro Iwamatsu 661bd3980ccSNobuhiro Iwamatsu sprintf(dev->name, SHETHER_NAME); 662bd3980ccSNobuhiro Iwamatsu 663bd3980ccSNobuhiro Iwamatsu /* Register Device to EtherNet subsystem */ 664bd3980ccSNobuhiro Iwamatsu eth_register(dev); 6659751ee09SNobuhiro Iwamatsu 666c527ce92SMike Frysinger if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr)) 667c527ce92SMike Frysinger puts("Please set MAC address\n"); 6689751ee09SNobuhiro Iwamatsu 669bd3980ccSNobuhiro Iwamatsu return ret; 6709751ee09SNobuhiro Iwamatsu 6719751ee09SNobuhiro Iwamatsu err: 672bd3980ccSNobuhiro Iwamatsu if (dev) 6739751ee09SNobuhiro Iwamatsu free(dev); 674bd3980ccSNobuhiro Iwamatsu 675bd3980ccSNobuhiro Iwamatsu if (eth) 676bd3980ccSNobuhiro Iwamatsu free(eth); 677bd3980ccSNobuhiro Iwamatsu 678bd3980ccSNobuhiro Iwamatsu printf(SHETHER_NAME ": Failed\n"); 679bd3980ccSNobuhiro Iwamatsu return ret; 6809751ee09SNobuhiro Iwamatsu } 681