1use crate::clock::RefClockPin;
9use crate::pins::{MdioPinConfig, PhyResetPinConfig, RmiiPinConfig};
10
11#[derive(Clone, Copy, Debug)]
13pub struct BoardConfig {
14 pub rmii_pins: RmiiPinConfig,
16 pub mdio_pins: MdioPinConfig,
18 pub phy_reset: PhyResetPinConfig,
20 pub ref_clock: RefClockPin,
22 pub phy_addr: u8,
24}
25
26impl BoardConfig {
27 pub const WAVESHARE_P4_ETH: Self = Self {
36 rmii_pins: RmiiPinConfig::WAVESHARE_P4_ETH,
37 mdio_pins: MdioPinConfig::WAVESHARE_P4_ETH,
38 phy_reset: PhyResetPinConfig::WAVESHARE_P4_ETH,
39 ref_clock: RefClockPin::Gpio50,
40 phy_addr: 1,
41 };
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::clock::RefClockPin;
48
49 #[test]
53 fn waveshare_phy_addr_is_one_and_in_legal_range() {
54 let cfg = BoardConfig::WAVESHARE_P4_ETH;
55 assert_eq!(cfg.phy_addr, 1, "Waveshare straps the IP101 to MDIO addr 1");
56 assert!(cfg.phy_addr < 32, "MDIO addr must fit in 5 bits");
57 }
58
59 #[test]
60 fn waveshare_rmii_pin_map_matches_dev_board_silkscreen() {
61 let pins = BoardConfig::WAVESHARE_P4_ETH.rmii_pins;
62 assert_eq!(pins.txd0, 34);
63 assert_eq!(pins.txd1, 35);
64 assert_eq!(pins.tx_en, 49);
65 assert_eq!(pins.rxd0, 30);
66 assert_eq!(pins.rxd1, 29);
67 assert_eq!(pins.crs_dv, 28);
68 }
69
70 #[test]
71 fn waveshare_mdio_pins_match_dev_board_silkscreen() {
72 let pins = BoardConfig::WAVESHARE_P4_ETH.mdio_pins;
73 assert_eq!(pins.mdc, 31);
74 assert_eq!(pins.mdio, 52);
75 }
76
77 #[test]
78 fn waveshare_phy_reset_is_gpio51_active_low() {
79 let reset = BoardConfig::WAVESHARE_P4_ETH.phy_reset;
80 assert_eq!(reset.pin, 51);
81 assert!(
82 reset.active_low,
83 "IP101GRI RST_N is active low — flipping this strands the PHY in reset"
84 );
85 }
86
87 #[test]
88 fn waveshare_ref_clock_pad_is_gpio50() {
89 assert!(matches!(
90 BoardConfig::WAVESHARE_P4_ETH.ref_clock,
91 RefClockPin::Gpio50
92 ));
93 }
94
95 #[test]
99 fn board_config_is_copy_clone() {
100 fn assert_copy<T: Copy>() {}
101 fn assert_clone<T: Clone>() {}
102 assert_copy::<BoardConfig>();
103 assert_clone::<BoardConfig>();
104
105 let a = BoardConfig::WAVESHARE_P4_ETH;
106 let b = a; let _c = a.clone();
108 assert_eq!(a.phy_addr, b.phy_addr);
109 }
110
111 #[test]
114 fn all_waveshare_gpio_numbers_fit_p4_pinout() {
115 let cfg = BoardConfig::WAVESHARE_P4_ETH;
116 let pins = [
117 cfg.rmii_pins.txd0,
118 cfg.rmii_pins.txd1,
119 cfg.rmii_pins.tx_en,
120 cfg.rmii_pins.rxd0,
121 cfg.rmii_pins.rxd1,
122 cfg.rmii_pins.crs_dv,
123 cfg.mdio_pins.mdc,
124 cfg.mdio_pins.mdio,
125 cfg.phy_reset.pin,
126 ];
127 for p in pins {
128 assert!(p < 56, "P4 has GPIO 0..55; got {}", p);
129 }
130 }
131
132 #[test]
135 fn waveshare_pin_assignments_are_unique() {
136 let cfg = BoardConfig::WAVESHARE_P4_ETH;
137 let pins = [
138 cfg.rmii_pins.txd0,
139 cfg.rmii_pins.txd1,
140 cfg.rmii_pins.tx_en,
141 cfg.rmii_pins.rxd0,
142 cfg.rmii_pins.rxd1,
143 cfg.rmii_pins.crs_dv,
144 cfg.mdio_pins.mdc,
145 cfg.mdio_pins.mdio,
146 cfg.phy_reset.pin,
147 ];
148 let mut sorted = pins;
149 sorted.sort();
150 for w in sorted.windows(2) {
151 assert_ne!(w[0], w[1], "duplicate GPIO assignment in BoardConfig: {}", w[0]);
152 }
153 }
154}