1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Rust Platform driver sample. 4 5 use kernel::{ 6 c_str, 7 device::{ 8 self, 9 property::{FwNodeReferenceArgs, NArgs}, 10 Core, 11 }, 12 of, platform, 13 prelude::*, 14 str::CString, 15 types::ARef, 16 }; 17 18 struct SampleDriver { 19 pdev: ARef<platform::Device>, 20 } 21 22 struct Info(u32); 23 24 kernel::of_device_table!( 25 OF_TABLE, 26 MODULE_OF_TABLE, 27 <SampleDriver as platform::Driver>::IdInfo, 28 [(of::DeviceId::new(c_str!("test,rust-device")), Info(42))] 29 ); 30 31 impl platform::Driver for SampleDriver { 32 type IdInfo = Info; 33 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 34 35 fn probe( 36 pdev: &platform::Device<Core>, 37 info: Option<&Self::IdInfo>, 38 ) -> Result<Pin<KBox<Self>>> { 39 dev_dbg!(pdev.as_ref(), "Probe Rust Platform driver sample.\n"); 40 41 if let Some(info) = info { 42 dev_info!(pdev.as_ref(), "Probed with info: '{}'.\n", info.0); 43 } 44 45 Self::properties_parse(pdev.as_ref())?; 46 47 let drvdata = KBox::new(Self { pdev: pdev.into() }, GFP_KERNEL)?; 48 49 Ok(drvdata.into()) 50 } 51 } 52 53 impl SampleDriver { 54 fn properties_parse(dev: &device::Device) -> Result { 55 let fwnode = dev.fwnode().ok_or(ENOENT)?; 56 57 if let Ok(idx) = 58 fwnode.property_match_string(c_str!("compatible"), c_str!("test,rust-device")) 59 { 60 dev_info!(dev, "matched compatible string idx = {}\n", idx); 61 } 62 63 let name = c_str!("compatible"); 64 let prop = fwnode.property_read::<CString>(name).required_by(dev)?; 65 dev_info!(dev, "'{name}'='{prop:?}'\n"); 66 67 let name = c_str!("test,bool-prop"); 68 let prop = fwnode.property_read_bool(c_str!("test,bool-prop")); 69 dev_info!(dev, "'{name}'='{prop}'\n"); 70 71 if fwnode.property_present(c_str!("test,u32-prop")) { 72 dev_info!(dev, "'test,u32-prop' is present\n"); 73 } 74 75 let name = c_str!("test,u32-optional-prop"); 76 let prop = fwnode.property_read::<u32>(name).or(0x12); 77 dev_info!(dev, "'{name}'='{prop:#x}' (default = 0x12)\n",); 78 79 // A missing required property will print an error. Discard the error to 80 // prevent properties_parse from failing in that case. 81 let name = c_str!("test,u32-required-prop"); 82 let _ = fwnode.property_read::<u32>(name).required_by(dev); 83 84 let name = c_str!("test,u32-prop"); 85 let prop: u32 = fwnode.property_read(name).required_by(dev)?; 86 dev_info!(dev, "'{name}'='{prop:#x}'\n"); 87 88 let name = c_str!("test,i16-array"); 89 let prop: [i16; 4] = fwnode.property_read(name).required_by(dev)?; 90 dev_info!(dev, "'{name}'='{prop:?}'\n"); 91 let len = fwnode.property_count_elem::<u16>(name)?; 92 dev_info!(dev, "'{name}' length is {len}\n",); 93 94 let name = c_str!("test,i16-array"); 95 let prop: KVec<i16> = fwnode.property_read_array_vec(name, 4)?.required_by(dev)?; 96 dev_info!(dev, "'{name}'='{prop:?}' (KVec)\n"); 97 98 for child in fwnode.children() { 99 let name = c_str!("test,ref-arg"); 100 let nargs = NArgs::N(2); 101 let prop: FwNodeReferenceArgs = child.property_get_reference_args(name, nargs, 0)?; 102 dev_info!(dev, "'{name}'='{prop:?}'\n"); 103 } 104 105 Ok(()) 106 } 107 } 108 109 impl Drop for SampleDriver { 110 fn drop(&mut self) { 111 dev_dbg!(self.pdev.as_ref(), "Remove Rust Platform driver sample.\n"); 112 } 113 } 114 115 kernel::module_platform_driver! { 116 type: SampleDriver, 117 name: "rust_driver_platform", 118 authors: ["Danilo Krummrich"], 119 description: "Rust Platform driver", 120 license: "GPL v2", 121 } 122