diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2025-02-25 16:03:25 -0800 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2025-02-25 16:03:25 -0800 | 
| commit | 0b119045b79a672bc6d8f18641c60fc8ce1b4585 (patch) | |
| tree | 69c63ecfec55b9576c34dc742e0c38f46f8a317a /rust/kernel/of.rs | |
| parent | 7f7573bd4f37d4edc168c5b5def0bc2a1951c657 (diff) | |
| parent | d082ecbc71e9e0bf49883ee4afd435a77a5101b6 (diff) | |
Merge tag 'v6.14-rc4' into next
Sync up with the mainline.
Diffstat (limited to 'rust/kernel/of.rs')
| -rw-r--r-- | rust/kernel/of.rs | 60 | 
1 files changed, 60 insertions, 0 deletions
| diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs new file mode 100644 index 000000000000..04f2d8ef29cb --- /dev/null +++ b/rust/kernel/of.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Device Tree / Open Firmware abstractions. + +use crate::{bindings, device_id::RawDeviceId, prelude::*}; + +/// IdTable type for OF drivers. +pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; + +/// An open firmware device id. +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct DeviceId(bindings::of_device_id); + +// SAFETY: +// * `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and does not add +//   additional invariants, so it's safe to transmute to `RawType`. +// * `DRIVER_DATA_OFFSET` is the offset to the `data` field. +unsafe impl RawDeviceId for DeviceId { +    type RawType = bindings::of_device_id; + +    const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data); + +    fn index(&self) -> usize { +        self.0.data as _ +    } +} + +impl DeviceId { +    /// Create a new device id from an OF 'compatible' string. +    pub const fn new(compatible: &'static CStr) -> Self { +        let src = compatible.as_bytes_with_nul(); +        // Replace with `bindings::of_device_id::default()` once stabilized for `const`. +        // SAFETY: FFI type is valid to be zero-initialized. +        let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() }; + +        // TODO: Use `clone_from_slice` once the corresponding types do match. +        let mut i = 0; +        while i < src.len() { +            of.compatible[i] = src[i] as _; +            i += 1; +        } + +        Self(of) +    } +} + +/// Create an OF `IdTable` with an "alias" for modpost. +#[macro_export] +macro_rules! of_device_table { +    ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { +        const $table_name: $crate::device_id::IdArray< +            $crate::of::DeviceId, +            $id_info_type, +            { $table_data.len() }, +        > = $crate::device_id::IdArray::new($table_data); + +        $crate::module_device_table!("of", $module_table_name, $table_name); +    }; +} | 
