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 let tmp = self.banks[0];
77 self.banks[0] = self.banks[1];
78 self.banks[1] = tmp;
79 }
80 }
81
82 fn apply_bank_config(&self) {
84 for i in 0..UNIPHIER_SBC_NR_BANKS {
85 let offset = UNIPHIER_SBC_BASE + i * UNIPHIER_SBC_STRIDE;
86
87 if !self.banks[i].is_valid() {
88 let dummy_val = if i < 2 { UNIPHIER_SBC_BASE_DUMMY } else { 0 };
89 self.regs.write32(offset, dummy_val);
90 continue;
91 }
92
93 let bank = &self.banks[i];
94 let mask = !(bank.size() - 1);
95 let reg_val =
96 (bank.base & 0xFFFE_0000) | (((!mask) >> 16) & 0xFFFE) | UNIPHIER_SBC_BASE_BE;
97
98 self.regs.write32(offset, reg_val);
99 }
100 }
101
102 pub fn add_child(&mut self, child: BusChild) {
104 self.children.push(child);
105 }
106}
107
108impl BusDriver for UniphierSystemBus {
109 fn name(&self) -> &str {
111 "uniphier-system-bus"
112 }
113
114 fn compatible(&self) -> &[&str] {
116 COMPATIBLE
117 }
118
119 fn init(&mut self, base: usize) -> Result<(), BusError> {
121 self.regs.init(base, 0x400);
122 self.check_boot_swap();
123 self.apply_bank_config();
124 self.power_state = PowerState::On;
125 Ok(())
126 }
127
128 fn shutdown(&mut self) -> Result<(), BusError> {
130 self.power_state = PowerState::Off;
131 Ok(())
132 }
133
134 fn resume(&mut self) -> Result<(), BusError> {
136 self.apply_bank_config();
137 self.power_state = PowerState::On;
138 Ok(())
139 }
140
141 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
143 if !self.regs.is_valid() {
144 return Err(BusError::InitFailed);
145 }
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.write32(offset, value);
155 Ok(())
156 }
157
158 fn children(&self) -> Vec<BusChild> {
160 self.children.clone()
161 }
162}