zephyr/drivers/ethernet/eth_dwmac_mmu.c
Nicolas Pitre bc41234104 ethernet: Synopsys DesignWare MAC driver
This is a driver for the Synopsys DesignWare MAC. It should work
with the "DesignWare Cores Ethernet Quality-of-Service" versions 4.x
and 5.x.

This driver uses a zero-copy strategy, meaning that the hardware
reads and writes data directly from/to packet fragment buffers
provided by the network subsystem without first copying the data into
a dedicated DMA bounce buffer.

Platform specific setup is necessary for the hardware to work.
Currently, only the STM32H7X series is implemented and tested.
While this part needs refinement, this driver performs better and uses
far less code space than the HAL-based alternative.

Not yet implemented:

- MDIO (it is WIP, currently relying on default PHY config)
- PTP support
- VLAN support
- various hardware offloads (when available)

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2021-10-27 10:43:05 -04:00

100 lines
2.5 KiB
C

/*
* Driver for Synopsys DesignWare MAC
*
* Copyright (c) 2021 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME dwmac_plat
#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define DT_DRV_COMPAT snps_designware_ethernet
#include <sys/types.h>
#include <sys/mem_manage.h>
#include <zephyr.h>
#include <cache.h>
#include <net/ethernet.h>
#include "eth_dwmac_priv.h"
int dwmac_bus_init(struct dwmac_priv *p)
{
p->base_addr = DT_INST_REG_ADDR(0);
return 0;
}
#if (CONFIG_DCACHE_LINE_SIZE+0 == 0)
#error "CONFIG_DCACHE_LINE_SIZE must be configured to a non-zero value"
#endif
static struct dwmac_dma_desc __aligned(CONFIG_DCACHE_LINE_SIZE)
dwmac_tx_rx_descriptors[NB_TX_DESCS + NB_RX_DESCS];
static const uint8_t dwmac_mac_addr[6] = DT_INST_PROP(0, local_mac_address);
void dwmac_platform_init(struct dwmac_priv *p)
{
uint8_t *desc_uncached_addr;
uintptr_t desc_phys_addr;
/* make sure no valid cache lines map to the descriptor area */
sys_cache_data_range(dwmac_tx_rx_descriptors,
sizeof(dwmac_tx_rx_descriptors),
K_CACHE_INVD);
desc_phys_addr = z_mem_phys_addr(dwmac_tx_rx_descriptors);
/* remap descriptor rings uncached */
z_phys_map(&desc_uncached_addr, desc_phys_addr,
sizeof(dwmac_tx_rx_descriptors),
K_MEM_PERM_RW | K_MEM_CACHE_NONE);
LOG_DBG("desc virt %p uncached %p phys 0x%lx",
dwmac_tx_rx_descriptors, desc_uncached_addr, desc_phys_addr);
p->tx_descs = (void *)desc_uncached_addr;
desc_uncached_addr += NB_TX_DESCS * sizeof(struct dwmac_dma_desc);
p->rx_descs = (void *)desc_uncached_addr;
p->tx_descs_phys = desc_phys_addr;
desc_phys_addr += NB_TX_DESCS * sizeof(struct dwmac_dma_desc);
p->rx_descs_phys = desc_phys_addr;
/* basic configuration for this platform */
REG_WRITE(MAC_CONF,
MAC_CONF_PS |
MAC_CONF_FES |
MAC_CONF_DM);
REG_WRITE(DMA_SYSBUS_MODE,
DMA_SYSBUS_MODE_AAL |
#ifdef CONFIG_64BIT
DMA_SYSBUS_MODE_EAME |
#endif
DMA_SYSBUS_MODE_FB);
/* set up IRQs (still masked for now) */
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), dwmac_isr,
DEVICE_DT_INST_GET(0), 0);
irq_enable(DT_INST_IRQN(0));
/* retrieve MAC address */
memcpy(p->mac_addr, dwmac_mac_addr, sizeof(p->mac_addr));
}
/* Our private device instance */
static struct dwmac_priv dwmac_instance;
ETH_NET_DEVICE_DT_INST_DEFINE(0,
dwmac_probe,
NULL,
&dwmac_instance,
NULL,
CONFIG_ETH_INIT_PRIORITY,
&dwmac_api,
NET_ETH_MTU);