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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
use super::Error;
use crate::prelude::*;
use crate::target::generic::Variant::Val;
const DELAY_PLL_ENABLE_WITH_150K: MicroSeconds = MicroSeconds(80);
const DELAY_PLL_ENABLE_WITH_32K: MicroSeconds = MicroSeconds(160);
const I2C_BLOCK: u8 = 0x66;
mod i2c {
pub const IR_CAL_DELAY: u8 = 0;
pub const IR_CAL_EXT_CAP: u8 = 1;
pub const OC_LREF: u8 = 2;
pub const OC_DIV_7_0: u8 = 3;
pub const OC_ENB_FCAL: u8 = 4;
pub const OC_DCUR: u8 = 5;
pub const BBADC_DSMP: u8 = 9;
pub const OC_ENB_VCON: u8 = 10;
pub const ENDIV5: u8 = 11;
pub const BBADC_CAL_7_0: u8 = 12;
}
mod val {
pub const ENDIV5_VAL_320M: u8 = 0x43;
pub const BBADC_DSMP_VAL_320M: u8 = 0x84;
pub const ENDIV5_VAL_480M: u8 = 0xc3;
pub const BBADC_DSMP_VAL_480M: u8 = 0x74;
pub const IR_CAL_DELAY_VAL: u8 = 0x18;
pub const IR_CAL_EXT_CAP_VAL: u8 = 0x20;
pub const OC_ENB_FCAL_VAL: u8 = 0x9a;
pub const OC_ENB_VCON_VAL: u8 = 0x00;
pub const BBADC_CAL_7_0_VAL: u8 = 0x00;
}
struct Config(u8, u8, u8, u8, u8, u8);
impl Config {
const PLL_320M_XTAL_40M: Config = Config(0, 32, 0, 0, 6, 3);
const PLL_320M_XTAL_26M: Config = Config(12, 224, 4, 1, 0, 1);
const PLL_320M_XTAL_24M: Config = Config(11, 224, 4, 1, 0, 1);
const PLL_480M_XTAL_40M: Config = Config(0, 28, 0, 0, 6, 3);
const PLL_480M_XTAL_26M: Config = Config(12, 144, 4, 1, 0, 1);
const PLL_480M_XTAL_24M: Config = Config(11, 144, 4, 1, 0, 1);
fn get_lref(&self) -> u8 {
(self.3 << 7) | (self.2 << 4) | self.0
}
fn get_div7_0(&self) -> u8 {
self.1
}
fn get_dcur(&self) -> u8 {
(self.5 << 6) | self.4
}
}
impl super::ClockControl {
fn write_i2c(&mut self, address: u8, data: u8) {
self.rtc_control.pll.write(|w| unsafe {
w.block()
.bits(I2C_BLOCK)
.addr()
.bits(address)
.data()
.bits(data)
.write()
.set_bit()
});
while self.rtc_control.pll.read().busy().bit_is_set() {}
}
fn _read_i2c(&mut self, address: u8) -> u8 {
self.rtc_control.pll.write(|w| unsafe {
w.block()
.bits(I2C_BLOCK)
.addr()
.bits(address)
.write()
.clear_bit()
});
while self.rtc_control.pll.read().busy().bit_is_set() {}
self.rtc_control.pll.read().data().bits()
}
pub(crate) fn pll_disable(&mut self) {
self.rtc_control.options0.modify(|_, w| {
w.bias_i2c_force_pd()
.bit(self.rtc_control.ana_conf.read().plla_force_pd().bit())
.bb_i2c_force_pd()
.set_bit()
.bbpll_force_pd()
.set_bit()
.bbpll_i2c_force_pd()
.set_bit()
});
self.pll_frequency = super::FREQ_OFF;
self.pll_d2_frequency = super::FREQ_OFF;
}
pub(crate) fn pll_enable(&mut self, high: bool) -> Result<(), Error> {
self.rtc_control.options0.modify(|_, w| {
w.bias_i2c_force_pd()
.clear_bit()
.bb_i2c_force_pd()
.clear_bit()
.bbpll_force_pd()
.clear_bit()
.bbpll_i2c_force_pd()
.clear_bit()
});
self.write_i2c(i2c::IR_CAL_DELAY, val::IR_CAL_DELAY_VAL);
self.write_i2c(i2c::IR_CAL_EXT_CAP, val::IR_CAL_EXT_CAP_VAL);
self.write_i2c(i2c::OC_ENB_FCAL, val::OC_ENB_FCAL_VAL);
self.write_i2c(i2c::OC_ENB_VCON, val::OC_ENB_VCON_VAL);
self.write_i2c(i2c::BBADC_CAL_7_0, val::BBADC_CAL_7_0_VAL);
self.set_pll_frequency(high)
}
pub(crate) fn set_pll_frequency(&mut self, high: bool) -> Result<(), Error> {
let pll_config = match high {
false => {
self.pll_frequency = super::PLL_FREQ_320M;
self.pll_d2_frequency = self.pll_frequency / 2;
self.write_i2c(i2c::ENDIV5, val::ENDIV5_VAL_320M);
self.write_i2c(i2c::BBADC_DSMP, val::BBADC_DSMP_VAL_320M);
match self.xtal_frequency {
Hertz(40_000_000) => Config::PLL_320M_XTAL_40M,
Hertz(26_000_000) => Config::PLL_320M_XTAL_26M,
Hertz(24_000_000) => Config::PLL_320M_XTAL_24M,
_ => return Err(Error::UnsupportedPLLConfig),
}
}
true => {
self.pll_frequency = super::PLL_FREQ_480M;
self.pll_d2_frequency = self.pll_frequency / 2;
self.write_i2c(i2c::ENDIV5, val::ENDIV5_VAL_480M);
self.write_i2c(i2c::BBADC_DSMP, val::BBADC_DSMP_VAL_480M);
match self.xtal_frequency {
Hertz(40_000_000) => Config::PLL_480M_XTAL_40M,
Hertz(26_000_000) => Config::PLL_480M_XTAL_26M,
Hertz(24_000_000) => Config::PLL_480M_XTAL_24M,
_ => return Err(Error::UnsupportedPLLConfig),
}
}
};
self.write_i2c(i2c::OC_LREF, pll_config.get_lref());
self.write_i2c(i2c::OC_DIV_7_0, pll_config.get_div7_0());
self.write_i2c(i2c::OC_DCUR, pll_config.get_dcur());
let delay_us = if let Ok(super::SlowRTCSource::RTC150k) = self.slow_rtc_source() {
DELAY_PLL_ENABLE_WITH_150K
} else {
DELAY_PLL_ENABLE_WITH_32K
};
self.delay(delay_us);
Ok(())
}
pub fn pll_frequency(&self) -> Hertz {
if self.rtc_control.options0.read().bbpll_force_pd().bit() {
return super::FREQ_OFF;
}
match self
.dport_control
.cpu_per_conf()
.read()
.cpuperiod_sel()
.variant()
{
Val(super::CPUPERIOD_SEL_A::SEL_80) => super::PLL_FREQ_320M,
Val(super::CPUPERIOD_SEL_A::SEL_160) => super::PLL_FREQ_320M,
Val(super::CPUPERIOD_SEL_A::SEL_240) => super::PLL_FREQ_480M,
_ => super::FREQ_OFF,
}
}
}