@@ -17,7 +17,7 @@ use proc_macro2::{Ident, TokenStream};
1717use quote:: { format_ident, quote} ;
1818use 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
2222use 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" ) ]
185248pub enum RawInfo {
0 commit comments