strat9_bus_drivers/
bt1_axi.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3use core::sync::atomic::{AtomicU64, Ordering};
4
5const BT1_AXI_WERRL: usize = 0x110;
6const BT1_AXI_WERRH: usize = 0x114;
7const BT1_AXI_WERRH_TYPE: u32 = 1 << 23;
8const BT1_AXI_WERRH_ADDR_SHIFT: u32 = 24;
9const BT1_AXI_WERRH_ADDR_MASK: u32 = 0xFF00_0000;
10
11const COMPATIBLE: &[&str] = &["baikal,bt1-axi"];
12
13pub struct Bt1Axi {
14 qos_regs: MmioRegion,
15 sys_regs: MmioRegion,
16 error_count: AtomicU64,
17 power_state: PowerState,
18}
19
20impl Bt1Axi {
21 pub fn new() -> Self {
23 Self {
24 qos_regs: MmioRegion::new(),
25 sys_regs: MmioRegion::new(),
26 error_count: AtomicU64::new(0),
27 power_state: PowerState::Off,
28 }
29 }
30
31 pub fn init_sys_regs(&mut self, base: usize, size: usize) {
33 self.sys_regs.init(base, size);
34 }
35
36 pub fn read_error_info(&self) -> Option<AxiErrorInfo> {
38 if !self.sys_regs.is_valid() {
39 return None;
40 }
41 let low = self.sys_regs.read32(BT1_AXI_WERRL);
42 let high = self.sys_regs.read32(BT1_AXI_WERRH);
43
44 let is_no_slave = (high & BT1_AXI_WERRH_TYPE) != 0;
45 let addr_high = (high & BT1_AXI_WERRH_ADDR_MASK) >> BT1_AXI_WERRH_ADDR_SHIFT;
46
47 Some(AxiErrorInfo {
48 address_low: low,
49 address_high: addr_high,
50 is_no_slave,
51 })
52 }
53}
54
55pub struct AxiErrorInfo {
56 pub address_low: u32,
57 pub address_high: u32,
58 pub is_no_slave: bool,
59}
60
61impl AxiErrorInfo {
62 pub fn full_address(&self) -> u64 {
64 ((self.address_high as u64) << 32) | (self.address_low as u64)
65 }
66
67 pub fn error_type_str(&self) -> &'static str {
69 if self.is_no_slave {
70 "no slave"
71 } else {
72 "slave protocol error"
73 }
74 }
75}
76
77impl BusDriver for Bt1Axi {
78 fn name(&self) -> &str {
80 "bt1-axi"
81 }
82
83 fn compatible(&self) -> &[&str] {
85 COMPATIBLE
86 }
87
88 fn init(&mut self, base: usize) -> Result<(), BusError> {
90 self.qos_regs.init(base, 0x200);
91 self.power_state = PowerState::On;
92 Ok(())
93 }
94
95 fn shutdown(&mut self) -> Result<(), BusError> {
97 self.power_state = PowerState::Off;
98 Ok(())
99 }
100
101 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
103 if !self.qos_regs.is_valid() {
104 return Err(BusError::InitFailed);
105 }
106 Ok(self.qos_regs.read32(offset))
107 }
108
109 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
111 if !self.qos_regs.is_valid() {
112 return Err(BusError::InitFailed);
113 }
114 self.qos_regs.write32(offset, value);
115 Ok(())
116 }
117
118 fn error_count(&self) -> u64 {
120 self.error_count.load(Ordering::Relaxed)
121 }
122
123 fn handle_irq(&mut self) -> bool {
125 if let Some(_info) = self.read_error_info() {
126 self.error_count.fetch_add(1, Ordering::Relaxed);
127 return true;
128 }
129 false
130 }
131}