diff --git a/drivers/ethernet/eth_lan9250.c b/drivers/ethernet/eth_lan9250.c index f16e2eaac94e1..7e80df6d627e9 100644 --- a/drivers/ethernet/eth_lan9250.c +++ b/drivers/ethernet/eth_lan9250.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "eth_lan9250_priv.h" @@ -678,17 +679,48 @@ static int lan9250_init(const struct device *dev) return -EINVAL; } - if (gpio_pin_configure_dt(&config->interrupt, GPIO_INPUT)) { + ret = gpio_pin_configure_dt(&config->interrupt, GPIO_INPUT); + if (ret < 0) { LOG_ERR("Unable to configure GPIO pin %u", config->interrupt.pin); - return -EINVAL; + return ret; } - gpio_init_callback(&(context->gpio_cb), lan9250_gpio_callback, BIT(config->interrupt.pin)); - if (gpio_add_callback(config->interrupt.port, &(context->gpio_cb))) { - return -EINVAL; + gpio_init_callback(&(context->gpio_cb), lan9250_gpio_callback, + BIT(config->interrupt.pin)); + ret = gpio_add_callback(config->interrupt.port, &context->gpio_cb); + if (ret < 0) { + return ret; } - gpio_pin_interrupt_configure_dt(&config->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + ret = gpio_pin_interrupt_configure_dt(&config->interrupt, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Unable to enable GPIO INT %u", config->interrupt.pin); + return ret; + } + + if (config->reset.port != NULL) { + if (!gpio_is_ready_dt(&config->reset)) { + LOG_ERR("GPIO port %s not ready", config->reset.port->name); + return -EINVAL; + } + + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT); + if (ret < 0) { + LOG_ERR("Unable to configure GPIO pin %u", config->reset.pin); + return ret; + } + + /* See Section 19.6.3 from the LAN9250 Data Sheet + * + * trstia is 200 microseconds min (use 250 us) + * tcfg is 15 milliseconds min (use 20 ms for after reset) + */ + gpio_pin_set_dt(&config->reset, 1); + k_usleep(250); + gpio_pin_set_dt(&config->reset, 0); + k_msleep(20); + } /* Reset and wait for ready on the LAN9250 SPI device */ ret = lan9250_sw_reset(dev); @@ -697,6 +729,14 @@ static int lan9250_init(const struct device *dev) return ret; } lan9250_configure(dev); + + /* use a random MAC address if requested in the device tree */ + if (config->random_mac) { + sys_rand_get(context->mac_address, sizeof(context->mac_address)); + /* locally administered, unicast address */ + context->mac_address[0] &= ~(BIT(0) | BIT(2) | BIT(3)); + context->mac_address[0] |= BIT(1); + } lan9250_set_macaddr(dev); k_thread_create(&context->thread, context->thread_stack, @@ -718,7 +758,9 @@ static int lan9250_init(const struct device *dev) static const struct lan9250_config lan9250_##inst##_config = { \ .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8)), \ .interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ + .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ .timeout = CONFIG_ETH_LAN9250_BUF_ALLOC_TIMEOUT, \ + .random_mac = DT_INST_PROP(inst, zephyr_random_mac_address), \ }; \ \ ETH_NET_DEVICE_DT_INST_DEFINE(inst, lan9250_init, NULL, &lan9250_##inst##_runtime, \ diff --git a/drivers/ethernet/eth_lan9250_priv.h b/drivers/ethernet/eth_lan9250_priv.h index b6379216bdf3e..58668853ebe09 100644 --- a/drivers/ethernet/eth_lan9250_priv.h +++ b/drivers/ethernet/eth_lan9250_priv.h @@ -312,6 +312,7 @@ struct lan9250_config { struct gpio_dt_spec reset; uint8_t full_duplex; int32_t timeout; + bool random_mac; }; struct lan9250_runtime {