Skip to main content

strat9_bus_drivers/
ti_sysc.rs

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    /// Creates a new instance.
84    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    /// Sets offsets.
99    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    /// Sets quirks.
106    pub fn set_quirks(&mut self, quirks: SyscQuirks) {
107        self.quirks = quirks;
108    }
109
110    /// Performs the add child operation.
111    pub fn add_child(&mut self, child: BusChild) {
112        self.children.push(child);
113    }
114
115    /// Reads sysc.
116    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    /// Writes sysc.
130    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    /// Reads revision.
141    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    /// Enables module.
149    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    /// Disables module.
169    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    /// Performs the softreset operation.
185    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    /// Performs the name operation.
220    fn name(&self) -> &str {
221        "ti-sysc"
222    }
223
224    /// Performs the compatible operation.
225    fn compatible(&self) -> &[&str] {
226        COMPATIBLE
227    }
228
229    /// Performs the init operation.
230    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    /// Performs the shutdown operation.
244    fn shutdown(&mut self) -> Result<(), BusError> {
245        self.disable_module();
246        self.power_state = PowerState::Off;
247        Ok(())
248    }
249
250    /// Performs the suspend operation.
251    fn suspend(&mut self) -> Result<(), BusError> {
252        self.disable_module();
253        self.power_state = PowerState::Suspended;
254        Ok(())
255    }
256
257    /// Performs the resume operation.
258    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    /// Reads reg.
268    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    /// Writes reg.
276    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    /// Performs the children operation.
285    fn children(&self) -> Vec<BusChild> {
286        self.children.clone()
287    }
288}