1.1 --- a/pkg/devices/lib/cpm/src/common.cc Sat Sep 16 17:56:49 2023 +0200
1.2 +++ b/pkg/devices/lib/cpm/src/common.cc Sun Sep 17 18:41:41 2023 +0200
1.3 @@ -117,14 +117,9 @@
1.4 uint32_t
1.5 Source::get_frequency(Cpm_regs ®s)
1.6 {
1.7 - // Return the external clock frequency without any input clock.
1.8 -
1.9 - if (get_number() == 0)
1.10 - return regs.exclk_freq;
1.11 -
1.12 // Clocks with one source yield that input frequency.
1.13
1.14 - else if (get_number() == 1)
1.15 + if (get_number() == 1)
1.16 return regs.get_clock(get_input(0))->get_frequency(regs);
1.17
1.18 // With multiple sources, obtain the selected source for the clock.
1.19 @@ -146,8 +141,133 @@
1.20
1.21
1.22
1.23 +// Clock control.
1.24 +
1.25 +Control_base::~Control_base()
1.26 +{
1.27 +}
1.28 +
1.29 +void
1.30 +Control_base::change_disable(Cpm_regs ®s)
1.31 +{
1.32 + (void) regs;
1.33 +}
1.34 +
1.35 +void
1.36 +Control_base::change_enable(Cpm_regs ®s)
1.37 +{
1.38 + (void) regs;
1.39 +}
1.40 +
1.41 +int
1.42 +Control::have_clock(Cpm_regs ®s)
1.43 +{
1.44 + if (_gate.is_defined())
1.45 + return !_gate.get_field(regs);
1.46 + else
1.47 + return true;
1.48 +}
1.49 +
1.50 +void
1.51 +Control::start_clock(Cpm_regs ®s)
1.52 +{
1.53 + if (_gate.is_defined())
1.54 + _gate.set_field(regs, 0);
1.55 +}
1.56 +
1.57 +void
1.58 +Control::stop_clock(Cpm_regs ®s)
1.59 +{
1.60 + if (_gate.is_defined())
1.61 + _gate.set_field(regs, 1);
1.62 +}
1.63 +
1.64 +void
1.65 +Control::wait_busy(Cpm_regs ®s)
1.66 +{
1.67 + if (_busy.is_defined())
1.68 + while (_busy.get_field(regs));
1.69 +}
1.70 +
1.71 +void
1.72 +Control::change_disable(Cpm_regs ®s)
1.73 +{
1.74 + if (_change_enable.is_defined())
1.75 + _change_enable.set_field(regs, 0);
1.76 +}
1.77 +
1.78 +void
1.79 +Control::change_enable(Cpm_regs ®s)
1.80 +{
1.81 + if (_change_enable.is_defined())
1.82 + _change_enable.set_field(regs, 1);
1.83 +}
1.84 +
1.85 +// Undefined control.
1.86 +
1.87 +Control Control::undefined;
1.88 +
1.89 +
1.90 +
1.91 +// PLL-specific control.
1.92 +
1.93 +int
1.94 +Control_pll::have_pll(Cpm_regs ®s)
1.95 +{
1.96 + return _stable.get_field(regs);
1.97 +}
1.98 +
1.99 +int
1.100 +Control_pll::pll_enabled(Cpm_regs ®s)
1.101 +{
1.102 + return _enable.get_field(regs);
1.103 +}
1.104 +
1.105 +int
1.106 +Control_pll::pll_bypassed(Cpm_regs ®s)
1.107 +{
1.108 + return _bypass.get_field(regs);
1.109 +}
1.110 +
1.111 +// Clock control.
1.112 +
1.113 +int
1.114 +Control_pll::have_clock(Cpm_regs ®s)
1.115 +{
1.116 + return have_pll(regs) && pll_enabled(regs);
1.117 +}
1.118 +
1.119 +void
1.120 +Control_pll::start_clock(Cpm_regs ®s)
1.121 +{
1.122 + _enable.set_field(regs, 1);
1.123 + while (!have_pll(regs));
1.124 +}
1.125 +
1.126 +void
1.127 +Control_pll::stop_clock(Cpm_regs ®s)
1.128 +{
1.129 + _enable.set_field(regs, 0);
1.130 + while (have_pll(regs));
1.131 +}
1.132 +
1.133 +void
1.134 +Control_pll::wait_busy(Cpm_regs ®s)
1.135 +{
1.136 + if (pll_enabled(regs) && !pll_bypassed(regs))
1.137 + while (!have_pll(regs));
1.138 +}
1.139 +
1.140 +
1.141 +
1.142 // Clock dividers.
1.143
1.144 +Divider_base::~Divider_base()
1.145 +{
1.146 +}
1.147 +
1.148 +
1.149 +
1.150 uint32_t
1.151 Divider::get_divider(Cpm_regs ®s)
1.152 {
1.153 @@ -158,10 +278,10 @@
1.154 }
1.155
1.156 void
1.157 -Divider::set_divider(Cpm_regs ®s, uint32_t division)
1.158 +Divider::set_divider(Cpm_regs ®s, uint32_t divider)
1.159 {
1.160 if (_divider.is_defined())
1.161 - _divider.set_field(regs, division - 1);
1.162 + _divider.set_field(regs, divider - 1);
1.163 }
1.164
1.165 // Output clock frequencies.
1.166 @@ -180,129 +300,235 @@
1.167
1.168 // Feedback (13-bit) multiplier.
1.169
1.170 -uint16_t
1.171 +uint32_t
1.172 Divider_pll::get_multiplier(Cpm_regs ®s)
1.173 {
1.174 return _multiplier.get_field(regs) + 1;
1.175 }
1.176
1.177 void
1.178 -Divider_pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
1.179 +Divider_pll::set_multiplier(Cpm_regs ®s, uint32_t multiplier)
1.180 {
1.181 _multiplier.set_field(regs, multiplier - 1);
1.182 }
1.183
1.184 // Input (6-bit) divider.
1.185
1.186 -uint8_t
1.187 -Divider_pll::get_input_division(Cpm_regs ®s)
1.188 +uint32_t
1.189 +Divider_pll::get_input_divider(Cpm_regs ®s)
1.190 {
1.191 - return _input_division.get_field(regs) + 1;
1.192 + return _input_divider.get_field(regs) + 1;
1.193 }
1.194
1.195 void
1.196 -Divider_pll::set_input_division(Cpm_regs ®s, uint8_t divider)
1.197 +Divider_pll::set_input_divider(Cpm_regs ®s, uint32_t divider)
1.198 {
1.199 - _input_division.set_field(regs, divider - 1);
1.200 + _input_divider.set_field(regs, divider - 1);
1.201 }
1.202
1.203 // Output (dual 3-bit) dividers.
1.204
1.205 -uint8_t
1.206 -Divider_pll::get_output_division(Cpm_regs ®s)
1.207 +uint32_t
1.208 +Divider_pll::get_output_divider(Cpm_regs ®s)
1.209 {
1.210 - uint8_t d0 = _output_division0.get_field(regs);
1.211 - uint8_t d1 = _output_division1.get_field(regs);
1.212 + uint32_t d0 = _output_divider0.get_field(regs);
1.213 + uint32_t d1 = _output_divider1.get_field(regs);
1.214
1.215 return d0 * d1;
1.216 }
1.217
1.218 void
1.219 -Divider_pll::set_output_division(Cpm_regs ®s, uint8_t divider)
1.220 +Divider_pll::set_output_divider(Cpm_regs ®s, uint32_t divider)
1.221 {
1.222 // Assert 1 as a minimum.
1.223 // Divider 0 must be less than or equal to divider 1.
1.224
1.225 - uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
1.226 - uint8_t d1 = divider / d0;
1.227 + uint32_t d0 = (uint32_t) floor(sqrt(divider ? divider : 1));
1.228 + uint32_t d1 = divider / d0;
1.229
1.230 - _output_division0.set_field(regs, d0);
1.231 - _output_division1.set_field(regs, d1);
1.232 + _output_divider0.set_field(regs, d0);
1.233 + _output_divider1.set_field(regs, d1);
1.234 }
1.235
1.236 uint32_t
1.237 Divider_pll::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
1.238 {
1.239 return (source_frequency * get_multiplier(regs)) /
1.240 - (get_input_division(regs) * get_output_division(regs));
1.241 + (get_input_divider(regs) * get_output_divider(regs));
1.242 }
1.243
1.244 void
1.245 -Divider_pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.246 - uint8_t in_divider, uint8_t out_divider)
1.247 +Divider_pll::set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.248 + uint32_t in_divider, uint32_t out_divider)
1.249 {
1.250 set_multiplier(regs, multiplier);
1.251 - set_input_division(regs, in_divider);
1.252 - set_output_division(regs, out_divider);
1.253 + set_input_divider(regs, in_divider);
1.254 + set_output_divider(regs, out_divider);
1.255 }
1.256
1.257
1.258
1.259 -// Clock control.
1.260 +// I2S clock divider.
1.261 +
1.262 +uint32_t
1.263 +Divider_i2s::get_multiplier(Cpm_regs ®s)
1.264 +{
1.265 + return _multiplier.get_field(regs);
1.266 +}
1.267 +
1.268 +uint32_t
1.269 +Divider_i2s::get_divider_D(Cpm_regs ®s)
1.270 +{
1.271 + return _divider_D.get_field(regs);
1.272 +}
1.273 +
1.274 +uint32_t
1.275 +Divider_i2s::get_divider_N(Cpm_regs ®s)
1.276 +{
1.277 + return _divider_N.get_field(regs);
1.278 +}
1.279 +
1.280 +uint32_t
1.281 +Divider_i2s::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
1.282 +{
1.283 + return (source_frequency * get_multiplier(regs)) /
1.284 + (get_divider_N(regs) * get_divider_D(regs));
1.285 +}
1.286 +
1.287 +void
1.288 +Divider_i2s::set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.289 + uint32_t divider_N, uint32_t divider_D)
1.290 +{
1.291 + if (divider_N < 2 * multiplier)
1.292 + return;
1.293 +
1.294 + _multiplier.set_field(regs, multiplier);
1.295 + _divider_N.set_field(regs, divider_N);
1.296 + _divider_D.set_field(regs, divider_D);
1.297 +}
1.298 +
1.299 +
1.300 +
1.301 +// Clock interface.
1.302 +
1.303 +Clock_base::~Clock_base()
1.304 +{
1.305 +}
1.306 +
1.307 +
1.308 +
1.309 +// Null clock.
1.310
1.311 int
1.312 -Clock_base::have_clock(Cpm_regs ®s)
1.313 +Clock_null::have_clock(Cpm_regs ®s)
1.314 +{
1.315 + (void) regs;
1.316 + return false;
1.317 +}
1.318 +
1.319 +void
1.320 +Clock_null::start_clock(Cpm_regs ®s)
1.321 +{
1.322 + (void) regs;
1.323 +}
1.324 +
1.325 +void
1.326 +Clock_null::stop_clock(Cpm_regs ®s)
1.327 +{
1.328 + (void) regs;
1.329 +}
1.330 +
1.331 +// Output clock frequencies.
1.332 +
1.333 +uint32_t
1.334 +Clock_null::get_frequency(Cpm_regs ®s)
1.335 +{
1.336 + (void) regs;
1.337 + return 0;
1.338 +}
1.339 +
1.340 +
1.341 +
1.342 +// Passive clock.
1.343 +
1.344 +int
1.345 +Clock_passive::have_clock(Cpm_regs ®s)
1.346 {
1.347 (void) regs;
1.348 return true;
1.349 }
1.350
1.351 void
1.352 -Clock_base::start_clock(Cpm_regs ®s)
1.353 +Clock_passive::start_clock(Cpm_regs ®s)
1.354 {
1.355 (void) regs;
1.356 }
1.357
1.358 void
1.359 -Clock_base::stop_clock(Cpm_regs ®s)
1.360 +Clock_passive::stop_clock(Cpm_regs ®s)
1.361 {
1.362 (void) regs;
1.363 }
1.364
1.365 -// Default divider.
1.366 +// Output clock frequencies.
1.367
1.368 uint32_t
1.369 -Clock_base::get_divider(Cpm_regs ®s)
1.370 +Clock_passive::get_frequency(Cpm_regs ®s)
1.371 {
1.372 - (void) regs;
1.373 - return 1;
1.374 + // NOTE: Return the external clock frequency.
1.375 +
1.376 + return regs.exclk_freq;
1.377 +}
1.378 +
1.379 +
1.380 +
1.381 +// Active clock interface.
1.382 +
1.383 +Clock_active::~Clock_active()
1.384 +{
1.385 +}
1.386 +
1.387 +// Clock control.
1.388 +
1.389 +int
1.390 +Clock_active::have_clock(Cpm_regs ®s)
1.391 +{
1.392 + return _get_control().have_clock(regs);
1.393 }
1.394
1.395 void
1.396 -Clock_base::set_divider(Cpm_regs ®s, uint32_t division)
1.397 +Clock_active::start_clock(Cpm_regs ®s)
1.398 {
1.399 - (void) regs;
1.400 - (void) division;
1.401 + _get_control().start_clock(regs);
1.402 +}
1.403 +
1.404 +void
1.405 +Clock_active::stop_clock(Cpm_regs ®s)
1.406 +{
1.407 + _get_control().stop_clock(regs);
1.408 }
1.409
1.410 // Clock sources.
1.411
1.412 uint8_t
1.413 -Clock_base::get_source(Cpm_regs ®s)
1.414 +Clock_active::get_source(Cpm_regs ®s)
1.415 {
1.416 return _source.get_source(regs);
1.417 }
1.418
1.419 void
1.420 -Clock_base::set_source(Cpm_regs ®s, uint8_t source)
1.421 +Clock_active::set_source(Cpm_regs ®s, uint8_t source)
1.422 {
1.423 + _get_control().change_enable(regs);
1.424 _source.set_source(regs, source);
1.425 + _get_control().wait_busy(regs);
1.426 + _get_control().change_disable(regs);
1.427 }
1.428
1.429 // Clock source frequencies.
1.430
1.431 uint32_t
1.432 -Clock_base::get_source_frequency(Cpm_regs ®s)
1.433 +Clock_active::get_source_frequency(Cpm_regs ®s)
1.434 {
1.435 return _source.get_frequency(regs);
1.436 }
1.437 @@ -310,105 +536,83 @@
1.438 // Output clock frequencies.
1.439
1.440 uint32_t
1.441 -Clock_base::get_frequency(Cpm_regs ®s)
1.442 +Clock_active::get_frequency(Cpm_regs ®s)
1.443 {
1.444 return get_source_frequency(regs);
1.445 }
1.446
1.447
1.448
1.449 -// PLL-specific control.
1.450 -
1.451 -int
1.452 -Pll::have_pll(Cpm_regs ®s)
1.453 -{
1.454 - return _stable.get_field(regs);
1.455 -}
1.456 +// Divided clock interface.
1.457
1.458 -int
1.459 -Pll::pll_enabled(Cpm_regs ®s)
1.460 +Clock_divided::~Clock_divided()
1.461 {
1.462 - return _enable.get_field(regs);
1.463 -}
1.464 -
1.465 -int
1.466 -Pll::pll_bypassed(Cpm_regs ®s)
1.467 -{
1.468 - return _bypass.get_field(regs);
1.469 }
1.470
1.471 -// Clock control.
1.472 +// Output clock frequencies.
1.473
1.474 -int
1.475 -Pll::have_clock(Cpm_regs ®s)
1.476 +uint32_t
1.477 +Clock_divided::get_frequency(Cpm_regs ®s)
1.478 {
1.479 - return have_pll(regs) && pll_enabled(regs);
1.480 + return _get_divider().get_frequency(regs, get_source_frequency(regs));
1.481 }
1.482
1.483 -void
1.484 -Pll::start_clock(Cpm_regs ®s)
1.485 +
1.486 +
1.487 +// PLL boilerplate.
1.488 +
1.489 +Pll::~Pll()
1.490 {
1.491 - _enable.set_field(regs, 1);
1.492 - while (!have_pll(regs));
1.493 -}
1.494 -
1.495 -void
1.496 -Pll::stop_clock(Cpm_regs ®s)
1.497 -{
1.498 - _enable.set_field(regs, 0);
1.499 - while (have_pll(regs));
1.500 }
1.501
1.502 // Feedback (13-bit) multiplier.
1.503
1.504 -uint16_t
1.505 +uint32_t
1.506 Pll::get_multiplier(Cpm_regs ®s)
1.507 {
1.508 return _divider.get_multiplier(regs);
1.509 }
1.510
1.511 void
1.512 -Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
1.513 +Pll::set_multiplier(Cpm_regs ®s, uint32_t multiplier)
1.514 {
1.515 _divider.set_multiplier(regs, multiplier);
1.516 }
1.517
1.518 // Input (6-bit) divider.
1.519
1.520 -uint8_t
1.521 -Pll::get_input_division(Cpm_regs ®s)
1.522 +uint32_t
1.523 +Pll::get_input_divider(Cpm_regs ®s)
1.524 {
1.525 - return _divider.get_input_division(regs);
1.526 + return _divider.get_input_divider(regs);
1.527 }
1.528
1.529 void
1.530 -Pll::set_input_division(Cpm_regs ®s, uint8_t divider)
1.531 +Pll::set_input_divider(Cpm_regs ®s, uint32_t divider)
1.532 {
1.533 - _divider.set_input_division(regs, divider);
1.534 + _divider.set_input_divider(regs, divider);
1.535 }
1.536
1.537 // Output (dual 3-bit) dividers.
1.538
1.539 -uint8_t
1.540 -Pll::get_output_division(Cpm_regs ®s)
1.541 +uint32_t
1.542 +Pll::get_output_divider(Cpm_regs ®s)
1.543 {
1.544 - return _divider.get_output_division(regs);
1.545 + return _divider.get_output_divider(regs);
1.546 }
1.547
1.548 void
1.549 -Pll::set_output_division(Cpm_regs ®s, uint8_t divider)
1.550 +Pll::set_output_divider(Cpm_regs ®s, uint32_t divider)
1.551 {
1.552 - _divider.set_output_division(regs, divider);
1.553 + _divider.set_output_divider(regs, divider);
1.554 }
1.555
1.556 uint32_t
1.557 Pll::get_frequency(Cpm_regs ®s)
1.558 {
1.559 - // Test for PLL enable and not PLL bypass.
1.560 -
1.561 - if (pll_enabled(regs))
1.562 + if (have_clock(regs))
1.563 {
1.564 - if (!pll_bypassed(regs))
1.565 + if (!_control.pll_bypassed(regs))
1.566 return _divider.get_frequency(regs, get_source_frequency(regs));
1.567 else
1.568 return get_source_frequency(regs);
1.569 @@ -418,63 +622,15 @@
1.570 }
1.571
1.572 void
1.573 -Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.574 - uint8_t in_divider, uint8_t out_divider)
1.575 +Pll::set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.576 + uint32_t in_divider, uint32_t out_divider)
1.577 {
1.578 - set_pll_parameters(regs, multiplier, in_divider, out_divider);
1.579 -
1.580 - if (pll_enabled(regs) && !pll_bypassed(regs))
1.581 - while (!have_pll(regs));
1.582 + set_parameters(regs, multiplier, in_divider, out_divider);
1.583 + _control.wait_busy(regs);
1.584 }
1.585
1.586
1.587
1.588 -// Clock control.
1.589 -
1.590 -void
1.591 -Clock::change_disable(Cpm_regs ®s)
1.592 -{
1.593 - if (_change_enable.is_defined())
1.594 - _change_enable.set_field(regs, 0);
1.595 -}
1.596 -
1.597 -void
1.598 -Clock::change_enable(Cpm_regs ®s)
1.599 -{
1.600 - if (_change_enable.is_defined())
1.601 - _change_enable.set_field(regs, 1);
1.602 -}
1.603 -
1.604 -int
1.605 -Clock::have_clock(Cpm_regs ®s)
1.606 -{
1.607 - if (_gate.is_defined())
1.608 - return !_gate.get_field(regs);
1.609 - else
1.610 - return true;
1.611 -}
1.612 -
1.613 -void
1.614 -Clock::start_clock(Cpm_regs ®s)
1.615 -{
1.616 - if (_gate.is_defined())
1.617 - _gate.set_field(regs, 0);
1.618 -}
1.619 -
1.620 -void
1.621 -Clock::stop_clock(Cpm_regs ®s)
1.622 -{
1.623 - if (_gate.is_defined())
1.624 - _gate.set_field(regs, 1);
1.625 -}
1.626 -
1.627 -void
1.628 -Clock::wait_busy(Cpm_regs ®s)
1.629 -{
1.630 - if (_busy.is_defined())
1.631 - while (_busy.get_field(regs));
1.632 -}
1.633 -
1.634 // Clock dividers.
1.635
1.636 uint32_t
1.637 @@ -484,27 +640,10 @@
1.638 }
1.639
1.640 void
1.641 -Clock::set_divider(Cpm_regs ®s, uint32_t division)
1.642 -{
1.643 - change_enable(regs);
1.644 - _divider.set_divider(regs, division);
1.645 - wait_busy(regs);
1.646 - change_disable(regs);
1.647 -}
1.648 -
1.649 -void
1.650 -Clock::set_source(Cpm_regs ®s, uint8_t source)
1.651 +Clock::set_divider(Cpm_regs ®s, uint32_t divider)
1.652 {
1.653 - change_enable(regs);
1.654 - Clock_base::set_source(regs, source);
1.655 - wait_busy(regs);
1.656 - change_disable(regs);
1.657 + _control.change_enable(regs);
1.658 + _divider.set_divider(regs, divider);
1.659 + _control.wait_busy(regs);
1.660 + _control.change_disable(regs);
1.661 }
1.662 -
1.663 -// Output clock frequencies.
1.664 -
1.665 -uint32_t
1.666 -Clock::get_frequency(Cpm_regs ®s)
1.667 -{
1.668 - return _divider.get_frequency(regs, get_source_frequency(regs));
1.669 -}