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