diff --git a/drivers/ethernet/CMakeLists.txt b/drivers/ethernet/CMakeLists.txt index 1f0d26e82ed..3eb6bbc4e63 100644 --- a/drivers/ethernet/CMakeLists.txt +++ b/drivers/ethernet/CMakeLists.txt @@ -43,6 +43,7 @@ zephyr_library_sources_ifdef(CONFIG_ETH_XMC4XXX eth_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_ETH_TEST eth_test.c) zephyr_library_sources_ifdef(CONFIG_ETH_RENESAS_RA eth_renesas_ra.c) zephyr_library_sources_ifdef(CONFIG_ETH_LAN9250 eth_lan9250.c) +zephyr_library_sources_ifdef(CONFIG_ETH_SY1XX eth_sensry_sy1xx_mac.c) if(CONFIG_ETH_NXP_S32_NETC) zephyr_library_sources(eth_nxp_s32_netc.c) diff --git a/drivers/ethernet/Kconfig b/drivers/ethernet/Kconfig index 17901b3c2b6..d864c9c6e13 100644 --- a/drivers/ethernet/Kconfig +++ b/drivers/ethernet/Kconfig @@ -75,6 +75,7 @@ source "drivers/ethernet/Kconfig.lan865x" source "drivers/ethernet/Kconfig.xmc4xxx" source "drivers/ethernet/Kconfig.test" source "drivers/ethernet/Kconfig.lan9250" +source "drivers/ethernet/Kconfig.sy1xx_mac" source "drivers/ethernet/eth_nxp_enet_qos/Kconfig" diff --git a/drivers/ethernet/Kconfig.sy1xx_mac b/drivers/ethernet/Kconfig.sy1xx_mac new file mode 100644 index 00000000000..8493aa5305f --- /dev/null +++ b/drivers/ethernet/Kconfig.sy1xx_mac @@ -0,0 +1,11 @@ +# Copyright (c) 2025 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +config ETH_SY1XX + bool "Sensry SY1XX Ethernet driver" + default y + depends on DT_HAS_SENSRY_SY1XX_MAC_ENABLED + select MDIO + select PINCTRL + help + Enable Sensry SY1XX Ethernet MAC driver. diff --git a/drivers/ethernet/eth_sensry_sy1xx_mac.c b/drivers/ethernet/eth_sensry_sy1xx_mac.c new file mode 100644 index 00000000000..6a885cbc913 --- /dev/null +++ b/drivers/ethernet/eth_sensry_sy1xx_mac.c @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2025 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT sensry_sy1xx_mac + +#include +LOG_MODULE_REGISTER(sy1xx_mac, CONFIG_ETHERNET_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include +#include "eth.h" + +/* MAC register offsets */ +#define SY1XX_MAC_VERSION_REG 0x0000 +#define SY1XX_MAC_ADDRESS_LOW_REG 0x0004 +#define SY1XX_MAC_ADDRESS_HIGH_REG 0x0008 +#define SY1XX_MAC_CTRL_REG 0x000c + +/* MAC control register bit offsets */ +#define SY1XX_MAC_CTRL_RESET_OFFS (0) +#define SY1XX_MAC_CTRL_RX_EN_OFFS (1) +#define SY1XX_MAC_CTRL_TX_EN_OFFS (2) +#define SY1XX_MAC_CTRL_GMII_OFFS (3) +#define SY1XX_MAC_CTRL_CLK_DIV_OFFS (8) +#define SY1XX_MAC_CTRL_CLK_SEL_OFFS (10) + +/* MAC clock sources */ +#define SY1XX_MAC_CTRL_CLK_SEL_REF_CLK 0 +#define SY1XX_MAC_CTRL_CLK_SEL_MII_CLK 1 + +/* Clock divider options */ +#define SY1XX_MAC_CTRL_CLK_DIV_1 0x0 +#define SY1XX_MAC_CTRL_CLK_DIV_5 0x1 +#define SY1XX_MAC_CTRL_CLK_DIV_10 0x2 +#define SY1XX_MAC_CTRL_CLK_DIV_50 0x3 + +/* Clock divider mask */ +#define SY1XX_MAC_CTRL_CLK_DIV_MASK (0x3) + +#define MAX_MAC_PACKET_LEN 1600 +#define MAX_TX_RETRIES 5 +#define RECEIVE_GRACE_TIME_MSEC 1 + +#define SY1XX_ETH_STACK_SIZE 4096 +#define SY1XX_ETH_THREAD_PRIORITY K_PRIO_PREEMPT(0) + +struct sy1xx_mac_dev_config { + /* address of controller configuration registers */ + uint32_t ctrl_addr; + /* address of udma for data transfers */ + uint32_t base_addr; + /* optional - enable promiscuous mode */ + bool promiscuous_mode; + /* optional - device tree mac */ + bool use_local_mac_address; + uint8_t local_mac_address[6]; + /* optional - random mac */ + bool use_zephyr_random_mac; + + /* phy config */ + const struct device *phy_dev; + + /* pinctrl for rgmii pins */ + const struct pinctrl_dev_config *pcfg; +}; + +struct sy1xx_mac_dma_buffers { + uint8_t tx[MAX_MAC_PACKET_LEN]; + uint8_t rx[MAX_MAC_PACKET_LEN]; +}; + +struct sy1xx_mac_dev_data { + struct k_mutex mutex; + + /* current state of link and mac address */ + bool link_is_up; + enum phy_link_speed link_speed; + + uint8_t mac_addr[6]; + + /* intermediate, linear buffers that can hold a received or transmit msg */ + struct { + uint8_t tx[MAX_MAC_PACKET_LEN]; + uint16_t tx_len; + + uint8_t rx[MAX_MAC_PACKET_LEN]; + uint16_t rx_len; + } temp; + + /* buffers used for dma transfer, cannot be accessed while transfer active */ + struct sy1xx_mac_dma_buffers *dma_buffers; + + struct k_thread rx_data_thread; + + K_KERNEL_STACK_MEMBER(rx_data_thread_stack, SY1XX_ETH_STACK_SIZE); + + struct net_if *iface; +}; + +/* prototypes */ +static int sy1xx_mac_set_mac_addr(const struct device *dev, uint8_t *mac_addr); +static int sy1xx_mac_set_promiscuous_mode(const struct device *dev, bool promiscuous_mode); +static int sy1xx_mac_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config); +static void sy1xx_mac_rx_thread_entry(void *p1, void *p2, void *p3); + +static int sy1xx_mac_initialize(const struct device *dev) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data; + int ret; + + data->link_is_up = false; + data->link_speed = -1; + + k_mutex_init(&data->mutex); + + /* PAD config */ + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + LOG_ERR("failed to configure pins"); + return ret; + } + + /* create the receiver thread */ + k_thread_create(&data->rx_data_thread, (k_thread_stack_t *)data->rx_data_thread_stack, + SY1XX_ETH_STACK_SIZE, sy1xx_mac_rx_thread_entry, (void *)dev, NULL, NULL, + SY1XX_ETH_THREAD_PRIORITY, 0, K_NO_WAIT); + + /* start suspended and resume once we have link */ + k_thread_suspend(&data->rx_data_thread); + + k_thread_name_set(&data->rx_data_thread, "mac-rx-thread"); + + return 0; +} + +static int sy1xx_mac_set_promiscuous_mode(const struct device *dev, bool promiscuous_mode) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + uint32_t prom; + + /* set promiscuous mode */ + prom = sys_read32(cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG); + if (promiscuous_mode) { + prom &= ~BIT(16); + } else { + prom |= BIT(16); + } + sys_write32(prom, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG); + + return 0; +} + +static int sy1xx_mac_set_mac_addr(const struct device *dev, uint8_t *mac_addr) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data; + int ret; + uint32_t v_low, v_high; + + LOG_INF("%s set link address %02x:%02x:%02x:%02x:%02x:%02x", dev->name, mac_addr[0], + mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + /* update mac in controller */ + v_low = sys_get_le32(&mac_addr[0]); + sys_write32(v_low, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_LOW_REG); + + v_high = sys_read32(cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG); + v_high |= (v_high & 0xffff0000) | sys_get_le16(&mac_addr[4]); + sys_write32(v_high, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG); + + memcpy(data->mac_addr, mac_addr, 6); + + /* Register Ethernet MAC Address with the upper layer */ + ret = net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr), + NET_LINK_ETHERNET); + if (ret) { + LOG_ERR("%s failed to set link address", dev->name); + return ret; + } + + return 0; +} + +static int sy1xx_mac_start(const struct device *dev) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data; + uint8_t rand_mac_addr[6]; + + extern void sy1xx_udma_disable_clock(sy1xx_udma_module_t module, uint32_t instance); + + /* UDMA clock reset and enable */ + sy1xx_udma_enable_clock(SY1XX_UDMA_MODULE_MAC, 0); + sy1xx_udma_disable_clock(SY1XX_UDMA_MODULE_MAC, 0); + sy1xx_udma_enable_clock(SY1XX_UDMA_MODULE_MAC, 0); + + /* reset mac controller */ + sys_write32(0x0001, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + sys_write32(0x0000, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + + /* preset mac addr */ + if (cfg->use_local_mac_address) { + /* prio 0 -- from device tree */ + sy1xx_mac_set_mac_addr(dev, cfg->local_mac_address); + } else if (cfg->use_zephyr_random_mac) { + /* prio 1 -- generate random, if set in device tree */ + sys_rand_get(&rand_mac_addr, 6); + /* Set MAC address locally administered, unicast (LAA) */ + rand_mac_addr[0] |= 0x02; + sy1xx_mac_set_mac_addr(dev, rand_mac_addr); + } else { + /* no preset mac address available */ + } + + sy1xx_mac_set_promiscuous_mode(dev, cfg->promiscuous_mode); + + k_thread_resume(&data->rx_data_thread); + + return 0; +} + +static int sy1xx_mac_stop(const struct device *dev) +{ + struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data; + + k_thread_suspend(&data->rx_data_thread); + return 0; +} + +static void phy_link_state_changed(const struct device *pdev, struct phy_link_state *state, + void *user_data) +{ + const struct device *dev = (const struct device *)user_data; + struct sy1xx_mac_dev_data *const data = dev->data; + const struct sy1xx_mac_dev_config *const cfg = dev->config; + bool is_up; + enum phy_link_speed speed; + uint32_t v, en; + + is_up = state->is_up; + speed = state->speed; + + if (speed != data->link_speed) { + data->link_speed = speed; + + /* configure mac, based on provided link information 1Gbs/100MBit/... */ + v = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + + /* mask out relevant bits */ + v &= ~(BIT(SY1XX_MAC_CTRL_GMII_OFFS) | BIT(SY1XX_MAC_CTRL_CLK_SEL_OFFS) | + (SY1XX_MAC_CTRL_CLK_DIV_MASK << SY1XX_MAC_CTRL_CLK_DIV_OFFS)); + + switch (speed) { + case LINK_FULL_10BASE_T: + LOG_INF("link speed FULL_10BASE_T"); + /* 2.5MHz, MAC is clock source */ + v |= (SY1XX_MAC_CTRL_CLK_SEL_MII_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) | + (SY1XX_MAC_CTRL_CLK_DIV_10 << SY1XX_MAC_CTRL_CLK_DIV_OFFS); + break; + case LINK_FULL_100BASE_T: + LOG_INF("link speed FULL_100BASE_T"); + /* 25MHz, MAC is clock source */ + v |= (SY1XX_MAC_CTRL_CLK_SEL_MII_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) | + (SY1XX_MAC_CTRL_CLK_DIV_1 << SY1XX_MAC_CTRL_CLK_DIV_OFFS); + break; + case LINK_FULL_1000BASE_T: + LOG_INF("link speed FULL_1000BASE_T"); + /* 125MHz, Phy is clock source */ + v |= BIT(SY1XX_MAC_CTRL_GMII_OFFS) | + (SY1XX_MAC_CTRL_CLK_SEL_REF_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) | + (SY1XX_MAC_CTRL_CLK_DIV_1 << SY1XX_MAC_CTRL_CLK_DIV_OFFS); + break; + default: + LOG_ERR("invalid link speed"); + return; + } + sys_write32(v, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + } + + if (is_up != data->link_is_up) { + data->link_is_up = is_up; + + if (is_up) { + LOG_DBG("Link up"); + + /* enable mac controller */ + en = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + en |= BIT(SY1XX_MAC_CTRL_TX_EN_OFFS) | BIT(SY1XX_MAC_CTRL_RX_EN_OFFS); + sys_write32(en, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + + /* Announce link up status */ + net_eth_carrier_on(data->iface); + + } else { + LOG_DBG("Link down"); + + /* disable mac controller */ + en = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + en &= ~(BIT(SY1XX_MAC_CTRL_TX_EN_OFFS) | BIT(SY1XX_MAC_CTRL_RX_EN_OFFS)); + sys_write32(en, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG); + + /* Announce link down status */ + net_eth_carrier_off(data->iface); + } + } +} + +static void sy1xx_mac_iface_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *const data = dev->data; + + LOG_INF("Interface init %s (%.8x)", net_if_get_device(iface)->name, iface); + + data->iface = iface; + + ethernet_init(iface); + + if (device_is_ready(cfg->phy_dev)) { + phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev); + } else { + LOG_ERR("PHY device not ready"); + } + + /* Do not start the interface until PHY link is up */ + if (!(data->link_is_up)) { + LOG_INF("found PHY link down"); + net_if_carrier_off(iface); + } +} + +static enum ethernet_hw_caps sy1xx_mac_get_caps(const struct device *dev) +{ + enum ethernet_hw_caps supported = 0; + + /* basic implemented features */ + supported |= ETHERNET_PROMISC_MODE; + supported |= ETHERNET_LINK_1000BASE_T; + supported |= ETHERNET_PROMISC_MODE; + + return supported; +} + +static int sy1xx_mac_get_config(const struct device *dev, enum ethernet_config_type type, + struct ethernet_config *config) +{ + struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data; + + /* we currently support only 1000mbit/s full duplex */ + switch (type) { + case ETHERNET_CONFIG_TYPE_LINK: + config->l.link_1000bt = true; + break; + + case ETHERNET_CONFIG_TYPE_DUPLEX: + config->full_duplex = true; + break; + + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + memcpy(config->mac_address.addr, data->mac_addr, 6); + break; + default: + return -ENOTSUP; + } + return 0; +} + +static int sy1xx_mac_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + int ret = 0; + + switch (type) { + + case ETHERNET_CONFIG_TYPE_PROMISC_MODE: + ret = sy1xx_mac_set_promiscuous_mode(dev, config->promisc_mode); + break; + + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + ret = sy1xx_mac_set_mac_addr(dev, (uint8_t *)&(config->mac_address.addr)); + break; + default: + return -ENOTSUP; + } + return ret; +} + +static const struct device *sy1xx_mac_get_phy(const struct device *dev) +{ + const struct sy1xx_mac_dev_config *const cfg = dev->config; + + return cfg->phy_dev; +} + +/* + * rx ready status of eth is different to any other rx udma, + * so we implement here + */ +static int32_t sy1xx_mac_udma_is_finished_rx(uint32_t base) +{ + uint32_t isBusy = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + 0x00) & (BIT(17)); + + return isBusy ? 0 : 1; +} + +static int sy1xx_mac_low_level_send(const struct device *dev, uint8_t *tx, uint16_t len) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *const data = dev->data; + + if (len == 0) { + return -EINVAL; + } + + if (len > MAX_MAC_PACKET_LEN) { + return -EINVAL; + } + + if (!SY1XX_UDMA_IS_FINISHED_TX(cfg->base_addr)) { + return -EBUSY; + } + + /* udma is ready, double check if last transmission was successful */ + if (SY1XX_UDMA_GET_REMAINING_TX(cfg->base_addr)) { + SY1XX_UDMA_CANCEL_TX(cfg->base_addr); + LOG_ERR("tx - last transmission failed"); + return -EINVAL; + } + + /* copy data to dma buffer */ + for (uint32_t i = 0; i < len; i++) { + data->dma_buffers->tx[i] = tx[i]; + } + + /* start dma transfer */ + SY1XX_UDMA_START_TX(cfg->base_addr, (uint32_t)data->dma_buffers->tx, len, 0); + + return 0; +} + +static int sy1xx_mac_low_level_receive(const struct device *dev, uint8_t *rx, uint16_t *len) +{ + struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config; + struct sy1xx_mac_dev_data *const data = dev->data; + int ret; + uint32_t bytes_transferred; + + *len = 0; + + /* rx udma still busy */ + if (0 == sy1xx_mac_udma_is_finished_rx(cfg->base_addr)) { + return -EBUSY; + } + + /* rx udma is ready */ + bytes_transferred = SY1XX_UDMA_READ_REG(cfg->base_addr, SY1XX_UDMA_CFG_REG) & 0x0000ffff; + if (bytes_transferred) { + /* message received, copy data */ + memcpy(rx, data->dma_buffers->rx, bytes_transferred); + *len = bytes_transferred; + ret = 0; + } else { + /* no data, should never happen */ + SY1XX_UDMA_CANCEL_RX(cfg->base_addr); + ret = -EINVAL; + } + + /* start new reception */ + SY1XX_UDMA_START_RX(cfg->base_addr, (uint32_t)data->dma_buffers->rx, MAX_MAC_PACKET_LEN, 0); + + return ret; +} + +static int sy1xx_mac_send(const struct device *dev, struct net_pkt *pkt) +{ + struct sy1xx_mac_dev_data *const data = dev->data; + int ret; + uint32_t retries_left; + struct net_buf *frag; + + k_mutex_lock(&data->mutex, K_FOREVER); + + /* push all fragments of the packet into one linear buffer */ + frag = pkt->buffer; + data->temp.tx_len = 0; + do { + /* copy fragment to buffer */ + for (uint32_t i = 0; i < frag->len; i++) { + if (data->temp.tx_len < MAX_MAC_PACKET_LEN) { + data->temp.tx[data->temp.tx_len++] = frag->data[i]; + } else { + LOG_ERR("tx buffer overflow"); + k_mutex_unlock(&data->mutex); + return -ENOMEM; + } + } + + frag = frag->frags; + } while (frag); + + /* hand over linear tx frame to udma */ + retries_left = MAX_TX_RETRIES; + while (retries_left) { + ret = sy1xx_mac_low_level_send(dev, data->temp.tx, data->temp.tx_len); + if (ret == 0) { + break; + } + if (ret != -EBUSY) { + LOG_ERR("tx error"); + k_mutex_unlock(&data->mutex); + return ret; + } + k_sleep(K_MSEC(1)); + retries_left--; + }; + + k_mutex_unlock(&data->mutex); + return ret; +} + +static int sy1xx_mac_receive_data(const struct device *dev, uint8_t *rx, uint16_t len) +{ + struct sy1xx_mac_dev_data *const data = dev->data; + struct net_pkt *rx_pkt; + int ret; + + rx_pkt = net_pkt_alloc_with_buffer(data->iface, len, AF_UNSPEC, 0, K_FOREVER); + if (rx_pkt == NULL) { + LOG_ERR("rx packet allocation failed"); + return -EINVAL; + } + + /* add data to the net_pkt */ + if (net_pkt_write(rx_pkt, rx, len)) { + LOG_ERR("failed to write data to net_pkt"); + net_pkt_unref(rx_pkt); + return -EINVAL; + } + + /* register new packet in stack */ + ret = net_recv_data(data->iface, rx_pkt); + if (ret) { + LOG_ERR("rx packet registration failed"); + return ret; + } + + return 0; +} + +static void sy1xx_mac_rx_thread_entry(void *p1, void *p2, void *p3) +{ + const struct device *dev = p1; + struct sy1xx_mac_dev_data *const data = dev->data; + int ret; + + while (true) { + ret = sy1xx_mac_low_level_receive(dev, data->temp.rx, &data->temp.rx_len); + if (ret == 0) { + /* register a new received frame */ + if (data->temp.rx_len) { + sy1xx_mac_receive_data(dev, data->temp.rx, data->temp.rx_len); + } + } else { + /* + * rx thread is running at higher prio, in case of error or busy, + * we could lock up the system partially. + */ + + /* we wait and try again */ + k_sleep(K_MSEC(RECEIVE_GRACE_TIME_MSEC)); + } + } +} + +const struct ethernet_api sy1xx_mac_driver_api = { + .start = sy1xx_mac_start, + .stop = sy1xx_mac_stop, + .iface_api.init = sy1xx_mac_iface_init, + .get_capabilities = sy1xx_mac_get_caps, + .get_config = sy1xx_mac_get_config, + .set_config = sy1xx_mac_set_config, + .send = sy1xx_mac_send, + .get_phy = sy1xx_mac_get_phy, +}; + +#define SY1XX_MAC_INIT(n) \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static const struct sy1xx_mac_dev_config sy1xx_mac_dev_config_##n = { \ + .ctrl_addr = DT_INST_REG_ADDR_BY_NAME(n, ctrl), \ + .base_addr = DT_INST_REG_ADDR_BY_NAME(n, data), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .promiscuous_mode = DT_INST_PROP_OR(n, promiscuous_mode, false), \ + .local_mac_address = DT_INST_PROP_OR(n, local_mac_address, {0}), \ + .use_local_mac_address = DT_INST_NODE_HAS_PROP(n, local_mac_address), \ + .use_zephyr_random_mac = DT_INST_NODE_HAS_PROP(n, zephyr_random_mac_address), \ + .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle))}; \ + \ + static struct sy1xx_mac_dma_buffers __attribute__((section(".udma_access"))) \ + __aligned(4) sy1xx_mac_dma_buffers_##n; \ + \ + static struct sy1xx_mac_dev_data sy1xx_mac_dev_data##n = { \ + .dma_buffers = &sy1xx_mac_dma_buffers_##n, \ + }; \ + \ + ETH_NET_DEVICE_DT_INST_DEFINE(n, &sy1xx_mac_initialize, NULL, &sy1xx_mac_dev_data##n, \ + &sy1xx_mac_dev_config_##n, CONFIG_ETH_INIT_PRIORITY, \ + &sy1xx_mac_driver_api, NET_ETH_MTU); + +DT_INST_FOREACH_STATUS_OKAY(SY1XX_MAC_INIT) diff --git a/dts/bindings/ethernet/sensry,sy1xx-mac.yaml b/dts/bindings/ethernet/sensry,sy1xx-mac.yaml new file mode 100644 index 00000000000..412c405bcce --- /dev/null +++ b/dts/bindings/ethernet/sensry,sy1xx-mac.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +compatible: "sensry,sy1xx-mac" + +include: [ethernet-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + reg: + required: true + + reg-names: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + phy-handle: + required: true + + promiscuous-mode: + type: boolean + description: | + Optional feature flag - Enable promiscuous mode. When set, all valid + frames will be accepted.