strat9_bus_drivers/
ts_nbus.rs1use crate::{BusChild, BusDriver, BusError, PowerState};
2use alloc::{string::String, vec::Vec};
3
4const TS_NBUS_DIRECTION_IN: bool = false;
5const TS_NBUS_DIRECTION_OUT: bool = true;
6const TS_NBUS_WRITE_ADR: bool = false;
7const TS_NBUS_WRITE_VAL: bool = true;
8
9const MAX_POLL_RDY: u32 = 10000;
10
11const COMPATIBLE: &[&str] = &["technologic,ts-nbus"];
12
13pub struct GpioPin {
32 pub base: usize,
34 pub offset: u32,
36 pub active_low: bool,
38}
39
40impl GpioPin {
41 pub const DATA_REG_OFFSET: usize = 0x00;
43 pub const DIR_REG_OFFSET: usize = 0x04;
45
46 pub fn is_configured(&self) -> bool {
48 self.base != 0 && self.offset < 32
49 }
50
51 fn read_data(&self) -> u32 {
53 unsafe { core::ptr::read_volatile((self.base + Self::DATA_REG_OFFSET) as *const u32) }
56 }
57
58 fn write_data(&self, val: u32) {
60 unsafe { core::ptr::write_volatile((self.base + Self::DATA_REG_OFFSET) as *mut u32, val) }
62 }
63
64 fn rmw_bit(&self, reg_offset: usize, set: bool) {
66 let addr = (self.base + reg_offset) as *const u32;
67 let mut val = unsafe { core::ptr::read_volatile(addr) };
69 let mask = 1u32 << self.offset;
70 if set {
71 val |= mask;
72 } else {
73 val &= !mask;
74 }
75 unsafe { core::ptr::write_volatile(addr as *mut u32, val) };
77 }
78
79 pub fn set_high(&self) {
81 let bit = !self.active_low;
82 self.rmw_bit(Self::DATA_REG_OFFSET, bit);
83 }
84
85 pub fn set_low(&self) {
87 let bit = self.active_low;
88 self.rmw_bit(Self::DATA_REG_OFFSET, bit);
89 }
90
91 pub fn get_value(&self) -> bool {
93 let raw = self.read_data() & (1u32 << self.offset) != 0;
94 raw != self.active_low
95 }
96
97 pub fn set_direction_input(&self) {
99 self.rmw_bit(Self::DIR_REG_OFFSET, false);
100 }
101
102 pub fn set_direction_output(&self) {
104 self.rmw_bit(Self::DIR_REG_OFFSET, true);
105 }
106}
107
108pub struct TsNbus {
109 data_pins: [Option<GpioPin>; 8],
110 csn: Option<GpioPin>,
111 txrx: Option<GpioPin>,
112 strobe: Option<GpioPin>,
113 ale: Option<GpioPin>,
114 rdy: Option<GpioPin>,
115 power_state: PowerState,
116 children: Vec<BusChild>,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum NbusControlPin {
122 Csn,
124 TxRx,
126 Strobe,
128 Ale,
130 Rdy,
132}
133
134impl TsNbus {
135 pub fn new() -> Self {
137 Self {
138 data_pins: [const { None }; 8],
139 csn: None,
140 txrx: None,
141 strobe: None,
142 ale: None,
143 rdy: None,
144 power_state: PowerState::Off,
145 children: Vec::new(),
146 }
147 }
148
149 pub fn set_data_pin(&mut self, index: usize, pin: GpioPin) -> Result<(), BusError> {
152 if index >= 8 {
153 return Err(BusError::InvalidArgument);
154 }
155 self.data_pins[index] = Some(pin);
156 Ok(())
157 }
158
159 pub fn set_control_pin(&mut self, which: NbusControlPin, pin: GpioPin) {
161 let slot = match which {
162 NbusControlPin::Csn => &mut self.csn,
163 NbusControlPin::TxRx => &mut self.txrx,
164 NbusControlPin::Strobe => &mut self.strobe,
165 NbusControlPin::Ale => &mut self.ale,
166 NbusControlPin::Rdy => &mut self.rdy,
167 };
168 *slot = Some(pin);
169 }
170
171 fn validate_pins(&self) -> Result<(), BusError> {
174 for (i, p) in self.data_pins.iter().enumerate() {
175 match p {
176 Some(p) if p.is_configured() => {}
177 _ => return Err(BusError::InvalidArgument),
178 }
179 }
180 for p in [&self.csn, &self.txrx, &self.strobe, &self.ale, &self.rdy] {
181 match p {
182 Some(p) if p.is_configured() => {}
183 _ => return Err(BusError::InvalidArgument),
184 }
185 }
186 Ok(())
187 }
188
189 fn set_data_direction(&self, output: bool) {
191 for p in self.data_pins.iter().flatten() {
192 if output {
193 p.set_direction_output();
194 } else {
195 p.set_direction_input();
196 }
197 }
198 }
199
200 fn write_byte(&self, val: u8) {
202 for i in 0..8 {
203 if let Some(ref p) = self.data_pins[i] {
204 if (val >> i) & 1 != 0 {
205 p.set_high();
206 } else {
207 p.set_low();
208 }
209 }
210 }
211 }
212
213 fn read_byte(&self) -> u8 {
215 let mut val = 0u8;
216 for i in 0..8 {
217 if let Some(ref p) = self.data_pins[i]
218 && p.get_value()
219 {
220 val |= 1 << i;
221 }
222 }
223 val
224 }
225
226 fn start_transaction(&self) {
228 if let Some(ref s) = self.strobe {
229 s.set_high();
230 }
231 }
232
233 fn end_transaction(&self) {
235 if let Some(ref s) = self.strobe {
236 s.set_low();
237 }
238 }
239
240 fn wait_rdy(&self) -> Result<(), BusError> {
242 for _ in 0..MAX_POLL_RDY {
243 if let Some(ref r) = self.rdy
244 && r.get_value()
245 {
246 return Ok(());
247 }
248 }
249 Err(BusError::Timeout)
250 }
251
252 fn reset_bus(&self) {
254 self.write_byte(0);
255 if let Some(ref c) = self.csn {
256 c.set_low();
257 }
258 if let Some(ref s) = self.strobe {
259 s.set_low();
260 }
261 if let Some(ref a) = self.ale {
262 a.set_low();
263 }
264 }
265
266 pub fn bus_read(&self, address: u16) -> Result<u16, BusError> {
268 self.set_data_direction(true);
269 if let Some(ref t) = self.txrx {
270 t.set_low();
271 }
272 if let Some(ref a) = self.ale {
273 a.set_high();
274 }
275
276 self.write_byte((address >> 8) as u8);
277 self.start_transaction();
278 self.end_transaction();
279
280 self.write_byte(address as u8);
281 self.start_transaction();
282 self.end_transaction();
283
284 if let Some(ref a) = self.ale {
285 a.set_low();
286 }
287 self.set_data_direction(false);
288
289 if let Some(ref c) = self.csn {
290 c.set_high();
291 }
292 self.start_transaction();
293 self.wait_rdy()?;
294 let msb = self.read_byte();
295 self.end_transaction();
296
297 self.start_transaction();
298 self.wait_rdy()?;
299 let lsb = self.read_byte();
300 self.end_transaction();
301
302 if let Some(ref c) = self.csn {
303 c.set_low();
304 }
305
306 Ok(((msb as u16) << 8) | (lsb as u16))
307 }
308
309 pub fn bus_write(&self, address: u16, value: u16) -> Result<(), BusError> {
311 self.set_data_direction(true);
312 if let Some(ref t) = self.txrx {
313 t.set_high();
314 }
315 if let Some(ref a) = self.ale {
316 a.set_high();
317 }
318
319 self.write_byte((address >> 8) as u8);
320 self.start_transaction();
321 self.end_transaction();
322
323 self.write_byte(address as u8);
324 self.start_transaction();
325 self.end_transaction();
326
327 if let Some(ref a) = self.ale {
328 a.set_low();
329 }
330 if let Some(ref c) = self.csn {
331 c.set_high();
332 }
333
334 self.write_byte((value >> 8) as u8);
335 self.start_transaction();
336 self.wait_rdy()?;
337 self.end_transaction();
338
339 self.write_byte(value as u8);
340 self.start_transaction();
341 self.wait_rdy()?;
342 self.end_transaction();
343
344 if let Some(ref c) = self.csn {
345 c.set_low();
346 }
347
348 Ok(())
349 }
350
351 pub fn add_child(&mut self, child: BusChild) {
353 self.children.push(child);
354 }
355}
356
357impl BusDriver for TsNbus {
358 fn name(&self) -> &str {
360 "ts-nbus"
361 }
362
363 fn compatible(&self) -> &[&str] {
365 COMPATIBLE
366 }
367
368 fn probe(&self) -> bool {
370 false
371 }
372
373 fn init(&mut self, _base: usize) -> Result<(), BusError> {
375 self.validate_pins()?;
376 self.reset_bus();
377 self.power_state = PowerState::On;
378 Ok(())
379 }
380
381 fn shutdown(&mut self) -> Result<(), BusError> {
383 self.reset_bus();
384 self.power_state = PowerState::Off;
385 Ok(())
386 }
387
388 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
390 let off = u16::try_from(offset).map_err(|_| BusError::InvalidAddress)?;
393 let val = self.bus_read(off)?;
394 Ok(val as u32)
395 }
396
397 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
399 let off = u16::try_from(offset).map_err(|_| BusError::InvalidAddress)?;
400 self.bus_write(off, value as u16)
401 }
402
403 fn children(&self) -> Vec<BusChild> {
405 self.children.clone()
406 }
407}