Skip to main content

strat9_bus_drivers/
imx_weim.rs

1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const MAX_CS_REGS_COUNT: usize = 6;
5const MAX_CS_COUNT: usize = 6;
6
7const COMPATIBLE: &[&str] = &[
8    "fsl,imx1-weim",
9    "fsl,imx27-weim",
10    "fsl,imx50-weim",
11    "fsl,imx51-weim",
12    "fsl,imx6q-weim",
13];
14
15#[derive(Clone, Copy)]
16pub struct WeimDevtype {
17    pub cs_count: usize,
18    pub cs_regs_count: usize,
19    pub cs_stride: usize,
20    pub wcr_offset: usize,
21    pub wcr_bcm: u32,
22    pub wcr_cont_bclk: u32,
23}
24
25pub const IMX1_WEIM: WeimDevtype = WeimDevtype {
26    cs_count: 6,
27    cs_regs_count: 2,
28    cs_stride: 0x08,
29    wcr_offset: 0,
30    wcr_bcm: 0,
31    wcr_cont_bclk: 0,
32};
33
34pub const IMX27_WEIM: WeimDevtype = WeimDevtype {
35    cs_count: 6,
36    cs_regs_count: 3,
37    cs_stride: 0x10,
38    wcr_offset: 0,
39    wcr_bcm: 0,
40    wcr_cont_bclk: 0,
41};
42
43pub const IMX50_WEIM: WeimDevtype = WeimDevtype {
44    cs_count: 4,
45    cs_regs_count: 6,
46    cs_stride: 0x18,
47    wcr_offset: 0x90,
48    wcr_bcm: 1 << 0,
49    wcr_cont_bclk: 1 << 3,
50};
51
52pub const IMX51_WEIM: WeimDevtype = WeimDevtype {
53    cs_count: 6,
54    cs_regs_count: 6,
55    cs_stride: 0x18,
56    wcr_offset: 0,
57    wcr_bcm: 0,
58    wcr_cont_bclk: 0,
59};
60
61pub struct CsTiming {
62    pub is_applied: bool,
63    pub regs: [u32; MAX_CS_REGS_COUNT],
64}
65
66impl CsTiming {
67    /// Creates a new instance.
68    pub const fn new() -> Self {
69        Self {
70            is_applied: false,
71            regs: [0; MAX_CS_REGS_COUNT],
72        }
73    }
74}
75
76pub struct ImxWeim {
77    regs: MmioRegion,
78    devtype: WeimDevtype,
79    timings: [CsTiming; MAX_CS_COUNT],
80    power_state: PowerState,
81    children: Vec<BusChild>,
82}
83
84impl ImxWeim {
85    /// Creates a new instance.
86    pub fn new(devtype: WeimDevtype) -> Self {
87        Self {
88            regs: MmioRegion::new(),
89            devtype,
90            timings: [const { CsTiming::new() }; MAX_CS_COUNT],
91            power_state: PowerState::Off,
92            children: Vec::new(),
93        }
94    }
95
96    /// Sets cs timing.
97    pub fn set_cs_timing(&mut self, cs: usize, regs: &[u32]) {
98        if cs >= self.devtype.cs_count || regs.len() > self.devtype.cs_regs_count {
99            return;
100        }
101        for (i, &val) in regs.iter().enumerate() {
102            self.timings[cs].regs[i] = val;
103        }
104        self.timings[cs].is_applied = true;
105    }
106
107    /// Performs the apply timings operation.
108    pub fn apply_timings(&self) {
109        for cs in 0..self.devtype.cs_count {
110            if !self.timings[cs].is_applied {
111                continue;
112            }
113            let base = cs * self.devtype.cs_stride;
114            for i in 0..self.devtype.cs_regs_count {
115                self.regs.write32(base + i * 4, self.timings[cs].regs[i]);
116            }
117        }
118    }
119
120    /// Sets burst clock.
121    pub fn set_burst_clock(&self, enable: bool) {
122        if self.devtype.wcr_offset == 0 {
123            return;
124        }
125        let mut wcr = self.regs.read32(self.devtype.wcr_offset);
126        if enable {
127            wcr |= self.devtype.wcr_bcm;
128        } else {
129            wcr &= !self.devtype.wcr_bcm;
130        }
131        self.regs.write32(self.devtype.wcr_offset, wcr);
132    }
133
134    /// Performs the add child operation.
135    pub fn add_child(&mut self, child: BusChild) {
136        self.children.push(child);
137    }
138}
139
140impl BusDriver for ImxWeim {
141    /// Performs the name operation.
142    fn name(&self) -> &str {
143        "imx-weim"
144    }
145
146    /// Performs the compatible operation.
147    fn compatible(&self) -> &[&str] {
148        COMPATIBLE
149    }
150
151    /// Performs the init operation.
152    fn init(&mut self, base: usize) -> Result<(), BusError> {
153        let size = self.devtype.cs_count * self.devtype.cs_stride + 0x100;
154        self.regs.init(base, size);
155        self.apply_timings();
156        self.power_state = PowerState::On;
157        Ok(())
158    }
159
160    /// Performs the shutdown operation.
161    fn shutdown(&mut self) -> Result<(), BusError> {
162        self.power_state = PowerState::Off;
163        Ok(())
164    }
165
166    /// Reads reg.
167    fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
168        if !self.regs.is_valid() {
169            return Err(BusError::InitFailed);
170        }
171        Ok(self.regs.read32(offset))
172    }
173
174    /// Writes reg.
175    fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
176        if !self.regs.is_valid() {
177            return Err(BusError::InitFailed);
178        }
179        self.regs.write32(offset, value);
180        Ok(())
181    }
182
183    /// Performs the children operation.
184    fn children(&self) -> Vec<BusChild> {
185        self.children.clone()
186    }
187}