strat9_bus_drivers/
intel_ixp4xx_eb.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const IXP4XX_EXP_CS_EN: u32 = 1 << 31;
5const IXP456_EXP_PAR_EN: u32 = 1 << 30;
6const IXP4XX_EXP_T1_MASK: u32 = 0x3 << 28;
7const IXP4XX_EXP_T1_SHIFT: u32 = 28;
8const IXP4XX_EXP_T2_MASK: u32 = 0x3 << 26;
9const IXP4XX_EXP_T2_SHIFT: u32 = 26;
10const IXP4XX_EXP_T3_MASK: u32 = 0xF << 22;
11const IXP4XX_EXP_T3_SHIFT: u32 = 22;
12const IXP4XX_EXP_T4_MASK: u32 = 0x3 << 20;
13const IXP4XX_EXP_T4_SHIFT: u32 = 20;
14const IXP4XX_EXP_T5_MASK: u32 = 0xF << 16;
15const IXP4XX_EXP_T5_SHIFT: u32 = 16;
16const IXP4XX_EXP_CYC_TYPE_MASK: u32 = 0x3 << 14;
17const IXP4XX_EXP_CYC_TYPE_SHIFT: u32 = 14;
18const IXP4XX_EXP_SIZE_MASK: u32 = 0xF << 10;
19const IXP4XX_EXP_SIZE_SHIFT: u32 = 10;
20const IXP4XX_EXP_BYTE_RD16: u32 = 1 << 6;
21const IXP4XX_EXP_HRDY_POL: u32 = 1 << 5;
22const IXP4XX_EXP_MUX_EN: u32 = 1 << 4;
23const IXP4XX_EXP_SPLT_EN: u32 = 1 << 3;
24const IXP4XX_EXP_WR_EN: u32 = 1 << 1;
25const IXP4XX_EXP_BYTE_EN: u32 = 1 << 0;
26
27const IXP4XX_EXP_CNFG0: usize = 0x20;
28const IXP4XX_EXP_CNFG0_MEM_MAP: u32 = 1 << 31;
29
30const BOOT_BASE: u64 = 0x0000_0000;
31const NORMAL_BASE: u64 = 0x5000_0000;
32const CS_STRIDE: u64 = 0x0100_0000;
33const MAX_CS: usize = 8;
34
35const COMPATIBLE: &[&str] = &[
36 "intel,ixp42x-expansion-bus-controller",
37 "intel,ixp43x-expansion-bus-controller",
38 "intel,ixp45x-expansion-bus-controller",
39 "intel,ixp46x-expansion-bus-controller",
40];
41
42pub struct CsTimingConfig {
43 pub t1: u32,
44 pub t2: u32,
45 pub t3: u32,
46 pub t4: u32,
47 pub t5: u32,
48 pub cycle_type: u32,
49 pub byte_rd16: bool,
50 pub mux_en: bool,
51 pub splt_en: bool,
52 pub wr_en: bool,
53 pub byte_en: bool,
54 pub hrdy_pol: bool,
55}
56
57pub struct IntelIxp4xxEb {
58 regs: MmioRegion,
59 bus_base: u64,
60 num_cs: usize,
61 is_42x: bool,
62 is_43x: bool,
63 power_state: PowerState,
64 children: Vec<BusChild>,
65}
66
67impl IntelIxp4xxEb {
68 pub fn new() -> Self {
70 Self {
71 regs: MmioRegion::new(),
72 bus_base: NORMAL_BASE,
73 num_cs: MAX_CS,
74 is_42x: false,
75 is_43x: false,
76 power_state: PowerState::Off,
77 children: Vec::new(),
78 }
79 }
80
81 pub fn set_variant(&mut self, is_42x: bool, is_43x: bool) {
83 self.is_42x = is_42x;
84 self.is_43x = is_43x;
85 if is_43x {
86 self.num_cs = 4;
87 }
88 }
89
90 fn detect_bus_base(&mut self) {
92 let cnfg0 = self.regs.read32(IXP4XX_EXP_CNFG0);
93 self.bus_base = if cnfg0 & IXP4XX_EXP_CNFG0_MEM_MAP != 0 {
94 NORMAL_BASE
95 } else {
96 BOOT_BASE
97 };
98 }
99
100 pub fn configure_cs(&self, cs: usize, config: &CsTimingConfig) -> Result<(), BusError> {
102 if cs >= self.num_cs {
103 return Err(BusError::InvalidArgument);
104 }
105
106 let offset = cs * 4;
107 let mut val = IXP4XX_EXP_CS_EN;
108
109 val |= (config.t1 << IXP4XX_EXP_T1_SHIFT) & IXP4XX_EXP_T1_MASK;
110 val |= (config.t2 << IXP4XX_EXP_T2_SHIFT) & IXP4XX_EXP_T2_MASK;
111 val |= (config.t3 << IXP4XX_EXP_T3_SHIFT) & IXP4XX_EXP_T3_MASK;
112 val |= (config.t4 << IXP4XX_EXP_T4_SHIFT) & IXP4XX_EXP_T4_MASK;
113 val |= (config.t5 << IXP4XX_EXP_T5_SHIFT) & IXP4XX_EXP_T5_MASK;
114 val |= (config.cycle_type << IXP4XX_EXP_CYC_TYPE_SHIFT) & IXP4XX_EXP_CYC_TYPE_MASK;
115
116 if config.byte_rd16 {
117 val |= IXP4XX_EXP_BYTE_RD16;
118 }
119 if config.mux_en {
120 val |= IXP4XX_EXP_MUX_EN;
121 }
122 if config.splt_en {
123 val |= IXP4XX_EXP_SPLT_EN;
124 }
125 if config.wr_en {
126 val |= IXP4XX_EXP_WR_EN;
127 }
128 if config.byte_en {
129 val |= IXP4XX_EXP_BYTE_EN;
130 }
131 if config.hrdy_pol && self.is_42x {
132 val |= IXP4XX_EXP_HRDY_POL;
133 }
134
135 self.regs.write32(offset, val);
136 Ok(())
137 }
138
139 pub fn cs_base_addr(&self, cs: usize) -> u64 {
141 self.bus_base + (cs as u64) * CS_STRIDE
142 }
143
144 pub fn add_child(&mut self, child: BusChild) {
146 self.children.push(child);
147 }
148}
149
150impl BusDriver for IntelIxp4xxEb {
151 fn name(&self) -> &str {
153 "intel-ixp4xx-eb"
154 }
155
156 fn compatible(&self) -> &[&str] {
158 COMPATIBLE
159 }
160
161 fn init(&mut self, base: usize) -> Result<(), BusError> {
163 self.regs.init(base, 0x30);
164 self.detect_bus_base();
165 self.power_state = PowerState::On;
166 Ok(())
167 }
168
169 fn shutdown(&mut self) -> Result<(), BusError> {
171 self.power_state = PowerState::Off;
172 Ok(())
173 }
174
175 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
177 if !self.regs.is_valid() {
178 return Err(BusError::InitFailed);
179 }
180 Ok(self.regs.read32(offset))
181 }
182
183 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
185 if !self.regs.is_valid() {
186 return Err(BusError::InitFailed);
187 }
188 self.regs.write32(offset, value);
189 Ok(())
190 }
191
192 fn children(&self) -> Vec<BusChild> {
194 self.children.clone()
195 }
196}