Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers/imx-enet: Add support for ethernet in imxrt1170-evkb #99

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ac79e47
drivers/imx6-enet: rename files
julianuziemblo Oct 9, 2024
36d1e93
drivers: fix code style
julianuziemblo Oct 9, 2024
4fd88f9
drivers/ephy: add ephy_printf
julianuziemblo Oct 9, 2024
4fb7bbe
drivers/imx-enet: improve selftest debug info
julianuziemblo Oct 9, 2024
957be27
drivers/imx-enet: fix possible integer overflow
julianuziemblo Oct 9, 2024
1827c33
drivers/gpio: put all gpio functionality into gpio.c
julianuziemblo Oct 9, 2024
20e9262
drivers/gpio: rename file
julianuziemblo Oct 9, 2024
97c4d5a
drivers/imx6ull-gpio: fix gpio_wait
julianuziemblo Oct 9, 2024
b2d4149
drivers/gpio: add gpio functionality for imxrt106x
julianuziemblo Oct 9, 2024
0fa87d4
drivers/imx-enet: Add support for ethernet in imxrt1064-evk
julianuziemblo Oct 9, 2024
1028823
drivers/(bdring, imx-enet): fix atomic semantics
julianuziemblo Oct 9, 2024
c6177d5
drivers/pktmem: fix allocPktBuf and freePktBuf
julianuziemblo Oct 9, 2024
a6476b9
drivers/ephy: support different PHY per ENET device
julianuziemblo Dec 5, 2024
957e656
Update README.md
julianuziemblo Dec 5, 2024
6c1f27e
drivers/ephy: add support for RTL8201FI ethernet PHY
julianuziemblo Dec 5, 2024
6d1d27b
drivers/imxrt106x-gpio: rename file
julianuziemblo Dec 5, 2024
4e85c2c
drivers/imx-enet: add support for ENET1 in imxrt1170-evkb
julianuziemblo Dec 5, 2024
657d774
drivers/ephy: add support for RTL8211FDI gigabit ethernet PHY
julianuziemblo Dec 5, 2024
ce2d65b
drivers/imx-enet: add support for ENET_1G in imxrt1170-evkb
julianuziemblo Dec 5, 2024
5bb9cbd
drivers/netif: support 2 MDIO busses on imxrt117x
julianuziemblo Dec 9, 2024
4c12eaf
Update README.md
julianuziemblo Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,17 @@ where *driver* is one of:

For qemu, it's usually: `rtl:0x10:10`

2. iMX.6ULL ENET module (== "Freescale Ethernet Controller"?)
2. iMX ENET module (== "Freescale Ethernet Controller"?)

enet:mmio:irq[:no-mdio][:phyinfo]

. | ENET1 | ENET2
---- | ----- | ----
mmio | 0x02188000 | 0x020b4000
irq | 150 | 152

`no-mdio` disables MDIO support (only one module can drive MDIO bus)

When an external PHY is used, *phyinfo* is formatted as follows:

PHY:[busnr.]id[:reset:[-]n:/dev/gpioX][:irq:[-]n:/dev/gpioX]
PHY:model:[busnr.]id[:reset:[-]n:/dev/gpioX][:irq:[-]n:/dev/gpioX]

model = PHY chip model in lowercase, e.g. `ksz8081rnb`

busnr = bus registered by driver (in driver-arg-order, counted from 0)

Expand All @@ -48,8 +45,18 @@ n = pin number

iMX.6ULL's evaluation board needs:
```
enet:0x02188000:150:PHY:0.2:reset:-1:/dev/gpio6:irq:-5:/dev/gpio5
enet:0x020b4000:152:no-mdio:PHY:0.1:reset:-2:/dev/gpio6:irq:-6:/dev/gpio5
enet:0x02188000:150:PHY:ksz8081rnb:0.2:irq:5:/dev/gpio5 enet:0x020b4000:152:no-mdio:PHY:ksz8081rnb:0.1:irq:6:/dev/gpio5
```

