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            let tmp = self.banks[0];
77            self.banks[0] = self.banks[1];
78            self.banks[1] = tmp;
79        }
80    }
81
82    /// Performs the apply bank config operation.
83    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    /// Performs the add child operation.
103    pub fn add_child(&mut self, child: BusChild) {
104        self.children.push(child);
105    }
106}
107
108impl BusDriver for UniphierSystemBus {
109    /// Performs the name operation.
110    fn name(&self) -> &str {
111        "uniphier-system-bus"
112    }
113
114    /// Performs the compatible operation.
115    fn compatible(&self) -> &[&str] {
116        COMPATIBLE
117    }
118
119    /// Performs the init operation.
120    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    /// Performs the shutdown operation.
129    fn shutdown(&mut self) -> Result<(), BusError> {
130        self.power_state = PowerState::Off;
131        Ok(())
132    }
133
134    /// Performs the resume operation.
135    fn resume(&mut self) -> Result<(), BusError> {
136        self.apply_bank_config();
137        self.power_state = PowerState::On;
138        Ok(())
139    }
140
141    /// Reads reg.
142    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    /// Writes reg.
150    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    /// Performs the children operation.
159    fn children(&self) -> Vec<BusChild> {
160        self.children.clone()
161    }
162}