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