xref: /linux/samples/rust/rust_driver_platform.rs (revision 2a1ea59de83bf367215e2a4dd9bf8bbd061349b3)
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