diff options
Diffstat (limited to 'libhw/rp2040_include')
-rw-r--r-- | libhw/rp2040_include/libhw/rp2040_hwspi.h | 63 | ||||
-rw-r--r-- | libhw/rp2040_include/libhw/w5500.h | 102 |
2 files changed, 165 insertions, 0 deletions
diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h new file mode 100644 index 0000000..8e44e50 --- /dev/null +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -0,0 +1,63 @@ +/* libhw/rp2040_hwspi.h - `implements_spi` implementation for the RP2040's + * ARM Primecell SSP (PL022) (header file) + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-Licence-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBHW_RP2040_HWSPI_H_ +#define _LIBHW_RP2040_HWSPI_H_ + +#include <pico/binary_info.h> /* for bi_* */ + +#include <libhw/generic/spi.h> + +enum rp2040_hwspi_instance { + RP2040_HWSPI_0 = 0, + RP2040_HWSPI_1 = 1, +}; + +struct rp2040_hwspi { + implements_spi; + + void /*spi_inst_t*/ *inst; + uint pin_cs; +}; + +/** + * Initialize an instance of `struct rp2040_hwspi`. + * + * @param self : struct rp2040_hwspi : the structure to initialize + * @param name : char * : a name for the SPI port; to include in the bininfo + * @param inst_num : enum rp2040_hwspi_instance : the PL220 instance number; RP2040_HWSPI_{0,1} + * @param mode : enum spi_mode : the SPI mode; SPI_MODE_{0..3} + * @param pin_miso : uint : pin number; 0, 4, 16, or 20 for _HWSPI_0; 8, 12, 24, or 28 for _HWSPI_1 + * @param pin_mosi : uint : pin number; 3, 7, 19, or 23 for _HWSPI_0; 11, 15, or 27 for _HWSPI_1 + * @param pin_clk : uint : pin number; 2, 6, 18, or 22 for _HWSPI_0; 10, 14, or 26 for _HWSPI_1 + * @param pin_cs : uint : pin number; any unused GPIO pin + * + * There is no bit-order argument; the RP2040's hardware SPI always + * uses MSB-first bit order. + */ +#define rp2040_hwspi_init(self, name, \ + inst_num, mode, baudrate_hz, \ + pin_miso, pin_mosi, pin_clk, pin_cs) \ + do { \ + bi_decl(bi_4pins_with_names(pin_miso, name" SPI MISO", \ + pin_mosi, name" SPI MOSI", \ + pin_mosi, name" SPI CLK", \ + pin_mosi, name" SPI CS")); \ + _rp2040_hwspi_init(self, \ + inst_num, mode, baudrate_hz, \ + pin_miso, pin_mosi, pin_clk, pin_cs); \ + } while(0) +void _rp2040_hwspi_init(struct rp2040_hwspi *self, + enum rp2040_hwspi_instance inst_num, + enum spi_mode mode, + uint baudrate_hz, + uint pin_miso, + uint pin_mosi, + uint pin_clk, + uint pin_cs); + +#endif /* _LIBHW_RP2040_HWSPI_H_ */ diff --git a/libhw/rp2040_include/libhw/w5500.h b/libhw/rp2040_include/libhw/w5500.h new file mode 100644 index 0000000..6b5a690 --- /dev/null +++ b/libhw/rp2040_include/libhw/w5500.h @@ -0,0 +1,102 @@ +/* libhw/w5500.h - <libhw/generic/net.h> implementation for the WIZnet W5500 chip + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-Licence-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBHW_W5500_H_ +#define _LIBHW_W5500_H_ + +#include <libcr_ipc/sema.h> +#include <libcr_ipc/mutex.h> + +#include <libhw/generic/net.h> +#include <libhw/generic/spi.h> + +struct _w5500_tcp_conn { + /* const-after-init */ + implements_net_stream_conn; + /* mutable */ + bool read_open; + bool write_open; +}; + +struct _w5500_tcp_listener { + /* const-after-init */ + implements_net_stream_listener; + uint8_t socknum; + struct _w5500_tcp_conn active_conn; + + /* mutable */ + uint16_t port; + cr_mutex_t cmd_mu; + cr_sema_t listen_sema, read_sema; +}; + +struct w5500 { + /* const-after-init */ + implements_spi *spidev; + uint pin_intr; + uint pin_reset; + struct net_eth_addr hwaddr; + + /* mutable */ + uint16_t next_local_port; + struct _w5500_tcp_listener listeners[8]; + cr_sema_t intr; +}; + +/** + * Initialize a WIZnet W5500 Ethernet-and-TCP/IP-offload chip. + * + * The W5500 has 3 lines of communication with the MCU: + * + * - An SPI-based RPC protocol: + * + mode: mode 0 or mode 3 + * + bit-order: MSB-first + * + clock frequency: 33.3MHz - 80MHz + * - An interrupt pin that it pulls low when an event happens (to let + * 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. + */ +#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); \ + } while (0) +void _w5500_init(struct w5500 *self, + implements_spi *spi, uint pin_intr, uint pin_reset, + struct net_eth_addr addr); + +/** + * TODO. + */ +void w5500_hard_reset(struct w5500 *self); + +/** + * TODO. + */ +void w5500_soft_reset(struct w5500 *self); + +struct w5500_netcfg { + struct net_ip4_addr gateway_addr; + struct net_ip4_addr subnet_mask; + struct net_ip4_addr addr; +}; + +/** + * TODO. + */ +void w5500_netcfg(struct w5500 *self, struct w5500_netcfg cfg); + +implements_net_stream_listener *w5500_tcp_listen(struct w5500 *self, uint8_t socknum, + uint16_t port); + +/** + * TODO. + */ +implements_net_packet_conn *w5500_udp_conn(struct w5500 *self, uint8_t socknum, + uint16_t port); + +#endif /* _LIBHW_W5500_H_ */ |