Skip to content

Commit

Permalink
drivers: ethernet: enc28j60: Added carrier status update functionality
Browse files Browse the repository at this point in the history
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 <[email protected]>

Fixes zephyrproject-rtos#51214
  • Loading branch information
chewduh authored and carlescufi committed Oct 31, 2022
1 parent f460c21 commit e35ce37
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
51 changes: 51 additions & 0 deletions drivers/ethernet/eth_enc28j60.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
}
}
}
}
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/ethernet/eth_enc28j60_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 */

Expand Down Expand Up @@ -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_*/

0 comments on commit e35ce37

Please sign in to comment.