drivers: ethernet: enc28j60: Added carrier status update functionality
Expanded the enc28j60 driver to update its carrier status whenever the Ethernet cable is plugged in or out. I used the enc424j600 driver as reference, as this driver already included this functionality. The driver will now take the interface offline whenever the cable is not plugged in and stop sending packets. The respective events are also generated for use in the application. I tested it locally on my nRF52840 based gateway board using the enc28j60 network chip. Everything worked as expected. Signed-off-by: Paul Jans <paul.jans.1999@hotmail.com> Fixes #51214
This commit is contained in:
parent
f460c21578
commit
e35ce37443
|
@ -296,6 +296,35 @@ static void eth_enc28j60_write_phy(const struct device *dev,
|
|||
} while ((data_mistat & ENC28J60_BIT_MISTAT_BUSY));
|
||||
}
|
||||
|
||||
static void eth_enc28j60_read_phy(const struct device *dev,
|
||||
uint16_t reg_addr,
|
||||
int16_t *data)
|
||||
{
|
||||
uint8_t data_mistat;
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
|
||||
eth_enc28j60_set_bank(dev, ENC28J60_REG_MIREGADR);
|
||||
eth_enc28j60_write_reg(dev, ENC28J60_REG_MIREGADR, reg_addr);
|
||||
eth_enc28j60_write_reg(dev, ENC28J60_REG_MICMD,
|
||||
ENC28J60_BIT_MICMD_MIIRD);
|
||||
eth_enc28j60_set_bank(dev, ENC28J60_REG_MISTAT);
|
||||
|
||||
do {
|
||||
/* wait 10.24 useconds */
|
||||
k_busy_wait(D10D24S);
|
||||
eth_enc28j60_read_reg(dev, ENC28J60_REG_MISTAT,
|
||||
&data_mistat);
|
||||
} while ((data_mistat & ENC28J60_BIT_MISTAT_BUSY));
|
||||
|
||||
eth_enc28j60_set_bank(dev, ENC28J60_REG_MIREGADR);
|
||||
eth_enc28j60_write_reg(dev, ENC28J60_REG_MICMD, 0x0);
|
||||
eth_enc28j60_read_reg(dev, ENC28J60_REG_MIRDL, &lsb);
|
||||
eth_enc28j60_read_reg(dev, ENC28J60_REG_MIRDH, &msb);
|
||||
|
||||
*data = (msb << 8) | lsb;
|
||||
}
|
||||
|
||||
static void eth_enc28j60_gpio_callback(const struct device *dev,
|
||||
struct gpio_callback *cb,
|
||||
uint32_t pins)
|
||||
|
@ -686,6 +715,22 @@ static void eth_enc28j60_rx_thread(const struct device *dev)
|
|||
eth_enc28j60_clear_eth_reg(dev, ENC28J60_REG_EIR,
|
||||
ENC28J60_BIT_EIR_PKTIF
|
||||
| ENC28J60_BIT_EIR_RXERIF);
|
||||
} else if (int_stat & ENC28J60_BIT_EIR_LINKIF) {
|
||||
uint16_t phir;
|
||||
uint16_t phstat2;
|
||||
/* Clear link change interrupt flag by PHIR reg read */
|
||||
eth_enc28j60_read_phy(dev, ENC28J60_PHY_PHIR, &phir);
|
||||
eth_enc28j60_read_phy(dev, ENC28J60_PHY_PHSTAT2, &phstat2);
|
||||
if (phstat2 & ENC28J60_BIT_PHSTAT2_LSTAT) {
|
||||
LOG_INF("Link up");
|
||||
net_eth_carrier_on(context->iface);
|
||||
} else {
|
||||
LOG_INF("Link down");
|
||||
|
||||
if (context->iface_initialized) {
|
||||
net_eth_carrier_off(context->iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -719,6 +764,9 @@ static void eth_enc28j60_iface_init(struct net_if *iface)
|
|||
}
|
||||
|
||||
ethernet_init(iface);
|
||||
|
||||
net_if_carrier_off(iface);
|
||||
context->iface_initialized = true;
|
||||
}
|
||||
|
||||
static const struct ethernet_api api_funcs = {
|
||||
|
@ -781,6 +829,9 @@ static int eth_enc28j60_init(const struct device *dev)
|
|||
/* Enable interruptions */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_INTIE);
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_PKTIE);
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_LINKIE);
|
||||
eth_enc28j60_write_phy(dev, ENC28J60_PHY_PHIE, ENC28J60_BIT_PHIE_PGEIE |
|
||||
ENC28J60_BIT_PHIE_PLNKIE);
|
||||
|
||||
/* Enable Reception */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_ECON1,
|
||||
|
|
|
@ -154,6 +154,7 @@
|
|||
#define ENC28J60_BIT_EIR_PKTIF (0x40)
|
||||
#define ENC28J60_BIT_EIE_TXIE (0x08)
|
||||
#define ENC28J60_BIT_EIE_PKTIE (0x40)
|
||||
#define ENC28J60_BIT_EIE_LINKIE (0x10)
|
||||
#define ENC28J60_BIT_EIE_INTIE (0x80)
|
||||
#define ENC28J60_BIT_EIR_PKTIF (0x40)
|
||||
#define ENC28J60_BIT_EIR_DMAIF (0x20)
|
||||
|
@ -166,6 +167,9 @@
|
|||
#define ENC28J60_BIT_ESTAT_LATECOL (0x10)
|
||||
#define ENC28J60_BIT_PHCON1_PDPXMD (0x0100)
|
||||
#define ENC28J60_BIT_PHCON2_HDLDIS (0x0001)
|
||||
#define ENC28J60_BIT_PHSTAT2_LSTAT (0x0400)
|
||||
#define ENC28J60_BIT_PHIE_PGEIE (0x0002)
|
||||
#define ENC28J60_BIT_PHIE_PLNKIE (0x0010)
|
||||
|
||||
/* Driver Static Configuration */
|
||||
|
||||
|
@ -230,6 +234,7 @@ struct eth_enc28j60_runtime {
|
|||
struct gpio_callback gpio_cb;
|
||||
struct k_sem tx_rx_sem;
|
||||
struct k_sem int_sem;
|
||||
bool iface_initialized : 1;
|
||||
};
|
||||
|
||||
#endif /*_ENC28J60_*/
|
||||
|
|
Loading…
Reference in a new issue