strat9_bus_drivers/
sunxi_rsb.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const RSB_CTRL: usize = 0x00;
5const RSB_CCR: usize = 0x04;
6const RSB_INTE: usize = 0x08;
7const RSB_INTS: usize = 0x0C;
8const RSB_ADDR: usize = 0x10;
9const RSB_DATA: usize = 0x1C;
10const RSB_LCR: usize = 0x24;
11const RSB_DMCR: usize = 0x28;
12const RSB_CMD: usize = 0x2C;
13const RSB_DAR: usize = 0x30;
14
15const RSB_CTRL_START_TRANS: u32 = 1 << 7;
16const RSB_CTRL_ABORT_TRANS: u32 = 1 << 6;
17const RSB_CTRL_GLOBAL_INT_ENB: u32 = 1 << 1;
18const RSB_CTRL_SOFT_RST: u32 = 1 << 0;
19
20const RSB_INTS_TRANS_ERR_ACK: u32 = 1 << 16;
21const RSB_INTS_TRANS_ERR_DATA_MASK: u32 = 0xF << 8;
22const RSB_INTS_LOAD_BSY: u32 = 1 << 2;
23const RSB_INTS_TRANS_ERR: u32 = 1 << 1;
24const RSB_INTS_TRANS_OVER: u32 = 1 << 0;
25
26const RSB_DMCR_DEVICE_START: u32 = 1 << 31;
27const RSB_DMCR_MODE_DATA: u32 = 0x7C << 16;
28const RSB_DMCR_MODE_REG: u32 = 0x3E << 8;
29
30const RSB_CMD_RD8: u32 = 0x8B;
31const RSB_CMD_RD16: u32 = 0x9C;
32const RSB_CMD_RD32: u32 = 0xA6;
33const RSB_CMD_WR8: u32 = 0x4E;
34const RSB_CMD_WR16: u32 = 0x59;
35const RSB_CMD_WR32: u32 = 0x63;
36const RSB_CMD_STRA: u32 = 0xE8;
37
38const MAX_POLL: u32 = 10000;
39
40const COMPATIBLE: &[&str] = &["allwinner,sun8i-a23-rsb"];
41
42fn ccr_sda_out_delay(v: u32) -> u32 {
44 (v & 0x7) << 8
45}
46fn ccr_clk_div(v: u32) -> u32 {
48 v & 0xFF
49}
50fn dar_rta(v: u32) -> u32 {
52 (v & 0xFF) << 16
53}
54fn dar_da(v: u32) -> u32 {
56 v & 0xFFFF
57}
58
59pub struct RsbAddrMap {
60 pub hwaddr: u16,
61 pub rtaddr: u8,
62}
63
64pub const DEFAULT_ADDR_MAP: &[RsbAddrMap] = &[
65 RsbAddrMap {
66 hwaddr: 0x3A3,
67 rtaddr: 0x2D,
68 },
69 RsbAddrMap {
70 hwaddr: 0x745,
71 rtaddr: 0x3A,
72 },
73 RsbAddrMap {
74 hwaddr: 0xE89,
75 rtaddr: 0x4E,
76 },
77];
78
79pub struct SunxiRsb {
80 regs: MmioRegion,
81 clock_freq: u32,
82 power_state: PowerState,
83 children: Vec<BusChild>,
84}
85
86impl SunxiRsb {
87 pub fn new() -> Self {
89 Self {
90 regs: MmioRegion::new(),
91 clock_freq: 3_000_000,
92 power_state: PowerState::Off,
93 children: Vec::new(),
94 }
95 }
96
97 pub fn set_clock_freq(&mut self, freq: u32) {
99 self.clock_freq = freq;
100 }
101
102 fn soft_reset(&self) {
104 self.regs.write32(RSB_CTRL, RSB_CTRL_SOFT_RST);
105 for _ in 0..MAX_POLL {
106 if self.regs.read32(RSB_CTRL) & RSB_CTRL_SOFT_RST == 0 {
107 return;
108 }
109 }
110 }
111
112 fn wait_transfer_complete(&self) -> Result<u32, BusError> {
114 for _ in 0..MAX_POLL {
115 let status = self.regs.read32(RSB_INTS);
116 if status & RSB_INTS_LOAD_BSY != 0 {
117 self.regs.write32(RSB_INTS, status);
118 return Err(BusError::Timeout);
119 }
120 if status & RSB_INTS_TRANS_ERR != 0 {
121 self.regs.write32(RSB_INTS, status);
122 return Err(BusError::ProtocolError);
123 }
124 if status & RSB_INTS_TRANS_OVER != 0 {
125 self.regs.write32(RSB_INTS, status);
126 return Ok(status);
127 }
128 }
129 Err(BusError::Timeout)
130 }
131
132 fn start_transfer(&self) {
134 self.regs
135 .write32(RSB_CTRL, RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB);
136 }
137
138 pub fn set_runtime_address(&self, hwaddr: u16, rtaddr: u8) -> Result<(), BusError> {
140 self.regs.write32(RSB_CMD, RSB_CMD_STRA);
141 self.regs
142 .write32(RSB_DAR, dar_rta(rtaddr as u32) | dar_da(hwaddr as u32));
143 self.start_transfer();
144 self.wait_transfer_complete()?;
145 Ok(())
146 }
147
148 pub fn init_device_mode(&self) -> Result<(), BusError> {
150 self.regs.write32(
151 RSB_DMCR,
152 RSB_DMCR_DEVICE_START | RSB_DMCR_MODE_DATA | RSB_DMCR_MODE_REG,
153 );
154 for _ in 0..MAX_POLL {
155 if self.regs.read32(RSB_DMCR) & RSB_DMCR_DEVICE_START == 0 {
156 return Ok(());
157 }
158 }
159 Err(BusError::Timeout)
160 }
161
162 pub fn read8(&self, rtaddr: u8, reg: u8) -> Result<u8, BusError> {
164 self.regs.write32(RSB_CMD, RSB_CMD_RD8);
165 self.regs.write32(RSB_DAR, dar_rta(rtaddr as u32));
166 self.regs.write32(RSB_ADDR, reg as u32);
167 self.start_transfer();
168 self.wait_transfer_complete()?;
169 Ok(self.regs.read32(RSB_DATA) as u8)
170 }
171
172 pub fn write8(&self, rtaddr: u8, reg: u8, val: u8) -> Result<(), BusError> {
174 self.regs.write32(RSB_CMD, RSB_CMD_WR8);
175 self.regs.write32(RSB_DAR, dar_rta(rtaddr as u32));
176 self.regs.write32(RSB_ADDR, reg as u32);
177 self.regs.write32(RSB_DATA, val as u32);
178 self.start_transfer();
179 self.wait_transfer_complete()?;
180 Ok(())
181 }
182
183 pub fn read16(&self, rtaddr: u8, reg: u8) -> Result<u16, BusError> {
185 self.regs.write32(RSB_CMD, RSB_CMD_RD16);
186 self.regs.write32(RSB_DAR, dar_rta(rtaddr as u32));
187 self.regs.write32(RSB_ADDR, reg as u32);
188 self.start_transfer();
189 self.wait_transfer_complete()?;
190 Ok(self.regs.read32(RSB_DATA) as u16)
191 }
192
193 pub fn write16(&self, rtaddr: u8, reg: u8, val: u16) -> Result<(), BusError> {
195 self.regs.write32(RSB_CMD, RSB_CMD_WR16);
196 self.regs.write32(RSB_DAR, dar_rta(rtaddr as u32));
197 self.regs.write32(RSB_ADDR, reg as u32);
198 self.regs.write32(RSB_DATA, val as u32);
199 self.start_transfer();
200 self.wait_transfer_complete()?;
201 Ok(())
202 }
203
204 pub fn add_child(&mut self, child: BusChild) {
206 self.children.push(child);
207 }
208}
209
210impl BusDriver for SunxiRsb {
211 fn name(&self) -> &str {
213 "sunxi-rsb"
214 }
215
216 fn compatible(&self) -> &[&str] {
218 COMPATIBLE
219 }
220
221 fn init(&mut self, base: usize) -> Result<(), BusError> {
223 self.regs.init(base, 0x40);
224 self.soft_reset();
225 self.regs
226 .write32(RSB_CCR, ccr_sda_out_delay(1) | ccr_clk_div(3));
227 self.init_device_mode()?;
228 self.power_state = PowerState::On;
229 Ok(())
230 }
231
232 fn shutdown(&mut self) -> Result<(), BusError> {
234 self.soft_reset();
235 self.power_state = PowerState::Off;
236 Ok(())
237 }
238
239 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
241 if !self.regs.is_valid() {
242 return Err(BusError::InitFailed);
243 }
244 Ok(self.regs.read32(offset))
245 }
246
247 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
249 if !self.regs.is_valid() {
250 return Err(BusError::InitFailed);
251 }
252 self.regs.write32(offset, value);
253 Ok(())
254 }
255
256 fn children(&self) -> Vec<BusChild> {
258 self.children.clone()
259 }
260}