Skip to content

Commit 0480107

Browse files
committed
zephyr-build: All augments for gpios
This isn't really quite right, as the "unique" values here are per pin, and if the pin were to be used across the system, nothing would enforce these to be unique. Signed-off-by: David Brown <[email protected]>
1 parent 389948d commit 0480107

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

zephyr-build/src/devicetree.rs

+7
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ impl Word {
271271
_ => None,
272272
}
273273
}
274+
275+
pub fn get_phandle(&self) -> Option<&Phandle> {
276+
match self {
277+
Word::Phandle(ph) => Some(ph),
278+
_ => None,
279+
}
280+
}
274281
}
275282

276283
// To avoid recursion, the debug printer for Phandle just prints the name.

zephyr-build/src/devicetree/augment.rs

+64-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use proc_macro2::{Ident, TokenStream};
1717
use quote::{format_ident, quote};
1818
use serde::{Deserialize, Serialize};
1919

20-
use crate::devicetree::{output::dt_to_lower_id, Word};
20+
use crate::devicetree::{output::dt_to_lower_id, Value, Word};
2121

2222
use super::{DeviceTree, Node};
2323

@@ -145,6 +145,13 @@ pub enum Action {
145145
/// in.
146146
kconfig: Option<String>,
147147
},
148+
/// Generate a getter for a gpio assignment property.
149+
GpioPins {
150+
/// The name of the property holding the pins.
151+
property: String,
152+
/// The name of the getter function.
153+
getter: String,
154+
},
148155
/// Generate all of the labels as its own node.
149156
Labels,
150157
}
@@ -155,6 +162,38 @@ impl Action {
155162
Action::Instance { raw, device, kconfig } => {
156163
raw.generate(node, device, kconfig.as_deref())
157164
}
165+
Action::GpioPins { property, getter } => {
166+
let upper_getter = getter.to_uppercase();
167+
let getter = format_ident!("{}", getter);
168+
// TODO: This isn't actually right, these unique values should be based on the pin
169+
// definition so that we'll get a compile error if two parts of the DT reference the
170+
// same pin.
171+
172+
let pins = node.get_property(property).unwrap();
173+
let npins = pins.len();
174+
175+
let uniques: Vec<_> = (0..npins).map(|n| {
176+
format_ident!("{}_UNIQUE_{}", upper_getter, n)
177+
}).collect();
178+
179+
let pins = pins
180+
.iter()
181+
.zip(uniques.iter())
182+
.map(|(pin, unique)| decode_gpios_gpio(unique, pin));
183+
184+
let unique_defs = uniques.iter().map(|u| {
185+
quote! {
186+
static #u: crate::device::Unique = crate::device::Unique::new();
187+
}
188+
});
189+
190+
quote! {
191+
#(#unique_defs)*
192+
pub fn #getter() -> [Option<crate::device::gpio::GpioPin>; #npins] {
193+
[#(#pins),*]
194+
}
195+
}
196+
}
158197
Action::Labels => {
159198
let nodes = tree.labels.iter().map(|(k, v)| {
160199
let name = dt_to_lower_id(k);
@@ -180,6 +219,30 @@ impl Action {
180219
}
181220
}
182221

222+
/// Decode a single gpio entry.
223+
fn decode_gpios_gpio(unique: &Ident, entry: &Value) -> TokenStream {
224+
let entry = if let Value::Words(w) = entry {
225+
w
226+
} else {
227+
panic!("gpios list is not list of <&gpionnn aa bbb>");
228+
};
229+
if entry.len() != 3 {
230+
panic!("gpios currently must be three items");
231+
}
232+
let gpio_route = entry[0].get_phandle().unwrap().node_ref().route_to_rust();
233+
let args: Vec<u32> = entry[1..].iter().map(|n| n.get_number().unwrap()).collect();
234+
235+
quote! {
236+
// TODO: Don't hard code this but put in yaml file.
237+
unsafe {
238+
crate::device::gpio::GpioPin::new(
239+
&#unique,
240+
#gpio_route :: get_instance_raw(),
241+
#(#args),*)
242+
}
243+
}
244+
}
245+
183246
#[derive(Debug, Serialize, Deserialize)]
184247
#[serde(tag = "type", rename_all = "snake_case", content = "value")]
185248
pub enum RawInfo {

0 commit comments

Comments
 (0)