1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const SYSC_IDLE_SMART: u32 = 2;
5const SYSC_IDLE_NO: u32 = 1;
6const SYSC_IDLE_FORCE: u32 = 0;
7
8const MAX_MODULE_SOFTRESET_WAIT: u32 = 10000;
9
10const COMPATIBLE: &[&str] = &[
11 "ti,sysc-omap2",
12 "ti,sysc-omap4",
13 "ti,sysc-omap4-timer",
14 "ti,sysc-omap4-simple",
15 "ti,sysc-omap2-timer",
16 "ti,sysc-omap3430-sr",
17 "ti,sysc-omap3630-sr",
18 "ti,sysc-omap4-sr",
19 "ti,sysc-omap3-sham",
20 "ti,sysc-omap-aes",
21 "ti,sysc-mcasp",
22 "ti,sysc-dra7-mcasp",
23 "ti,sysc-usb-host-fs",
24 "ti,sysc-dra7-mcan",
25 "ti,sysc-pruss",
26];
27
28bitflags::bitflags! {
29 #[derive(Debug, Clone, Copy)]
30 pub struct SyscQuirks: u32 {
31 const QUIRK_16BIT = 1 << 0;
32 const QUIRK_RESET_STATUS = 1 << 1;
33 const QUIRK_SWSUP_SIDLE = 1 << 2;
34 const QUIRK_SWSUP_MSTANDBY = 1 << 3;
35 const QUIRK_SWSUP_SIDLE_ACT = 1 << 4;
36 const QUIRK_NO_IDLE = 1 << 5;
37 const QUIRK_NO_RESET_ON_INIT = 1 << 6;
38 const QUIRK_EXT_OPT_CLK = 1 << 7;
39 const QUIRK_REINIT_ON_CTX_LOST = 1 << 8;
40 }
41}
42
43pub struct SyscRegbits {
44 pub midle_shift: u32,
45 pub sidle_shift: u32,
46 pub clkact_shift: u32,
47 pub srst_shift: u32,
48 pub autoidle_shift: u32,
49 pub emufree_shift: u32,
50}
51
52pub const REGBITS_OMAP2: SyscRegbits = SyscRegbits {
53 midle_shift: 12,
54 sidle_shift: 3,
55 clkact_shift: 8,
56 srst_shift: 1,
57 autoidle_shift: 0,
58 emufree_shift: 5,
59};
60
61pub const REGBITS_OMAP4: SyscRegbits = SyscRegbits {
62 midle_shift: 4,
63 sidle_shift: 2,
64 clkact_shift: 0,
65 srst_shift: 0,
66 autoidle_shift: 0,
67 emufree_shift: 1,
68};
69
70pub struct TiSysc {
71 regs: MmioRegion,
72 rev_offset: Option<usize>,
73 sysc_offset: Option<usize>,
74 syss_offset: Option<usize>,
75 regbits: &'static SyscRegbits,
76 quirks: SyscQuirks,
77 revision: u32,
78 power_state: PowerState,
79 children: Vec<BusChild>,
80}
81
82impl TiSysc {
83 pub fn new(regbits: &'static SyscRegbits) -> Self {
85 Self {
86 regs: MmioRegion::new(),
87 rev_offset: Some(0),
88 sysc_offset: None,
89 syss_offset: None,
90 regbits,
91 quirks: SyscQuirks::empty(),
92 revision: 0,
93 power_state: PowerState::Off,
94 children: Vec::new(),
95 }
96 }
97
98 pub fn set_offsets(&mut self, rev: Option<usize>, sysc: Option<usize>, syss: Option<usize>) {
100 self.rev_offset = rev;
101 self.sysc_offset = sysc;
102 self.syss_offset = syss;
103 }
104
105 pub fn set_quirks(&mut self, quirks: SyscQuirks) {
107 self.quirks = quirks;
108 }
109
110 pub fn add_child(&mut self, child: BusChild) {
112 self.children.push(child);
113 }
114
115 fn read_sysc(&self) -> u32 {
117 match self.sysc_offset {
118 Some(off) => {
119 if self.quirks.contains(SyscQuirks::QUIRK_16BIT) {
120 self.regs.read16(off) as u32
121 } else {
122 self.regs.read32(off)
123 }
124 }
125 None => 0,
126 }
127 }
128
129 fn write_sysc(&self, val: u32) {
131 if let Some(off) = self.sysc_offset {
132 if self.quirks.contains(SyscQuirks::QUIRK_16BIT) {
133 self.regs.write16(off, val as u16);
134 } else {
135 self.regs.write32(off, val);
136 }
137 }
138 }
139
140 pub fn read_revision(&self) -> u32 {
142 match self.rev_offset {
143 Some(off) => self.regs.read32(off),
144 None => 0,
145 }
146 }
147
148 pub fn enable_module(&self) {
150 let mut val = self.read_sysc();
151 let sidle_mask = 0x3 << self.regbits.sidle_shift;
152 val &= !sidle_mask;
153 val |= SYSC_IDLE_SMART << self.regbits.sidle_shift;
154
155 if self.regbits.midle_shift > 0 {
156 let midle_mask = 0x3 << self.regbits.midle_shift;
157 val &= !midle_mask;
158 val |= SYSC_IDLE_SMART << self.regbits.midle_shift;
159 }
160
161 if self.regbits.autoidle_shift > 0 || self.regbits.clkact_shift > 0 {
162 val |= 1 << self.regbits.autoidle_shift;
163 }
164
165 self.write_sysc(val);
166 }
167
168 pub fn disable_module(&self) {
170 let mut val = self.read_sysc();
171 let sidle_mask = 0x3 << self.regbits.sidle_shift;
172 val &= !sidle_mask;
173 val |= SYSC_IDLE_FORCE << self.regbits.sidle_shift;
174
175 if self.regbits.midle_shift > 0 {
176 let midle_mask = 0x3 << self.regbits.midle_shift;
177 val &= !midle_mask;
178 val |= SYSC_IDLE_FORCE << self.regbits.midle_shift;
179 }
180
181 self.write_sysc(val);
182 }
183
184 pub fn softreset(&self) -> Result<(), BusError> {
186 if self.quirks.contains(SyscQuirks::QUIRK_NO_RESET_ON_INIT) {
187 return Ok(());
188 }
189
190 if self.sysc_offset.is_none() {
191 return Err(BusError::NotSupported);
192 }
193
194 let mut val = self.read_sysc();
195 val |= 1 << self.regbits.srst_shift;
196 self.write_sysc(val);
197
198 for _ in 0..MAX_MODULE_SOFTRESET_WAIT {
199 let current = self.read_sysc();
200 if (current & (1 << self.regbits.srst_shift)) == 0 {
201 return Ok(());
202 }
203 }
204
205 if let Some(syss) = self.syss_offset {
206 for _ in 0..MAX_MODULE_SOFTRESET_WAIT {
207 let status = self.regs.read32(syss);
208 if (status & 1) != 0 {
209 return Ok(());
210 }
211 }
212 }
213
214 Err(BusError::Timeout)
215 }
216}
217
218impl BusDriver for TiSysc {
219 fn name(&self) -> &str {
221 "ti-sysc"
222 }
223
224 fn compatible(&self) -> &[&str] {
226 COMPATIBLE
227 }
228
229 fn init(&mut self, base: usize) -> Result<(), BusError> {
231 self.regs.init(base, 0x100);
232 self.revision = self.read_revision();
233
234 if !self.quirks.contains(SyscQuirks::QUIRK_NO_RESET_ON_INIT) {
235 self.softreset()?;
236 }
237
238 self.enable_module();
239 self.power_state = PowerState::On;
240 Ok(())
241 }
242
243 fn shutdown(&mut self) -> Result<(), BusError> {
245 self.disable_module();
246 self.power_state = PowerState::Off;
247 Ok(())
248 }
249
250 fn suspend(&mut self) -> Result<(), BusError> {
252 self.disable_module();
253 self.power_state = PowerState::Suspended;
254 Ok(())
255 }
256
257 fn resume(&mut self) -> Result<(), BusError> {
259 if self.quirks.contains(SyscQuirks::QUIRK_REINIT_ON_CTX_LOST) {
260 self.softreset()?;
261 }
262 self.enable_module();
263 self.power_state = PowerState::On;
264 Ok(())
265 }
266
267 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
269 if !self.regs.is_valid() {
270 return Err(BusError::InitFailed);
271 }
272 Ok(self.regs.read32(offset))
273 }
274
275 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
277 if !self.regs.is_valid() {
278 return Err(BusError::InitFailed);
279 }
280 self.regs.write32(offset, value);
281 Ok(())
282 }
283
284 fn children(&self) -> Vec<BusChild> {
286 self.children.clone()
287 }
288}