From ca7a66d7875cc25713f946fc6c20395c0a7a3feb Mon Sep 17 00:00:00 2001 From: Dean Sellers Date: Mon, 1 May 2023 14:05:58 +1000 Subject: [PATCH] drivers: ethernet: enc28j60: Prevent infinate loop on driver init In the case that there is a situation where the controller oscillator start-up timer doesn't expire, or the SPI can't read the CLKRDY bit the driver would hang during init. The config option ETH_ENC28J60_CLKRDY_INIT_WAIT_MS sets the time that the driver will wait for OST before returning an ETIMEDOUT error. Signed-off-by: Dean Sellers --- drivers/ethernet/Kconfig.enc28j60 | 10 ++++++++++ drivers/ethernet/eth_enc28j60.c | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/ethernet/Kconfig.enc28j60 b/drivers/ethernet/Kconfig.enc28j60 index d402de47e12..884a9ef4acf 100644 --- a/drivers/ethernet/Kconfig.enc28j60 +++ b/drivers/ethernet/Kconfig.enc28j60 @@ -30,6 +30,16 @@ config ETH_ENC28J60_RX_THREAD_PRIO Priority level for internal thread which is ran for incoming packet processing. +config ETH_ENC28J60_CLKRDY_INIT_WAIT_MS + int "Time to wait for the CLKRDY bit on driver init" + depends on ETH_ENC28J60 + default 2 + help + Timeout in milliseconds. Maximum time the initialisation + of the driver will wait for the OST to expire, indicated + by the CLKRDY bit set. If timeout driver init will fail + with -ETIMEDOUT. + config ETH_ENC28J60_TIMEOUT int "IP buffer timeout" depends on ETH_ENC28J60 diff --git a/drivers/ethernet/eth_enc28j60.c b/drivers/ethernet/eth_enc28j60.c index e00dae5527e..f5ee3d260e8 100644 --- a/drivers/ethernet/eth_enc28j60.c +++ b/drivers/ethernet/eth_enc28j60.c @@ -335,7 +335,7 @@ static void eth_enc28j60_gpio_callback(const struct device *dev, k_sem_give(&context->int_sem); } -static void eth_enc28j60_init_buffers(const struct device *dev) +static int eth_enc28j60_init_buffers(const struct device *dev) { uint8_t data_estat; @@ -375,11 +375,20 @@ static void eth_enc28j60_init_buffers(const struct device *dev) ENC28J60_RECEIVE_FILTERS); /* Waiting for OST */ + /* 32 bits for this timer should be fine, rollover not an issue with initialisation */ + uint32_t start_wait = (uint32_t) k_uptime_get(); do { + /* If the CLK isn't ready don't wait forever */ + if ((k_uptime_get_32() - start_wait) > CONFIG_ETH_ENC28J60_CLKRDY_INIT_WAIT_MS) { + LOG_ERR("OST wait timed out"); + return -ETIMEDOUT; + } /* wait 10.24 useconds */ k_busy_wait(D10D24S); eth_enc28j60_read_reg(dev, ENC28J60_REG_ESTAT, &data_estat); } while (!(data_estat & ENC28J60_BIT_ESTAT_CLKRDY)); + + return 0; } static void eth_enc28j60_init_mac(const struct device *dev) @@ -821,7 +830,9 @@ static int eth_enc28j60_init(const struct device *dev) context->mac_address[1] = MICROCHIP_OUI_B1; context->mac_address[2] = MICROCHIP_OUI_B2; - eth_enc28j60_init_buffers(dev); + if (eth_enc28j60_init_buffers(dev)) { + return -ETIMEDOUT; + } eth_enc28j60_init_mac(dev); eth_enc28j60_init_phy(dev);