1 // SPDX-License-Identifier: GPL-2.0 2 3 //! `register!` macro to define register layout and accessors. 4 //! 5 //! A single register typically includes several fields, which are accessed through a combination 6 //! of bit-shift and mask operations that introduce a class of potential mistakes, notably because 7 //! not all possible field values are necessarily valid. 8 //! 9 //! The `register!` macro in this module provides an intuitive and readable syntax for defining a 10 //! dedicated type for each register. Each such type comes with its own field accessors that can 11 //! return an error if a field's value is invalid. 12 13 /// Trait providing a base address to be added to the offset of a relative register to obtain 14 /// its actual offset. 15 /// 16 /// The `T` generic argument is used to distinguish which base to use, in case a type provides 17 /// several bases. It is given to the `register!` macro to restrict the use of the register to 18 /// implementors of this particular variant. 19 pub(crate) trait RegisterBase<T> { 20 const BASE: usize; 21 } 22 23 /// Defines a dedicated type for a register with an absolute offset, including getter and setter 24 /// methods for its fields and methods to read and write it from an `Io` region. 25 /// 26 /// Example: 27 /// 28 /// ```no_run 29 /// register!(BOOT_0 @ 0x00000100, "Basic revision information about the GPU" { 30 /// 3:0 minor_revision as u8, "Minor revision of the chip"; 31 /// 7:4 major_revision as u8, "Major revision of the chip"; 32 /// 28:20 chipset as u32 ?=> Chipset, "Chipset model"; 33 /// }); 34 /// ``` 35 /// 36 /// This defines a `BOOT_0` type which can be read or written from offset `0x100` of an `Io` 37 /// region. It is composed of 3 fields, for instance `minor_revision` is made of the 4 least 38 /// significant bits of the register. Each field can be accessed and modified using accessor 39 /// methods: 40 /// 41 /// ```no_run 42 /// // Read from the register's defined offset (0x100). 43 /// let boot0 = BOOT_0::read(&bar); 44 /// pr_info!("chip revision: {}.{}", boot0.major_revision(), boot0.minor_revision()); 45 /// 46 /// // `Chipset::try_from` is called with the value of the `chipset` field and returns an 47 /// // error if it is invalid. 48 /// let chipset = boot0.chipset()?; 49 /// 50 /// // Update some fields and write the value back. 51 /// boot0.set_major_revision(3).set_minor_revision(10).write(&bar); 52 /// 53 /// // Or, just read and update the register in a single step: 54 /// BOOT_0::alter(&bar, |r| r.set_major_revision(3).set_minor_revision(10)); 55 /// ``` 56 /// 57 /// Fields are defined as follows: 58 /// 59 /// - `as <type>` simply returns the field value casted to <type>, typically `u32`, `u16`, `u8` or 60 /// `bool`. Note that `bool` fields must have a range of 1 bit. 61 /// - `as <type> => <into_type>` calls `<into_type>`'s `From::<<type>>` implementation and returns 62 /// the result. 63 /// - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation 64 /// and returns the result. This is useful with fields for which not all values are valid. 65 /// 66 /// The documentation strings are optional. If present, they will be added to the type's 67 /// definition, or the field getter and setter methods they are attached to. 68 /// 69 /// It is also possible to create a alias register by using the `=> ALIAS` syntax. This is useful 70 /// for cases where a register's interpretation depends on the context: 71 /// 72 /// ```no_run 73 /// register!(SCRATCH @ 0x00000200, "Scratch register" { 74 /// 31:0 value as u32, "Raw value"; 75 /// }); 76 /// 77 /// register!(SCRATCH_BOOT_STATUS => SCRATCH, "Boot status of the firmware" { 78 /// 0:0 completed as bool, "Whether the firmware has completed booting"; 79 /// }); 80 /// ``` 81 /// 82 /// In this example, `SCRATCH_0_BOOT_STATUS` uses the same I/O address as `SCRATCH`, while also 83 /// providing its own `completed` field. 84 /// 85 /// ## Relative registers 86 /// 87 /// A register can be defined as being accessible from a fixed offset of a provided base. For 88 /// instance, imagine the following I/O space: 89 /// 90 /// ```text 91 /// +-----------------------------+ 92 /// | ... | 93 /// | | 94 /// 0x100--->+------------CPU0-------------+ 95 /// | | 96 /// 0x110--->+-----------------------------+ 97 /// | CPU_CTL | 98 /// +-----------------------------+ 99 /// | ... | 100 /// | | 101 /// | | 102 /// 0x200--->+------------CPU1-------------+ 103 /// | | 104 /// 0x210--->+-----------------------------+ 105 /// | CPU_CTL | 106 /// +-----------------------------+ 107 /// | ... | 108 /// +-----------------------------+ 109 /// ``` 110 /// 111 /// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset `0x10` of their I/O 112 /// space segment. Since both instances of `CPU_CTL` share the same layout, we don't want to define 113 /// them twice and would prefer a way to select which one to use from a single definition 114 /// 115 /// This can be done using the `Base[Offset]` syntax when specifying the register's address. 116 /// 117 /// `Base` is an arbitrary type (typically a ZST) to be used as a generic parameter of the 118 /// [`RegisterBase`] trait to provide the base as a constant, i.e. each type providing a base for 119 /// this register needs to implement `RegisterBase<Base>`. Here is the above example translated 120 /// into code: 121 /// 122 /// ```no_run 123 /// // Type used to identify the base. 124 /// pub(crate) struct CpuCtlBase; 125 /// 126 /// // ZST describing `CPU0`. 127 /// struct Cpu0; 128 /// impl RegisterBase<CpuCtlBase> for Cpu0 { 129 /// const BASE: usize = 0x100; 130 /// } 131 /// // Singleton of `CPU0` used to identify it. 132 /// const CPU0: Cpu0 = Cpu0; 133 /// 134 /// // ZST describing `CPU1`. 135 /// struct Cpu1; 136 /// impl RegisterBase<CpuCtlBase> for Cpu1 { 137 /// const BASE: usize = 0x200; 138 /// } 139 /// // Singleton of `CPU1` used to identify it. 140 /// const CPU1: Cpu1 = Cpu1; 141 /// 142 /// // This makes `CPU_CTL` accessible from all implementors of `RegisterBase<CpuCtlBase>`. 143 /// register!(CPU_CTL @ CpuCtlBase[0x10], "CPU core control" { 144 /// 0:0 start as bool, "Start the CPU core"; 145 /// }); 146 /// 147 /// // The `read`, `write` and `alter` methods of relative registers take an extra `base` argument 148 /// // that is used to resolve its final address by adding its `BASE` to the offset of the 149 /// // register. 150 /// 151 /// // Start `CPU0`. 152 /// CPU_CTL::alter(bar, &CPU0, |r| r.set_start(true)); 153 /// 154 /// // Start `CPU1`. 155 /// CPU_CTL::alter(bar, &CPU1, |r| r.set_start(true)); 156 /// 157 /// // Aliases can also be defined for relative register. 158 /// register!(CPU_CTL_ALIAS => CpuCtlBase[CPU_CTL], "Alias to CPU core control" { 159 /// 1:1 alias_start as bool, "Start the aliased CPU core"; 160 /// }); 161 /// 162 /// // Start the aliased `CPU0`. 163 /// CPU_CTL_ALIAS::alter(bar, &CPU0, |r| r.set_alias_start(true)); 164 /// ``` 165 macro_rules! register { 166 // Creates a register at a fixed offset of the MMIO space. 167 ($name:ident @ $offset:literal $(, $comment:literal)? { $($fields:tt)* } ) => { 168 register!(@core $name $(, $comment)? { $($fields)* } ); 169 register!(@io_fixed $name @ $offset); 170 }; 171 172 // Creates an alias register of fixed offset register `alias` with its own fields. 173 ($name:ident => $alias:ident $(, $comment:literal)? { $($fields:tt)* } ) => { 174 register!(@core $name $(, $comment)? { $($fields)* } ); 175 register!(@io_fixed $name @ $alias::OFFSET); 176 }; 177 178 // Creates a register at a relative offset from a base address provider. 179 ($name:ident @ $base:ty [ $offset:literal ] $(, $comment:literal)? { $($fields:tt)* } ) => { 180 register!(@core $name $(, $comment)? { $($fields)* } ); 181 register!(@io_relative $name @ $base [ $offset ]); 182 }; 183 184 // Creates an alias register of relative offset register `alias` with its own fields. 185 ($name:ident => $base:ty [ $alias:ident ] $(, $comment:literal)? { $($fields:tt)* }) => { 186 register!(@core $name $(, $comment)? { $($fields)* } ); 187 register!(@io_relative $name @ $base [ $alias::OFFSET ]); 188 }; 189 190 // All rules below are helpers. 191 192 // Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`, 193 // `Default`, `BitOr`, and conversion to the value type) and field accessor methods. 194 (@core $name:ident $(, $comment:literal)? { $($fields:tt)* }) => { 195 $( 196 #[doc=$comment] 197 )? 198 #[repr(transparent)] 199 #[derive(Clone, Copy)] 200 pub(crate) struct $name(u32); 201 202 impl ::core::ops::BitOr for $name { 203 type Output = Self; 204 205 fn bitor(self, rhs: Self) -> Self::Output { 206 Self(self.0 | rhs.0) 207 } 208 } 209 210 impl ::core::convert::From<$name> for u32 { 211 fn from(reg: $name) -> u32 { 212 reg.0 213 } 214 } 215 216 register!(@fields_dispatcher $name { $($fields)* }); 217 }; 218 219 // Captures the fields and passes them to all the implementers that require field information. 220 // 221 // Used to simplify the matching rules for implementers, so they don't need to match the entire 222 // complex fields rule even though they only make use of part of it. 223 (@fields_dispatcher $name:ident { 224 $($hi:tt:$lo:tt $field:ident as $type:tt 225 $(?=> $try_into_type:ty)? 226 $(=> $into_type:ty)? 227 $(, $comment:literal)? 228 ; 229 )* 230 } 231 ) => { 232 register!(@field_accessors $name { 233 $( 234 $hi:$lo $field as $type 235 $(?=> $try_into_type)? 236 $(=> $into_type)? 237 $(, $comment)? 238 ; 239 )* 240 }); 241 register!(@debug $name { $($field;)* }); 242 register!(@default $name { $($field;)* }); 243 }; 244 245 // Defines all the field getter/methods methods for `$name`. 246 ( 247 @field_accessors $name:ident { 248 $($hi:tt:$lo:tt $field:ident as $type:tt 249 $(?=> $try_into_type:ty)? 250 $(=> $into_type:ty)? 251 $(, $comment:literal)? 252 ; 253 )* 254 } 255 ) => { 256 $( 257 register!(@check_field_bounds $hi:$lo $field as $type); 258 )* 259 260 #[allow(dead_code)] 261 impl $name { 262 $( 263 register!(@field_accessor $name $hi:$lo $field as $type 264 $(?=> $try_into_type)? 265 $(=> $into_type)? 266 $(, $comment)? 267 ; 268 ); 269 )* 270 } 271 }; 272 273 // Boolean fields must have `$hi == $lo`. 274 (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => { 275 #[allow(clippy::eq_op)] 276 const _: () = { 277 ::kernel::build_assert!( 278 $hi == $lo, 279 concat!("boolean field `", stringify!($field), "` covers more than one bit") 280 ); 281 }; 282 }; 283 284 // Non-boolean fields must have `$hi >= $lo`. 285 (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => { 286 #[allow(clippy::eq_op)] 287 const _: () = { 288 ::kernel::build_assert!( 289 $hi >= $lo, 290 concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB") 291 ); 292 }; 293 }; 294 295 // Catches fields defined as `bool` and convert them into a boolean value. 296 ( 297 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as bool => $into_type:ty 298 $(, $comment:literal)?; 299 ) => { 300 register!( 301 @leaf_accessor $name $hi:$lo $field 302 { |f| <$into_type>::from(if f != 0 { true } else { false }) } 303 $into_type => $into_type $(, $comment)?; 304 ); 305 }; 306 307 // Shortcut for fields defined as `bool` without the `=>` syntax. 308 ( 309 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as bool $(, $comment:literal)?; 310 ) => { 311 register!(@field_accessor $name $hi:$lo $field as bool => bool $(, $comment)?;); 312 }; 313 314 // Catches the `?=>` syntax for non-boolean fields. 315 ( 316 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt ?=> $try_into_type:ty 317 $(, $comment:literal)?; 318 ) => { 319 register!(@leaf_accessor $name $hi:$lo $field 320 { |f| <$try_into_type>::try_from(f as $type) } $try_into_type => 321 ::core::result::Result< 322 $try_into_type, 323 <$try_into_type as ::core::convert::TryFrom<$type>>::Error 324 > 325 $(, $comment)?;); 326 }; 327 328 // Catches the `=>` syntax for non-boolean fields. 329 ( 330 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt => $into_type:ty 331 $(, $comment:literal)?; 332 ) => { 333 register!(@leaf_accessor $name $hi:$lo $field 334 { |f| <$into_type>::from(f as $type) } $into_type => $into_type $(, $comment)?;); 335 }; 336 337 // Shortcut for non-boolean fields defined without the `=>` or `?=>` syntax. 338 ( 339 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt 340 $(, $comment:literal)?; 341 ) => { 342 register!(@field_accessor $name $hi:$lo $field as $type => $type $(, $comment)?;); 343 }; 344 345 // Generates the accessor methods for a single field. 346 ( 347 @leaf_accessor $name:ident $hi:tt:$lo:tt $field:ident 348 { $process:expr } $to_type:ty => $res_type:ty $(, $comment:literal)?; 349 ) => { 350 ::kernel::macros::paste!( 351 const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 352 const [<$field:upper _MASK>]: u32 = ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); 353 const [<$field:upper _SHIFT>]: u32 = Self::[<$field:upper _MASK>].trailing_zeros(); 354 ); 355 356 $( 357 #[doc="Returns the value of this field:"] 358 #[doc=$comment] 359 )? 360 #[inline(always)] 361 pub(crate) fn $field(self) -> $res_type { 362 ::kernel::macros::paste!( 363 const MASK: u32 = $name::[<$field:upper _MASK>]; 364 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 365 ); 366 let field = ((self.0 & MASK) >> SHIFT); 367 368 $process(field) 369 } 370 371 ::kernel::macros::paste!( 372 $( 373 #[doc="Sets the value of this field:"] 374 #[doc=$comment] 375 )? 376 #[inline(always)] 377 pub(crate) fn [<set_ $field>](mut self, value: $to_type) -> Self { 378 const MASK: u32 = $name::[<$field:upper _MASK>]; 379 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 380 let value = (u32::from(value) << SHIFT) & MASK; 381 self.0 = (self.0 & !MASK) | value; 382 383 self 384 } 385 ); 386 }; 387 388 // Generates the `Debug` implementation for `$name`. 389 (@debug $name:ident { $($field:ident;)* }) => { 390 impl ::core::fmt::Debug for $name { 391 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { 392 f.debug_struct(stringify!($name)) 393 .field("<raw>", &format_args!("{:#x}", &self.0)) 394 $( 395 .field(stringify!($field), &self.$field()) 396 )* 397 .finish() 398 } 399 } 400 }; 401 402 // Generates the `Default` implementation for `$name`. 403 (@default $name:ident { $($field:ident;)* }) => { 404 /// Returns a value for the register where all fields are set to their default value. 405 impl ::core::default::Default for $name { 406 fn default() -> Self { 407 #[allow(unused_mut)] 408 let mut value = Self(Default::default()); 409 410 ::kernel::macros::paste!( 411 $( 412 value.[<set_ $field>](Default::default()); 413 )* 414 ); 415 416 value 417 } 418 } 419 }; 420 421 // Generates the IO accessors for a fixed offset register. 422 (@io_fixed $name:ident @ $offset:expr) => { 423 #[allow(dead_code)] 424 impl $name { 425 pub(crate) const OFFSET: usize = $offset; 426 427 /// Read the register from its address in `io`. 428 #[inline(always)] 429 pub(crate) fn read<const SIZE: usize, T>(io: &T) -> Self where 430 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 431 { 432 Self(io.read32($offset)) 433 } 434 435 /// Write the value contained in `self` to the register address in `io`. 436 #[inline(always)] 437 pub(crate) fn write<const SIZE: usize, T>(self, io: &T) where 438 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 439 { 440 io.write32(self.0, $offset) 441 } 442 443 /// Read the register from its address in `io` and run `f` on its value to obtain a new 444 /// value to write back. 445 #[inline(always)] 446 pub(crate) fn alter<const SIZE: usize, T, F>( 447 io: &T, 448 f: F, 449 ) where 450 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 451 F: ::core::ops::FnOnce(Self) -> Self, 452 { 453 let reg = f(Self::read(io)); 454 reg.write(io); 455 } 456 } 457 }; 458 459 // Generates the IO accessors for a relative offset register. 460 (@io_relative $name:ident @ $base:ty [ $offset:expr ]) => { 461 #[allow(dead_code)] 462 impl $name { 463 pub(crate) const OFFSET: usize = $offset; 464 465 /// Read the register from `io`, using the base address provided by `base` and adding 466 /// the register's offset to it. 467 #[inline(always)] 468 pub(crate) fn read<const SIZE: usize, T, B>( 469 io: &T, 470 #[allow(unused_variables)] 471 base: &B, 472 ) -> Self where 473 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 474 B: crate::regs::macros::RegisterBase<$base>, 475 { 476 const OFFSET: usize = $name::OFFSET; 477 478 let value = io.read32( 479 <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET 480 ); 481 482 Self(value) 483 } 484 485 /// Write the value contained in `self` to `io`, using the base address provided by 486 /// `base` and adding the register's offset to it. 487 #[inline(always)] 488 pub(crate) fn write<const SIZE: usize, T, B>( 489 self, 490 io: &T, 491 #[allow(unused_variables)] 492 base: &B, 493 ) where 494 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 495 B: crate::regs::macros::RegisterBase<$base>, 496 { 497 const OFFSET: usize = $name::OFFSET; 498 499 io.write32( 500 self.0, 501 <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET 502 ); 503 } 504 505 /// Read the register from `io`, using the base address provided by `base` and adding 506 /// the register's offset to it, then run `f` on its value to obtain a new value to 507 /// write back. 508 #[inline(always)] 509 pub(crate) fn alter<const SIZE: usize, T, B, F>( 510 io: &T, 511 base: &B, 512 f: F, 513 ) where 514 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, 515 B: crate::regs::macros::RegisterBase<$base>, 516 F: ::core::ops::FnOnce(Self) -> Self, 517 { 518 let reg = f(Self::read(io, base)); 519 reg.write(io, base); 520 } 521 } 522 }; 523 } 524