Skip to main content

strat9_bus_drivers/
qcom_ssc_block_bus.rs

1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const AXI_HALTREQ_REG: usize = 0x0;
5const AXI_HALTACK_REG: usize = 0x4;
6const AXI_IDLE_REG: usize = 0x8;
7
8const SSCAON_CONFIG0_CLAMP_EN_OVRD: u32 = 1 << 4;
9const SSCAON_CONFIG0_CLAMP_EN_OVRD_VAL: u32 = 1 << 5;
10const SSCAON_CONFIG1_CFG: u32 = 1 << 31;
11
12const MAX_HALT_WAIT: u32 = 10000;
13
14const COMPATIBLE: &[&str] = &["qcom,ssc-block-bus"];
15
16pub struct QcomSscBlockBus {
17    halt_regs: MmioRegion,
18    config0_regs: MmioRegion,
19    config1_regs: MmioRegion,
20    power_state: PowerState,
21    children: Vec<BusChild>,
22}
23
24impl QcomSscBlockBus {
25    /// Creates a new instance.
26    pub fn new() -> Self {
27        Self {
28            halt_regs: MmioRegion::new(),
29            config0_regs: MmioRegion::new(),
30            config1_regs: MmioRegion::new(),
31            power_state: PowerState::Off,
32            children: Vec::new(),
33        }
34    }
35
36    /// Initializes halt regs.
37    pub fn init_halt_regs(&mut self, base: usize) {
38        self.halt_regs.init(base, 0x10);
39    }
40
41    /// Initializes config regs.
42    pub fn init_config_regs(&mut self, config0_base: usize, config1_base: usize) {
43        self.config0_regs.init(config0_base, 0x10);
44        self.config1_regs.init(config1_base, 0x10);
45    }
46
47    /// Performs the bus init operation.
48    fn bus_init(&self) -> Result<(), BusError> {
49        self.config0_regs
50            .clear_bits32(0, SSCAON_CONFIG0_CLAMP_EN_OVRD_VAL);
51        self.config0_regs
52            .set_bits32(0, SSCAON_CONFIG0_CLAMP_EN_OVRD);
53        self.config1_regs.clear_bits32(0, SSCAON_CONFIG1_CFG);
54
55        self.halt_regs.write32(AXI_HALTREQ_REG, 0);
56
57        for _ in 0..MAX_HALT_WAIT {
58            let idle = self.halt_regs.read32(AXI_IDLE_REG);
59            if idle != 0 {
60                return Ok(());
61            }
62        }
63
64        Ok(())
65    }
66
67    /// Performs the bus deinit operation.
68    fn bus_deinit(&self) {
69        self.halt_regs.write32(AXI_HALTREQ_REG, 1);
70
71        for _ in 0..MAX_HALT_WAIT {
72            let ack = self.halt_regs.read32(AXI_HALTACK_REG);
73            if ack != 0 {
74                break;
75            }
76        }
77
78        self.config0_regs
79            .set_bits32(0, SSCAON_CONFIG0_CLAMP_EN_OVRD_VAL);
80        self.config1_regs.set_bits32(0, SSCAON_CONFIG1_CFG);
81    }
82
83    /// Performs the add child operation.
84    pub fn add_child(&mut self, child: BusChild) {
85        self.children.push(child);
86    }
87}
88
89impl BusDriver for QcomSscBlockBus {
90    /// Performs the name operation.
91    fn name(&self) -> &str {
92        "qcom-ssc-block-bus"
93    }
94
95    /// Performs the compatible operation.
96    fn compatible(&self) -> &[&str] {
97        COMPATIBLE
98    }
99
100    /// Performs the init operation.
101    fn init(&mut self, base: usize) -> Result<(), BusError> {
102        self.halt_regs.init(base, 0x10);
103        self.bus_init()?;
104        self.power_state = PowerState::On;
105        Ok(())
106    }
107
108    /// Performs the shutdown operation.
109    fn shutdown(&mut self) -> Result<(), BusError> {
110        self.bus_deinit();
111        self.power_state = PowerState::Off;
112        Ok(())
113    }
114
115    /// Reads reg.
116    fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
117        if !self.halt_regs.is_valid() {
118            return Err(BusError::InitFailed);
119        }
120        Ok(self.halt_regs.read32(offset))
121    }
122
123    /// Writes reg.
124    fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
125        if !self.halt_regs.is_valid() {
126            return Err(BusError::InitFailed);
127        }
128        self.halt_regs.write32(offset, value);
129        Ok(())
130    }
131
132    /// Performs the children operation.
133    fn children(&self) -> Vec<BusChild> {
134        self.children.clone()
135    }
136}