1799e125cSJiandong Zheng /* 2799e125cSJiandong Zheng * Copyright 2014 Broadcom Corporation. 3799e125cSJiandong Zheng * 4799e125cSJiandong Zheng * SPDX-License-Identifier: GPL-2.0+ 5799e125cSJiandong Zheng */ 6799e125cSJiandong Zheng 7799e125cSJiandong Zheng #include <common.h> 8799e125cSJiandong Zheng #include <malloc.h> 9799e125cSJiandong Zheng #include <net.h> 10799e125cSJiandong Zheng #include <config.h> 11799e125cSJiandong Zheng 12799e125cSJiandong Zheng #include <phy.h> 13799e125cSJiandong Zheng #include <miiphy.h> 14799e125cSJiandong Zheng 15799e125cSJiandong Zheng #include <asm/io.h> 16799e125cSJiandong Zheng 17799e125cSJiandong Zheng #include <netdev.h> 18799e125cSJiandong Zheng #include "bcm-sf2-eth.h" 19799e125cSJiandong Zheng 20799e125cSJiandong Zheng #if defined(CONFIG_BCM_SF2_ETH_GMAC) 21799e125cSJiandong Zheng #include "bcm-sf2-eth-gmac.h" 22799e125cSJiandong Zheng #else 23799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to define a MAC!" 24799e125cSJiandong Zheng #endif 25799e125cSJiandong Zheng 26799e125cSJiandong Zheng #define BCM_NET_MODULE_DESCRIPTION "Broadcom Starfighter2 Ethernet driver" 27799e125cSJiandong Zheng #define BCM_NET_MODULE_VERSION "0.1" 28799e125cSJiandong Zheng #define BCM_SF2_ETH_DEV_NAME "bcm_sf2" 29799e125cSJiandong Zheng 30799e125cSJiandong Zheng static const char banner[] = 31799e125cSJiandong Zheng BCM_NET_MODULE_DESCRIPTION " " BCM_NET_MODULE_VERSION "\n"; 32799e125cSJiandong Zheng 33799e125cSJiandong Zheng static int bcm_sf2_eth_init(struct eth_device *dev) 34799e125cSJiandong Zheng { 35799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 36799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 37799e125cSJiandong Zheng struct phy_device *phydev; 38799e125cSJiandong Zheng int rc = 0; 39799e125cSJiandong Zheng int i; 40799e125cSJiandong Zheng 41799e125cSJiandong Zheng rc = eth->mac_init(dev); 42799e125cSJiandong Zheng if (rc) { 43799e125cSJiandong Zheng error("%s: Couldn't cofigure MAC!\n", __func__); 44799e125cSJiandong Zheng return rc; 45799e125cSJiandong Zheng } 46799e125cSJiandong Zheng 47799e125cSJiandong Zheng /* disable DMA */ 48799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_RX); 49799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_TX); 50799e125cSJiandong Zheng 51799e125cSJiandong Zheng eth->port_num = 0; 52799e125cSJiandong Zheng debug("Connecting PHY 0...\n"); 53799e125cSJiandong Zheng phydev = phy_connect(miiphy_get_dev_by_name(dev->name), 54799e125cSJiandong Zheng 0, dev, eth->phy_interface); 55799e125cSJiandong Zheng if (phydev != NULL) { 56799e125cSJiandong Zheng eth->port[0] = phydev; 57799e125cSJiandong Zheng eth->port_num += 1; 58799e125cSJiandong Zheng } else { 59799e125cSJiandong Zheng debug("No PHY found for port 0\n"); 60799e125cSJiandong Zheng } 61799e125cSJiandong Zheng 62799e125cSJiandong Zheng for (i = 0; i < eth->port_num; i++) 63799e125cSJiandong Zheng phy_config(eth->port[i]); 64799e125cSJiandong Zheng 65799e125cSJiandong Zheng return rc; 66799e125cSJiandong Zheng } 67799e125cSJiandong Zheng 68799e125cSJiandong Zheng /* 69799e125cSJiandong Zheng * u-boot net functions 70799e125cSJiandong Zheng */ 71799e125cSJiandong Zheng 72799e125cSJiandong Zheng static int bcm_sf2_eth_send(struct eth_device *dev, void *packet, int length) 73799e125cSJiandong Zheng { 74799e125cSJiandong Zheng struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); 75799e125cSJiandong Zheng uint8_t *buf = (uint8_t *)packet; 76799e125cSJiandong Zheng int rc = 0; 77799e125cSJiandong Zheng int i = 0; 78799e125cSJiandong Zheng 79799e125cSJiandong Zheng debug("%s enter\n", __func__); 80799e125cSJiandong Zheng 81799e125cSJiandong Zheng /* load buf and start transmit */ 82799e125cSJiandong Zheng rc = dma->tx_packet(dma, buf, length); 83799e125cSJiandong Zheng if (rc) { 84799e125cSJiandong Zheng debug("ERROR - Tx failed\n"); 85799e125cSJiandong Zheng return rc; 86799e125cSJiandong Zheng } 87799e125cSJiandong Zheng 88799e125cSJiandong Zheng while (!(dma->check_tx_done(dma))) { 89799e125cSJiandong Zheng udelay(100); 90799e125cSJiandong Zheng debug("."); 91799e125cSJiandong Zheng i++; 92799e125cSJiandong Zheng if (i > 20) { 93799e125cSJiandong Zheng error("%s: Tx timeout: retried 20 times\n", __func__); 94799e125cSJiandong Zheng rc = -1; 95799e125cSJiandong Zheng break; 96799e125cSJiandong Zheng } 97799e125cSJiandong Zheng } 98799e125cSJiandong Zheng 99799e125cSJiandong Zheng debug("%s exit rc(0x%x)\n", __func__, rc); 100799e125cSJiandong Zheng return rc; 101799e125cSJiandong Zheng } 102799e125cSJiandong Zheng 103799e125cSJiandong Zheng static int bcm_sf2_eth_receive(struct eth_device *dev) 104799e125cSJiandong Zheng { 105799e125cSJiandong Zheng struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); 106*1fd92db8SJoe Hershberger uint8_t *buf = (uint8_t *)net_rx_packets[0]; 107799e125cSJiandong Zheng int rcvlen; 108799e125cSJiandong Zheng int rc = 0; 109799e125cSJiandong Zheng int i = 0; 110799e125cSJiandong Zheng 111799e125cSJiandong Zheng while (1) { 112799e125cSJiandong Zheng /* Poll Rx queue to get a packet */ 113799e125cSJiandong Zheng rcvlen = dma->check_rx_done(dma, buf); 114799e125cSJiandong Zheng if (rcvlen < 0) { 115799e125cSJiandong Zheng /* No packet received */ 116799e125cSJiandong Zheng rc = -1; 117799e125cSJiandong Zheng debug("\nNO More Rx\n"); 118799e125cSJiandong Zheng break; 119799e125cSJiandong Zheng } else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) { 120799e125cSJiandong Zheng error("%s: Wrong Ethernet packet size (%d B), skip!\n", 121799e125cSJiandong Zheng __func__, rcvlen); 122799e125cSJiandong Zheng break; 123799e125cSJiandong Zheng } else { 124799e125cSJiandong Zheng debug("recieved\n"); 125799e125cSJiandong Zheng 126799e125cSJiandong Zheng /* Forward received packet to uboot network handler */ 127*1fd92db8SJoe Hershberger net_process_received_packet(buf, rcvlen); 128799e125cSJiandong Zheng 129799e125cSJiandong Zheng if (++i >= PKTBUFSRX) 130799e125cSJiandong Zheng i = 0; 131*1fd92db8SJoe Hershberger buf = net_rx_packets[i]; 132799e125cSJiandong Zheng } 133799e125cSJiandong Zheng } 134799e125cSJiandong Zheng 135799e125cSJiandong Zheng return rc; 136799e125cSJiandong Zheng } 137799e125cSJiandong Zheng 138799e125cSJiandong Zheng static int bcm_sf2_eth_write_hwaddr(struct eth_device *dev) 139799e125cSJiandong Zheng { 140799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 141799e125cSJiandong Zheng 142799e125cSJiandong Zheng printf(" ETH MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 143799e125cSJiandong Zheng dev->enetaddr[0], dev->enetaddr[1], dev->enetaddr[2], 144799e125cSJiandong Zheng dev->enetaddr[3], dev->enetaddr[4], dev->enetaddr[5]); 145799e125cSJiandong Zheng 146799e125cSJiandong Zheng return eth->set_mac_addr(dev->enetaddr); 147799e125cSJiandong Zheng } 148799e125cSJiandong Zheng 149799e125cSJiandong Zheng static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt) 150799e125cSJiandong Zheng { 151799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 152799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 153799e125cSJiandong Zheng int i; 154799e125cSJiandong Zheng 155799e125cSJiandong Zheng debug("Enabling BCM SF2 Ethernet.\n"); 156799e125cSJiandong Zheng 157799e125cSJiandong Zheng /* Set MAC address from env */ 158799e125cSJiandong Zheng if (bcm_sf2_eth_write_hwaddr(dev) != 0) { 159799e125cSJiandong Zheng error("%s: MAC set error when opening !\n", __func__); 160799e125cSJiandong Zheng return -1; 161799e125cSJiandong Zheng } 162799e125cSJiandong Zheng 163799e125cSJiandong Zheng eth->enable_mac(); 164799e125cSJiandong Zheng 165799e125cSJiandong Zheng /* enable tx and rx DMA */ 166799e125cSJiandong Zheng dma->enable_dma(dma, MAC_DMA_RX); 167799e125cSJiandong Zheng dma->enable_dma(dma, MAC_DMA_TX); 168799e125cSJiandong Zheng 169799e125cSJiandong Zheng /* 170799e125cSJiandong Zheng * Need to start PHY here because link speed can change 171799e125cSJiandong Zheng * before each ethernet operation 172799e125cSJiandong Zheng */ 173799e125cSJiandong Zheng for (i = 0; i < eth->port_num; i++) { 174799e125cSJiandong Zheng if (phy_startup(eth->port[i])) { 175799e125cSJiandong Zheng error("%s: PHY %d startup failed!\n", __func__, i); 176799e125cSJiandong Zheng if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) { 177799e125cSJiandong Zheng error("%s: No default port %d!\n", __func__, i); 178799e125cSJiandong Zheng return -1; 179799e125cSJiandong Zheng } 180799e125cSJiandong Zheng } 181799e125cSJiandong Zheng } 182799e125cSJiandong Zheng 183799e125cSJiandong Zheng /* Set MAC speed using default port */ 184799e125cSJiandong Zheng i = CONFIG_BCM_SF2_ETH_DEFAULT_PORT; 185799e125cSJiandong Zheng debug("PHY %d: speed:%d, duplex:%d, link:%d\n", i, 186799e125cSJiandong Zheng eth->port[i]->speed, eth->port[i]->duplex, eth->port[i]->link); 187799e125cSJiandong Zheng eth->set_mac_speed(eth->port[i]->speed, eth->port[i]->duplex); 188799e125cSJiandong Zheng 189799e125cSJiandong Zheng debug("Enable Ethernet Done.\n"); 190799e125cSJiandong Zheng 191799e125cSJiandong Zheng return 0; 192799e125cSJiandong Zheng } 193799e125cSJiandong Zheng 194799e125cSJiandong Zheng static void bcm_sf2_eth_close(struct eth_device *dev) 195799e125cSJiandong Zheng { 196799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 197799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 198799e125cSJiandong Zheng 199799e125cSJiandong Zheng /* disable DMA */ 200799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_RX); 201799e125cSJiandong Zheng dma->disable_dma(dma, MAC_DMA_TX); 202799e125cSJiandong Zheng 203799e125cSJiandong Zheng eth->disable_mac(); 204799e125cSJiandong Zheng } 205799e125cSJiandong Zheng 206799e125cSJiandong Zheng int bcm_sf2_eth_register(bd_t *bis, u8 dev_num) 207799e125cSJiandong Zheng { 208799e125cSJiandong Zheng struct eth_device *dev; 209799e125cSJiandong Zheng struct eth_info *eth; 210799e125cSJiandong Zheng int rc; 211799e125cSJiandong Zheng 212799e125cSJiandong Zheng dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 213799e125cSJiandong Zheng if (dev == NULL) { 214799e125cSJiandong Zheng error("%s: Not enough memory!\n", __func__); 215799e125cSJiandong Zheng return -1; 216799e125cSJiandong Zheng } 217799e125cSJiandong Zheng 218799e125cSJiandong Zheng eth = (struct eth_info *)malloc(sizeof(struct eth_info)); 219799e125cSJiandong Zheng if (eth == NULL) { 220799e125cSJiandong Zheng error("%s: Not enough memory!\n", __func__); 221799e125cSJiandong Zheng return -1; 222799e125cSJiandong Zheng } 223799e125cSJiandong Zheng 224799e125cSJiandong Zheng printf(banner); 225799e125cSJiandong Zheng 226799e125cSJiandong Zheng memset(dev, 0, sizeof(*dev)); 227799e125cSJiandong Zheng sprintf(dev->name, "%s_%s-%hu", BCM_SF2_ETH_DEV_NAME, 228799e125cSJiandong Zheng BCM_SF2_ETH_MAC_NAME, dev_num); 229799e125cSJiandong Zheng 230799e125cSJiandong Zheng dev->priv = (void *)eth; 231799e125cSJiandong Zheng dev->iobase = 0; 232799e125cSJiandong Zheng 233799e125cSJiandong Zheng dev->init = bcm_sf2_eth_open; 234799e125cSJiandong Zheng dev->halt = bcm_sf2_eth_close; 235799e125cSJiandong Zheng dev->send = bcm_sf2_eth_send; 236799e125cSJiandong Zheng dev->recv = bcm_sf2_eth_receive; 237799e125cSJiandong Zheng dev->write_hwaddr = bcm_sf2_eth_write_hwaddr; 238799e125cSJiandong Zheng 239799e125cSJiandong Zheng #ifdef CONFIG_BCM_SF2_ETH_GMAC 240799e125cSJiandong Zheng if (gmac_add(dev)) { 241799e125cSJiandong Zheng free(eth); 242799e125cSJiandong Zheng free(dev); 243799e125cSJiandong Zheng error("%s: Adding GMAC failed!\n", __func__); 244799e125cSJiandong Zheng return -1; 245799e125cSJiandong Zheng } 246799e125cSJiandong Zheng #else 247799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to register a MAC!" 248799e125cSJiandong Zheng #endif 249799e125cSJiandong Zheng 250799e125cSJiandong Zheng eth_register(dev); 251799e125cSJiandong Zheng 252799e125cSJiandong Zheng #ifdef CONFIG_CMD_MII 253799e125cSJiandong Zheng miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write); 254799e125cSJiandong Zheng #endif 255799e125cSJiandong Zheng 256799e125cSJiandong Zheng /* Initialization */ 257799e125cSJiandong Zheng debug("Ethernet initialization ..."); 258799e125cSJiandong Zheng 259799e125cSJiandong Zheng rc = bcm_sf2_eth_init(dev); 260799e125cSJiandong Zheng if (rc != 0) { 261799e125cSJiandong Zheng error("%s: configuration failed!\n", __func__); 262799e125cSJiandong Zheng return -1; 263799e125cSJiandong Zheng } 264799e125cSJiandong Zheng 265799e125cSJiandong Zheng printf("Basic ethernet functionality initialized\n"); 266799e125cSJiandong Zheng 267799e125cSJiandong Zheng return 0; 268799e125cSJiandong Zheng } 269