Skip to main content

strat9_bus_drivers/
bt1_axi.rs

1use 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    /// Creates a new instance.
22    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    /// Initializes sys regs.
32    pub fn init_sys_regs(&mut self, base: usize, size: usize) {
33        self.sys_regs.init(base, size);
34    }
35
36    /// Reads error info.
37    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    /// Performs the full address operation.
63    pub fn full_address(&self) -> u64 {
64        ((self.address_high as u64) << 32) | (self.address_low as u64)
65    }
66
67    /// Performs the error type str operation.
68    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    /// Performs the name operation.
79    fn name(&self) -> &str {
80        "bt1-axi"
81    }
82
83    /// Performs the compatible operation.
84    fn compatible(&self) -> &[&str] {
85        COMPATIBLE
86    }
87
88    /// Performs the init operation.
89    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    /// Performs the shutdown operation.
96    fn shutdown(&mut self) -> Result<(), BusError> {
97        self.power_state = PowerState::Off;
98        Ok(())
99    }
100
101    /// Reads reg.
102    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    /// Writes reg.
110    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    /// Performs the error count operation.
119    fn error_count(&self) -> u64 {
120        self.error_count.load(Ordering::Relaxed)
121    }
122
123    /// Handles irq.
124    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}