1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
- //! Amba devices drivers.
3
+ //! Amba devices and drivers.
4
4
//!
5
5
//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
6
6
7
7
use crate :: {
8
8
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 ,
10
10
} ;
11
11
12
12
/// A registration of an amba driver.
13
13
pub type Registration < T > = driver:: Registration < Adapter < T > > ;
14
14
15
15
/// Id of an Amba device.
16
- pub struct DeviceId < T = ( ) > {
16
+ #[ derive( Clone , Copy ) ]
17
+ pub struct DeviceId {
17
18
/// Device id.
18
19
pub id : u32 ,
19
20
20
21
/// Mask that identifies which bits are valid in the device id.
21
22
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
+ } ;
22
33
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
+ }
26
41
}
27
42
28
43
/// An amba driver.
@@ -39,11 +54,11 @@ pub trait Driver {
39
54
/// The type holding information about each device id supported by the driver.
40
55
type IdInfo : ' static = ( ) ;
41
56
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 ;
44
59
45
60
/// 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 > ;
47
62
48
63
/// Cleans any resources up that are associated with the device.
49
64
///
@@ -56,24 +71,22 @@ pub struct Adapter<T: Driver>(T);
56
71
57
72
impl < T : Driver > driver:: DriverOps for Adapter < T > {
58
73
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 ;
62
74
63
75
unsafe fn register (
64
76
reg : * mut bindings:: amba_driver ,
65
77
name : & ' static CStr ,
66
78
module : & ' static ThisModule ,
67
- id_table : * const bindings:: amba_id ,
68
79
) -> Result {
69
80
// SAFETY: By the safety requirements of this function (defined in the trait defintion),
70
81
// `reg` is non-null and valid.
71
82
let amba = unsafe { & mut * reg } ;
72
83
amba. drv . name = name. as_char_ptr ( ) ;
73
84
amba. drv . owner = module. 0 ;
74
- amba. id_table = id_table;
75
85
amba. probe = Some ( probe_callback :: < T > ) ;
76
86
amba. remove = Some ( remove_callback :: < T > ) ;
87
+ if let Some ( t) = T :: ID_TABLE {
88
+ amba. id_table = t. as_ref ( ) ;
89
+ }
77
90
if cfg ! ( CONFIG_PM ) {
78
91
// SAFETY: `probe_callback` sets the driver data after calling `T::Data::into_pointer`,
79
92
// 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> {
90
103
// `reg` was passed (and updated) by a previous successful call to `amba_driver_register`.
91
104
unsafe { bindings:: amba_driver_unregister ( reg) } ;
92
105
}
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
- }
101
106
}
102
107
103
108
unsafe extern "C" fn probe_callback < T : Driver > (
@@ -109,11 +114,18 @@ unsafe extern "C" fn probe_callback<T: Driver>(
109
114
// duration of this call, so it is guaranteed to remain alive for the lifetime of `dev`.
110
115
let mut dev = unsafe { Device :: from_ptr( adev) } ;
111
116
// 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) ?;
117
129
let ptr = T :: Data :: into_pointer( data) ;
118
130
// SAFETY: `adev` is valid for write by the contract with the C code.
119
131
unsafe { bindings:: amba_set_drvdata( adev, ptr as _) } ;
@@ -193,17 +205,17 @@ unsafe impl device::RawDevice for Device {
193
205
///
194
206
/// ```ignore
195
207
/// # 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};
197
209
/// #
198
210
/// struct MyDriver;
199
211
/// impl amba::Driver for MyDriver {
200
212
/// // [...]
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 {
202
214
/// # Ok(())
203
215
/// # }
204
- /// # declare_amba_id_table! [
205
- /// # { id: 0x00041061, mask: 0x000fffff, data: () } ,
206
- /// # ];
216
+ /// # define_amba_id_table! {(), [
217
+ /// # ( { id: 0x00041061, mask: 0x000fffff }, None) ,
218
+ /// # ]}
207
219
/// }
208
220
///
209
221
/// module_amba_driver! {
@@ -220,34 +232,28 @@ macro_rules! module_amba_driver {
220
232
} ;
221
233
}
222
234
223
- /// Declares the id table for amba devices.
235
+ /// Defines the id table for amba devices.
224
236
///
225
237
/// # Examples
226
238
///
227
239
/// ```
228
240
/// # use kernel::prelude::*;
229
- /// # use kernel::{amba, declare_amba_id_table };
241
+ /// # use kernel::{amba, define_amba_id_table };
230
242
/// #
231
243
/// # struct Sample;
232
244
/// # 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 {
234
246
/// # Ok(())
235
247
/// # }
236
- /// declare_amba_id_table! [
237
- /// { id: 0x00041061, mask: 0x000fffff, data: () } ,
238
- /// ];
248
+ /// define_amba_id_table! {(), [
249
+ /// ( { id: 0x00041061, mask: 0x000fffff }, None) ,
250
+ /// ]}
239
251
/// # }
240
252
/// ```
241
253
#[ 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) * ) ;
247
258
} ;
248
-
249
- // Cover case without a trailing comma.
250
- ( $( ( $( $entry: tt) * ) ) ,* ) => {
251
- $crate:: declare_amba_id_table!{ $( { $( $entry) * } , ) * }
252
- }
253
259
}
0 commit comments