iMX.RT1064's evaluation board needs:
```
enet:0x402D8000:130:PHY:ksz8081rnb:0.2:irq:-10:/dev/gpio1:reset:-9:/dev/gpio1
```

iMX.RT1170's evaluation board B (EVKB) needs:
```
enet:0x40424000:153:PHY:rtl8201fi-vc-cg:0.3:reset:12:/dev/gpio12:irq:-11:/dev/gpio9
enet:0x40420000:157:PHY:rtl8211fdi-cg:1.1:reset:-14:/dev/gpio11:irq:-13:/dev/gpio11
```

## Build
Expand Down
2 changes: 1 addition & 1 deletion _targets/Makefile.armv7a7-imx6ull
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
NET_DRIVERS_SUPPORTED := enet tuntap
NET_DRIVERS ?= $(NET_DRIVERS_SUPPORTED)

DRIVERS_SRCS_enet = imx6-enet.c ephy.c gpio.c imx6ull-gpio.c $(DRIVERS_SRCS_UTIL) hw-debug.c
DRIVERS_SRCS_enet = imx-enet.c ephy.c imx6ull-gpio.c $(DRIVERS_SRCS_UTIL) hw-debug.c
6 changes: 4 additions & 2 deletions _targets/Makefile.armv7m7-imxrt106x
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#
# iMX RT1064 target
#
# Copyright 2021 Phoenix Systems
# Copyright 2021, 2024 Phoenix Systems
#

NET_DRIVERS_SUPPORTED := pppou pppos
NET_DRIVERS_SUPPORTED := pppou pppos enet
NET_DRIVERS ?= $(NET_DRIVERS_SUPPORTED)
PPPOS_MODEM := huawei

DRIVERS_SRCS_enet = imx-enet.c ephy.c imxrt-gpio.c $(DRIVERS_SRCS_UTIL)
4 changes: 3 additions & 1 deletion _targets/Makefile.armv7m7-imxrt117x
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# Copyright 2022 Phoenix Systems
#

NET_DRIVERS_SUPPORTED := pppou pppos
NET_DRIVERS_SUPPORTED := pppou pppos enet
NET_DRIVERS ?= $(NET_DRIVERS_SUPPORTED)
PPPOS_MODEM := huawei

DRIVERS_SRCS_enet = imx-enet.c ephy.c imxrt-gpio.c $(DRIVERS_SRCS_UTIL) hw-debug.c
7 changes: 0 additions & 7 deletions drivers/Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
# Makefile for lwip drivers to be included

ifeq ($(EPHY_KSZ8081),RNA)
LOCAL_CFLAGS := -DEPHY_KSZ8081RNA
endif
ifeq ($(EPHY_KSZ8081),RND)
LOCAL_CFLAGS := -DEPHY_KSZ8081RND
endif

# make possible to specify defalult APN name externally
ifneq ($(PPPOS_DEFAULT_APN),)
LOCAL_CFLAGS := -DPPPOS_DEFAULT_APN=\"$(PPPOS_DEFAULT_APN)\"
Expand Down
109 changes: 65 additions & 44 deletions drivers/bdring.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


#define MAX_TX_FRAGMENTS 8
Expand All @@ -41,7 +42,7 @@
*/


