1
2 /*
3 * Copyright (c) 2006-2021, RT-Thread Development Team
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2020-10-30 bigmagic first version
10 * 2023-03-28 WangXiaoyao Modify pbuf_alloc
11 */
12
13 #include <rthw.h>
14 #include <stdint.h>
15 #include <rtthread.h>
16 #include <lwip/sys.h>
17 #include <netif/ethernetif.h>
18
19 #include "mbox.h"
20 #include "raspi4.h"
21 #include "drv_eth.h"
22
23 #define LOG_LVL DBG_LOG
24 #define LOG_TAG "drv.eth"
25 #include <rtdbg.h>
26
27 static int link_speed = 0;
28 static int link_flag = 0;
29
30 #define DMA_DISC_ADDR_SIZE (4 * 1024 *1024)
31
32 #define RX_DESC_BASE (mac_reg_base_addr + GENET_RX_OFF)
33 #define TX_DESC_BASE (mac_reg_base_addr + GENET_TX_OFF)
34
35 #define MAX_ADDR_LEN (6)
36
37 #define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
38 #define lower_32_bits(n) ((rt_uint32_t)(n))
39
40 #define BIT(nr) (1UL << (nr))
41
42 static rt_thread_t link_thread_tid = RT_NULL;
43 #define LINK_THREAD_STACK_SIZE (8192)
44 #define LINK_THREAD_PRIORITY (20)
45 #define LINK_THREAD_TIMESLICE (10)
46
47 static rt_uint32_t tx_index = 0;
48 static rt_uint32_t rx_index = 0;
49 static rt_uint32_t index_flag = 0;
50
51 struct rt_eth_dev
52 {
53 struct eth_device parent;
54 rt_uint8_t dev_addr[MAX_ADDR_LEN];
55 char *name;
56 void *iobase;
57 int state;
58 int index;
59 struct rt_timer link_timer;
60 void *priv;
61 };
62 static struct rt_eth_dev eth_dev;
63 static struct rt_semaphore link_ack;
64
read32(void * addr)65 static inline rt_uint32_t read32(void *addr)
66 {
67 return (*((volatile unsigned int*)(addr)));
68 }
69
write32(void * addr,rt_uint32_t value)70 static inline void write32(void *addr, rt_uint32_t value)
71 {
72 (*((volatile unsigned int*)(addr))) = value;
73 }
74
eth_rx_irq(int irq,void * param)75 static void eth_rx_irq(int irq, void *param)
76 {
77 rt_uint32_t val = 0;
78 val = read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT);
79 val &= ~read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT_MASK);
80
81 write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR, val);
82
83 if (val & GENET_IRQ_RXDMA_DONE)
84 {
85 eth_device_ready(ð_dev.parent);
86 }
87
88 if (val & GENET_IRQ_TXDMA_DONE)
89 {
90 //todo
91 }
92 }
93
94 /* We only support RGMII (as used on the RPi4). */
bcmgenet_interface_set(void)95 static int bcmgenet_interface_set(void)
96 {
97 int phy_mode = PHY_INTERFACE_MODE_RGMII;
98 switch (phy_mode)
99 {
100 case PHY_INTERFACE_MODE_RGMII:
101 case PHY_INTERFACE_MODE_RGMII_RXID:
102 write32(mac_reg_base_addr + SYS_PORT_CTRL, PORT_MODE_EXT_GPHY);
103 break;
104
105 default:
106 rt_kprintf("unknown phy mode: %d\n", mac_reg_base_addr);
107 return -1;
108 }
109 return 0;
110 }
111
bcmgenet_umac_reset(void)112 static void bcmgenet_umac_reset(void)
113 {
114 rt_uint32_t reg;
115 reg = read32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL);
116 reg |= BIT(1);
117 write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg);
118
119 reg &= ~BIT(1);
120 write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg);
121
122 DELAY_MICROS(10);
123
124 write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), 0);
125 DELAY_MICROS(10);
126
127 write32(mac_reg_base_addr + UMAC_CMD, 0);
128 write32(mac_reg_base_addr + UMAC_CMD, (CMD_SW_RESET | CMD_LCL_LOOP_EN));
129 DELAY_MICROS(2);
130
131 write32(mac_reg_base_addr + UMAC_CMD, 0);
132 /* clear tx/rx counter */
133 write32(mac_reg_base_addr + UMAC_MIB_CTRL, MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT);
134 write32(mac_reg_base_addr + UMAC_MIB_CTRL, 0);
135 write32(mac_reg_base_addr + UMAC_MAX_FRAME_LEN, ENET_MAX_MTU_SIZE);
136
137 /* init rx registers, enable ip header optimization */
138 reg = read32(mac_reg_base_addr + RBUF_CTRL);
139 reg |= RBUF_ALIGN_2B;
140 write32(mac_reg_base_addr + RBUF_CTRL, reg);
141 write32(mac_reg_base_addr + RBUF_TBUF_SIZE_CTRL, 1);
142 }
143
bcmgenet_disable_dma(void)144 static void bcmgenet_disable_dma(void)
145 {
146 rt_uint32_t tdma_reg = 0, rdma_reg = 0;
147
148 tdma_reg = read32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL);
149 tdma_reg &= ~(1UL << DMA_EN);
150 write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, tdma_reg);
151 rdma_reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL);
152 rdma_reg &= ~(1UL << DMA_EN);
153 write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, rdma_reg);
154 write32(mac_reg_base_addr + UMAC_TX_FLUSH, 1);
155 DELAY_MICROS(100);
156 write32(mac_reg_base_addr + UMAC_TX_FLUSH, 0);
157 }
158
bcmgenet_enable_dma(void)159 static void bcmgenet_enable_dma(void)
160 {
161 rt_uint32_t reg = 0;
162 rt_uint32_t dma_ctrl = 0;
163
164 dma_ctrl = (1 << (DEFAULT_Q + DMA_RING_BUF_EN_SHIFT)) | DMA_EN;
165 write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, dma_ctrl);
166
167 reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL);
168 write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, dma_ctrl | reg);
169 }
170
bcmgenet_mdio_write(rt_uint32_t addr,rt_uint32_t reg,rt_uint32_t value)171 static int bcmgenet_mdio_write(rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t value)
172 {
173 int count = 10000;
174 rt_uint32_t val;
175 val = MDIO_WR | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & value);
176 write32(mac_reg_base_addr + MDIO_CMD, val);
177
178 rt_uint32_t reg_val = read32(mac_reg_base_addr + MDIO_CMD);
179 reg_val = reg_val | MDIO_START_BUSY;
180 write32(mac_reg_base_addr + MDIO_CMD, reg_val);
181
182 while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count))
183 DELAY_MICROS(1);
184
185 reg_val = read32(mac_reg_base_addr + MDIO_CMD);
186
187 return reg_val & 0xffff;
188 }
189
bcmgenet_mdio_read(rt_uint32_t addr,rt_uint32_t reg)190 static int bcmgenet_mdio_read(rt_uint32_t addr, rt_uint32_t reg)
191 {
192 int count = 10000;
193 rt_uint32_t val = 0;
194 rt_uint32_t reg_val = 0;
195
196 val = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT);
197 write32(mac_reg_base_addr + MDIO_CMD, val);
198
199 reg_val = read32(mac_reg_base_addr + MDIO_CMD);
200 reg_val = reg_val | MDIO_START_BUSY;
201 write32(mac_reg_base_addr + MDIO_CMD, reg_val);
202
203 while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count))
204 DELAY_MICROS(1);
205
206 reg_val = read32(mac_reg_base_addr + MDIO_CMD);
207
208 return reg_val & 0xffff;
209 }
210
bcmgenet_gmac_write_hwaddr(void)211 static int bcmgenet_gmac_write_hwaddr(void)
212 {
213 rt_uint8_t addr[6];
214 rt_uint32_t reg;
215 bcm271x_mbox_hardware_get_mac_address(&addr[0]);
216
217 reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
218 write32(mac_reg_base_addr + UMAC_MAC0, reg);
219
220 reg = addr[4] << 8 | addr[5];
221 write32(mac_reg_base_addr + UMAC_MAC1, reg);
222 return 0;
223 }
224
get_ethernet_uid(void)225 static int get_ethernet_uid(void)
226 {
227 rt_uint32_t uid_high = 0;
228 rt_uint32_t uid_low = 0;
229 rt_uint32_t uid = 0;
230
231 uid_high = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_HIGH);
232 uid_low = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_LOW);
233 uid = (uid_high << 16 | uid_low);
234
235 if (BCM54213PE_VERSION_B1 == uid)
236 {
237 LOG_I("version is B1\n");
238 }
239 return uid;
240 }
241
bcmgenet_mdio_init(void)242 static void bcmgenet_mdio_init(void)
243 {
244 rt_uint32_t ret = 0;
245 /*get ethernet uid*/
246 ret = get_ethernet_uid();
247 if (ret == 0) return;
248
249 /* reset phy */
250 bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
251 /* read control reg */
252 bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
253 /* reset phy again */
254 bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
255 /* read control reg */
256 bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
257 /* read status reg */
258 bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
259 /* read status reg */
260 bcmgenet_mdio_read(1, BCM54213PE_IEEE_EXTENDED_STATUS);
261 bcmgenet_mdio_read(1, BCM54213PE_AUTO_NEGOTIATION_ADV);
262
263 bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
264 bcmgenet_mdio_read(1, BCM54213PE_CONTROL);
265 /* half full duplex capability */
266 bcmgenet_mdio_write(1, BCM54213PE_CONTROL, (CONTROL_HALF_DUPLEX_CAPABILITY | CONTROL_FULL_DUPLEX_CAPABILITY));
267 bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
268
269 /* set mii control */
270 bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, (MII_CONTROL_AUTO_NEGOTIATION_ENABLED | MII_CONTROL_AUTO_NEGOTIATION_RESTART | MII_CONTROL_PHY_FULL_DUPLEX | MII_CONTROL_SPEED_SELECTION));
271 }
272
rx_ring_init(void)273 static void rx_ring_init(void)
274 {
275 write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
276 write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
277 write32(mac_reg_base_addr + RDMA_READ_PTR, 0x0);
278 write32(mac_reg_base_addr + RDMA_WRITE_PTR, 0x0);
279 write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_END_ADDR, RX_DESCS * DMA_DESC_SIZE / 4 - 1);
280
281 write32(mac_reg_base_addr + RDMA_PROD_INDEX, 0x0);
282 write32(mac_reg_base_addr + RDMA_CONS_INDEX, 0x0);
283 write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
284 write32(mac_reg_base_addr + RDMA_XON_XOFF_THRESH, DMA_FC_THRESH_VALUE);
285 write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
286 }
287
tx_ring_init(void)288 static void tx_ring_init(void)
289 {
290 write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
291 write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
292 write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
293 write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
294 write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
295 write32(mac_reg_base_addr + TDMA_WRITE_PTR, 0x0);
296 write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_END_ADDR, TX_DESCS * DMA_DESC_SIZE / 4 - 1);
297 write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0x0);
298 write32(mac_reg_base_addr + TDMA_CONS_INDEX, 0x0);
299 write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH, 0x1);
300 write32(mac_reg_base_addr + TDMA_FLOW_PERIOD, 0x0);
301 write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
302 write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
303 }
304
rx_descs_init(void)305 static void rx_descs_init(void)
306 {
307 char *rxbuffs = (char *)RECV_DATA_NO_CACHE;
308 rt_uint32_t len_stat, i;
309 void *desc_base = (void *)RX_DESC_BASE;
310
311 len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
312 for (i = 0; i < RX_DESCS; i++)
313 {
314 write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_LO), lower_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
315 write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_HI), upper_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
316 write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_LENGTH_STATUS), len_stat);
317 }
318 }
319
bcmgenet_adjust_link(void)320 static int bcmgenet_adjust_link(void)
321 {
322 rt_uint32_t speed;
323 rt_uint32_t phy_dev_speed = link_speed;
324
325 switch (phy_dev_speed)
326 {
327 case SPEED_1000:
328 speed = UMAC_SPEED_1000;
329 break;
330 case SPEED_100:
331 speed = UMAC_SPEED_100;
332 break;
333 case SPEED_10:
334 speed = UMAC_SPEED_10;
335 break;
336 default:
337 rt_kprintf("bcmgenet: Unsupported PHY speed: %d\n", phy_dev_speed);
338 return -1;
339 }
340
341 rt_uint32_t reg1 = read32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL);
342 //reg1 &= ~(1UL << OOB_DISABLE);
343
344 //rt_kprintf("OOB_DISABLE is %d\n", OOB_DISABLE);
345 reg1 |= (RGMII_LINK | RGMII_MODE_EN | ID_MODE_DIS);
346 write32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL, reg1);
347 DELAY_MICROS(1000);
348 write32(mac_reg_base_addr + UMAC_CMD, speed << CMD_SPEED_SHIFT);
349 return 0;
350 }
351
link_irq(void * param)352 void link_irq(void *param)
353 {
354 if ((bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS) & MII_STATUS_LINK_UP) != 0)
355 {
356 rt_sem_release(&link_ack);
357 }
358 }
359
bcmgenet_gmac_eth_start(void)360 static int bcmgenet_gmac_eth_start(void)
361 {
362 rt_uint32_t ret;
363 rt_uint32_t count = 10000;
364
365 bcmgenet_umac_reset();
366
367 bcmgenet_gmac_write_hwaddr();
368 /* Disable RX/TX DMA and flush TX queues */
369 bcmgenet_disable_dma();
370 rx_ring_init();
371 rx_descs_init();
372 tx_ring_init();
373
374 /* Enable RX/TX DMA */
375 bcmgenet_enable_dma();
376
377 /* Update MAC registers based on PHY property */
378 ret = bcmgenet_adjust_link();
379 if(ret)
380 {
381 rt_kprintf("bcmgenet: adjust PHY link failed: %d\n", ret);
382 return ret;
383 }
384
385 /* wait tx index clear */
386 while ((read32(mac_reg_base_addr + TDMA_CONS_INDEX) != 0) && (--count))
387 DELAY_MICROS(1);
388
389 tx_index = read32(mac_reg_base_addr + TDMA_CONS_INDEX);
390 write32(mac_reg_base_addr + TDMA_PROD_INDEX, tx_index);
391
392 index_flag = read32(mac_reg_base_addr + RDMA_PROD_INDEX);
393
394 rx_index = index_flag % 256;
395
396 write32(mac_reg_base_addr + RDMA_CONS_INDEX, index_flag);
397 write32(mac_reg_base_addr + RDMA_PROD_INDEX, index_flag);
398
399 /* Enable Rx/Tx */
400 rt_uint32_t rx_tx_en;
401 rx_tx_en = read32(mac_reg_base_addr + UMAC_CMD);
402 rx_tx_en |= (CMD_TX_EN | CMD_RX_EN);
403
404 write32(mac_reg_base_addr + UMAC_CMD, rx_tx_en);
405
406 // eanble IRQ for TxDMA done and RxDMA done
407 write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR_MASK, GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
408 return 0;
409 }
410
411 static rt_uint32_t prev_recv_cnt = 0;
412 static rt_uint32_t cur_recv_cnt = 0;
bcmgenet_gmac_eth_recv(rt_uint8_t ** packetp)413 static rt_uint32_t bcmgenet_gmac_eth_recv(rt_uint8_t **packetp)
414 {
415 void* desc_base;
416 rt_uint32_t length = 0;
417 size_t addr = 0;
418 rt_uint32_t prod_index = read32(mac_reg_base_addr + RDMA_PROD_INDEX);
419 //get next
420 if(prod_index == index_flag)
421 {
422 cur_recv_cnt = index_flag;
423 index_flag = 0x7fffffff;
424 //no buff
425 return 0;
426 }
427 else
428 {
429 if(prev_recv_cnt == (prod_index & 0xffffUL))
430 {
431 return 0;
432 }
433
434 desc_base = RX_DESC_BASE + rx_index * DMA_DESC_SIZE;
435 length = read32(desc_base + DMA_DESC_LENGTH_STATUS);
436 length = (length >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK;
437 addr = read32(desc_base + DMA_DESC_ADDRESS_LO);
438 /* To cater for the IP headepr alignment the hardware does.
439 * This would actually not be needed if we don't program
440 * RBUF_ALIGN_2B
441 */
442 *packetp = (rt_uint8_t *)(addr + RX_BUF_OFFSET);
443
444 rx_index = rx_index + 1;
445 if(rx_index >= 256)
446 {
447 rx_index = 0;
448 }
449 write32(mac_reg_base_addr + RDMA_CONS_INDEX, cur_recv_cnt);
450
451 cur_recv_cnt = cur_recv_cnt + 1;
452
453 if(cur_recv_cnt > 0xffff)
454 {
455 cur_recv_cnt = 0;
456 }
457 prev_recv_cnt = cur_recv_cnt;
458
459 return length;
460 }
461 }
462
bcmgenet_gmac_eth_send(void * packet,int length)463 static int bcmgenet_gmac_eth_send(void *packet, int length)
464 {
465 rt_ubase_t level;
466 void *desc_base = (TX_DESC_BASE + tx_index * DMA_DESC_SIZE);
467 rt_uint32_t len_stat = length << DMA_BUFLENGTH_SHIFT;
468
469 rt_uint32_t prod_index, cons;
470 rt_uint32_t tries = 100;
471
472 prod_index = read32(mac_reg_base_addr + TDMA_PROD_INDEX);
473
474 len_stat |= 0x3F << DMA_TX_QTAG_SHIFT;
475 len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP;
476
477 write32((desc_base + DMA_DESC_ADDRESS_LO), SEND_DATA_NO_CACHE);
478 write32((desc_base + DMA_DESC_ADDRESS_HI), 0);
479 write32((desc_base + DMA_DESC_LENGTH_STATUS), len_stat);
480
481 tx_index = tx_index == 255? 0 : tx_index + 1;
482 prod_index = prod_index + 1;
483
484 if (prod_index == 0xe000)
485 {
486 write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0);
487 prod_index = 0;
488 }
489
490 /* Start Transmisson */
491 write32(mac_reg_base_addr + TDMA_PROD_INDEX, prod_index);
492
493 level = rt_hw_interrupt_disable();
494 do
495 {
496 cons = read32(mac_reg_base_addr + TDMA_CONS_INDEX);
497 } while ((cons & 0xffff) < prod_index && --tries);
498 rt_hw_interrupt_enable(level);
499
500 if (!tries)
501 {
502 rt_kprintf("send err! tries is %d\n", tries);
503 return -1;
504 }
505
506 return 0;
507 }
508
link_task_entry(void * param)509 static void link_task_entry(void *param)
510 {
511 struct eth_device *eth_device = (struct eth_device *)param;
512 RT_ASSERT(eth_device != RT_NULL);
513 struct rt_eth_dev *dev = ð_dev;
514
515 //start mdio
516 bcmgenet_mdio_init();
517
518 //start timer link
519 rt_timer_init(&dev->link_timer, "link_timer",
520 link_irq,
521 NULL,
522 100,
523 RT_TIMER_FLAG_PERIODIC);
524 rt_timer_start(&dev->link_timer);
525
526 //link wait forever
527 rt_sem_take(&link_ack, RT_WAITING_FOREVER);
528 eth_device_linkchange(ð_dev.parent, RT_TRUE); //link up
529 rt_timer_stop(&dev->link_timer);
530
531 //set mac
532 // bcmgenet_gmac_write_hwaddr();
533 bcmgenet_gmac_write_hwaddr();
534
535 //check link speed
536 if ((bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 10)) || (bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 11)))
537 {
538 link_speed = 1000;
539 LOG_I("Support link mode Speed 1000M\n");
540 }
541 else if ((bcmgenet_mdio_read(1, 0x05) & (1 << 7)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 8)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 9)))
542 {
543 link_speed = 100;
544 LOG_I("Support link mode Speed 100M\n");
545 }
546 else
547 {
548 link_speed = 10;
549 LOG_I("Support link mode Speed 10M\n");
550 }
551
552 bcmgenet_gmac_eth_start();
553
554 rt_hw_interrupt_install(ETH_IRQ, eth_rx_irq, NULL, "eth_irq");
555 rt_hw_interrupt_umask(ETH_IRQ);
556
557 link_flag = 1;
558 }
559
bcmgenet_eth_init(rt_device_t device)560 static rt_err_t bcmgenet_eth_init(rt_device_t device)
561 {
562 rt_uint32_t ret = 0;
563 rt_uint32_t hw_reg = 0;
564
565 /* Read GENET HW version */
566 rt_uint8_t major = 0;
567 hw_reg = read32(mac_reg_base_addr + SYS_REV_CTRL);
568 major = (hw_reg >> 24) & 0x0f;
569 if (major != 6)
570 {
571 if (major == 5)
572 major = 4;
573 else if (major == 0)
574 major = 1;
575
576 LOG_W("Unsupported GENETv%d.%d\n", major, (hw_reg >> 16) & 0x0f);
577 return -RT_ERROR;
578 }
579 /* set interface */
580 ret = bcmgenet_interface_set();
581 if (ret)
582 {
583 return ret;
584 }
585
586 /* rbuf clear */
587 write32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL, 0);
588
589 /* disable MAC while updating its registers */
590 write32(mac_reg_base_addr + UMAC_CMD, 0);
591 /* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
592 write32(mac_reg_base_addr + UMAC_CMD, CMD_SW_RESET | CMD_LCL_LOOP_EN);
593
594 link_thread_tid = rt_thread_create("link", link_task_entry, (void *)device,
595 LINK_THREAD_STACK_SIZE,
596 LINK_THREAD_PRIORITY, LINK_THREAD_TIMESLICE);
597 if (link_thread_tid != RT_NULL)
598 rt_thread_startup(link_thread_tid);
599
600 return RT_EOK;
601 }
602
bcmgenet_eth_control(rt_device_t dev,int cmd,void * args)603 static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args)
604 {
605 switch (cmd)
606 {
607 case NIOCTL_GADDR:
608 if (args)
609 rt_memcpy(args, eth_dev.dev_addr, 6);
610 else
611 return -RT_ERROR;
612 break;
613 default:
614 break;
615 }
616 return RT_EOK;
617 }
618
rt_eth_tx(rt_device_t device,struct pbuf * p)619 rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p)
620 {
621 int copy_len = 0;
622
623 /* lock eth device */
624 if (link_flag != 1)
625 {
626 LOG_I("link disconnected\n");
627 return -RT_ERROR;
628 }
629
630 copy_len = pbuf_copy_partial(p, eth_send_no_cache, p->tot_len, 0);
631 if (copy_len == 0)
632 {
633
634 LOG_I("copy len is zero\n");
635 return -RT_ERROR;
636 }
637 bcmgenet_gmac_eth_send((void *)eth_send_no_cache, p->tot_len);
638
639 return RT_EOK;
640 }
641
rt_eth_rx(rt_device_t device)642 struct pbuf *rt_eth_rx(rt_device_t device)
643 {
644 int recv_len = 0;
645 size_t addr_point;
646 struct pbuf *pbuf = RT_NULL;
647 if (link_flag != 1)
648 {
649 return RT_NULL;
650 }
651
652 recv_len = bcmgenet_gmac_eth_recv((rt_uint8_t **)&addr_point);
653 if (recv_len > 0)
654 {
655 pbuf = pbuf_alloc(PBUF_LINK, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL);
656 if (pbuf != RT_NULL)
657 {
658 //calc offset
659 addr_point= (size_t)(addr_point+ (eth_recv_no_cache - RECV_DATA_NO_CACHE));
660 rt_memcpy(pbuf->payload, (char *)addr_point, recv_len);
661 }
662 }
663
664 return pbuf;
665 }
666
667 #ifdef RT_USING_DEVICE_OPS
668 static struct rt_device_ops eth_devops = {
669 .init = bcmgenet_eth_init,
670 .control = bcmgenet_eth_control,
671 };
672 #endif /* RT_USING_DEVICE_OPS */
673
rt_hw_eth_init(void)674 int rt_hw_eth_init(void)
675 {
676 rt_uint8_t mac_addr[6] = {0xdc, 0xa6, 0x32, 0x28, 0x22, 0x50};
677
678 rt_sem_init(&link_ack, "link_ack", 0, RT_IPC_FLAG_FIFO);
679
680 memset(ð_dev, 0, sizeof(eth_dev));
681 memset((void *)eth_send_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE));
682 memset((void *)eth_recv_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE));
683 bcm271x_mbox_hardware_get_mac_address(&mac_addr[0]);
684
685 eth_dev.iobase = mac_reg_base_addr;
686 eth_dev.name = "e0";
687 eth_dev.dev_addr[0] = mac_addr[0];
688 eth_dev.dev_addr[1] = mac_addr[1];
689 eth_dev.dev_addr[2] = mac_addr[2];
690 eth_dev.dev_addr[3] = mac_addr[3];
691 eth_dev.dev_addr[4] = mac_addr[4];
692 eth_dev.dev_addr[5] = mac_addr[5];
693
694 eth_dev.parent.parent.type = RT_Device_Class_NetIf;
695 #ifdef RT_USING_DEVICE_OPS
696 eth_dev.parent.parent.ops = ð_devops;
697 #else /* !RT_USING_DEVICE_OPS */
698 eth_dev.parent.parent.init = bcmgenet_eth_init;
699 eth_dev.parent.parent.open = RT_NULL;
700 eth_dev.parent.parent.close = RT_NULL;
701 eth_dev.parent.parent.read = RT_NULL;
702 eth_dev.parent.parent.write = RT_NULL;
703 eth_dev.parent.parent.control = bcmgenet_eth_control;
704 #endif /* RT_USING_DEVICE_OPS */
705 eth_dev.parent.parent.user_data = RT_NULL;
706
707 eth_dev.parent.eth_tx = rt_eth_tx;
708 eth_dev.parent.eth_rx = rt_eth_rx;
709
710 eth_device_init(&(eth_dev.parent), "e0");
711 eth_device_linkchange(ð_dev.parent, RT_FALSE); //link down
712 return 0;
713 }
714 INIT_COMPONENT_EXPORT(rt_hw_eth_init);
715