summaryrefslogtreecommitdiff
path: root/libhw_cr/rp2040_include
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-09-28 17:01:59 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-09-28 17:01:59 -0600
commitfce80f2dc24ef45142ff92f74ebf809a39e06768 (patch)
tree01c591ca26460e7ca30597a85adff173d1ffc9a0 /libhw_cr/rp2040_include
parentbbf836c886a348bab4fad92d7ba448d1bbc9c910 (diff)
parent35c0f64218f4aa562f2dcde8eace87962bcab4e4 (diff)
Merge branch 'lukeshu/linkdown'HEADmain
Diffstat (limited to 'libhw_cr/rp2040_include')
-rw-r--r--libhw_cr/rp2040_include/libhw/w5500.h24
1 files changed, 18 insertions, 6 deletions
diff --git a/libhw_cr/rp2040_include/libhw/w5500.h b/libhw_cr/rp2040_include/libhw/w5500.h
index 43c58a3..d4ca4de 100644
--- a/libhw_cr/rp2040_include/libhw/w5500.h
+++ b/libhw_cr/rp2040_include/libhw/w5500.h
@@ -12,6 +12,7 @@
#include <libcr_ipc/chan.h>
#include <libcr_ipc/mutex.h>
#include <libcr_ipc/sema.h>
+#include <libmisc/linkedlist.h>
#include <libmisc/private.h>
#include <libhw/generic/net.h>
@@ -41,19 +42,23 @@ struct _w5500_socket {
END_PRIVATE(LIBHW_W5500_H);
};
+SLIST_DECLARE(_w5500_link_waitlist);
+
struct w5500 {
BEGIN_PRIVATE(LIBHW_W5500_H);
/* const-after-init */
lo_interface spi spidev;
uint pin_intr;
uint pin_reset;
+ uint pin_linkled;
struct net_eth_addr hwaddr;
/* mutable */
uint16_t next_local_port;
struct _w5500_socket sockets[8];
struct _w5500_socket *free;
- cr_sema_t intr;
+ cr_sema_t intr_sema;
+ struct _w5500_link_waitlist linkup_waiters;
cr_mutex_t mu;
END_PRIVATE(LIBHW_W5500_H);
};
@@ -72,14 +77,21 @@ LO_IMPLEMENTATION_H(net_iface, struct w5500, w5500_if);
* the MCU know that it should do an SPI RPC "get" to see what
* happened.)
* - A reset pin that the MCU can pull low to reset the W5500.
+ *
+ * Additionally (even though it isn't supposed to be a line of
+ * communication with the MCU) we watch the link-LED output of the
+ * W5500 (low=has link, high=no link) to know when to do an SPI RPC
+ * "get" on the PHYCFG register for link status, since that isn't one
+ * of the things that triggers the interrupt pin.
*/
-#define w5500_init(self, name, spi, pin_intr, pin_reset, eth_addr) do { \
- bi_decl(bi_2pins_with_names(pin_intr, name" interrupt", \
- pin_reset, name" reset")); \
- _w5500_init(self, spi, pin_intr, pin_reset, eth_addr); \
+#define w5500_init(self, name, spi, pin_intr, pin_reset, pin_linkled, eth_addr) do { \
+ bi_decl(bi_3pins_with_names(pin_intr, name" interrupt", \
+ pin_reset, name" reset", \
+ pin_linkled, name" link-LED")); \
+ _w5500_init(self, spi, pin_intr, pin_reset, pin_linkled, eth_addr); \
} while (0)
void _w5500_init(struct w5500 *self,
- lo_interface spi spi, uint pin_intr, uint pin_reset,
+ lo_interface spi spi, uint pin_intr, uint pin_reset, uint pin_linkled,
struct net_eth_addr addr);
/**