static int is_power_of_2(size_t n)
static bool is_power_of_2(size_t n)
{
return !(n & (n - 1));
}
Expand All @@ -55,9 +56,10 @@ int net_initRings(net_bufdesc_ring_t *rings, const size_t *sizes, size_t nrings,
void *p;

align = ops->ring_alignment;
if (align) {
if (!is_power_of_2(align))
if (align != 0) {
if (!is_power_of_2(align)) {
return -EINVAL;
}
--align;
}

Expand All @@ -68,40 +70,45 @@ int net_initRings(net_bufdesc_ring_t *rings, const size_t *sizes, size_t nrings,
sz += sizes[i] * ops->desc_size;
sz = (sz + align) & ~align;

if (!is_power_of_2(sizes[i]))
if (!is_power_of_2(sizes[i])) {
return -EINVAL;
}
}

bufp = calloc(nb, sizeof(*bufp));
if (!bufp)
bufp = calloc(nb, sizeof(*bufp)); // NOLINT
if (bufp == NULL) {
return -ENOMEM;
}

p = dmammap(sz);
if (!p) {
if (p == NULL) {
free(bufp);
return -ENOMEM;
}

psz = sz;
phys = mphys(p, &psz);
if ((psz != sz) || (phys & align)) {
if (psz != sz)
if ((psz != sz) || ((phys & align) != 0)) {
if (psz != sz) {
printf("ERROR: got non-contiguous ring buffer (%zu/%zu segment)\n", psz, sz);
else
}
else {
printf("ERROR: got unaligned ring buffer (at 0x%zx, align mask: 0x%zx)\n", (size_t)phys, align);
}
munmap(p, sz);
free(bufp);
return -ENODEV;
}

/*printf("descriptor rings: virt 0x%zx phys 0x%zx\n", (size_t)p, (size_t)phys);*/
/* printf("descriptor rings: virt 0x%zx phys 0x%zx\n", (size_t)p, (size_t)phys); */

memset(p, 0, sz);

for (i = 0; i < nrings; ++i) {
rings[i].ring = p;
rings[i].bufp = bufp;
rings[i].head = rings[i].tail = 0;
atomic_init(&rings[i].head, 0);
atomic_init(&rings[i].tail, 0);
rings[i].last = sizes[i] - 1;
rings[i].phys = phys;
rings[i].ops = ops;
Expand All @@ -125,30 +132,35 @@ size_t net_receivePackets(net_bufdesc_ring_t *ring, struct netif *ni, unsigned e

mutexLock(ring->lock);
n = 0;
i = ring->head;
i = atomic_load(&ring->head);
pkt = NULL;

for (;;) {
if (i == ring->tail)
if (i == atomic_load(&ring->tail)) {
break;
}

sz = ring->ops->nextRxBufferSize(ring, i);
if (!sz)
if (sz == 0) {
break;
}

p = ring->bufp[i];
p->tot_len = p->len = sz;

if (!pkt)
if (pkt == NULL) {
pkt = p;
else
}
else {
pbuf_cat(pkt, p);
}

if (ring->ops->pktRxFinished(ring, i)) {
pbuf_header_force(p, ETH_PAD_SIZE - ethpad);
#ifdef LWIP_HOOK_ETH_INPUT
if (LWIP_HOOK_ETH_INPUT(p, ni))
if (LWIP_HOOK_ETH_INPUT(p, ni)) {
pbuf_free(p);
}
else
#endif
{
Expand All @@ -157,11 +169,11 @@ size_t net_receivePackets(net_bufdesc_ring_t *ring, struct netif *ni, unsigned e
pkt = NULL;
}

i = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
i = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
++n;
}

ring->head = i;
atomic_store(&ring->head, i);
mutexUnlock(ring->lock);
return n;
}
Expand All @@ -176,25 +188,26 @@ size_t net_refillRx(net_bufdesc_ring_t *ring, size_t ethpad)

n = 0;
i = ring->tail;
nxt = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
sz = ring->ops->pkt_buf_sz;
nxt = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
sz = net_maxDMAPbufSize;

while (nxt != ring->head) {
while (nxt != atomic_load(&ring->head)) {
p = net_allocDMAPbuf(&pa, sz);
if (!p)
if (p == NULL) {
break;
}

pbuf_header_force(p, ethpad - ETH_PAD_SIZE);

ring->bufp[i] = p;
ring->ops->fillRxDesc(ring, i, pa, sz, 0);

i = nxt;
nxt = (nxt + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
nxt = (nxt + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
++n;
}

ring->tail = i;
atomic_store(&ring->tail, i);
mutexUnlock(ring->lock);
return n;
}
Expand All @@ -206,23 +219,25 @@ size_t net_reapTxFinished(net_bufdesc_ring_t *ring)
mutexLock(ring->lock);

n = 0;
i = ring->tail;
i = atomic_load(&ring->tail);
head = atomic_load(&ring->head);
while (i != head) {
if (!ring->ops->nextTxDone(ring, i))
if (ring->ops->nextTxDone(ring, i) == 0) {
break;
}

if (ring->bufp[i]) {
if (ring->bufp[i] != NULL) {
pbuf_free(ring->bufp[i]);
ring->bufp[i] = NULL;
}

i = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
i = (i + 1) & ring->last; // NOTE: 2^n ring size verified in net_initRings
++n;
}

if (n)
if (n > 0) {
atomic_store(&ring->tail, i);
}

mutexUnlock(ring->lock);
return n;
Expand All @@ -237,11 +252,12 @@ static size_t net_fillFragments(struct pbuf *p, addr_t *pa, size_t *psz, size_t
sz = p->tot_len;
n = fragsz = 0;

while (sz) {
if (++n >= max_n)
while (sz != 0) {
if (++n >= max_n) {
return 0;
}

if (!fragsz) {
if (fragsz == 0) {
fragsz = p->len;
data = p->payload;
}
Expand All @@ -251,10 +267,12 @@ static size_t net_fillFragments(struct pbuf *p, addr_t *pa, size_t *psz, size_t
sz -= *psz;
fragsz -= *psz;

if (!fragsz)
if (fragsz == 0) {
p = p->next;
else
}
else {
data += *psz;
}

++psz, ++pa;
}
Expand All @@ -271,31 +289,34 @@ size_t net_transmitPacket(net_bufdesc_ring_t *ring, struct pbuf *p)
int last;

p = net_makeDMAPbuf(p);
if (!p)
if (p == NULL) {
return 0;
}

mutexLock(ring->lock);
// NOTE: 2^n ring size verified in net_initRings
n = atomic_load(&ring->tail); // access tail once - it may be advanced by tx_done thread
i = ring->head;
n = atomic_load(&ring->tail); // access tail once - it may be advanced by tx_done thread
i = atomic_load(&ring->head);
n = (n - i - 1) & ring->last;
if (n > MAX_TX_FRAGMENTS)
if (n > MAX_TX_FRAGMENTS) {
n = MAX_TX_FRAGMENTS;
}

frags = n = net_fillFragments(p, pa, psz, n, ring->ops->max_tx_frag);
if (!frags) {
if (frags == 0) {
pbuf_free(p);
mutexUnlock(ring->lock);
return 0; /* dropped: too many fragments or empty packet */
return 0; /* dropped: too many fragments or empty packet */
}

/* fill fragments from last to avoid race against HW */
i = ni = (i + n) & ring->last;
ring->bufp[i] = p;
last = BDRING_SEG_LAST;
while (n--) {
if (!n)
while (n-- > 0) {
if (n == 0) {
last |= BDRING_SEG_FIRST;
}
i = (i - 1) & ring->last;
ring->ops->fillTxDesc(ring, i, pa[n], psz[n], last);
last = 0;
Expand Down
9 changes: 3 additions & 6 deletions drivers/bdring.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ enum {
};


typedef struct net_bufdesc_ops_
{
typedef struct net_bufdesc_ops_ {
size_t (*nextRxBufferSize)(const net_bufdesc_ring_t *ring, size_t i);
int (*pktRxFinished)(const net_bufdesc_ring_t *ring, size_t i);
void (*fillRxDesc)(const net_bufdesc_ring_t *ring, size_t i, addr_t pa, size_t sz, unsigned seg /* = zero */);
Expand All @@ -37,16 +36,14 @@ typedef struct net_bufdesc_ops_

size_t desc_size;
size_t ring_alignment;
size_t pkt_buf_sz;
size_t max_tx_frag;
} net_bufdesc_ops_t;


struct net_bufdesc_ring_
{
struct net_bufdesc_ring_ {
volatile void *ring;
struct pbuf **bufp;
volatile unsigned head, tail;
_Atomic volatile unsigned head, tail;
unsigned last;
addr_t phys;
const net_bufdesc_ops_t *ops;
Expand Down
Loading
Loading