strat9_bus_drivers/
sun50i_de2.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const COMPATIBLE: &[&str] = &["allwinner,sun50i-a64-de2"];
5
6#[derive(Debug, Clone, Copy)]
13pub struct SramConfig {
14 pub ctrl_base: usize,
17 pub ctrl_offset: usize,
19 pub owner_mask: u32,
21 pub de2_owner: u32,
23}
24
25impl SramConfig {
26 fn apply_field(current: u32, cfg: &Self) -> u32 {
28 let shift = cfg.owner_mask.trailing_zeros();
29 (current & !cfg.owner_mask) | ((cfg.de2_owner << shift) & cfg.owner_mask)
30 }
31}
32
33pub struct Sun50iDe2 {
34 regs: MmioRegion,
35 power_state: PowerState,
36 sram_claimed: bool,
37 sram_config: Option<SramConfig>,
38 children: Vec<BusChild>,
39}
40
41impl Sun50iDe2 {
42 pub fn new() -> Self {
44 Self {
45 regs: MmioRegion::new(),
46 power_state: PowerState::Off,
47 sram_claimed: false,
48 sram_config: None,
49 children: Vec::new(),
50 }
51 }
52
53 pub fn set_sram_config(&mut self, cfg: SramConfig) {
56 self.sram_config = Some(cfg);
57 }
58
59 pub fn claim_sram(&mut self) -> Result<(), BusError> {
67 let cfg = match &self.sram_config {
68 Some(cfg) => *cfg,
69 None => return Err(BusError::InitFailed),
70 };
71
72 let addr = (cfg.ctrl_base + cfg.ctrl_offset) as *mut u32;
75 let current = unsafe { core::ptr::read_volatile(addr) };
76 let updated = SramConfig::apply_field(current, &cfg);
77 unsafe { core::ptr::write_volatile(addr, updated) };
78
79 let readback = unsafe { core::ptr::read_volatile(addr) };
81 if readback != updated {
82 return Err(BusError::BusFault);
83 }
84
85 self.sram_claimed = true;
86 Ok(())
87 }
88
89 pub fn release_sram(&mut self) {
93 if let Some(cfg) = self.sram_config {
94 let addr = (cfg.ctrl_base + cfg.ctrl_offset) as *mut u32;
96 let current = unsafe { core::ptr::read_volatile(addr) };
97 let restored = current & !cfg.owner_mask;
98 unsafe { core::ptr::write_volatile(addr, restored) };
99 }
100 self.sram_claimed = false;
101 }
102
103 pub fn sram_claimed(&self) -> bool {
105 self.sram_claimed
106 }
107
108 pub fn add_child(&mut self, child: BusChild) {
110 self.children.push(child);
111 }
112}
113
114impl BusDriver for Sun50iDe2 {
115 fn name(&self) -> &str {
117 "sun50i-de2"
118 }
119
120 fn compatible(&self) -> &[&str] {
122 COMPATIBLE
123 }
124
125 fn init(&mut self, base: usize) -> Result<(), BusError> {
127 self.regs.init(base, 0x1000);
128 self.claim_sram()?;
129 self.power_state = PowerState::On;
130 Ok(())
131 }
132
133 fn shutdown(&mut self) -> Result<(), BusError> {
135 self.release_sram();
136 self.power_state = PowerState::Off;
137 Ok(())
138 }
139
140 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
142 if !self.regs.is_valid() {
143 return Err(BusError::InitFailed);
144 }
145 self.regs.check_user_offset(offset)?;
146 Ok(self.regs.read32(offset))
147 }
148
149 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
151 if !self.regs.is_valid() {
152 return Err(BusError::InitFailed);
153 }
154 self.regs.check_user_offset(offset)?;
155 self.regs.write32(offset, value);
156 Ok(())
157 }
158
159 fn children(&self) -> Vec<BusChild> {
161 self.children.clone()
162 }
163}