strat9_bus_drivers/
uniphier_system_bus.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const UNIPHIER_SBC_BASE: usize = 0x100;
5const UNIPHIER_SBC_CTRL0: usize = 0x200;
6const UNIPHIER_SBC_STRIDE: usize = 0x10;
7const UNIPHIER_SBC_NR_BANKS: usize = 8;
8
9const UNIPHIER_SBC_BASE_BE: u32 = 1 << 0;
10const UNIPHIER_SBC_BASE_DUMMY: u32 = 0xFFFF_FFFF;
11
12const MIN_BANK_SIZE: u32 = 128 * 1024;
13
14const COMPATIBLE: &[&str] = &["socionext,uniphier-system-bus"];
15
16#[derive(Clone, Copy)]
17pub struct BankConfig {
18 pub base: u32,
19 pub end: u32,
20}
21
22impl BankConfig {
23 pub const fn empty() -> Self {
25 Self { base: 0, end: 0 }
26 }
27
28 pub fn is_valid(&self) -> bool {
30 self.end > self.base
31 }
32
33 pub fn size(&self) -> u32 {
35 self.end - self.base
36 }
37}
38
39pub struct UniphierSystemBus {
40 regs: MmioRegion,
41 banks: [BankConfig; UNIPHIER_SBC_NR_BANKS],
42 boot_swap: bool,
43 power_state: PowerState,
44 children: Vec<BusChild>,
45}
46
47impl UniphierSystemBus {
48 pub fn new() -> Self {
50 Self {
51 regs: MmioRegion::new(),
52 banks: [BankConfig::empty(); UNIPHIER_SBC_NR_BANKS],
53 boot_swap: false,
54 power_state: PowerState::Off,
55 children: Vec::new(),
56 }
57 }
58
59 pub fn set_bank(&mut self, index: usize, base: u32, end: u32) {
61 if index < UNIPHIER_SBC_NR_BANKS {
62 let aligned_base = base & !((MIN_BANK_SIZE) - 1);
63 let aligned_end = (end + MIN_BANK_SIZE - 1) & !((MIN_BANK_SIZE) - 1);
64 self.banks[index] = BankConfig {
65 base: aligned_base,
66 end: aligned_end,
67 };
68 }
69 }
70
71 pub fn check_boot_swap(&mut self) {
73 let bank0_base = self.regs.read32(UNIPHIER_SBC_BASE);
74 self.boot_swap = (bank0_base & UNIPHIER_SBC_BASE_BE) != 0;
75 if self.boot_swap {
76 self.banks.swap(0, 1);
77 }
78 }
79
80 fn apply_bank_config(&self) {
82 for i in 0..UNIPHIER_SBC_NR_BANKS {
83 let offset = UNIPHIER_SBC_BASE + i * UNIPHIER_SBC_STRIDE;
84
85 if !self.banks[i].is_valid() {
86 let dummy_val = if i < 2 { UNIPHIER_SBC_BASE_DUMMY } else { 0 };
87 self.regs.write32(offset, dummy_val);
88 continue;
89 }
90
91 let bank = &self.banks[i];
92 let mask = !(bank.size() - 1);
93 let reg_val =
94 (bank.base & 0xFFFE_0000) | (((!mask) >> 16) & 0xFFFE) | UNIPHIER_SBC_BASE_BE;
95
96 self.regs.write32(offset, reg_val);
97 }
98 }
99
100 pub fn add_child(&mut self, child: BusChild) {
102 self.children.push(child);
103 }
104}
105
106impl BusDriver for UniphierSystemBus {
107 fn name(&self) -> &str {
109 "uniphier-system-bus"
110 }
111
112 fn compatible(&self) -> &[&str] {
114 COMPATIBLE
115 }
116
117 fn init(&mut self, base: usize) -> Result<(), BusError> {
119 self.regs.init(base, 0x400);
120 self.check_boot_swap();
121 self.apply_bank_config();
122 self.power_state = PowerState::On;
123 Ok(())
124 }
125
126 fn shutdown(&mut self) -> Result<(), BusError> {
128 self.power_state = PowerState::Off;
129 Ok(())
130 }
131
132 fn resume(&mut self) -> Result<(), BusError> {
134 self.apply_bank_config();
135 self.power_state = PowerState::On;
136 Ok(())
137 }
138
139 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
141 if !self.regs.is_valid() {
142 return Err(BusError::InitFailed);
143 }
144 Ok(self.regs.read32(offset))
145 }
146
147 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
149 if !self.regs.is_valid() {
150 return Err(BusError::InitFailed);
151 }
152 self.regs.write32(offset, value);
153 Ok(())
154 }
155
156 fn children(&self) -> Vec<BusChild> {
158 self.children.clone()
159 }
160}