11// SPDX-License-Identifier: GPL-2.0
22
3- //! Amba devices drivers.
3+ //! Amba devices and drivers.
44//!
55//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
66
77use crate :: {
88 bindings, c_types, device, driver, error:: from_kernel_result, io_mem:: Resource , power,
9- str:: CStr , to_result, types:: PointerWrapper , Error , Result , ThisModule ,
9+ str:: CStr , to_result, types:: PointerWrapper , Result , ThisModule ,
1010} ;
1111
1212/// A registration of an amba driver.
1313pub type Registration < T > = driver:: Registration < Adapter < T > > ;
1414
1515/// Id of an Amba device.
16- pub struct DeviceId < T = ( ) > {
16+ #[ derive( Clone , Copy ) ]
17+ pub struct DeviceId {
1718 /// Device id.
1819 pub id : u32 ,
1920
2021 /// Mask that identifies which bits are valid in the device id.
2122 pub mask : u32 ,
23+ }
24+
25+ // SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `amba_id::data`.
26+ unsafe impl const driver:: RawDeviceId for DeviceId {
27+ type RawType = bindings:: amba_id ;
28+ const ZERO : Self :: RawType = bindings:: amba_id {
29+ id : 0 ,
30+ mask : 0 ,
31+ data : core:: ptr:: null_mut ( ) ,
32+ } ;
2233
23- /// Context data to be associated with the device id. This is carried over to [`Driver::probe`]
24- /// so that drivers can encode any information they may need then.
25- pub data : T ,
34+ fn to_rawid ( & self , offset : isize ) -> Self :: RawType {
35+ bindings:: amba_id {
36+ id : self . id ,
37+ mask : self . mask ,
38+ data : offset as _ ,
39+ }
40+ }
2641}
2742
2843/// An amba driver.
@@ -39,11 +54,11 @@ pub trait Driver {
3954 /// The type holding information about each device id supported by the driver.
4055 type IdInfo : ' static = ( ) ;
4156
42- /// The table of device ids supported by the drivers .
43- const ID_TABLE : & ' static [ DeviceId < Self :: IdInfo > ] ;
57+ /// The table of device ids supported by the driver .
58+ const ID_TABLE : Option < driver :: IdTable < ' static , DeviceId , Self :: IdInfo > > = None ;
4459
4560 /// Probes for the device with the given id.
46- fn probe ( dev : & mut Device , id : & DeviceId < Self :: IdInfo > ) -> Result < Self :: Data > ;
61+ fn probe ( dev : & mut Device , id_info : Option < & Self :: IdInfo > ) -> Result < Self :: Data > ;
4762
4863 /// Cleans any resources up that are associated with the device.
4964 ///
@@ -56,24 +71,22 @@ pub struct Adapter<T: Driver>(T);
5671
5772impl < T : Driver > driver:: DriverOps for Adapter < T > {
5873 type RegType = bindings:: amba_driver ;
59- type RawIdType = bindings:: amba_id ;
60- type IdType = DeviceId < T :: IdInfo > ;
61- const ID_TABLE : & ' static [ Self :: IdType ] = T :: ID_TABLE ;
6274
6375 unsafe fn register (
6476 reg : * mut bindings:: amba_driver ,
6577 name : & ' static CStr ,
6678 module : & ' static ThisModule ,
67- id_table : * const bindings:: amba_id ,
6879 ) -> Result {
6980 // SAFETY: By the safety requirements of this function (defined in the trait defintion),
7081 // `reg` is non-null and valid.
7182 let amba = unsafe { & mut * reg } ;
7283 amba. drv . name = name. as_char_ptr ( ) ;
7384 amba. drv . owner = module. 0 ;
74- amba. id_table = id_table;
7585 amba. probe = Some ( probe_callback :: < T > ) ;
7686 amba. remove = Some ( remove_callback :: < T > ) ;
87+ if let Some ( t) = T :: ID_TABLE {
88+ amba. id_table = t. as_ref ( ) ;
89+ }
7790 if cfg ! ( CONFIG_PM ) {
7891 // SAFETY: `probe_callback` sets the driver data after calling `T::Data::into_pointer`,
7992 // and we guarantee that `T::Data` is the same as `T::PowerOps::Data` by a constraint
@@ -90,14 +103,6 @@ impl<T: Driver> driver::DriverOps for Adapter<T> {
90103 // `reg` was passed (and updated) by a previous successful call to `amba_driver_register`.
91104 unsafe { bindings:: amba_driver_unregister ( reg) } ;
92105 }
93-
94- fn to_raw_id ( index : usize , id : & Self :: IdType ) -> Self :: RawIdType {
95- bindings:: amba_id {
96- id : id. id ,
97- mask : id. mask ,
98- data : index as _ ,
99- }
100- }
101106}
102107
103108unsafe extern "C" fn probe_callback < T : Driver > (
@@ -109,11 +114,18 @@ unsafe extern "C" fn probe_callback<T: Driver>(
109114 // duration of this call, so it is guaranteed to remain alive for the lifetime of `dev`.
110115 let mut dev = unsafe { Device :: from_ptr( adev) } ;
111116 // SAFETY: `aid` is valid by the requirements the contract with the C code.
112- let index = unsafe { ( * aid) . data } as usize ;
113- if index >= T :: ID_TABLE . len( ) {
114- return Err ( Error :: ENXIO ) ;
115- }
116- let data = T :: probe( & mut dev, & T :: ID_TABLE [ index] ) ?;
117+ let offset = unsafe { ( * aid) . data } ;
118+ let info = if offset. is_null( ) {
119+ None
120+ } else {
121+ // SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`,
122+ // which guarantees that the resulting pointer is within the table.
123+ let ptr = unsafe { aid. cast:: <u8 >( ) . offset( offset as _) . cast:: <Option <T :: IdInfo >>( ) } ;
124+ // SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for
125+ // read.
126+ unsafe { ( & * ptr) . as_ref( ) }
127+ } ;
128+ let data = T :: probe( & mut dev, info) ?;
117129 let ptr = T :: Data :: into_pointer( data) ;
118130 // SAFETY: `adev` is valid for write by the contract with the C code.
119131 unsafe { bindings:: amba_set_drvdata( adev, ptr as _) } ;
@@ -193,17 +205,17 @@ unsafe impl device::RawDevice for Device {
193205///
194206/// ```ignore
195207/// # use kernel::prelude::*;
196- /// # use kernel::{amba, declare_amba_id_table , module_amba_driver};
208+ /// # use kernel::{amba, define_amba_id_table , module_amba_driver};
197209/// #
198210/// struct MyDriver;
199211/// impl amba::Driver for MyDriver {
200212/// // [...]
201- /// # fn probe(_dev: &mut amba::Device, _id: &amba::DeviceId< Self::IdInfo>) -> Result {
213+ /// # fn probe(_dev: &mut amba::Device, _id: Option<& Self::IdInfo>) -> Result {
202214/// # Ok(())
203215/// # }
204- /// # declare_amba_id_table! [
205- /// # { id: 0x00041061, mask: 0x000fffff, data: () } ,
206- /// # ];
216+ /// # define_amba_id_table! {(), [
217+ /// # ( { id: 0x00041061, mask: 0x000fffff }, None) ,
218+ /// # ]}
207219/// }
208220///
209221/// module_amba_driver! {
@@ -220,34 +232,28 @@ macro_rules! module_amba_driver {
220232 } ;
221233}
222234
223- /// Declares the id table for amba devices.
235+ /// Defines the id table for amba devices.
224236///
225237/// # Examples
226238///
227239/// ```
228240/// # use kernel::prelude::*;
229- /// # use kernel::{amba, declare_amba_id_table };
241+ /// # use kernel::{amba, define_amba_id_table };
230242/// #
231243/// # struct Sample;
232244/// # impl kernel::amba::Driver for Sample {
233- /// # fn probe(_dev: &mut amba::Device, _id: &amba::DeviceId< Self::IdInfo>) -> Result {
245+ /// # fn probe(_dev: &mut amba::Device, _id: Option<& Self::IdInfo>) -> Result {
234246/// # Ok(())
235247/// # }
236- /// declare_amba_id_table! [
237- /// { id: 0x00041061, mask: 0x000fffff, data: () } ,
238- /// ];
248+ /// define_amba_id_table! {(), [
249+ /// ( { id: 0x00041061, mask: 0x000fffff }, None) ,
250+ /// ]}
239251/// # }
240252/// ```
241253#[ macro_export]
242- macro_rules! declare_amba_id_table {
243- ( $( { $( $entry: tt) * } , ) * ) => {
244- const ID_TABLE : & ' static [ $crate:: amba:: DeviceId <Self :: IdInfo >] = & [
245- $( $crate:: amba:: DeviceId { $( $entry) * } , ) *
246- ] ;
254+ macro_rules! define_amba_id_table {
255+ ( $data_type: ty, $( $t: tt) * ) => {
256+ type IdInfo = $data_type;
257+ $crate:: define_id_table!( ID_TABLE , $crate:: amba:: DeviceId , $data_type, $( $t) * ) ;
247258 } ;
248-
249- // Cover case without a trailing comma.
250- ( $( ( $( $entry: tt) * ) ) ,* ) => {
251- $crate:: declare_amba_id_table!{ $( { $( $entry) * } , ) * }
252- }
253259}
0 commit comments