1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2013-05-19 Bernard porting from LPC17xx drivers.
9 */
10
11 #include <rtthread.h>
12 #include "lwipopts.h"
13 #include <netif/ethernetif.h>
14 #include <board.h>
15
16 #include "lpc_pinsel.h"
17 #include "drv_emac.h"
18
19 #define EMAC_PHY_AUTO 0
20 #define EMAC_PHY_10MBIT 1
21 #define EMAC_PHY_100MBIT 2
22
23 #define MAX_ADDR_LEN 6
24
25 /* EMAC_RAM_BASE is defined in board.h and the size is 16KB */
26 #define RX_DESC_BASE ETH_RAM_BASE
27 #define RX_STAT_BASE (RX_DESC_BASE + NUM_RX_FRAG*8)
28 #define TX_DESC_BASE (RX_STAT_BASE + NUM_RX_FRAG*8)
29 #define TX_STAT_BASE (TX_DESC_BASE + NUM_TX_FRAG*8)
30 #define RX_BUF_BASE (TX_STAT_BASE + NUM_TX_FRAG*4)
31 #define TX_BUF_BASE (RX_BUF_BASE + NUM_RX_FRAG*ETH_FRAG_SIZE)
32
33 /* RX and TX descriptor and status definitions. */
34 #define RX_DESC_PACKET(i) (*(unsigned int *)(RX_DESC_BASE + 8*i))
35 #define RX_DESC_CTRL(i) (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
36 #define RX_STAT_INFO(i) (*(unsigned int *)(RX_STAT_BASE + 8*i))
37 #define RX_STAT_HASHCRC(i) (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
38 #define TX_DESC_PACKET(i) (*(unsigned int *)(TX_DESC_BASE + 8*i))
39 #define TX_DESC_CTRL(i) (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
40 #define TX_STAT_INFO(i) (*(unsigned int *)(TX_STAT_BASE + 4*i))
41 #define RX_BUF(i) (RX_BUF_BASE + ETH_FRAG_SIZE*i)
42 #define TX_BUF(i) (TX_BUF_BASE + ETH_FRAG_SIZE*i)
43
44 struct lpc_emac
45 {
46 /* inherit from ethernet device */
47 struct eth_device parent;
48
49 rt_uint8_t phy_mode;
50
51 /* interface address info. */
52 rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
53 };
54 static struct lpc_emac lpc_emac_device;
55 static struct rt_semaphore sem_lock;
56 static struct rt_event tx_event;
57
58 /* Local Function Prototypes */
59 static void write_PHY(rt_uint32_t PhyReg, rt_uint32_t Value);
60 static rt_uint16_t read_PHY(rt_uint8_t PhyReg) ;
61
ENET_IRQHandler(void)62 void ENET_IRQHandler(void)
63 {
64 rt_uint32_t status;
65
66 /* enter interrupt */
67 rt_interrupt_enter();
68
69 status = LPC_EMAC->IntStatus;
70
71 if (status & INT_RX_DONE)
72 {
73 /* Disable EMAC RxDone interrupts. */
74 LPC_EMAC->IntEnable = INT_TX_DONE;
75
76 /* a frame has been received */
77 eth_device_ready(&(lpc_emac_device.parent));
78 }
79 else if (status & INT_TX_DONE)
80 {
81 /* set event */
82 rt_event_send(&tx_event, 0x01);
83 }
84
85 if (status & INT_RX_OVERRUN)
86 {
87 rt_kprintf("rx overrun\n");
88 }
89
90 if (status & INT_TX_UNDERRUN)
91 {
92 rt_kprintf("tx underrun\n");
93 }
94
95 /* Clear the interrupt. */
96 LPC_EMAC->IntClear = status;
97
98 /* leave interrupt */
99 rt_interrupt_leave();
100 }
101
102 /* phy write */
write_PHY(rt_uint32_t PhyReg,rt_uint32_t Value)103 static void write_PHY(rt_uint32_t PhyReg, rt_uint32_t Value)
104 {
105 unsigned int tout;
106
107 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
108 LPC_EMAC->MWTD = Value;
109
110 /* Wait utill operation completed */
111 tout = 0;
112 for (tout = 0; tout < MII_WR_TOUT; tout++)
113 {
114 if ((LPC_EMAC->MIND & MIND_BUSY) == 0)
115 {
116 break;
117 }
118 }
119 }
120
121 /* phy read */
read_PHY(rt_uint8_t PhyReg)122 static rt_uint16_t read_PHY(rt_uint8_t PhyReg)
123 {
124 rt_uint32_t tout;
125
126 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
127 LPC_EMAC->MCMD = MCMD_READ;
128
129 /* Wait until operation completed */
130 tout = 0;
131 for (tout = 0; tout < MII_RD_TOUT; tout++)
132 {
133 if ((LPC_EMAC->MIND & MIND_BUSY) == 0)
134 {
135 break;
136 }
137 }
138 LPC_EMAC->MCMD = 0;
139 return (LPC_EMAC->MRDD);
140 }
141
142 /* init rx descriptor */
rx_descr_init(void)143 rt_inline void rx_descr_init(void)
144 {
145 rt_uint32_t i;
146
147 for (i = 0; i < NUM_RX_FRAG; i++)
148 {
149 RX_DESC_PACKET(i) = RX_BUF(i);
150 RX_DESC_CTRL(i) = RCTRL_INT | (ETH_FRAG_SIZE - 1);
151 RX_STAT_INFO(i) = 0;
152 RX_STAT_HASHCRC(i) = 0;
153 }
154
155 /* Set EMAC Receive Descriptor Registers. */
156 LPC_EMAC->RxDescriptor = RX_DESC_BASE;
157 LPC_EMAC->RxStatus = RX_STAT_BASE;
158 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;
159
160 /* Rx Descriptors Point to 0 */
161 LPC_EMAC->RxConsumeIndex = 0;
162 }
163
164 /* init tx descriptor */
tx_descr_init(void)165 rt_inline void tx_descr_init(void)
166 {
167 rt_uint32_t i;
168
169 for (i = 0; i < NUM_TX_FRAG; i++)
170 {
171 TX_DESC_PACKET(i) = TX_BUF(i);
172 TX_DESC_CTRL(i) = (1ul << 31) | (1ul << 30) | (1ul << 29) | (1ul << 28) | (1ul << 26) | (ETH_FRAG_SIZE - 1);
173 TX_STAT_INFO(i) = 0;
174 }
175
176 /* Set EMAC Transmit Descriptor Registers. */
177 LPC_EMAC->TxDescriptor = TX_DESC_BASE;
178 LPC_EMAC->TxStatus = TX_STAT_BASE;
179 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;
180
181 /* Tx Descriptors Point to 0 */
182 LPC_EMAC->TxProduceIndex = 0;
183 }
184
185 /*
186 TX_EN P1_4
187 TXD0 P1_0
188 TXD1 P1_1
189
190 RXD0 P1_9
191 RXD1 P1_10
192 RX_ER P1_14
193 CRS_DV P1_8
194
195 MDC P1_16
196 MDIO P1_17
197
198 REF_CLK P1_15
199 */
lpc_emac_init(rt_device_t dev)200 static rt_err_t lpc_emac_init(rt_device_t dev)
201 {
202 /* Initialize the EMAC ethernet controller. */
203 rt_uint32_t regv, tout;
204
205 /* Power Up the EMAC controller. */
206 LPC_SC->PCONP |= (1UL << 30);
207
208 /* Enable P1 Ethernet Pins. */
209 PINSEL_ConfigPin(1, 0, 1); /**< P1_0 ENET_TXD0 */
210 PINSEL_ConfigPin(1, 1, 1); /**< P1_1 ENET_TXD1 */
211 PINSEL_ConfigPin(1, 4, 1); /**< P1_4 ENET_TX_EN */
212 PINSEL_ConfigPin(1, 8, 1); /**< P1_8 ENET_CRS_DV */
213 PINSEL_ConfigPin(1, 9, 1); /**< P1_9 ENET_RXD0 */
214 PINSEL_ConfigPin(1, 10, 1); /**< P1_10 ENET_RXD1 */
215 PINSEL_ConfigPin(1, 14, 1); /**< P1_14 ENET_RX_ER */
216 PINSEL_ConfigPin(1, 15, 1); /**< P1_15 ENET_REF_CLK */
217 PINSEL_ConfigPin(1, 16, 1); /**< P1_16 ENET_MDC */
218 PINSEL_ConfigPin(1, 17, 1); /**< P1_17 ENET_MDIO */
219
220 /* Reset all EMAC internal modules. */
221 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
222 MAC1_SIM_RES | MAC1_SOFT_RES;
223 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES;
224
225 /* A short delay after reset. */
226 for (tout = 100; tout; tout--);
227
228 /* Initialize MAC control registers. */
229 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
230 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
231 LPC_EMAC->MAXF = ETH_MAX_FLEN;
232 LPC_EMAC->CLRT = CLRT_DEF;
233 LPC_EMAC->IPGR = IPGR_DEF;
234
235 /* PCLK=18MHz, clock select=6, MDC=18/6=3MHz */
236 /* Enable Reduced MII interface. */
237 LPC_EMAC->MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
238 for (tout = 100; tout; tout--);
239 LPC_EMAC->MCFG = MCFG_CLK_DIV20;
240
241 /* Enable Reduced MII interface. */
242 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
243
244 /* Reset Reduced MII Logic. */
245 LPC_EMAC->SUPP = SUPP_RES_RMII | SUPP_SPEED;
246 for (tout = 100; tout; tout--);
247 LPC_EMAC->SUPP = SUPP_SPEED;
248
249 /* Put the PHY in reset mode */
250 write_PHY(PHY_REG_BMCR, 0x8000);
251 for (tout = 1000; tout; tout--);
252
253 /* Configure the PHY device */
254 /* Configure the PHY device */
255 switch (lpc_emac_device.phy_mode)
256 {
257 case EMAC_PHY_AUTO:
258 /* Use autonegotiation about the link speed. */
259 write_PHY(PHY_REG_BMCR, PHY_AUTO_NEG);
260 break;
261 case EMAC_PHY_10MBIT:
262 /* Connect at 10MBit */
263 write_PHY(PHY_REG_BMCR, PHY_FULLD_10M);
264 break;
265 case EMAC_PHY_100MBIT:
266 /* Connect at 100MBit */
267 write_PHY(PHY_REG_BMCR, PHY_FULLD_100M);
268 break;
269 }
270 if (tout >= 0x100000) return -RT_ERROR; // auto_neg failed
271
272 regv = 0x0004;
273 /* Configure Full/Half Duplex mode. */
274 if (regv & 0x0004)
275 {
276 /* Full duplex is enabled. */
277 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
278 LPC_EMAC->Command |= CR_FULL_DUP;
279 LPC_EMAC->IPGT = IPGT_FULL_DUP;
280 }
281 else
282 {
283 /* Half duplex mode. */
284 LPC_EMAC->IPGT = IPGT_HALF_DUP;
285 }
286
287 /* Configure 100MBit/10MBit mode. */
288 if (regv & 0x0002)
289 {
290 /* 10MBit mode. */
291 LPC_EMAC->SUPP = 0;
292 }
293 else
294 {
295 /* 100MBit mode. */
296 LPC_EMAC->SUPP = SUPP_SPEED;
297 }
298
299 /* Set the Ethernet MAC Address registers */
300 LPC_EMAC->SA0 = (lpc_emac_device.dev_addr[1] << 8) | lpc_emac_device.dev_addr[0];
301 LPC_EMAC->SA1 = (lpc_emac_device.dev_addr[3] << 8) | lpc_emac_device.dev_addr[2];
302 LPC_EMAC->SA2 = (lpc_emac_device.dev_addr[5] << 8) | lpc_emac_device.dev_addr[4];
303
304 /* Initialize Tx and Rx DMA Descriptors */
305 rx_descr_init();
306 tx_descr_init();
307
308 /* Receive Broadcast and Perfect Match Packets */
309 LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN;
310
311 /* Reset all interrupts */
312 LPC_EMAC->IntClear = 0xFFFF;
313
314 /* Enable EMAC interrupts. */
315 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
316
317 /* Enable receive and transmit mode of MAC Ethernet core */
318 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN);
319 LPC_EMAC->MAC1 |= MAC1_REC_EN;
320
321 /* Enable the ENET Interrupt */
322 NVIC_EnableIRQ(ENET_IRQn);
323
324 return RT_EOK;
325 }
326
lpc_emac_open(rt_device_t dev,rt_uint16_t oflag)327 static rt_err_t lpc_emac_open(rt_device_t dev, rt_uint16_t oflag)
328 {
329 return RT_EOK;
330 }
331
lpc_emac_close(rt_device_t dev)332 static rt_err_t lpc_emac_close(rt_device_t dev)
333 {
334 return RT_EOK;
335 }
336
lpc_emac_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)337 static rt_ssize_t lpc_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
338 {
339 rt_set_errno(-RT_ENOSYS);
340 return 0;
341 }
342
lpc_emac_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)343 static rt_ssize_t lpc_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
344 {
345 rt_set_errno(-RT_ENOSYS);
346 return 0;
347 }
348
lpc_emac_control(rt_device_t dev,int cmd,void * args)349 static rt_err_t lpc_emac_control(rt_device_t dev, int cmd, void *args)
350 {
351 switch (cmd)
352 {
353 case NIOCTL_GADDR:
354 /* get mac address */
355 if (args) rt_memcpy(args, lpc_emac_device.dev_addr, 6);
356 else return -RT_ERROR;
357 break;
358
359 default :
360 break;
361 }
362
363 return RT_EOK;
364 }
365
366 /* EtherNet Device Interface */
367 /* transmit packet. */
lpc_emac_tx(rt_device_t dev,struct pbuf * p)368 rt_err_t lpc_emac_tx(rt_device_t dev, struct pbuf *p)
369 {
370 rt_uint32_t Index, IndexNext;
371 rt_uint8_t *ptr;
372
373 /* calculate next index */
374 IndexNext = LPC_EMAC->TxProduceIndex + 1;
375 if (IndexNext > LPC_EMAC->TxDescriptorNumber) IndexNext = 0;
376
377 /* check whether block is full */
378 while (IndexNext == LPC_EMAC->TxConsumeIndex)
379 {
380 rt_err_t result;
381 rt_uint32_t recved;
382
383 /* there is no block yet, wait a flag */
384 result = rt_event_recv(&tx_event, 0x01,
385 RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved);
386
387 RT_ASSERT(result == RT_EOK);
388 }
389
390 /* lock EMAC device */
391 rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
392
393 /* get produce index */
394 Index = LPC_EMAC->TxProduceIndex;
395
396 /* calculate next index */
397 IndexNext = LPC_EMAC->TxProduceIndex + 1;
398 if (IndexNext > LPC_EMAC->TxDescriptorNumber)
399 IndexNext = 0;
400
401 /* copy data to tx buffer */
402 ptr = (rt_uint8_t *)TX_BUF(Index);
403 pbuf_copy_partial(p, ptr, p->tot_len, 0);
404
405 TX_DESC_CTRL(Index) &= ~0x7ff;
406 TX_DESC_CTRL(Index) |= (p->tot_len - 1) & 0x7ff;
407
408 /* change index to the next */
409 LPC_EMAC->TxProduceIndex = IndexNext;
410
411 /* unlock EMAC device */
412 rt_sem_release(&sem_lock);
413
414 return RT_EOK;
415 }
416
417 /* reception packet. */
lpc_emac_rx(rt_device_t dev)418 struct pbuf *lpc_emac_rx(rt_device_t dev)
419 {
420 struct pbuf *p;
421 rt_uint32_t size;
422 rt_uint32_t Index;
423
424 /* init p pointer */
425 p = RT_NULL;
426
427 /* lock EMAC device */
428 rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
429
430 Index = LPC_EMAC->RxConsumeIndex;
431 if (Index != LPC_EMAC->RxProduceIndex)
432 {
433 size = (RX_STAT_INFO(Index) & 0x7ff) + 1;
434 if (size > ETH_FRAG_SIZE) size = ETH_FRAG_SIZE;
435
436 /* allocate buffer */
437 p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM);
438 if (p != RT_NULL)
439 {
440 pbuf_take(p, (rt_uint8_t *)RX_BUF(Index), size);
441 }
442
443 /* move Index to the next */
444 if (++Index > LPC_EMAC->RxDescriptorNumber)
445 Index = 0;
446
447 /* set consume index */
448 LPC_EMAC->RxConsumeIndex = Index;
449 }
450 else
451 {
452 /* Enable RxDone interrupt */
453 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
454 }
455
456 /* unlock EMAC device */
457 rt_sem_release(&sem_lock);
458
459 return p;
460 }
461
rt_hw_emac_init(void)462 int rt_hw_emac_init(void)
463 {
464 rt_event_init(&tx_event, "tx_event", RT_IPC_FLAG_FIFO);
465 rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
466
467 /* set autonegotiation mode */
468 lpc_emac_device.phy_mode = EMAC_PHY_AUTO;
469
470 // OUI 00-60-37 NXP Semiconductors
471 lpc_emac_device.dev_addr[0] = 0x00;
472 lpc_emac_device.dev_addr[1] = 0x60;
473 lpc_emac_device.dev_addr[2] = 0x37;
474 /* set mac address: (only for test) */
475 lpc_emac_device.dev_addr[3] = 0x12;
476 lpc_emac_device.dev_addr[4] = 0x34;
477 lpc_emac_device.dev_addr[5] = 0x56;
478
479 lpc_emac_device.parent.parent.init = lpc_emac_init;
480 lpc_emac_device.parent.parent.open = lpc_emac_open;
481 lpc_emac_device.parent.parent.close = lpc_emac_close;
482 lpc_emac_device.parent.parent.read = lpc_emac_read;
483 lpc_emac_device.parent.parent.write = lpc_emac_write;
484 lpc_emac_device.parent.parent.control = lpc_emac_control;
485 lpc_emac_device.parent.parent.user_data = RT_NULL;
486
487 lpc_emac_device.parent.eth_rx = lpc_emac_rx;
488 lpc_emac_device.parent.eth_tx = lpc_emac_tx;
489
490 eth_device_init(&(lpc_emac_device.parent), "e0");
491 return 0;
492 }
493 INIT_DEVICE_EXPORT(rt_hw_emac_init);
494
495 #ifdef RT_USING_FINSH
496 #include <finsh.h>
emac_dump()497 void emac_dump()
498 {
499 rt_kprintf("Command : %08x\n", LPC_EMAC->Command);
500 rt_kprintf("Status : %08x\n", LPC_EMAC->Status);
501 rt_kprintf("RxStatus : %08x\n", LPC_EMAC->RxStatus);
502 rt_kprintf("TxStatus : %08x\n", LPC_EMAC->TxStatus);
503 rt_kprintf("IntEnable: %08x\n", LPC_EMAC->IntEnable);
504 rt_kprintf("IntStatus: %08x\n", LPC_EMAC->IntStatus);
505 }
506 FINSH_FUNCTION_EXPORT(emac_dump, dump emac register);
507 #endif
508
509