Skip to main content

strat9_bus_drivers/
uniphier_system_bus.rs

1use 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    /// Performs the empty operation.
24    pub const fn empty() -> Self {
25        Self { base: 0, end: 0 }
26    }
27
28    /// Returns whether valid.
29    pub fn is_valid(&self) -> bool {
30        self.end > self.base
31    }
32
33    /// Performs the size operation.
34    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    /// Creates a new instance.
49    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    /// Sets bank.
60    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    /// Performs the check boot swap operation.
72    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    /// Performs the apply bank config operation.
81    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    /// Performs the add child operation.
101    pub fn add_child(&mut self, child: BusChild) {
102        self.children.push(child);
103    }
104}
105
106impl BusDriver for UniphierSystemBus {
107    /// Performs the name operation.
108    fn name(&self) -> &str {
109        "uniphier-system-bus"
110    }
111
112    /// Performs the compatible operation.
113    fn compatible(&self) -> &[&str] {
114        COMPATIBLE
115    }
116
117    /// Performs the init operation.
118    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    /// Performs the shutdown operation.
127    fn shutdown(&mut self) -> Result<(), BusError> {
128        self.power_state = PowerState::Off;
129        Ok(())
130    }
131
132    /// Performs the resume operation.
133    fn resume(&mut self) -> Result<(), BusError> {
134        self.apply_bank_config();
135        self.power_state = PowerState::On;
136        Ok(())
137    }
138
139    /// Reads reg.
140    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    /// Writes reg.
148    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    /// Performs the children operation.
157    fn children(&self) -> Vec<BusChild> {
158        self.children.clone()
159    }
160}