Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / drivers / net / bcmbca / bcm-sf2-eth-gmac.c
1 /* SPDX-License-Identifier: GPL-2.0+
2 * *
3 * * Copyright 2019 Broadcom Ltd.
4 * */
5
6 #include <config.h>
7 #include <common.h>
8 #include <malloc.h>
9 #include <net.h>
10 #include <asm/io.h>
11 #include <phy.h>
12 #include <asm/system.h>
13 #include <linux/errno.h>
14 #include <linux/io.h>
15 #include <linux/ioport.h>
16 #include "pmc_drv.h"
17
18 #include "asm/arch/gmac.h"
19 #include "bcm_ethsw.h"
20
21 /*---------------------------------------------------------------------*/
22 /* specify number of BDs and buffers to use */
23 /*---------------------------------------------------------------------*/
24 #define NR_TX_BDS 40
25 #define NR_RX_BDS 40
26 #define ENET_ZLEN 60
27 #define ENET_MAX_MTU_SIZE 1522 /* Body(1500) + EH_SIZE(14) + FCS(4) + VLAN(4) */
28 #define DMA_MAX_BURST_LENGTH 8 /* in 64 bit words */
29 #define ENET_BUF_SIZE ((ENET_MAX_MTU_SIZE + 63) & ~63)
30 #define DMA_FC_THRESH_LO 5
31 #define DMA_FC_THRESH_HI 10
32 #define EMAC_TX_WATERMARK 32
33
34 // for now physical address = virtual
35 #define K0_TO_PHYS
36
37 typedef struct sf2gmac_priv {
38
39 volatile GmacIntf *gmac_intf;
40 volatile GmacMac *gmac_mac;
41 volatile DmaRegs *dmaCtrl;
42
43 struct udevice *sf2_devp;
44 bcm_ethsw_ops_t *sf2_ops;
45 unsigned char *rcv_buffer;
46 int init;
47
48 /* transmit variables */
49 volatile DmaChannelCfg *txDma; /* location of transmit DMA register set */
50 volatile DmaDesc *txBds; /* Memory location of tx Dma BD ring */
51 volatile DmaDesc *txFirstBdPtr; /* ptr to first allocated Tx BD */
52 volatile DmaDesc *txNextBdPtr; /* ptr to next Tx BD to transmit with */
53 volatile DmaDesc *txLastBdPtr; /* ptr to last allocated Tx BD */
54
55 /* receive variables */
56 volatile DmaChannelCfg *rxDma; /* location of receive DMA register set */
57 volatile DmaDesc *rxBds; /* Memory location of rx bd ring */
58 volatile DmaDesc *rxFirstBdPtr; /* ptr to first allocated rx bd */
59 volatile DmaDesc *rxBdReadPtr; /* ptr to next rx bd to be processed */
60 volatile DmaDesc *rxLastBdPtr; /* ptr to last allocated rx bd */
61
62 uint8_t* rxBuffers;
63 uint8_t* txBuffers;
64
65 } sf2gmac_priv;
66
67 #define IncRxBdPtr(x, s) if (x == ((sf2gmac_priv *)s)->rxLastBdPtr) \
68 x = ((sf2gmac_priv *)s)->rxBds; \
69 else x++
70 #define InctxBdPtr(x, s) if (x == ((sf2gmac_priv *)s)->txLastBdPtr) \
71 x = ((sf2gmac_priv *)s)->txBds; \
72 else x++
73
74
75 #define DMA_RX_CHAN 0
76 #define DMA_TX_CHAN 1
77
78 #define CACHE_ALIGN 64
79
80
81 /*
82 * init_dma: Initialize DMA control register
83 */
84
85 #define NUM_PORTS 1 // only 1 port supported
86 static void init_dma(struct sf2gmac_priv *softc)
87 {
88 uint32_t *StateRam;
89 int i;
90
91 /*
92 * clear State RAM
93 */
94 StateRam = (uint32_t *)&softc->dmaCtrl->stram.s[0];
95 for (i = 0; i < sizeof(DmaStateRam) / sizeof(uint32_t) * NUM_PORTS * 2; i++)
96 StateRam[i] = 0;
97
98 /*
99 * initialize IUDMA controller register
100 */
101 softc->dmaCtrl->controller_cfg = DMA_FLOWC_CH1_EN;
102 softc->dmaCtrl->flowctl_ch1_thresh_lo = DMA_FC_THRESH_LO;
103 softc->dmaCtrl->flowctl_ch1_thresh_hi = DMA_FC_THRESH_HI;
104 softc->dmaCtrl->flowctl_ch1_alloc = 0;
105
106 // transmit
107 softc->txDma->cfg = 0; /* initialize first (will enable later) */
108 softc->txDma->maxBurst = DMA_MAX_BURST_LENGTH;
109 softc->txDma->intMask = 0; /* mask all ints */
110 /* clr any pending interrupts on channel */
111 softc->txDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE;
112 softc->txDma->intMask = DMA_DONE;
113 softc->dmaCtrl->stram.s[DMA_TX_CHAN].baseDescPtr = (uint32_t)softc->txFirstBdPtr;
114
115 // receive
116 softc->rxDma->cfg = 0; // initialize first (will enable later)
117 softc->rxDma->maxBurst = DMA_MAX_BURST_LENGTH;
118 softc->rxDma->intMask = 0; /* mask all ints */
119 /* clr any pending interrupts on channel */
120 softc->rxDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE;
121 softc->rxDma->intMask = DMA_DONE;
122 softc->dmaCtrl->stram.s[DMA_RX_CHAN].baseDescPtr = (uint32_t)softc->rxFirstBdPtr;
123 }
124
125
126 static void gmac_init(sf2gmac_priv *priv)
127 {
128 volatile GmacIntf *GMAC_INTF = priv->gmac_intf;
129 volatile GmacMac *GMAC_MAC = priv->gmac_mac;
130
131 /* Reset GMAC */
132 GMAC_MAC->Cmd.sw_reset = 1;
133 udelay(20);
134 GMAC_MAC->Cmd.sw_reset = 0;
135
136 GMAC_INTF->Flush.txfifo_flush = 1;
137 GMAC_INTF->Flush.rxfifo_flush = 1;
138
139 GMAC_INTF->Flush.txfifo_flush = 0;
140 GMAC_INTF->Flush.rxfifo_flush = 0;
141
142 GMAC_INTF->MibCtrl.clrMib = 1;
143 GMAC_INTF->MibCtrl.clrMib = 0;
144
145 /* default CMD configuration */
146 GMAC_MAC->Cmd.eth_speed = CMD_ETH_SPEED_1000;
147
148 /* Disable Tx and Rx */
149 GMAC_MAC->Cmd.tx_ena = 0;
150 GMAC_MAC->Cmd.rx_ena = 0;
151
152 return;
153 }
154
155 static void gmac_enable_port(sf2gmac_priv *priv, int enable)
156 {
157 volatile GmacMac *GMAC_MAC = priv->gmac_mac;
158
159 if( enable ) {
160 GMAC_MAC->Cmd.tx_ena = 1;
161 GMAC_MAC->Cmd.rx_ena = 1;
162 }
163 else {
164 GMAC_MAC->Cmd.tx_ena = 0;
165 GMAC_MAC->Cmd.rx_ena = 0;
166 }
167
168 return;
169 }
170
171 static int internal_open (struct sf2gmac_priv *softc)
172 {
173 int i;
174 unsigned char *p;
175
176 softc->rxDma = &softc->dmaCtrl->chcfg[DMA_RX_CHAN];
177 softc->txDma = &softc->dmaCtrl->chcfg[DMA_TX_CHAN];
178
179 // If doing SW reboot in EPI the controller can still be active
180 softc->rxDma->cfg = 0;
181 softc->txDma->cfg = 0;
182 softc->dmaCtrl->controller_cfg &= ~DMA_MASTER_EN;
183
184 // noncached memory can only be allocated once
185 if (softc->txBds == NULL)
186 {
187 // allocate a chunk of non cached memory for packet descriptors
188 p = noncached_alloc((NR_TX_BDS + NR_RX_BDS) * sizeof(DmaDesc), CACHE_ALIGN);
189 if( p == NULL ) {
190 printf( "BCM63xx : Fail alloctxBds mem\n" );
191 return -1;
192 }
193
194 softc->txBds = (DmaDesc *)p;
195 p += (NR_TX_BDS * sizeof(DmaDesc));
196 softc->rxBds = (DmaDesc *)p;
197 }
198
199 // allocate memory for RX and TX data (cached memory)
200 softc->rxBuffers = (uint8_t*)memalign( CACHE_ALIGN, NR_RX_BDS * ENET_BUF_SIZE );
201 if( softc->rxBuffers == NULL ) {
202 printf( "BCM63xx : Failed allocRxBuffer mem\n" );
203 return -1;
204 }
205 invalidate_dcache_range((unsigned long)softc->rxBuffers, (unsigned long)softc->rxBuffers + NR_RX_BDS * ENET_BUF_SIZE);
206
207 softc->txBuffers = (uint8_t*)memalign( CACHE_ALIGN, NR_TX_BDS * ENET_BUF_SIZE );
208 if( softc->txBuffers == NULL ) {
209 printf( "BCM63xx : Failed alloc txBuffer mem\n" );
210 free( (void *)(softc->rxBuffers) );
211 softc->rxBuffers = NULL;
212 return -1;
213 }
214 invalidate_dcache_range((unsigned long)softc->txBuffers, (unsigned long)softc->txBuffers + NR_TX_BDS * ENET_BUF_SIZE);
215
216 /* Init the Receive Buffer Descriptor Ring. */
217 softc->rxFirstBdPtr = softc->rxBdReadPtr = softc->rxBds;
218 softc->rxLastBdPtr = softc->rxBds + NR_RX_BDS - 1;
219
220 for(i = 0; i < NR_RX_BDS; i++) {
221 (softc->rxBds + i)->status = DMA_OWN;
222 (softc->rxBds + i)->length = ENET_BUF_SIZE;
223 (softc->rxBds + i)->address = K0_TO_PHYS( (uintptr_t)softc->rxBuffers + i * ENET_BUF_SIZE );
224 softc->dmaCtrl->flowctl_ch1_alloc = 1;
225 }
226 softc->rxLastBdPtr->status |= DMA_WRAP;
227
228 /* Init Transmit Buffer Descriptor Ring. */
229 softc->txFirstBdPtr = softc->txNextBdPtr = softc->txBds;
230 softc->txLastBdPtr = softc->txBds + NR_TX_BDS - 1;
231
232 for(i = 0; i < NR_TX_BDS; i++) {
233 (softc->txBds + i)->status = 0;
234 (softc->txBds + i)->length = 0;
235 (softc->txBds + i)->address = K0_TO_PHYS( (uintptr_t)softc->txBuffers + i * ENET_BUF_SIZE );
236 }
237 softc->txLastBdPtr->status = DMA_WRAP;
238
239 /* init dma registers */
240 init_dma(softc);
241 softc->dmaCtrl->controller_cfg |= DMA_MASTER_EN;
242 softc->rxDma->cfg |= DMA_ENABLE;
243
244 softc->rcv_buffer = (unsigned char *)memalign(sizeof(int), ENET_BUF_SIZE);
245 if (softc->rcv_buffer == NULL) {
246 printf("failed to allocate receive buffer\n");
247 return -1;
248 }
249
250 return 0;
251 }
252
253 static int bcmbca_sf2gmac_eth_start (struct udevice *dev)
254 {
255 int rc = 0;
256 struct sf2gmac_priv *priv = dev_get_priv(dev);
257
258 debug("bcmbca_sf2gmac_eth_start called %s\n", dev->name);
259 if (priv->init)
260 return 0;
261
262 rc = internal_open(priv);
263 if (rc) {
264 printf("internal open failed rx %d\n", rc);
265 return rc;
266 }
267
268 if (priv->sf2_devp)
269 priv->sf2_ops->open (priv->sf2_devp);
270
271 gmac_init(priv);
272 gmac_enable_port(priv, 1);
273
274 priv->init = 1;
275 return 0;
276 }
277
278 static void bcmbca_sf2gmac_eth_stop(struct udevice *dev)
279 {
280 struct sf2gmac_priv *priv = dev_get_priv(dev);
281
282 debug("bcmbca_sf2gmac_eth_stop called %s\n", dev->name);
283
284 return;
285 }
286
287 static int bcmbca_sf2gmac_eth_read_mac(struct udevice *dev)
288 {
289 return 0;
290 }
291
292 static int bcmbca_sf2gmac_eth_send(struct udevice *dev, void *buffer, int length)
293 {
294 volatile DmaDesc * CurrentBdPtr;
295 unsigned char * dstptr;
296 struct sf2gmac_priv *softc = dev_get_priv(dev);
297 uint32_t status, offset;
298 int timeout = 1000;
299
300 if (length > ENET_MAX_MTU_SIZE)
301 {
302 return -1;
303 }
304
305 CurrentBdPtr = softc->txNextBdPtr;
306
307 /* Find out if the next BD is available. */
308 if( CurrentBdPtr->status & DMA_OWN ) {
309 printf( "No tx BD available ?!\n" );
310 return -1;
311 }
312
313 dstptr = (unsigned char *)( CurrentBdPtr->address );
314 memcpy( dstptr, buffer, length );
315 flush_cache((unsigned long)dstptr, length);
316
317 /* Set status of DMA BD to be transmitted. */
318 status = DMA_SOP | DMA_EOP | DMA_APPEND_CRC | DMA_OWN;
319 if( CurrentBdPtr == softc->txLastBdPtr ) {
320 status |= DMA_WRAP;
321 }
322
323 CurrentBdPtr->length = length;
324 CurrentBdPtr->status = status;
325
326 barrier();
327 softc->txDma->cfg |= DMA_ENABLE;
328
329 // poll dma status until done
330 do {
331 udelay(10);
332 invalidate_dcache_range((unsigned long)dstptr, (unsigned long)dstptr + CACHE_ALIGN);
333 } while((CurrentBdPtr->status & DMA_OWN) && timeout--);
334
335 if (timeout > 0) {
336 //Advance BD pointer to next in the chain.
337 InctxBdPtr( CurrentBdPtr, softc );
338 softc->txNextBdPtr = CurrentBdPtr;
339 return 0;
340 }
341 else {
342 printf("timeout sending packet of size %d\n", length);
343 // clear the buffer pointer and force the PD pointer
344 softc->txDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE;
345 offset = softc->dmaCtrl->stram.s[DMA_TX_CHAN].state_data & RING_OFFSET_MASK;
346 softc->txNextBdPtr = (volatile DmaDesc *)((unsigned char *)softc->txFirstBdPtr + (offset * sizeof(DmaDesc)));
347 return -1;
348 }
349 }
350
351 static int bcmbca_sf2gmac_eth_recv(struct udevice *dev, int flags, uchar ** packetp)
352 {
353 int length, rc = 0;
354 uint16_t dmaFlag;
355 uint8_t *srcptr;
356 volatile DmaDesc * CurrentBdPtr;
357 struct sf2gmac_priv *softc = dev_get_priv(dev);
358
359 dmaFlag = (uint16_t) softc->rxBdReadPtr->status;
360
361 if (!(dmaFlag & DMA_EOP)) {
362 return -1;
363 }
364
365 CurrentBdPtr = softc->rxBdReadPtr;
366 srcptr = CurrentBdPtr->address;
367
368 length = CurrentBdPtr->length;
369
370 if (length == ENET_BUF_SIZE || length < ENET_ZLEN || length > ENET_MAX_MTU_SIZE)
371 {
372 printf("received data length is incorrect %d\n", length);
373 rc = -1;
374 goto out;
375 }
376 invalidate_dcache_range((unsigned long)srcptr, (unsigned long)srcptr + ENET_BUF_SIZE);
377 barrier();
378
379 *packetp = softc->rcv_buffer;
380
381 memcpy (*packetp, srcptr, length);
382 rc = length;
383
384 out:
385 CurrentBdPtr->length = ENET_BUF_SIZE;
386 CurrentBdPtr->status &= DMA_WRAP;
387 CurrentBdPtr->status |= DMA_OWN;
388
389 IncRxBdPtr( CurrentBdPtr, softc );
390 softc->rxBdReadPtr = CurrentBdPtr;
391 softc->dmaCtrl->flowctl_ch1_alloc = 1;
392
393 // enable rx dma
394 softc->rxDma->cfg = DMA_ENABLE;
395 return rc;
396 }
397
398 static int sf2gmac_free_pkt (struct udevice *dev, uchar *packet, int length)
399 {
400 struct sf2gmac_priv *priv = dev_get_priv(dev);
401 if (packet != priv->rcv_buffer)
402 printf("why free this? %p\n", packet);
403
404 return 0;
405 }
406
407 static const struct eth_ops sf2gmac_eth_ops = {
408 .start = bcmbca_sf2gmac_eth_start,
409 .send = bcmbca_sf2gmac_eth_send,
410 .recv = bcmbca_sf2gmac_eth_recv,
411 .stop = bcmbca_sf2gmac_eth_stop,
412 .free_pkt = sf2gmac_free_pkt,
413 .read_rom_hwaddr = bcmbca_sf2gmac_eth_read_mac,
414 };
415
416 static int sf2gmac_probe (struct udevice *dev)
417 {
418 int ret=0, size;
419 struct resource res;
420 struct udevice *sf2_devp;
421 struct sf2gmac_priv *priv = dev_get_priv(dev);
422 uint phandle_id;
423 const fdt32_t *list;
424
425 ret = dev_read_resource_byname(dev, "gmac-intf-base", &res);
426 if (ret) {
427 dev_err(dev, "can't get regs gmac-intf-base address(ret = %d)!\n", ret);
428 return ret;
429 }
430 priv->gmac_intf = devm_ioremap(dev, res.start, resource_size(&res));
431
432 ret = dev_read_resource_byname(dev, "gmac-mac-base", &res);
433 if (ret) {
434 dev_err(dev, "can't get regs gmac-mac-base address(ret = %d)!\n", ret);
435 return ret;
436 }
437 priv->gmac_mac = devm_ioremap(dev, res.start, resource_size(&res));
438
439 ret = dev_read_resource_byname(dev, "gmac-dma-base", &res);
440 if (ret) {
441 dev_err(dev, "can't get regs gmac-dma-base address(ret = %d)!\n", ret);
442 return ret;
443 }
444 priv->dmaCtrl = devm_ioremap(dev, res.start, resource_size(&res));
445
446 priv->sf2_devp = NULL;
447 list = dev_read_prop (dev, "ethsw", &size);
448 if (size > 0) {
449 phandle_id = fdt32_to_cpu(*list);
450 if (!uclass_get_device_by_phandle_id(UCLASS_NOP, phandle_id, &sf2_devp))
451 {
452 printf("sf2 found, should have been probed name %s driver name %s\n",
453 sf2_devp->name, sf2_devp->driver->name);
454 priv->sf2_devp = sf2_devp;
455 priv->sf2_ops = dev_get_priv(sf2_devp);
456 priv->sf2_ops->init (priv->sf2_devp);
457 PowerOnDevice(PMB_ADDR_GMAC);
458 }
459 }
460 // in case sf2 is not initialized, the sf2 gmac network interface will not work
461 if (priv->sf2_devp == NULL) {
462 printf("cannot find the pairing SF2 driver\n");
463 return -1;
464 }
465
466 priv->txBds = NULL;
467 priv->rxBds = NULL;
468 priv->init = 0;
469
470 return 0;
471 }
472
473 static int sf2gmac_remove(struct udevice *dev)
474 {
475 struct sf2gmac_priv *priv = dev_get_priv(dev);
476
477 if (!priv->init)
478 return 0;
479
480 if (priv->sf2_devp)
481 priv->sf2_ops->close (priv->sf2_devp);
482
483 gmac_enable_port(priv, 0);
484
485 free( (void *)(priv->rcv_buffer) );
486 free( (void *)(priv->rxBuffers) );
487 free( (void *)(priv->txBuffers) );
488 priv->rxBuffers = NULL;
489 priv->txBuffers = NULL;
490 priv->init = 0;
491 PowerOffDevice(PMB_ADDR_GMAC, 0);
492
493 return 0;
494 }
495
496 static const struct udevice_id bcmbca_sf2gmac_match_ids[] = {
497 { .compatible = "brcm,bcmbca-sf2gmac"},
498 { }
499 };
500
501
502 U_BOOT_DRIVER(sf2gmac) = {
503 .name = "sf2-gmac",
504 .id = UCLASS_ETH,
505 .of_match = bcmbca_sf2gmac_match_ids,
506 .flags = DM_REMOVE_ACTIVE_ALL,
507 .probe = sf2gmac_probe,
508 .remove = sf2gmac_remove,
509 .ops = &sf2gmac_eth_ops,
510 .priv_auto_alloc_size = sizeof(struct sf2gmac_priv),
511 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
512 };
513