1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
macro_rules! define_register {
[ $name:ident ] => {
#[allow(non_snake_case)]
mod $name {
use kernel::common::volatile_cell::VolatileCell;
pub struct $name(pub VolatileCell<u32>);
}
};
}
macro_rules! impl_register {
[ $name:ident, "RW" ] => {
impl ::usbc::common::register::RegisterRW for $name::$name {
#[inline]
fn read(&self) -> u32 {
self.0.get()
}
#[inline]
fn write(&self, val: u32) {
self.0.set(val);
}
}
};
[ $name:ident, "R" ] => {
impl ::usbc::common::register::RegisterR for $name::$name {
#[inline]
fn read(&self) -> u32 {
self.0.get()
}
}
};
[ $name:ident, "W" ] => {
impl ::usbc::common::register::RegisterW for $name::$name {
#[inline]
fn write(&self, val: u32) {
self.0.set(val);
}
}
};
}
#[macro_export]
macro_rules! register {
[ $base:expr, $offset:expr, $description:expr, $name:ident, $access:tt ] => {
define_register!($name);
impl_register!($name, $access);
pub const $name: ::kernel::common::static_ref::StaticRef<$name::$name> =
unsafe {
::kernel::common::static_ref::StaticRef::new(
($base + $offset) as *const $name::$name)
};
};
[ $base:expr, $offset:expr, $description:expr, $name:ident, $access:tt, $count:expr ] => {
define_register!($name);
impl_register!($name, $access);
pub const $name: ::kernel::common::static_ref::StaticRef<[$name::$name; $count]> =
unsafe {
::kernel::common::static_ref::StaticRef::new(
($base + $offset) as *const [$name::$name; $count])
};
};
}
#[macro_export]
macro_rules! registers {
[ $base:expr, {
$( $offset:expr => { $( $arg:tt ),* } ),*
} ] => {
$( register![ $base, $offset, $( $arg ),* ]; )*
};
}
#[macro_export]
macro_rules! bitfield {
[ $reg:ident, $field:ident, "RW", $valty:ty, $shift:expr, $mask:expr ] => {
#[allow(non_snake_case)]
mod $field {
pub struct $field;
}
impl $field::$field {
pub fn write(self, val: $valty) {
use usbc::common::register::*;
let w = $reg.read();
let val_bits = (val.to_word() & $mask) << $shift;
$reg.write((w & !($mask << $shift)) | val_bits);
}
}
pub const $field: $field::$field = $field::$field;
};
[ $reg:ident, $field:ident, "R", $valty:ty, $shift:expr, $mask:expr ] => {
#[allow(non_snake_case)]
mod $field {
pub struct $field;
}
impl $field::$field {
pub fn read(self) -> $valty {
use usbc::common::register::*;
FromWord::from_word(($reg.read() >> $shift) & $mask)
}
}
pub const $field: $field::$field = $field::$field;
};
}