1*799e125cSJiandong Zheng /* 2*799e125cSJiandong Zheng * Copyright 2014 Broadcom Corporation. 3*799e125cSJiandong Zheng * 4*799e125cSJiandong Zheng * SPDX-License-Identifier: GPL-2.0+ 5*799e125cSJiandong Zheng */ 6*799e125cSJiandong Zheng 7*799e125cSJiandong Zheng #include <common.h> 8*799e125cSJiandong Zheng #include <malloc.h> 9*799e125cSJiandong Zheng #include <net.h> 10*799e125cSJiandong Zheng #include <config.h> 11*799e125cSJiandong Zheng 12*799e125cSJiandong Zheng #include <phy.h> 13*799e125cSJiandong Zheng #include <miiphy.h> 14*799e125cSJiandong Zheng 15*799e125cSJiandong Zheng #include <asm/io.h> 16*799e125cSJiandong Zheng 17*799e125cSJiandong Zheng #include <netdev.h> 18*799e125cSJiandong Zheng #include "bcm-sf2-eth.h" 19*799e125cSJiandong Zheng 20*799e125cSJiandong Zheng #if defined(CONFIG_BCM_SF2_ETH_GMAC) 21*799e125cSJiandong Zheng #include "bcm-sf2-eth-gmac.h" 22*799e125cSJiandong Zheng #else 23*799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to define a MAC!" 24*799e125cSJiandong Zheng #endif 25*799e125cSJiandong Zheng 26*799e125cSJiandong Zheng #define BCM_NET_MODULE_DESCRIPTION "Broadcom Starfighter2 Ethernet driver" 27*799e125cSJiandong Zheng #define BCM_NET_MODULE_VERSION "0.1" 28*799e125cSJiandong Zheng #define BCM_SF2_ETH_DEV_NAME "bcm_sf2" 29*799e125cSJiandong Zheng 30*799e125cSJiandong Zheng static const char banner[] = 31*799e125cSJiandong Zheng BCM_NET_MODULE_DESCRIPTION " " BCM_NET_MODULE_VERSION "\n"; 32*799e125cSJiandong Zheng 33*799e125cSJiandong Zheng static int bcm_sf2_eth_init(struct eth_device *dev) 34*799e125cSJiandong Zheng { 35*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 36*799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 37*799e125cSJiandong Zheng struct phy_device *phydev; 38*799e125cSJiandong Zheng int rc = 0; 39*799e125cSJiandong Zheng int i; 40*799e125cSJiandong Zheng 41*799e125cSJiandong Zheng rc = eth->mac_init(dev); 42*799e125cSJiandong Zheng if (rc) { 43*799e125cSJiandong Zheng error("%s: Couldn't cofigure MAC!\n", __func__); 44*799e125cSJiandong Zheng return rc; 45*799e125cSJiandong Zheng } 46*799e125cSJiandong Zheng 47*799e125cSJiandong Zheng /* disable DMA */ 48*799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_RX); 49*799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_TX); 50*799e125cSJiandong Zheng 51*799e125cSJiandong Zheng eth->port_num = 0; 52*799e125cSJiandong Zheng debug("Connecting PHY 0...\n"); 53*799e125cSJiandong Zheng phydev = phy_connect(miiphy_get_dev_by_name(dev->name), 54*799e125cSJiandong Zheng 0, dev, eth->phy_interface); 55*799e125cSJiandong Zheng if (phydev != NULL) { 56*799e125cSJiandong Zheng eth->port[0] = phydev; 57*799e125cSJiandong Zheng eth->port_num += 1; 58*799e125cSJiandong Zheng } else { 59*799e125cSJiandong Zheng debug("No PHY found for port 0\n"); 60*799e125cSJiandong Zheng } 61*799e125cSJiandong Zheng 62*799e125cSJiandong Zheng for (i = 0; i < eth->port_num; i++) 63*799e125cSJiandong Zheng phy_config(eth->port[i]); 64*799e125cSJiandong Zheng 65*799e125cSJiandong Zheng return rc; 66*799e125cSJiandong Zheng } 67*799e125cSJiandong Zheng 68*799e125cSJiandong Zheng /* 69*799e125cSJiandong Zheng * u-boot net functions 70*799e125cSJiandong Zheng */ 71*799e125cSJiandong Zheng 72*799e125cSJiandong Zheng static int bcm_sf2_eth_send(struct eth_device *dev, void *packet, int length) 73*799e125cSJiandong Zheng { 74*799e125cSJiandong Zheng struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); 75*799e125cSJiandong Zheng uint8_t *buf = (uint8_t *)packet; 76*799e125cSJiandong Zheng int rc = 0; 77*799e125cSJiandong Zheng int i = 0; 78*799e125cSJiandong Zheng 79*799e125cSJiandong Zheng debug("%s enter\n", __func__); 80*799e125cSJiandong Zheng 81*799e125cSJiandong Zheng /* load buf and start transmit */ 82*799e125cSJiandong Zheng rc = dma->tx_packet(dma, buf, length); 83*799e125cSJiandong Zheng if (rc) { 84*799e125cSJiandong Zheng debug("ERROR - Tx failed\n"); 85*799e125cSJiandong Zheng return rc; 86*799e125cSJiandong Zheng } 87*799e125cSJiandong Zheng 88*799e125cSJiandong Zheng while (!(dma->check_tx_done(dma))) { 89*799e125cSJiandong Zheng udelay(100); 90*799e125cSJiandong Zheng debug("."); 91*799e125cSJiandong Zheng i++; 92*799e125cSJiandong Zheng if (i > 20) { 93*799e125cSJiandong Zheng error("%s: Tx timeout: retried 20 times\n", __func__); 94*799e125cSJiandong Zheng rc = -1; 95*799e125cSJiandong Zheng break; 96*799e125cSJiandong Zheng } 97*799e125cSJiandong Zheng } 98*799e125cSJiandong Zheng 99*799e125cSJiandong Zheng debug("%s exit rc(0x%x)\n", __func__, rc); 100*799e125cSJiandong Zheng return rc; 101*799e125cSJiandong Zheng } 102*799e125cSJiandong Zheng 103*799e125cSJiandong Zheng static int bcm_sf2_eth_receive(struct eth_device *dev) 104*799e125cSJiandong Zheng { 105*799e125cSJiandong Zheng struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); 106*799e125cSJiandong Zheng uint8_t *buf = (uint8_t *)NetRxPackets[0]; 107*799e125cSJiandong Zheng int rcvlen; 108*799e125cSJiandong Zheng int rc = 0; 109*799e125cSJiandong Zheng int i = 0; 110*799e125cSJiandong Zheng 111*799e125cSJiandong Zheng while (1) { 112*799e125cSJiandong Zheng /* Poll Rx queue to get a packet */ 113*799e125cSJiandong Zheng rcvlen = dma->check_rx_done(dma, buf); 114*799e125cSJiandong Zheng if (rcvlen < 0) { 115*799e125cSJiandong Zheng /* No packet received */ 116*799e125cSJiandong Zheng rc = -1; 117*799e125cSJiandong Zheng debug("\nNO More Rx\n"); 118*799e125cSJiandong Zheng break; 119*799e125cSJiandong Zheng } else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) { 120*799e125cSJiandong Zheng error("%s: Wrong Ethernet packet size (%d B), skip!\n", 121*799e125cSJiandong Zheng __func__, rcvlen); 122*799e125cSJiandong Zheng break; 123*799e125cSJiandong Zheng } else { 124*799e125cSJiandong Zheng debug("recieved\n"); 125*799e125cSJiandong Zheng 126*799e125cSJiandong Zheng /* Forward received packet to uboot network handler */ 127*799e125cSJiandong Zheng NetReceive(buf, rcvlen); 128*799e125cSJiandong Zheng 129*799e125cSJiandong Zheng if (++i >= PKTBUFSRX) 130*799e125cSJiandong Zheng i = 0; 131*799e125cSJiandong Zheng buf = NetRxPackets[i]; 132*799e125cSJiandong Zheng } 133*799e125cSJiandong Zheng } 134*799e125cSJiandong Zheng 135*799e125cSJiandong Zheng return rc; 136*799e125cSJiandong Zheng } 137*799e125cSJiandong Zheng 138*799e125cSJiandong Zheng static int bcm_sf2_eth_write_hwaddr(struct eth_device *dev) 139*799e125cSJiandong Zheng { 140*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 141*799e125cSJiandong Zheng 142*799e125cSJiandong Zheng printf(" ETH MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 143*799e125cSJiandong Zheng dev->enetaddr[0], dev->enetaddr[1], dev->enetaddr[2], 144*799e125cSJiandong Zheng dev->enetaddr[3], dev->enetaddr[4], dev->enetaddr[5]); 145*799e125cSJiandong Zheng 146*799e125cSJiandong Zheng return eth->set_mac_addr(dev->enetaddr); 147*799e125cSJiandong Zheng } 148*799e125cSJiandong Zheng 149*799e125cSJiandong Zheng static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt) 150*799e125cSJiandong Zheng { 151*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 152*799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 153*799e125cSJiandong Zheng int i; 154*799e125cSJiandong Zheng 155*799e125cSJiandong Zheng debug("Enabling BCM SF2 Ethernet.\n"); 156*799e125cSJiandong Zheng 157*799e125cSJiandong Zheng /* Set MAC address from env */ 158*799e125cSJiandong Zheng if (bcm_sf2_eth_write_hwaddr(dev) != 0) { 159*799e125cSJiandong Zheng error("%s: MAC set error when opening !\n", __func__); 160*799e125cSJiandong Zheng return -1; 161*799e125cSJiandong Zheng } 162*799e125cSJiandong Zheng 163*799e125cSJiandong Zheng eth->enable_mac(); 164*799e125cSJiandong Zheng 165*799e125cSJiandong Zheng /* enable tx and rx DMA */ 166*799e125cSJiandong Zheng dma->enable_dma(dma, MAC_DMA_RX); 167*799e125cSJiandong Zheng dma->enable_dma(dma, MAC_DMA_TX); 168*799e125cSJiandong Zheng 169*799e125cSJiandong Zheng /* 170*799e125cSJiandong Zheng * Need to start PHY here because link speed can change 171*799e125cSJiandong Zheng * before each ethernet operation 172*799e125cSJiandong Zheng */ 173*799e125cSJiandong Zheng for (i = 0; i < eth->port_num; i++) { 174*799e125cSJiandong Zheng if (phy_startup(eth->port[i])) { 175*799e125cSJiandong Zheng error("%s: PHY %d startup failed!\n", __func__, i); 176*799e125cSJiandong Zheng if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) { 177*799e125cSJiandong Zheng error("%s: No default port %d!\n", __func__, i); 178*799e125cSJiandong Zheng return -1; 179*799e125cSJiandong Zheng } 180*799e125cSJiandong Zheng } 181*799e125cSJiandong Zheng } 182*799e125cSJiandong Zheng 183*799e125cSJiandong Zheng /* Set MAC speed using default port */ 184*799e125cSJiandong Zheng i = CONFIG_BCM_SF2_ETH_DEFAULT_PORT; 185*799e125cSJiandong Zheng debug("PHY %d: speed:%d, duplex:%d, link:%d\n", i, 186*799e125cSJiandong Zheng eth->port[i]->speed, eth->port[i]->duplex, eth->port[i]->link); 187*799e125cSJiandong Zheng eth->set_mac_speed(eth->port[i]->speed, eth->port[i]->duplex); 188*799e125cSJiandong Zheng 189*799e125cSJiandong Zheng debug("Enable Ethernet Done.\n"); 190*799e125cSJiandong Zheng 191*799e125cSJiandong Zheng return 0; 192*799e125cSJiandong Zheng } 193*799e125cSJiandong Zheng 194*799e125cSJiandong Zheng static void bcm_sf2_eth_close(struct eth_device *dev) 195*799e125cSJiandong Zheng { 196*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 197*799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 198*799e125cSJiandong Zheng 199*799e125cSJiandong Zheng /* disable DMA */ 200*799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_RX); 201*799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_TX); 202*799e125cSJiandong Zheng 203*799e125cSJiandong Zheng eth->disable_mac(); 204*799e125cSJiandong Zheng } 205*799e125cSJiandong Zheng 206*799e125cSJiandong Zheng int bcm_sf2_eth_register(bd_t *bis, u8 dev_num) 207*799e125cSJiandong Zheng { 208*799e125cSJiandong Zheng struct eth_device *dev; 209*799e125cSJiandong Zheng struct eth_info *eth; 210*799e125cSJiandong Zheng int rc; 211*799e125cSJiandong Zheng 212*799e125cSJiandong Zheng dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 213*799e125cSJiandong Zheng if (dev == NULL) { 214*799e125cSJiandong Zheng error("%s: Not enough memory!\n", __func__); 215*799e125cSJiandong Zheng return -1; 216*799e125cSJiandong Zheng } 217*799e125cSJiandong Zheng 218*799e125cSJiandong Zheng eth = (struct eth_info *)malloc(sizeof(struct eth_info)); 219*799e125cSJiandong Zheng if (eth == NULL) { 220*799e125cSJiandong Zheng error("%s: Not enough memory!\n", __func__); 221*799e125cSJiandong Zheng return -1; 222*799e125cSJiandong Zheng } 223*799e125cSJiandong Zheng 224*799e125cSJiandong Zheng printf(banner); 225*799e125cSJiandong Zheng 226*799e125cSJiandong Zheng memset(dev, 0, sizeof(*dev)); 227*799e125cSJiandong Zheng sprintf(dev->name, "%s_%s-%hu", BCM_SF2_ETH_DEV_NAME, 228*799e125cSJiandong Zheng BCM_SF2_ETH_MAC_NAME, dev_num); 229*799e125cSJiandong Zheng 230*799e125cSJiandong Zheng dev->priv = (void *)eth; 231*799e125cSJiandong Zheng dev->iobase = 0; 232*799e125cSJiandong Zheng 233*799e125cSJiandong Zheng dev->init = bcm_sf2_eth_open; 234*799e125cSJiandong Zheng dev->halt = bcm_sf2_eth_close; 235*799e125cSJiandong Zheng dev->send = bcm_sf2_eth_send; 236*799e125cSJiandong Zheng dev->recv = bcm_sf2_eth_receive; 237*799e125cSJiandong Zheng dev->write_hwaddr = bcm_sf2_eth_write_hwaddr; 238*799e125cSJiandong Zheng 239*799e125cSJiandong Zheng #ifdef CONFIG_BCM_SF2_ETH_GMAC 240*799e125cSJiandong Zheng if (gmac_add(dev)) { 241*799e125cSJiandong Zheng free(eth); 242*799e125cSJiandong Zheng free(dev); 243*799e125cSJiandong Zheng error("%s: Adding GMAC failed!\n", __func__); 244*799e125cSJiandong Zheng return -1; 245*799e125cSJiandong Zheng } 246*799e125cSJiandong Zheng #else 247*799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to register a MAC!" 248*799e125cSJiandong Zheng #endif 249*799e125cSJiandong Zheng 250*799e125cSJiandong Zheng eth_register(dev); 251*799e125cSJiandong Zheng 252*799e125cSJiandong Zheng #ifdef CONFIG_CMD_MII 253*799e125cSJiandong Zheng miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write); 254*799e125cSJiandong Zheng #endif 255*799e125cSJiandong Zheng 256*799e125cSJiandong Zheng /* Initialization */ 257*799e125cSJiandong Zheng debug("Ethernet initialization ..."); 258*799e125cSJiandong Zheng 259*799e125cSJiandong Zheng rc = bcm_sf2_eth_init(dev); 260*799e125cSJiandong Zheng if (rc != 0) { 261*799e125cSJiandong Zheng error("%s: configuration failed!\n", __func__); 262*799e125cSJiandong Zheng return -1; 263*799e125cSJiandong Zheng } 264*799e125cSJiandong Zheng 265*799e125cSJiandong Zheng printf("Basic ethernet functionality initialized\n"); 266*799e125cSJiandong Zheng 267*799e125cSJiandong Zheng return 0; 268*799e125cSJiandong Zheng } 269