diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-12-26 23:21:58 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-12-26 23:34:27 +0100 |
| commit | 1b6799d93f0bbd6154c124d51aa47aeed0acf15d (patch) | |
| tree | 1c8e206bcfcfd533355cde2b5533660ee940f86e /src | |
| parent | 076ada4c0233d2f89c89cda4c01910a86add90ac (diff) | |
split bus, consts into separate mods.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bus.rs | 321 | ||||
| -rw-r--r-- | src/consts.rs | 105 | ||||
| -rw-r--r-- | src/lib.rs | 536 |
3 files changed, 496 insertions, 466 deletions
diff --git a/src/bus.rs b/src/bus.rs new file mode 100644 index 000000000..f220cffcd --- /dev/null +++ b/src/bus.rs | |||
| @@ -0,0 +1,321 @@ | |||
| 1 | use core::slice; | ||
| 2 | |||
| 3 | use embassy_time::{Duration, Timer}; | ||
| 4 | use embedded_hal_1::digital::OutputPin; | ||
| 5 | use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; | ||
| 6 | |||
| 7 | use crate::consts::*; | ||
| 8 | |||
| 9 | pub(crate) struct Bus<PWR, SPI> { | ||
| 10 | backplane_window: u32, | ||
| 11 | pwr: PWR, | ||
| 12 | spi: SPI, | ||
| 13 | } | ||
| 14 | |||
| 15 | impl<PWR, SPI> Bus<PWR, SPI> | ||
| 16 | where | ||
| 17 | PWR: OutputPin, | ||
| 18 | SPI: SpiDevice, | ||
| 19 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, | ||
| 20 | { | ||
| 21 | pub(crate) fn new(pwr: PWR, spi: SPI) -> Self { | ||
| 22 | Self { | ||
| 23 | backplane_window: 0xAAAA_AAAA, | ||
| 24 | pwr, | ||
| 25 | spi, | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | pub async fn init(&mut self) { | ||
| 30 | // Reset | ||
| 31 | self.pwr.set_low().unwrap(); | ||
| 32 | Timer::after(Duration::from_millis(20)).await; | ||
| 33 | self.pwr.set_high().unwrap(); | ||
| 34 | Timer::after(Duration::from_millis(250)).await; | ||
| 35 | |||
| 36 | while self.read32_swapped(REG_BUS_TEST_RO).await != FEEDBEAD {} | ||
| 37 | |||
| 38 | self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; | ||
| 39 | let val = self.read32_swapped(REG_BUS_TEST_RW).await; | ||
| 40 | assert_eq!(val, TEST_PATTERN); | ||
| 41 | |||
| 42 | // 32-bit word length, little endian (which is the default endianess). | ||
| 43 | self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; | ||
| 44 | |||
| 45 | let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; | ||
| 46 | assert_eq!(val, FEEDBEAD); | ||
| 47 | let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; | ||
| 48 | assert_eq!(val, TEST_PATTERN); | ||
| 49 | } | ||
| 50 | |||
| 51 | pub async fn wlan_read(&mut self, buf: &mut [u32]) { | ||
| 52 | let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4); | ||
| 53 | transaction!(&mut self.spi, |bus| async { | ||
| 54 | bus.write(&[cmd]).await?; | ||
| 55 | bus.read(buf).await?; | ||
| 56 | Ok(()) | ||
| 57 | }) | ||
| 58 | .await | ||
| 59 | .unwrap(); | ||
| 60 | } | ||
| 61 | |||
| 62 | pub async fn wlan_write(&mut self, buf: &[u32]) { | ||
| 63 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4); | ||
| 64 | transaction!(&mut self.spi, |bus| async { | ||
| 65 | bus.write(&[cmd]).await?; | ||
| 66 | bus.write(buf).await?; | ||
| 67 | Ok(()) | ||
| 68 | }) | ||
| 69 | .await | ||
| 70 | .unwrap(); | ||
| 71 | } | ||
| 72 | |||
| 73 | #[allow(unused)] | ||
| 74 | pub async fn bp_read(&mut self, mut addr: u32, mut data: &mut [u8]) { | ||
| 75 | // It seems the HW force-aligns the addr | ||
| 76 | // to 2 if data.len() >= 2 | ||
| 77 | // to 4 if data.len() >= 4 | ||
| 78 | // To simplify, enforce 4-align for now. | ||
| 79 | assert!(addr % 4 == 0); | ||
| 80 | |||
| 81 | let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; | ||
| 82 | |||
| 83 | while !data.is_empty() { | ||
| 84 | // Ensure transfer doesn't cross a window boundary. | ||
| 85 | let window_offs = addr & BACKPLANE_ADDRESS_MASK; | ||
| 86 | let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; | ||
| 87 | |||
| 88 | let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); | ||
| 89 | |||
| 90 | self.backplane_set_window(addr).await; | ||
| 91 | |||
| 92 | let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); | ||
| 93 | |||
| 94 | transaction!(&mut self.spi, |bus| async { | ||
| 95 | bus.write(&[cmd]).await?; | ||
| 96 | |||
| 97 | // 4-byte response delay. | ||
| 98 | let mut junk = [0; 1]; | ||
| 99 | bus.read(&mut junk).await?; | ||
| 100 | |||
| 101 | // Read data | ||
| 102 | bus.read(&mut buf[..(len + 3) / 4]).await?; | ||
| 103 | Ok(()) | ||
| 104 | }) | ||
| 105 | .await | ||
| 106 | .unwrap(); | ||
| 107 | |||
| 108 | data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]); | ||
| 109 | |||
| 110 | // Advance ptr. | ||
| 111 | addr += len as u32; | ||
| 112 | data = &mut data[len..]; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | pub async fn bp_write(&mut self, mut addr: u32, mut data: &[u8]) { | ||
| 117 | // It seems the HW force-aligns the addr | ||
| 118 | // to 2 if data.len() >= 2 | ||
| 119 | // to 4 if data.len() >= 4 | ||
| 120 | // To simplify, enforce 4-align for now. | ||
| 121 | assert!(addr % 4 == 0); | ||
| 122 | |||
| 123 | let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; | ||
| 124 | |||
| 125 | while !data.is_empty() { | ||
| 126 | // Ensure transfer doesn't cross a window boundary. | ||
| 127 | let window_offs = addr & BACKPLANE_ADDRESS_MASK; | ||
| 128 | let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; | ||
| 129 | |||
| 130 | let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); | ||
| 131 | slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); | ||
| 132 | |||
| 133 | self.backplane_set_window(addr).await; | ||
| 134 | |||
| 135 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); | ||
| 136 | |||
| 137 | transaction!(&mut self.spi, |bus| async { | ||
| 138 | bus.write(&[cmd]).await?; | ||
| 139 | bus.write(&buf[..(len + 3) / 4]).await?; | ||
| 140 | Ok(()) | ||
| 141 | }) | ||
| 142 | .await | ||
| 143 | .unwrap(); | ||
| 144 | |||
| 145 | // Advance ptr. | ||
| 146 | addr += len as u32; | ||
| 147 | data = &data[len..]; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | pub async fn bp_read8(&mut self, addr: u32) -> u8 { | ||
| 152 | self.backplane_readn(addr, 1).await as u8 | ||
| 153 | } | ||
| 154 | |||
| 155 | pub async fn bp_write8(&mut self, addr: u32, val: u8) { | ||
| 156 | self.backplane_writen(addr, val as u32, 1).await | ||
| 157 | } | ||
| 158 | |||
| 159 | pub async fn bp_read16(&mut self, addr: u32) -> u16 { | ||
| 160 | self.backplane_readn(addr, 2).await as u16 | ||
| 161 | } | ||
| 162 | |||
| 163 | #[allow(unused)] | ||
| 164 | pub async fn bp_write16(&mut self, addr: u32, val: u16) { | ||
| 165 | self.backplane_writen(addr, val as u32, 2).await | ||
| 166 | } | ||
| 167 | |||
| 168 | #[allow(unused)] | ||
| 169 | pub async fn bp_read32(&mut self, addr: u32) -> u32 { | ||
| 170 | self.backplane_readn(addr, 4).await | ||
| 171 | } | ||
| 172 | |||
| 173 | pub async fn bp_write32(&mut self, addr: u32, val: u32) { | ||
| 174 | self.backplane_writen(addr, val, 4).await | ||
| 175 | } | ||
| 176 | |||
| 177 | async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { | ||
| 178 | self.backplane_set_window(addr).await; | ||
| 179 | |||
| 180 | let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||
| 181 | if len == 4 { | ||
| 182 | bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG | ||
| 183 | } | ||
| 184 | self.readn(FUNC_BACKPLANE, bus_addr, len).await | ||
| 185 | } | ||
| 186 | |||
| 187 | async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { | ||
| 188 | self.backplane_set_window(addr).await; | ||
| 189 | |||
| 190 | let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||
| 191 | if len == 4 { | ||
| 192 | bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG | ||
| 193 | } | ||
| 194 | self.writen(FUNC_BACKPLANE, bus_addr, val, len).await | ||
| 195 | } | ||
| 196 | |||
| 197 | async fn backplane_set_window(&mut self, addr: u32) { | ||
| 198 | let new_window = addr & !BACKPLANE_ADDRESS_MASK; | ||
| 199 | |||
| 200 | if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { | ||
| 201 | self.write8( | ||
| 202 | FUNC_BACKPLANE, | ||
| 203 | REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH, | ||
| 204 | (new_window >> 24) as u8, | ||
| 205 | ) | ||
| 206 | .await; | ||
| 207 | } | ||
| 208 | if (new_window >> 16) as u8 != (self.backplane_window >> 16) as u8 { | ||
| 209 | self.write8( | ||
| 210 | FUNC_BACKPLANE, | ||
| 211 | REG_BACKPLANE_BACKPLANE_ADDRESS_MID, | ||
| 212 | (new_window >> 16) as u8, | ||
| 213 | ) | ||
| 214 | .await; | ||
| 215 | } | ||
| 216 | if (new_window >> 8) as u8 != (self.backplane_window >> 8) as u8 { | ||
| 217 | self.write8( | ||
| 218 | FUNC_BACKPLANE, | ||
| 219 | REG_BACKPLANE_BACKPLANE_ADDRESS_LOW, | ||
| 220 | (new_window >> 8) as u8, | ||
| 221 | ) | ||
| 222 | .await; | ||
| 223 | } | ||
| 224 | self.backplane_window = new_window; | ||
| 225 | } | ||
| 226 | |||
| 227 | pub async fn read8(&mut self, func: u32, addr: u32) -> u8 { | ||
| 228 | self.readn(func, addr, 1).await as u8 | ||
| 229 | } | ||
| 230 | |||
| 231 | pub async fn write8(&mut self, func: u32, addr: u32, val: u8) { | ||
| 232 | self.writen(func, addr, val as u32, 1).await | ||
| 233 | } | ||
| 234 | |||
| 235 | pub async fn read16(&mut self, func: u32, addr: u32) -> u16 { | ||
| 236 | self.readn(func, addr, 2).await as u16 | ||
| 237 | } | ||
| 238 | |||
| 239 | #[allow(unused)] | ||
| 240 | pub async fn write16(&mut self, func: u32, addr: u32, val: u16) { | ||
| 241 | self.writen(func, addr, val as u32, 2).await | ||
| 242 | } | ||
| 243 | |||
| 244 | pub async fn read32(&mut self, func: u32, addr: u32) -> u32 { | ||
| 245 | self.readn(func, addr, 4).await | ||
| 246 | } | ||
| 247 | |||
| 248 | #[allow(unused)] | ||
| 249 | pub async fn write32(&mut self, func: u32, addr: u32, val: u32) { | ||
| 250 | self.writen(func, addr, val, 4).await | ||
| 251 | } | ||
| 252 | |||
| 253 | async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { | ||
| 254 | let cmd = cmd_word(READ, INC_ADDR, func, addr, len); | ||
| 255 | let mut buf = [0; 1]; | ||
| 256 | |||
| 257 | transaction!(&mut self.spi, |bus| async { | ||
| 258 | bus.write(&[cmd]).await?; | ||
| 259 | if func == FUNC_BACKPLANE { | ||
| 260 | // 4-byte response delay. | ||
| 261 | bus.read(&mut buf).await?; | ||
| 262 | } | ||
| 263 | bus.read(&mut buf).await?; | ||
| 264 | Ok(()) | ||
| 265 | }) | ||
| 266 | .await | ||
| 267 | .unwrap(); | ||
| 268 | |||
| 269 | buf[0] | ||
| 270 | } | ||
| 271 | |||
| 272 | async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { | ||
| 273 | let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); | ||
| 274 | |||
| 275 | transaction!(&mut self.spi, |bus| async { | ||
| 276 | bus.write(&[cmd, val]).await?; | ||
| 277 | Ok(()) | ||
| 278 | }) | ||
| 279 | .await | ||
| 280 | .unwrap(); | ||
| 281 | } | ||
| 282 | |||
| 283 | async fn read32_swapped(&mut self, addr: u32) -> u32 { | ||
| 284 | let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); | ||
| 285 | let mut buf = [0; 1]; | ||
| 286 | |||
| 287 | transaction!(&mut self.spi, |bus| async { | ||
| 288 | bus.write(&[swap16(cmd)]).await?; | ||
| 289 | bus.read(&mut buf).await?; | ||
| 290 | Ok(()) | ||
| 291 | }) | ||
| 292 | .await | ||
| 293 | .unwrap(); | ||
| 294 | |||
| 295 | swap16(buf[0]) | ||
| 296 | } | ||
| 297 | |||
| 298 | async fn write32_swapped(&mut self, addr: u32, val: u32) { | ||
| 299 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); | ||
| 300 | |||
| 301 | transaction!(&mut self.spi, |bus| async { | ||
| 302 | bus.write(&[swap16(cmd), swap16(val)]).await?; | ||
| 303 | Ok(()) | ||
| 304 | }) | ||
| 305 | .await | ||
| 306 | .unwrap(); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | fn swap16(x: u32) -> u32 { | ||
| 311 | x.rotate_left(16) | ||
| 312 | } | ||
| 313 | |||
| 314 | fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 { | ||
| 315 | (write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF) | ||
| 316 | } | ||
| 317 | |||
| 318 | fn slice8_mut(x: &mut [u32]) -> &mut [u8] { | ||
| 319 | let len = x.len() * 4; | ||
| 320 | unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } | ||
| 321 | } | ||
diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 000000000..bee706600 --- /dev/null +++ b/src/consts.rs | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | #![allow(unused)] | ||
| 2 | pub(crate) const FUNC_BUS: u32 = 0; | ||
| 3 | pub(crate) const FUNC_BACKPLANE: u32 = 1; | ||
| 4 | pub(crate) const FUNC_WLAN: u32 = 2; | ||
| 5 | pub(crate) const FUNC_BT: u32 = 3; | ||
| 6 | |||
| 7 | pub(crate) const REG_BUS_CTRL: u32 = 0x0; | ||
| 8 | pub(crate) const REG_BUS_INTERRUPT: u32 = 0x04; // 16 bits - Interrupt status | ||
| 9 | pub(crate) const REG_BUS_INTERRUPT_ENABLE: u32 = 0x06; // 16 bits - Interrupt mask | ||
| 10 | pub(crate) const REG_BUS_STATUS: u32 = 0x8; | ||
| 11 | pub(crate) const REG_BUS_TEST_RO: u32 = 0x14; | ||
| 12 | pub(crate) const REG_BUS_TEST_RW: u32 = 0x18; | ||
| 13 | pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c; | ||
| 14 | pub(crate) const WORD_LENGTH_32: u32 = 0x1; | ||
| 15 | pub(crate) const HIGH_SPEED: u32 = 0x10; | ||
| 16 | |||
| 17 | // SPI_STATUS_REGISTER bits | ||
| 18 | pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; | ||
| 19 | pub(crate) const STATUS_UNDERFLOW: u32 = 0x00000002; | ||
| 20 | pub(crate) const STATUS_OVERFLOW: u32 = 0x00000004; | ||
| 21 | pub(crate) const STATUS_F2_INTR: u32 = 0x00000008; | ||
| 22 | pub(crate) const STATUS_F3_INTR: u32 = 0x00000010; | ||
| 23 | pub(crate) const STATUS_F2_RX_READY: u32 = 0x00000020; | ||
| 24 | pub(crate) const STATUS_F3_RX_READY: u32 = 0x00000040; | ||
| 25 | pub(crate) const STATUS_HOST_CMD_DATA_ERR: u32 = 0x00000080; | ||
| 26 | pub(crate) const STATUS_F2_PKT_AVAILABLE: u32 = 0x00000100; | ||
| 27 | pub(crate) const STATUS_F2_PKT_LEN_MASK: u32 = 0x000FFE00; | ||
| 28 | pub(crate) const STATUS_F2_PKT_LEN_SHIFT: u32 = 9; | ||
| 29 | pub(crate) const STATUS_F3_PKT_AVAILABLE: u32 = 0x00100000; | ||
| 30 | pub(crate) const STATUS_F3_PKT_LEN_MASK: u32 = 0xFFE00000; | ||
| 31 | pub(crate) const STATUS_F3_PKT_LEN_SHIFT: u32 = 21; | ||
| 32 | |||
| 33 | pub(crate) const REG_BACKPLANE_GPIO_SELECT: u32 = 0x10005; | ||
| 34 | pub(crate) const REG_BACKPLANE_GPIO_OUTPUT: u32 = 0x10006; | ||
| 35 | pub(crate) const REG_BACKPLANE_GPIO_ENABLE: u32 = 0x10007; | ||
| 36 | pub(crate) const REG_BACKPLANE_FUNCTION2_WATERMARK: u32 = 0x10008; | ||
| 37 | pub(crate) const REG_BACKPLANE_DEVICE_CONTROL: u32 = 0x10009; | ||
| 38 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_LOW: u32 = 0x1000A; | ||
| 39 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_MID: u32 = 0x1000B; | ||
| 40 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH: u32 = 0x1000C; | ||
| 41 | pub(crate) const REG_BACKPLANE_FRAME_CONTROL: u32 = 0x1000D; | ||
| 42 | pub(crate) const REG_BACKPLANE_CHIP_CLOCK_CSR: u32 = 0x1000E; | ||
| 43 | pub(crate) const REG_BACKPLANE_PULL_UP: u32 = 0x1000F; | ||
| 44 | pub(crate) const REG_BACKPLANE_READ_FRAME_BC_LOW: u32 = 0x1001B; | ||
| 45 | pub(crate) const REG_BACKPLANE_READ_FRAME_BC_HIGH: u32 = 0x1001C; | ||
| 46 | pub(crate) const REG_BACKPLANE_WAKEUP_CTRL: u32 = 0x1001E; | ||
| 47 | pub(crate) const REG_BACKPLANE_SLEEP_CSR: u32 = 0x1001F; | ||
| 48 | |||
| 49 | pub(crate) const BACKPLANE_WINDOW_SIZE: usize = 0x8000; | ||
| 50 | pub(crate) const BACKPLANE_ADDRESS_MASK: u32 = 0x7FFF; | ||
| 51 | pub(crate) const BACKPLANE_ADDRESS_32BIT_FLAG: u32 = 0x08000; | ||
| 52 | pub(crate) const BACKPLANE_MAX_TRANSFER_SIZE: usize = 64; | ||
| 53 | // Active Low Power (ALP) clock constants | ||
| 54 | pub(crate) const BACKPLANE_ALP_AVAIL_REQ: u8 = 0x08; | ||
| 55 | pub(crate) const BACKPLANE_ALP_AVAIL: u8 = 0x40; | ||
| 56 | |||
| 57 | // Broadcom AMBA (Advanced Microcontroller Bus Architecture) Interconnect | ||
| 58 | // (AI) pub (crate) constants | ||
| 59 | pub(crate) const AI_IOCTRL_OFFSET: u32 = 0x408; | ||
| 60 | pub(crate) const AI_IOCTRL_BIT_FGC: u8 = 0x0002; | ||
| 61 | pub(crate) const AI_IOCTRL_BIT_CLOCK_EN: u8 = 0x0001; | ||
| 62 | pub(crate) const AI_IOCTRL_BIT_CPUHALT: u8 = 0x0020; | ||
| 63 | |||
| 64 | pub(crate) const AI_RESETCTRL_OFFSET: u32 = 0x800; | ||
| 65 | pub(crate) const AI_RESETCTRL_BIT_RESET: u8 = 1; | ||
| 66 | |||
| 67 | pub(crate) const AI_RESETSTATUS_OFFSET: u32 = 0x804; | ||
| 68 | |||
| 69 | pub(crate) const TEST_PATTERN: u32 = 0x12345678; | ||
| 70 | pub(crate) const FEEDBEAD: u32 = 0xFEEDBEAD; | ||
| 71 | |||
| 72 | // SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits | ||
| 73 | pub(crate) const IRQ_DATA_UNAVAILABLE: u16 = 0x0001; // Requested data not available; Clear by writing a "1" | ||
| 74 | pub(crate) const IRQ_F2_F3_FIFO_RD_UNDERFLOW: u16 = 0x0002; | ||
| 75 | pub(crate) const IRQ_F2_F3_FIFO_WR_OVERFLOW: u16 = 0x0004; | ||
| 76 | pub(crate) const IRQ_COMMAND_ERROR: u16 = 0x0008; // Cleared by writing 1 | ||
| 77 | pub(crate) const IRQ_DATA_ERROR: u16 = 0x0010; // Cleared by writing 1 | ||
| 78 | pub(crate) const IRQ_F2_PACKET_AVAILABLE: u16 = 0x0020; | ||
| 79 | pub(crate) const IRQ_F3_PACKET_AVAILABLE: u16 = 0x0040; | ||
| 80 | pub(crate) const IRQ_F1_OVERFLOW: u16 = 0x0080; // Due to last write. Bkplane has pending write requests | ||
| 81 | pub(crate) const IRQ_MISC_INTR0: u16 = 0x0100; | ||
| 82 | pub(crate) const IRQ_MISC_INTR1: u16 = 0x0200; | ||
| 83 | pub(crate) const IRQ_MISC_INTR2: u16 = 0x0400; | ||
| 84 | pub(crate) const IRQ_MISC_INTR3: u16 = 0x0800; | ||
| 85 | pub(crate) const IRQ_MISC_INTR4: u16 = 0x1000; | ||
| 86 | pub(crate) const IRQ_F1_INTR: u16 = 0x2000; | ||
| 87 | pub(crate) const IRQ_F2_INTR: u16 = 0x4000; | ||
| 88 | pub(crate) const IRQ_F3_INTR: u16 = 0x8000; | ||
| 89 | |||
| 90 | pub(crate) const IOCTL_CMD_UP: u32 = 2; | ||
| 91 | pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26; | ||
| 92 | pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64; | ||
| 93 | pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263; | ||
| 94 | pub(crate) const IOCTL_CMD_GET_VAR: u32 = 262; | ||
| 95 | pub(crate) const IOCTL_CMD_SET_PASSPHRASE: u32 = 268; | ||
| 96 | |||
| 97 | pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0; | ||
| 98 | pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1; | ||
| 99 | pub(crate) const CHANNEL_TYPE_DATA: u8 = 2; | ||
| 100 | |||
| 101 | // CYW_SPID command structure constants. | ||
| 102 | pub(crate) const WRITE: bool = true; | ||
| 103 | pub(crate) const READ: bool = false; | ||
| 104 | pub(crate) const INC_ADDR: bool = true; | ||
| 105 | pub(crate) const FIXED_ADDR: bool = false; | ||
diff --git a/src/lib.rs b/src/lib.rs index 883e669de..fa73b32e0 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | // This mod MUST go first, so that the others see its macros. | 6 | // This mod MUST go first, so that the others see its macros. |
| 7 | pub(crate) mod fmt; | 7 | pub(crate) mod fmt; |
| 8 | 8 | ||
| 9 | mod bus; | ||
| 10 | mod consts; | ||
| 9 | mod countries; | 11 | mod countries; |
| 10 | mod events; | 12 | mod events; |
| 11 | mod structs; | 13 | mod structs; |
| @@ -23,132 +25,12 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; | |||
| 23 | use embassy_sync::channel::Channel; | 25 | use embassy_sync::channel::Channel; |
| 24 | use embassy_time::{block_for, Duration, Timer}; | 26 | use embassy_time::{block_for, Duration, Timer}; |
| 25 | use embedded_hal_1::digital::OutputPin; | 27 | use embedded_hal_1::digital::OutputPin; |
| 26 | use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; | 28 | use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice}; |
| 27 | 29 | ||
| 28 | use self::structs::*; | 30 | use crate::bus::Bus; |
| 31 | use crate::consts::*; | ||
| 29 | use crate::events::Event; | 32 | use crate::events::Event; |
| 30 | 33 | use crate::structs::*; | |
| 31 | fn swap16(x: u32) -> u32 { | ||
| 32 | x.rotate_left(16) | ||
| 33 | } | ||
| 34 | |||
| 35 | fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 { | ||
| 36 | (write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF) | ||
| 37 | } | ||
| 38 | |||
| 39 | fn slice8_mut(x: &mut [u32]) -> &mut [u8] { | ||
| 40 | let len = x.len() * 4; | ||
| 41 | unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } | ||
| 42 | } | ||
| 43 | |||
| 44 | mod constants { | ||
| 45 | #![allow(unused)] | ||
| 46 | pub(crate) const FUNC_BUS: u32 = 0; | ||
| 47 | pub(crate) const FUNC_BACKPLANE: u32 = 1; | ||
| 48 | pub(crate) const FUNC_WLAN: u32 = 2; | ||
| 49 | pub(crate) const FUNC_BT: u32 = 3; | ||
| 50 | |||
| 51 | pub(crate) const REG_BUS_CTRL: u32 = 0x0; | ||
| 52 | pub(crate) const REG_BUS_INTERRUPT: u32 = 0x04; // 16 bits - Interrupt status | ||
| 53 | pub(crate) const REG_BUS_INTERRUPT_ENABLE: u32 = 0x06; // 16 bits - Interrupt mask | ||
| 54 | pub(crate) const REG_BUS_STATUS: u32 = 0x8; | ||
| 55 | pub(crate) const REG_BUS_TEST_RO: u32 = 0x14; | ||
| 56 | pub(crate) const REG_BUS_TEST_RW: u32 = 0x18; | ||
| 57 | pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c; | ||
| 58 | pub(crate) const WORD_LENGTH_32: u32 = 0x1; | ||
| 59 | pub(crate) const HIGH_SPEED: u32 = 0x10; | ||
| 60 | |||
| 61 | // SPI_STATUS_REGISTER bits | ||
| 62 | pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; | ||
| 63 | pub(crate) const STATUS_UNDERFLOW: u32 = 0x00000002; | ||
| 64 | pub(crate) const STATUS_OVERFLOW: u32 = 0x00000004; | ||
| 65 | pub(crate) const STATUS_F2_INTR: u32 = 0x00000008; | ||
| 66 | pub(crate) const STATUS_F3_INTR: u32 = 0x00000010; | ||
| 67 | pub(crate) const STATUS_F2_RX_READY: u32 = 0x00000020; | ||
| 68 | pub(crate) const STATUS_F3_RX_READY: u32 = 0x00000040; | ||
| 69 | pub(crate) const STATUS_HOST_CMD_DATA_ERR: u32 = 0x00000080; | ||
| 70 | pub(crate) const STATUS_F2_PKT_AVAILABLE: u32 = 0x00000100; | ||
| 71 | pub(crate) const STATUS_F2_PKT_LEN_MASK: u32 = 0x000FFE00; | ||
| 72 | pub(crate) const STATUS_F2_PKT_LEN_SHIFT: u32 = 9; | ||
| 73 | pub(crate) const STATUS_F3_PKT_AVAILABLE: u32 = 0x00100000; | ||
| 74 | pub(crate) const STATUS_F3_PKT_LEN_MASK: u32 = 0xFFE00000; | ||
| 75 | pub(crate) const STATUS_F3_PKT_LEN_SHIFT: u32 = 21; | ||
| 76 | |||
| 77 | pub(crate) const REG_BACKPLANE_GPIO_SELECT: u32 = 0x10005; | ||
| 78 | pub(crate) const REG_BACKPLANE_GPIO_OUTPUT: u32 = 0x10006; | ||
| 79 | pub(crate) const REG_BACKPLANE_GPIO_ENABLE: u32 = 0x10007; | ||
| 80 | pub(crate) const REG_BACKPLANE_FUNCTION2_WATERMARK: u32 = 0x10008; | ||
| 81 | pub(crate) const REG_BACKPLANE_DEVICE_CONTROL: u32 = 0x10009; | ||
| 82 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_LOW: u32 = 0x1000A; | ||
| 83 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_MID: u32 = 0x1000B; | ||
| 84 | pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH: u32 = 0x1000C; | ||
| 85 | pub(crate) const REG_BACKPLANE_FRAME_CONTROL: u32 = 0x1000D; | ||
| 86 | pub(crate) const REG_BACKPLANE_CHIP_CLOCK_CSR: u32 = 0x1000E; | ||
| 87 | pub(crate) const REG_BACKPLANE_PULL_UP: u32 = 0x1000F; | ||
| 88 | pub(crate) const REG_BACKPLANE_READ_FRAME_BC_LOW: u32 = 0x1001B; | ||
| 89 | pub(crate) const REG_BACKPLANE_READ_FRAME_BC_HIGH: u32 = 0x1001C; | ||
| 90 | pub(crate) const REG_BACKPLANE_WAKEUP_CTRL: u32 = 0x1001E; | ||
| 91 | pub(crate) const REG_BACKPLANE_SLEEP_CSR: u32 = 0x1001F; | ||
| 92 | |||
| 93 | pub(crate) const BACKPLANE_WINDOW_SIZE: usize = 0x8000; | ||
| 94 | pub(crate) const BACKPLANE_ADDRESS_MASK: u32 = 0x7FFF; | ||
| 95 | pub(crate) const BACKPLANE_ADDRESS_32BIT_FLAG: u32 = 0x08000; | ||
| 96 | pub(crate) const BACKPLANE_MAX_TRANSFER_SIZE: usize = 64; | ||
| 97 | // Active Low Power (ALP) clock constants | ||
| 98 | pub(crate) const BACKPLANE_ALP_AVAIL_REQ: u8 = 0x08; | ||
| 99 | pub(crate) const BACKPLANE_ALP_AVAIL: u8 = 0x40; | ||
| 100 | |||
| 101 | // Broadcom AMBA (Advanced Microcontroller Bus Architecture) Interconnect | ||
| 102 | // (AI) pub (crate) constants | ||
| 103 | pub(crate) const AI_IOCTRL_OFFSET: u32 = 0x408; | ||
| 104 | pub(crate) const AI_IOCTRL_BIT_FGC: u8 = 0x0002; | ||
| 105 | pub(crate) const AI_IOCTRL_BIT_CLOCK_EN: u8 = 0x0001; | ||
| 106 | pub(crate) const AI_IOCTRL_BIT_CPUHALT: u8 = 0x0020; | ||
| 107 | |||
| 108 | pub(crate) const AI_RESETCTRL_OFFSET: u32 = 0x800; | ||
| 109 | pub(crate) const AI_RESETCTRL_BIT_RESET: u8 = 1; | ||
| 110 | |||
| 111 | pub(crate) const AI_RESETSTATUS_OFFSET: u32 = 0x804; | ||
| 112 | |||
| 113 | pub(crate) const TEST_PATTERN: u32 = 0x12345678; | ||
| 114 | pub(crate) const FEEDBEAD: u32 = 0xFEEDBEAD; | ||
| 115 | |||
| 116 | // SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits | ||
| 117 | pub(crate) const IRQ_DATA_UNAVAILABLE: u16 = 0x0001; // Requested data not available; Clear by writing a "1" | ||
| 118 | pub(crate) const IRQ_F2_F3_FIFO_RD_UNDERFLOW: u16 = 0x0002; | ||
| 119 | pub(crate) const IRQ_F2_F3_FIFO_WR_OVERFLOW: u16 = 0x0004; | ||
| 120 | pub(crate) const IRQ_COMMAND_ERROR: u16 = 0x0008; // Cleared by writing 1 | ||
| 121 | pub(crate) const IRQ_DATA_ERROR: u16 = 0x0010; // Cleared by writing 1 | ||
| 122 | pub(crate) const IRQ_F2_PACKET_AVAILABLE: u16 = 0x0020; | ||
| 123 | pub(crate) const IRQ_F3_PACKET_AVAILABLE: u16 = 0x0040; | ||
| 124 | pub(crate) const IRQ_F1_OVERFLOW: u16 = 0x0080; // Due to last write. Bkplane has pending write requests | ||
| 125 | pub(crate) const IRQ_MISC_INTR0: u16 = 0x0100; | ||
| 126 | pub(crate) const IRQ_MISC_INTR1: u16 = 0x0200; | ||
| 127 | pub(crate) const IRQ_MISC_INTR2: u16 = 0x0400; | ||
| 128 | pub(crate) const IRQ_MISC_INTR3: u16 = 0x0800; | ||
| 129 | pub(crate) const IRQ_MISC_INTR4: u16 = 0x1000; | ||
| 130 | pub(crate) const IRQ_F1_INTR: u16 = 0x2000; | ||
| 131 | pub(crate) const IRQ_F2_INTR: u16 = 0x4000; | ||
| 132 | pub(crate) const IRQ_F3_INTR: u16 = 0x8000; | ||
| 133 | |||
| 134 | pub(crate) const IOCTL_CMD_UP: u32 = 2; | ||
| 135 | pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26; | ||
| 136 | pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64; | ||
| 137 | pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263; | ||
| 138 | pub(crate) const IOCTL_CMD_GET_VAR: u32 = 262; | ||
| 139 | pub(crate) const IOCTL_CMD_SET_PASSPHRASE: u32 = 268; | ||
| 140 | |||
| 141 | pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0; | ||
| 142 | pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1; | ||
| 143 | pub(crate) const CHANNEL_TYPE_DATA: u8 = 2; | ||
| 144 | |||
| 145 | // CYW_SPID command structure constants. | ||
| 146 | pub(crate) const WRITE: bool = true; | ||
| 147 | pub(crate) const READ: bool = false; | ||
| 148 | pub(crate) const INC_ADDR: bool = true; | ||
| 149 | pub(crate) const FIXED_ADDR: bool = false; | ||
| 150 | } | ||
| 151 | use crate::constants::*; | ||
| 152 | 34 | ||
| 153 | #[derive(Clone, Copy)] | 35 | #[derive(Clone, Copy)] |
| 154 | pub enum IoctlType { | 36 | pub enum IoctlType { |
| @@ -565,15 +447,11 @@ impl<'a> embassy_net::Device for NetDevice<'a> { | |||
| 565 | } | 447 | } |
| 566 | 448 | ||
| 567 | pub struct Runner<'a, PWR, SPI> { | 449 | pub struct Runner<'a, PWR, SPI> { |
| 568 | state: &'a State, | 450 | bus: Bus<PWR, SPI>, |
| 569 | |||
| 570 | pwr: PWR, | ||
| 571 | spi: SPI, | ||
| 572 | 451 | ||
| 452 | state: &'a State, | ||
| 573 | ioctl_id: u16, | 453 | ioctl_id: u16, |
| 574 | sdpcm_seq: u8, | 454 | sdpcm_seq: u8, |
| 575 | backplane_window: u32, | ||
| 576 | |||
| 577 | sdpcm_seq_max: u8, | 455 | sdpcm_seq_max: u8, |
| 578 | 456 | ||
| 579 | #[cfg(feature = "firmware-logs")] | 457 | #[cfg(feature = "firmware-logs")] |
| @@ -600,14 +478,11 @@ where | |||
| 600 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, | 478 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, |
| 601 | { | 479 | { |
| 602 | let mut runner = Runner { | 480 | let mut runner = Runner { |
| 603 | state, | 481 | bus: Bus::new(pwr, spi), |
| 604 | pwr, | ||
| 605 | spi, | ||
| 606 | 482 | ||
| 483 | state, | ||
| 607 | ioctl_id: 0, | 484 | ioctl_id: 0, |
| 608 | sdpcm_seq: 0, | 485 | sdpcm_seq: 0, |
| 609 | backplane_window: 0xAAAA_AAAA, | ||
| 610 | |||
| 611 | sdpcm_seq_max: 1, | 486 | sdpcm_seq_max: 1, |
| 612 | 487 | ||
| 613 | #[cfg(feature = "firmware-logs")] | 488 | #[cfg(feature = "firmware-logs")] |
| @@ -631,62 +506,41 @@ where | |||
| 631 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, | 506 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, |
| 632 | { | 507 | { |
| 633 | async fn init(&mut self, firmware: &[u8]) { | 508 | async fn init(&mut self, firmware: &[u8]) { |
| 634 | // Reset | 509 | self.bus.init().await; |
| 635 | self.pwr.set_low().unwrap(); | ||
| 636 | Timer::after(Duration::from_millis(20)).await; | ||
| 637 | self.pwr.set_high().unwrap(); | ||
| 638 | Timer::after(Duration::from_millis(250)).await; | ||
| 639 | |||
| 640 | info!("waiting for ping..."); | ||
| 641 | while self.read32_swapped(REG_BUS_TEST_RO).await != FEEDBEAD {} | ||
| 642 | info!("ping ok"); | ||
| 643 | |||
| 644 | self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; | ||
| 645 | let val = self.read32_swapped(REG_BUS_TEST_RW).await; | ||
| 646 | assert_eq!(val, TEST_PATTERN); | ||
| 647 | |||
| 648 | // 32-bit word length, little endian (which is the default endianess). | ||
| 649 | self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; | ||
| 650 | |||
| 651 | let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; | ||
| 652 | assert_eq!(val, FEEDBEAD); | ||
| 653 | let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; | ||
| 654 | assert_eq!(val, TEST_PATTERN); | ||
| 655 | |||
| 656 | // No response delay in any of the funcs. | ||
| 657 | // seems to break backplane??? eat the 4-byte delay instead, that's what the vendor drivers do... | ||
| 658 | //self.write32(FUNC_BUS, REG_BUS_RESP_DELAY, 0).await; | ||
| 659 | 510 | ||
| 660 | // Init ALP (Active Low Power) clock | 511 | // Init ALP (Active Low Power) clock |
| 661 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ) | 512 | self.bus |
| 513 | .write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ) | ||
| 662 | .await; | 514 | .await; |
| 663 | info!("waiting for clock..."); | 515 | info!("waiting for clock..."); |
| 664 | while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {} | 516 | while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {} |
| 665 | info!("clock ok"); | 517 | info!("clock ok"); |
| 666 | 518 | ||
| 667 | let chip_id = self.bp_read16(0x1800_0000).await; | 519 | let chip_id = self.bus.bp_read16(0x1800_0000).await; |
| 668 | info!("chip ID: {}", chip_id); | 520 | info!("chip ID: {}", chip_id); |
| 669 | 521 | ||
| 670 | // Upload firmware. | 522 | // Upload firmware. |
| 671 | self.core_disable(Core::WLAN).await; | 523 | self.core_disable(Core::WLAN).await; |
| 672 | self.core_reset(Core::SOCSRAM).await; | 524 | self.core_reset(Core::SOCSRAM).await; |
| 673 | self.bp_write32(CHIP.socsram_base_address + 0x10, 3).await; | 525 | self.bus.bp_write32(CHIP.socsram_base_address + 0x10, 3).await; |
| 674 | self.bp_write32(CHIP.socsram_base_address + 0x44, 0).await; | 526 | self.bus.bp_write32(CHIP.socsram_base_address + 0x44, 0).await; |
| 675 | 527 | ||
| 676 | let ram_addr = CHIP.atcm_ram_base_address; | 528 | let ram_addr = CHIP.atcm_ram_base_address; |
| 677 | 529 | ||
| 678 | info!("loading fw"); | 530 | info!("loading fw"); |
| 679 | self.bp_write(ram_addr, firmware).await; | 531 | self.bus.bp_write(ram_addr, firmware).await; |
| 680 | 532 | ||
| 681 | info!("loading nvram"); | 533 | info!("loading nvram"); |
| 682 | // Round up to 4 bytes. | 534 | // Round up to 4 bytes. |
| 683 | let nvram_len = (NVRAM.len() + 3) / 4 * 4; | 535 | let nvram_len = (NVRAM.len() + 3) / 4 * 4; |
| 684 | self.bp_write(ram_addr + CHIP.chip_ram_size - 4 - nvram_len as u32, NVRAM) | 536 | self.bus |
| 537 | .bp_write(ram_addr + CHIP.chip_ram_size - 4 - nvram_len as u32, NVRAM) | ||
| 685 | .await; | 538 | .await; |
| 686 | 539 | ||
| 687 | let nvram_len_words = nvram_len as u32 / 4; | 540 | let nvram_len_words = nvram_len as u32 / 4; |
| 688 | let nvram_len_magic = (!nvram_len_words << 16) | nvram_len_words; | 541 | let nvram_len_magic = (!nvram_len_words << 16) | nvram_len_words; |
| 689 | self.bp_write32(ram_addr + CHIP.chip_ram_size - 4, nvram_len_magic) | 542 | self.bus |
| 543 | .bp_write32(ram_addr + CHIP.chip_ram_size - 4, nvram_len_magic) | ||
| 690 | .await; | 544 | .await; |
| 691 | 545 | ||
| 692 | // Start core! | 546 | // Start core! |
| @@ -694,18 +548,20 @@ where | |||
| 694 | self.core_reset(Core::WLAN).await; | 548 | self.core_reset(Core::WLAN).await; |
| 695 | assert!(self.core_is_up(Core::WLAN).await); | 549 | assert!(self.core_is_up(Core::WLAN).await); |
| 696 | 550 | ||
| 697 | while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} | 551 | while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} |
| 698 | 552 | ||
| 699 | // "Set up the interrupt mask and enable interrupts" | 553 | // "Set up the interrupt mask and enable interrupts" |
| 700 | self.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; | 554 | self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; |
| 701 | 555 | ||
| 702 | // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." | 556 | // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." |
| 703 | // Sounds scary... | 557 | // Sounds scary... |
| 704 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32).await; | 558 | self.bus |
| 559 | .write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32) | ||
| 560 | .await; | ||
| 705 | 561 | ||
| 706 | // wait for wifi startup | 562 | // wait for wifi startup |
| 707 | info!("waiting for wifi init..."); | 563 | info!("waiting for wifi init..."); |
| 708 | while self.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {} | 564 | while self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {} |
| 709 | 565 | ||
| 710 | // Some random configs related to sleep. | 566 | // Some random configs related to sleep. |
| 711 | // These aren't needed if we don't want to sleep the bus. | 567 | // These aren't needed if we don't want to sleep the bus. |
| @@ -713,25 +569,25 @@ where | |||
| 713 | // being on the same pin as MOSI/MISO? | 569 | // being on the same pin as MOSI/MISO? |
| 714 | 570 | ||
| 715 | /* | 571 | /* |
| 716 | let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL).await; | 572 | let mut val = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL).await; |
| 717 | val |= 0x02; // WAKE_TILL_HT_AVAIL | 573 | val |= 0x02; // WAKE_TILL_HT_AVAIL |
| 718 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL, val).await; | 574 | self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL, val).await; |
| 719 | self.write8(FUNC_BUS, 0xF0, 0x08).await; // SDIOD_CCCR_BRCM_CARDCAP.CMD_NODEC = 1 | 575 | self.bus.write8(FUNC_BUS, 0xF0, 0x08).await; // SDIOD_CCCR_BRCM_CARDCAP.CMD_NODEC = 1 |
| 720 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x02).await; // SBSDIO_FORCE_HT | 576 | self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x02).await; // SBSDIO_FORCE_HT |
| 721 | 577 | ||
| 722 | let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR).await; | 578 | let mut val = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR).await; |
| 723 | val |= 0x01; // SBSDIO_SLPCSR_KEEP_SDIO_ON | 579 | val |= 0x01; // SBSDIO_SLPCSR_KEEP_SDIO_ON |
| 724 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR, val).await; | 580 | self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR, val).await; |
| 725 | */ | 581 | */ |
| 726 | 582 | ||
| 727 | // clear pulls | 583 | // clear pulls |
| 728 | self.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await; | 584 | self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await; |
| 729 | let _ = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await; | 585 | let _ = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await; |
| 730 | 586 | ||
| 731 | // start HT clock | 587 | // start HT clock |
| 732 | //self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10).await; | 588 | //self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10).await; |
| 733 | //info!("waiting for HT clock..."); | 589 | //info!("waiting for HT clock..."); |
| 734 | //while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} | 590 | //while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} |
| 735 | //info!("clock ok"); | 591 | //info!("clock ok"); |
| 736 | 592 | ||
| 737 | #[cfg(feature = "firmware-logs")] | 593 | #[cfg(feature = "firmware-logs")] |
| @@ -744,13 +600,12 @@ where | |||
| 744 | async fn log_init(&mut self) { | 600 | async fn log_init(&mut self) { |
| 745 | // Initialize shared memory for logging. | 601 | // Initialize shared memory for logging. |
| 746 | 602 | ||
| 747 | let shared_addr = self | 603 | let addr = CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size; |
| 748 | .bp_read32(CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size) | 604 | let shared_addr = self.bus.bp_read32(addr).await; |
| 749 | .await; | ||
| 750 | info!("shared_addr {:08x}", shared_addr); | 605 | info!("shared_addr {:08x}", shared_addr); |
| 751 | 606 | ||
| 752 | let mut shared = [0; SharedMemData::SIZE]; | 607 | let mut shared = [0; SharedMemData::SIZE]; |
| 753 | self.bp_read(shared_addr, &mut shared).await; | 608 | self.bus.bp_read(shared_addr, &mut shared).await; |
| 754 | let shared = SharedMemData::from_bytes(&shared); | 609 | let shared = SharedMemData::from_bytes(&shared); |
| 755 | info!("shared: {:08x}", shared); | 610 | info!("shared: {:08x}", shared); |
| 756 | 611 | ||
| @@ -761,7 +616,7 @@ where | |||
| 761 | async fn log_read(&mut self) { | 616 | async fn log_read(&mut self) { |
| 762 | // Read log struct | 617 | // Read log struct |
| 763 | let mut log = [0; SharedMemLog::SIZE]; | 618 | let mut log = [0; SharedMemLog::SIZE]; |
| 764 | self.bp_read(self.log.addr, &mut log).await; | 619 | self.bus.bp_read(self.log.addr, &mut log).await; |
| 765 | let log = SharedMemLog::from_bytes(&log); | 620 | let log = SharedMemLog::from_bytes(&log); |
| 766 | 621 | ||
| 767 | let idx = log.idx as usize; | 622 | let idx = log.idx as usize; |
| @@ -774,7 +629,7 @@ where | |||
| 774 | // Read entire buf for now. We could read only what we need, but then we | 629 | // Read entire buf for now. We could read only what we need, but then we |
| 775 | // run into annoying alignment issues in `bp_read`. | 630 | // run into annoying alignment issues in `bp_read`. |
| 776 | let mut buf = [0; 0x400]; | 631 | let mut buf = [0; 0x400]; |
| 777 | self.bp_read(log.buf, &mut buf).await; | 632 | self.bus.bp_read(log.buf, &mut buf).await; |
| 778 | 633 | ||
| 779 | while self.log.last_idx != idx as usize { | 634 | while self.log.last_idx != idx as usize { |
| 780 | let b = buf[self.log.last_idx]; | 635 | let b = buf[self.log.last_idx]; |
| @@ -821,29 +676,19 @@ where | |||
| 821 | } | 676 | } |
| 822 | 677 | ||
| 823 | // Receive stuff | 678 | // Receive stuff |
| 824 | let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; | 679 | let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; |
| 825 | 680 | ||
| 826 | if irq & IRQ_F2_PACKET_AVAILABLE != 0 { | 681 | if irq & IRQ_F2_PACKET_AVAILABLE != 0 { |
| 827 | let mut status = 0xFFFF_FFFF; | 682 | let mut status = 0xFFFF_FFFF; |
| 828 | while status == 0xFFFF_FFFF { | 683 | while status == 0xFFFF_FFFF { |
| 829 | status = self.read32(FUNC_BUS, REG_BUS_STATUS).await; | 684 | status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await; |
| 830 | } | 685 | } |
| 831 | 686 | ||
| 832 | if status & STATUS_F2_PKT_AVAILABLE != 0 { | 687 | if status & STATUS_F2_PKT_AVAILABLE != 0 { |
| 833 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; | 688 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; |
| 834 | 689 | ||
| 835 | let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, len); | 690 | self.bus.wlan_read(&mut buf[..(len as usize + 3) / 4]).await; |
| 836 | |||
| 837 | transaction!(&mut self.spi, |bus| async { | ||
| 838 | bus.write(&[cmd]).await?; | ||
| 839 | bus.read(&mut buf[..(len as usize + 3) / 4]).await?; | ||
| 840 | Ok(()) | ||
| 841 | }) | ||
| 842 | .await | ||
| 843 | .unwrap(); | ||
| 844 | |||
| 845 | trace!("rx {:02x}", &slice8_mut(&mut buf)[..(len as usize).min(48)]); | 691 | trace!("rx {:02x}", &slice8_mut(&mut buf)[..(len as usize).min(48)]); |
| 846 | |||
| 847 | self.rx(&slice8_mut(&mut buf)[..len as usize]); | 692 | self.rx(&slice8_mut(&mut buf)[..len as usize]); |
| 848 | } | 693 | } |
| 849 | } | 694 | } |
| @@ -893,14 +738,7 @@ where | |||
| 893 | 738 | ||
| 894 | trace!(" {:02x}", &buf8[..total_len.min(48)]); | 739 | trace!(" {:02x}", &buf8[..total_len.min(48)]); |
| 895 | 740 | ||
| 896 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, total_len as _); | 741 | self.bus.wlan_write(&buf[..(total_len / 4)]).await; |
| 897 | transaction!(&mut self.spi, |bus| async { | ||
| 898 | bus.write(&[cmd]).await?; | ||
| 899 | bus.write(&buf[..(total_len / 4)]).await?; | ||
| 900 | Ok(()) | ||
| 901 | }) | ||
| 902 | .await | ||
| 903 | .unwrap(); | ||
| 904 | } | 742 | } |
| 905 | 743 | ||
| 906 | fn rx(&mut self, packet: &[u8]) { | 744 | fn rx(&mut self, packet: &[u8]) { |
| @@ -1086,52 +924,49 @@ where | |||
| 1086 | 924 | ||
| 1087 | trace!(" {:02x}", &buf8[..total_len.min(48)]); | 925 | trace!(" {:02x}", &buf8[..total_len.min(48)]); |
| 1088 | 926 | ||
| 1089 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, total_len as _); | 927 | self.bus.wlan_write(&buf[..total_len / 4]).await; |
| 1090 | |||
| 1091 | transaction!(&mut self.spi, |bus| async { | ||
| 1092 | bus.write(&[cmd]).await?; | ||
| 1093 | bus.write(&buf[..total_len / 4]).await?; | ||
| 1094 | Ok(()) | ||
| 1095 | }) | ||
| 1096 | .await | ||
| 1097 | .unwrap(); | ||
| 1098 | } | 928 | } |
| 1099 | 929 | ||
| 1100 | async fn core_disable(&mut self, core: Core) { | 930 | async fn core_disable(&mut self, core: Core) { |
| 1101 | let base = core.base_addr(); | 931 | let base = core.base_addr(); |
| 1102 | 932 | ||
| 1103 | // Dummy read? | 933 | // Dummy read? |
| 1104 | let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; | 934 | let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; |
| 1105 | 935 | ||
| 1106 | // Check it isn't already reset | 936 | // Check it isn't already reset |
| 1107 | let r = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; | 937 | let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; |
| 1108 | if r & AI_RESETCTRL_BIT_RESET != 0 { | 938 | if r & AI_RESETCTRL_BIT_RESET != 0 { |
| 1109 | return; | 939 | return; |
| 1110 | } | 940 | } |
| 1111 | 941 | ||
| 1112 | self.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; | 942 | self.bus.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; |
| 1113 | let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; | 943 | let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; |
| 1114 | 944 | ||
| 1115 | block_for(Duration::from_millis(1)); | 945 | block_for(Duration::from_millis(1)); |
| 1116 | 946 | ||
| 1117 | self.bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET).await; | 947 | self.bus |
| 1118 | let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; | 948 | .bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET) |
| 949 | .await; | ||
| 950 | let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; | ||
| 1119 | } | 951 | } |
| 1120 | 952 | ||
| 1121 | async fn core_reset(&mut self, core: Core) { | 953 | async fn core_reset(&mut self, core: Core) { |
| 1122 | self.core_disable(core).await; | 954 | self.core_disable(core).await; |
| 1123 | 955 | ||
| 1124 | let base = core.base_addr(); | 956 | let base = core.base_addr(); |
| 1125 | self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) | 957 | self.bus |
| 958 | .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) | ||
| 1126 | .await; | 959 | .await; |
| 1127 | let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; | 960 | let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; |
| 1128 | 961 | ||
| 1129 | self.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; | 962 | self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; |
| 1130 | 963 | ||
| 1131 | Timer::after(Duration::from_millis(1)).await; | 964 | Timer::after(Duration::from_millis(1)).await; |
| 1132 | 965 | ||
| 1133 | self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN).await; | 966 | self.bus |
| 1134 | let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; | 967 | .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN) |
| 968 | .await; | ||
| 969 | let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; | ||
| 1135 | 970 | ||
| 1136 | Timer::after(Duration::from_millis(1)).await; | 971 | Timer::after(Duration::from_millis(1)).await; |
| 1137 | } | 972 | } |
| @@ -1139,13 +974,13 @@ where | |||
| 1139 | async fn core_is_up(&mut self, core: Core) -> bool { | 974 | async fn core_is_up(&mut self, core: Core) -> bool { |
| 1140 | let base = core.base_addr(); | 975 | let base = core.base_addr(); |
| 1141 | 976 | ||
| 1142 | let io = self.bp_read8(base + AI_IOCTRL_OFFSET).await; | 977 | let io = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; |
| 1143 | if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN { | 978 | if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN { |
| 1144 | debug!("core_is_up: returning false due to bad ioctrl {:02x}", io); | 979 | debug!("core_is_up: returning false due to bad ioctrl {:02x}", io); |
| 1145 | return false; | 980 | return false; |
| 1146 | } | 981 | } |
| 1147 | 982 | ||
| 1148 | let r = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; | 983 | let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; |
| 1149 | if r & (AI_RESETCTRL_BIT_RESET) != 0 { | 984 | if r & (AI_RESETCTRL_BIT_RESET) != 0 { |
| 1150 | debug!("core_is_up: returning false due to bad resetctrl {:02x}", r); | 985 | debug!("core_is_up: returning false due to bad resetctrl {:02x}", r); |
| 1151 | return false; | 986 | return false; |
| @@ -1153,242 +988,11 @@ where | |||
| 1153 | 988 | ||
| 1154 | true | 989 | true |
| 1155 | } | 990 | } |
| 991 | } | ||
| 1156 | 992 | ||
| 1157 | #[allow(unused)] | 993 | fn slice8_mut(x: &mut [u32]) -> &mut [u8] { |
| 1158 | async fn bp_read(&mut self, mut addr: u32, mut data: &mut [u8]) { | 994 | let len = x.len() * 4; |
| 1159 | // It seems the HW force-aligns the addr | 995 | unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } |
| 1160 | // to 2 if data.len() >= 2 | ||
| 1161 | // to 4 if data.len() >= 4 | ||
| 1162 | // To simplify, enforce 4-align for now. | ||
| 1163 | assert!(addr % 4 == 0); | ||
| 1164 | |||
| 1165 | let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; | ||
| 1166 | |||
| 1167 | while !data.is_empty() { | ||
| 1168 | // Ensure transfer doesn't cross a window boundary. | ||
| 1169 | let window_offs = addr & BACKPLANE_ADDRESS_MASK; | ||
| 1170 | let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; | ||
| 1171 | |||
| 1172 | let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); | ||
| 1173 | |||
| 1174 | self.backplane_set_window(addr).await; | ||
| 1175 | |||
| 1176 | let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); | ||
| 1177 | |||
| 1178 | transaction!(&mut self.spi, |bus| async { | ||
| 1179 | bus.write(&[cmd]).await?; | ||
| 1180 | |||
| 1181 | // 4-byte response delay. | ||
| 1182 | let mut junk = [0; 1]; | ||
| 1183 | bus.read(&mut junk).await?; | ||
| 1184 | |||
| 1185 | // Read data | ||
| 1186 | bus.read(&mut buf[..(len + 3) / 4]).await?; | ||
| 1187 | Ok(()) | ||
| 1188 | }) | ||
| 1189 | .await | ||
| 1190 | .unwrap(); | ||
| 1191 | |||
| 1192 | data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]); | ||
| 1193 | |||
| 1194 | // Advance ptr. | ||
| 1195 | addr += len as u32; | ||
| 1196 | data = &mut data[len..]; | ||
| 1197 | } | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | async fn bp_write(&mut self, mut addr: u32, mut data: &[u8]) { | ||
| 1201 | // It seems the HW force-aligns the addr | ||
| 1202 | // to 2 if data.len() >= 2 | ||
| 1203 | // to 4 if data.len() >= 4 | ||
| 1204 | // To simplify, enforce 4-align for now. | ||
| 1205 | assert!(addr % 4 == 0); | ||
| 1206 | |||
| 1207 | let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; | ||
| 1208 | |||
| 1209 | while !data.is_empty() { | ||
| 1210 | // Ensure transfer doesn't cross a window boundary. | ||
| 1211 | let window_offs = addr & BACKPLANE_ADDRESS_MASK; | ||
| 1212 | let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; | ||
| 1213 | |||
| 1214 | let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); | ||
| 1215 | slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); | ||
| 1216 | |||
| 1217 | self.backplane_set_window(addr).await; | ||
| 1218 | |||
| 1219 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); | ||
| 1220 | |||
| 1221 | transaction!(&mut self.spi, |bus| async { | ||
| 1222 | bus.write(&[cmd]).await?; | ||
| 1223 | bus.write(&buf[..(len + 3) / 4]).await?; | ||
| 1224 | Ok(()) | ||
| 1225 | }) | ||
| 1226 | .await | ||
| 1227 | .unwrap(); | ||
| 1228 | |||
| 1229 | // Advance ptr. | ||
| 1230 | addr += len as u32; | ||
| 1231 | data = &data[len..]; | ||
| 1232 | } | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | async fn bp_read8(&mut self, addr: u32) -> u8 { | ||
| 1236 | self.backplane_readn(addr, 1).await as u8 | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | async fn bp_write8(&mut self, addr: u32, val: u8) { | ||
| 1240 | self.backplane_writen(addr, val as u32, 1).await | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | async fn bp_read16(&mut self, addr: u32) -> u16 { | ||
| 1244 | self.backplane_readn(addr, 2).await as u16 | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | #[allow(unused)] | ||
| 1248 | async fn bp_write16(&mut self, addr: u32, val: u16) { | ||
| 1249 | self.backplane_writen(addr, val as u32, 2).await | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | #[allow(unused)] | ||
| 1253 | async fn bp_read32(&mut self, addr: u32) -> u32 { | ||
| 1254 | self.backplane_readn(addr, 4).await | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | async fn bp_write32(&mut self, addr: u32, val: u32) { | ||
| 1258 | self.backplane_writen(addr, val, 4).await | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { | ||
| 1262 | self.backplane_set_window(addr).await; | ||
| 1263 | |||
| 1264 | let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||
| 1265 | if len == 4 { | ||
| 1266 | bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG | ||
| 1267 | } | ||
| 1268 | self.readn(FUNC_BACKPLANE, bus_addr, len).await | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { | ||
| 1272 | self.backplane_set_window(addr).await; | ||
| 1273 | |||
| 1274 | let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||
| 1275 | if len == 4 { | ||
| 1276 | bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG | ||
| 1277 | } | ||
| 1278 | self.writen(FUNC_BACKPLANE, bus_addr, val, len).await | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | async fn backplane_set_window(&mut self, addr: u32) { | ||
| 1282 | let new_window = addr & !BACKPLANE_ADDRESS_MASK; | ||
| 1283 | |||
| 1284 | if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { | ||
| 1285 | self.write8( | ||
| 1286 | FUNC_BACKPLANE, | ||
| 1287 | REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH, | ||
| 1288 | (new_window >> 24) as u8, | ||
| 1289 | ) | ||
| 1290 | .await; | ||
| 1291 | } | ||
| 1292 | if (new_window >> 16) as u8 != (self.backplane_window >> 16) as u8 { | ||
| 1293 | self.write8( | ||
| 1294 | FUNC_BACKPLANE, | ||
| 1295 | REG_BACKPLANE_BACKPLANE_ADDRESS_MID, | ||
| 1296 | (new_window >> 16) as u8, | ||
| 1297 | ) | ||
| 1298 | .await; | ||
| 1299 | } | ||
| 1300 | if (new_window >> 8) as u8 != (self.backplane_window >> 8) as u8 { | ||
| 1301 | self.write8( | ||
| 1302 | FUNC_BACKPLANE, | ||
| 1303 | REG_BACKPLANE_BACKPLANE_ADDRESS_LOW, | ||
| 1304 | (new_window >> 8) as u8, | ||
| 1305 | ) | ||
| 1306 | .await; | ||
| 1307 | } | ||
| 1308 | self.backplane_window = new_window; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | async fn read8(&mut self, func: u32, addr: u32) -> u8 { | ||
| 1312 | self.readn(func, addr, 1).await as u8 | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | async fn write8(&mut self, func: u32, addr: u32, val: u8) { | ||
| 1316 | self.writen(func, addr, val as u32, 1).await | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | async fn read16(&mut self, func: u32, addr: u32) -> u16 { | ||
| 1320 | self.readn(func, addr, 2).await as u16 | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | #[allow(unused)] | ||
| 1324 | async fn write16(&mut self, func: u32, addr: u32, val: u16) { | ||
| 1325 | self.writen(func, addr, val as u32, 2).await | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | async fn read32(&mut self, func: u32, addr: u32) -> u32 { | ||
| 1329 | self.readn(func, addr, 4).await | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | #[allow(unused)] | ||
| 1333 | async fn write32(&mut self, func: u32, addr: u32, val: u32) { | ||
| 1334 | self.writen(func, addr, val, 4).await | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { | ||
| 1338 | let cmd = cmd_word(READ, INC_ADDR, func, addr, len); | ||
| 1339 | let mut buf = [0; 1]; | ||
| 1340 | |||
| 1341 | transaction!(&mut self.spi, |bus| async { | ||
| 1342 | bus.write(&[cmd]).await?; | ||
| 1343 | if func == FUNC_BACKPLANE { | ||
| 1344 | // 4-byte response delay. | ||
| 1345 | bus.read(&mut buf).await?; | ||
| 1346 | } | ||
| 1347 | bus.read(&mut buf).await?; | ||
| 1348 | Ok(()) | ||
| 1349 | }) | ||
| 1350 | .await | ||
| 1351 | .unwrap(); | ||
| 1352 | |||
| 1353 | buf[0] | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { | ||
| 1357 | let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); | ||
| 1358 | |||
| 1359 | transaction!(&mut self.spi, |bus| async { | ||
| 1360 | bus.write(&[cmd, val]).await?; | ||
| 1361 | Ok(()) | ||
| 1362 | }) | ||
| 1363 | .await | ||
| 1364 | .unwrap(); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | async fn read32_swapped(&mut self, addr: u32) -> u32 { | ||
| 1368 | let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); | ||
| 1369 | let mut buf = [0; 1]; | ||
| 1370 | |||
| 1371 | transaction!(&mut self.spi, |bus| async { | ||
| 1372 | bus.write(&[swap16(cmd)]).await?; | ||
| 1373 | bus.read(&mut buf).await?; | ||
| 1374 | Ok(()) | ||
| 1375 | }) | ||
| 1376 | .await | ||
| 1377 | .unwrap(); | ||
| 1378 | |||
| 1379 | swap16(buf[0]) | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | async fn write32_swapped(&mut self, addr: u32, val: u32) { | ||
| 1383 | let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); | ||
| 1384 | |||
| 1385 | transaction!(&mut self.spi, |bus| async { | ||
| 1386 | bus.write(&[swap16(cmd), swap16(val)]).await?; | ||
| 1387 | Ok(()) | ||
| 1388 | }) | ||
| 1389 | .await | ||
| 1390 | .unwrap(); | ||
| 1391 | } | ||
| 1392 | } | 996 | } |
| 1393 | 997 | ||
| 1394 | macro_rules! nvram { | 998 | macro_rules! nvram { |
