1.1 --- a/pkg/devices/lib/cpm/include/cpm-common.h Sat Sep 16 17:56:49 2023 +0200
1.2 +++ b/pkg/devices/lib/cpm/include/cpm-common.h Sun Sep 17 18:41:41 2023 +0200
1.3 @@ -120,6 +120,8 @@
1.4
1.5
1.6
1.7 +// Controllable clock source.
1.8 +
1.9 class Source
1.10 {
1.11 Mux _inputs;
1.12 @@ -159,11 +161,96 @@
1.13
1.14
1.15
1.16 +// Common clock control.
1.17 +
1.18 +class Control_base
1.19 +{
1.20 +public:
1.21 + virtual ~Control_base();
1.22 +
1.23 + virtual void change_disable(Cpm_regs ®s);
1.24 + virtual void change_enable(Cpm_regs ®s);
1.25 +
1.26 + virtual void wait_busy(Cpm_regs ®s) = 0;
1.27 + virtual int have_clock(Cpm_regs ®s) = 0;
1.28 + virtual void start_clock(Cpm_regs ®s) = 0;
1.29 + virtual void stop_clock(Cpm_regs ®s) = 0;
1.30 +};
1.31 +
1.32 +
1.33 +
1.34 +// Clock control.
1.35 +
1.36 +class Control : public Control_base
1.37 +{
1.38 + Field _gate, _change_enable, _busy;
1.39 +
1.40 +public:
1.41 + explicit Control(Field gate,
1.42 + Field change_enable = Field::undefined,
1.43 + Field busy = Field::undefined)
1.44 + : _gate(gate), _change_enable(change_enable), _busy(busy)
1.45 + {
1.46 + }
1.47 +
1.48 + explicit Control()
1.49 + : _gate(Field::undefined), _change_enable(Field::undefined),
1.50 + _busy(Field::undefined)
1.51 + {
1.52 + }
1.53 +
1.54 + // Clock control.
1.55 +
1.56 + void change_disable(Cpm_regs ®s);
1.57 + void change_enable(Cpm_regs ®s);
1.58 +
1.59 + void wait_busy(Cpm_regs ®s);
1.60 + int have_clock(Cpm_regs ®s);
1.61 + void start_clock(Cpm_regs ®s);
1.62 + void stop_clock(Cpm_regs ®s);
1.63 +
1.64 + // Undefined control.
1.65 +
1.66 + static Control undefined;
1.67 +};
1.68 +
1.69 +
1.70 +
1.71 +// PLL control.
1.72 +
1.73 +class Control_pll : public Control_base
1.74 +{
1.75 + Field _enable, _stable, _bypass;
1.76 +
1.77 + // PLL_specific control.
1.78 +
1.79 + int have_pll(Cpm_regs ®s);
1.80 + int pll_enabled(Cpm_regs ®s);
1.81 +
1.82 +public:
1.83 + explicit Control_pll(Field enable, Field stable, Field bypass)
1.84 + : _enable(enable), _stable(stable), _bypass(bypass)
1.85 + {
1.86 + }
1.87 +
1.88 + // Clock control.
1.89 +
1.90 + int pll_bypassed(Cpm_regs ®s);
1.91 +
1.92 + void wait_busy(Cpm_regs ®s);
1.93 + int have_clock(Cpm_regs ®s);
1.94 + void start_clock(Cpm_regs ®s);
1.95 + void stop_clock(Cpm_regs ®s);
1.96 +};
1.97 +
1.98 +
1.99 +
1.100 // Frequency transformation.
1.101
1.102 -class Transform
1.103 +class Divider_base
1.104 {
1.105 public:
1.106 + virtual ~Divider_base();
1.107
1.108 // Output frequency.
1.109
1.110 @@ -172,7 +259,9 @@
1.111
1.112
1.113
1.114 -class Divider : public Transform
1.115 +// Simple divider for regular clocks.
1.116 +
1.117 +class Divider : public Divider_base
1.118 {
1.119 Field _divider;
1.120
1.121 @@ -190,7 +279,7 @@
1.122 // Clock divider.
1.123
1.124 uint32_t get_divider(Cpm_regs ®s);
1.125 - void set_divider(Cpm_regs ®s, uint32_t division);
1.126 + void set_divider(Cpm_regs ®s, uint32_t divider);
1.127
1.128 // Output frequency.
1.129
1.130 @@ -203,26 +292,28 @@
1.131
1.132
1.133
1.134 -class Divider_pll : public Transform
1.135 +// Divider for PLLs.
1.136 +
1.137 +class Divider_pll : public Divider_base
1.138 {
1.139 - Field _multiplier, _input_division, _output_division0, _output_division1;
1.140 + Field _multiplier, _input_divider, _output_divider0, _output_divider1;
1.141
1.142 public:
1.143 - explicit Divider_pll(Field multiplier, Field input_division,
1.144 - Field output_division0, Field output_division1)
1.145 - : _multiplier(multiplier), _input_division(input_division),
1.146 - _output_division0(output_division0), _output_division1(output_division1)
1.147 + explicit Divider_pll(Field multiplier, Field input_divider,
1.148 + Field output_divider0, Field output_divider1)
1.149 + : _multiplier(multiplier), _input_divider(input_divider),
1.150 + _output_divider0(output_divider0), _output_divider1(output_divider1)
1.151 {
1.152 }
1.153
1.154 // General frequency modifiers.
1.155
1.156 - uint16_t get_multiplier(Cpm_regs ®s);
1.157 - void set_multiplier(Cpm_regs ®s, uint16_t multiplier);
1.158 - uint8_t get_input_division(Cpm_regs ®s);
1.159 - void set_input_division(Cpm_regs ®s, uint8_t divider);
1.160 - uint8_t get_output_division(Cpm_regs ®s);
1.161 - void set_output_division(Cpm_regs ®s, uint8_t divider);
1.162 + uint32_t get_multiplier(Cpm_regs ®s);
1.163 + void set_multiplier(Cpm_regs ®s, uint32_t multiplier);
1.164 + uint32_t get_input_divider(Cpm_regs ®s);
1.165 + void set_input_divider(Cpm_regs ®s, uint32_t divider);
1.166 + uint32_t get_output_divider(Cpm_regs ®s);
1.167 + void set_output_divider(Cpm_regs ®s, uint32_t divider);
1.168
1.169 // Output frequency.
1.170
1.171 @@ -230,8 +321,40 @@
1.172
1.173 // Other operations.
1.174
1.175 - void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.176 - uint8_t in_divider, uint8_t out_divider);
1.177 + void set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.178 + uint32_t in_divider, uint32_t out_divider);
1.179 +};
1.180 +
1.181 +
1.182 +
1.183 +// Divider for I2S clocks.
1.184 +
1.185 +class Divider_i2s : public Divider_base
1.186 +{
1.187 + Field _multiplier, _divider_N, _divider_D;
1.188 +
1.189 +public:
1.190 + explicit Divider_i2s(Field multiplier, Field divider_N,
1.191 + Field divider_D)
1.192 + : _multiplier(multiplier), _divider_N(divider_N),
1.193 + _divider_D(divider_D)
1.194 + {
1.195 + }
1.196 +
1.197 + // General frequency modifiers.
1.198 +
1.199 + uint32_t get_multiplier(Cpm_regs ®s);
1.200 + uint32_t get_divider_N(Cpm_regs ®s);
1.201 + uint32_t get_divider_D(Cpm_regs ®s);
1.202 +
1.203 + // Output frequency.
1.204 +
1.205 + uint32_t get_frequency(Cpm_regs ®s, uint32_t source_frequency);
1.206 +
1.207 + // Other operations.
1.208 +
1.209 + void set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.210 + uint32_t divider_N, uint32_t divider_D);
1.211 };
1.212
1.213
1.214 @@ -240,13 +363,46 @@
1.215
1.216 class Clock_base
1.217 {
1.218 - Source _source;
1.219 -
1.220 public:
1.221 - explicit Clock_base(Source source)
1.222 - : _source(source)
1.223 - {
1.224 - }
1.225 + virtual ~Clock_base();
1.226 +
1.227 + // Clock control.
1.228 +
1.229 + virtual int have_clock(Cpm_regs ®s) = 0;
1.230 + virtual void start_clock(Cpm_regs ®s) = 0;
1.231 + virtual void stop_clock(Cpm_regs ®s) = 0;
1.232 +
1.233 + // Output frequency.
1.234 +
1.235 + virtual uint32_t get_frequency(Cpm_regs ®s) = 0;
1.236 +};
1.237 +
1.238 +
1.239 +
1.240 +// Null (absent or undefined) clock abstraction.
1.241 +
1.242 +class Clock_null : public Clock_base
1.243 +{
1.244 +public:
1.245 +
1.246 + // Clock control.
1.247 +
1.248 + int have_clock(Cpm_regs ®s);
1.249 + void start_clock(Cpm_regs ®s);
1.250 + void stop_clock(Cpm_regs ®s);
1.251 +
1.252 + // Output frequency.
1.253 +
1.254 + uint32_t get_frequency(Cpm_regs ®s);
1.255 +};
1.256 +
1.257 +
1.258 +
1.259 +// Passive (root or input) clock without any source of its own.
1.260 +
1.261 +class Clock_passive : public Clock_base
1.262 +{
1.263 +public:
1.264
1.265 // Clock control.
1.266
1.267 @@ -254,10 +410,40 @@
1.268 virtual void start_clock(Cpm_regs ®s);
1.269 virtual void stop_clock(Cpm_regs ®s);
1.270
1.271 - // Clock divider.
1.272 + // Output frequency.
1.273 +
1.274 + uint32_t get_frequency(Cpm_regs ®s);
1.275 +};
1.276 +
1.277 +
1.278 +
1.279 +// An actively managed clock with source.
1.280 +
1.281 +class Clock_active : public Clock_base
1.282 +{
1.283 +protected:
1.284 + Source _source;
1.285 +
1.286 + virtual Control_base &_get_control() = 0;
1.287
1.288 - virtual uint32_t get_divider(Cpm_regs ®s);
1.289 - virtual void set_divider(Cpm_regs ®s, uint32_t division);
1.290 +public:
1.291 + explicit Clock_active(Source source)
1.292 + : _source(source)
1.293 + {
1.294 + }
1.295 +
1.296 + explicit Clock_active()
1.297 + : _source(Source::undefined)
1.298 + {
1.299 + }
1.300 +
1.301 + virtual ~Clock_active();
1.302 +
1.303 + // Clock control.
1.304 +
1.305 + virtual int have_clock(Cpm_regs ®s);
1.306 + virtual void start_clock(Cpm_regs ®s);
1.307 + virtual void stop_clock(Cpm_regs ®s);
1.308
1.309 // Clock source.
1.310
1.311 @@ -275,98 +461,114 @@
1.312
1.313
1.314
1.315 -// PLL descriptions.
1.316 +// Divided clock interface.
1.317
1.318 -class Pll : public Clock_base
1.319 +class Clock_divided : public Clock_active
1.320 {
1.321 - Field _enable, _stable, _bypass;
1.322 - Divider_pll _divider;
1.323 +protected:
1.324 + virtual Divider_base &_get_divider() = 0;
1.325
1.326 public:
1.327 - explicit Pll(Source source,
1.328 - Field enable, Field stable, Field bypass,
1.329 - Divider_pll divider)
1.330 - : Clock_base(source),
1.331 - _enable(enable), _stable(stable), _bypass(bypass),
1.332 - _divider(divider)
1.333 + explicit Clock_divided(Source source)
1.334 + : Clock_active(source)
1.335 {
1.336 }
1.337
1.338 - // PLL_specific control.
1.339 -
1.340 - int have_pll(Cpm_regs ®s);
1.341 - int pll_enabled(Cpm_regs ®s);
1.342 - int pll_bypassed(Cpm_regs ®s);
1.343 -
1.344 - // Clock control.
1.345 -
1.346 - int have_clock(Cpm_regs ®s);
1.347 - void start_clock(Cpm_regs ®s);
1.348 - void stop_clock(Cpm_regs ®s);
1.349 -
1.350 - // General frequency modifiers.
1.351 -
1.352 - uint16_t get_multiplier(Cpm_regs ®s);
1.353 - void set_multiplier(Cpm_regs ®s, uint16_t multiplier);
1.354 - uint8_t get_input_division(Cpm_regs ®s);
1.355 - void set_input_division(Cpm_regs ®s, uint8_t divider);
1.356 - uint8_t get_output_division(Cpm_regs ®s);
1.357 - void set_output_division(Cpm_regs ®s, uint8_t divider);
1.358 -
1.359 - // PLL output frequency.
1.360 -
1.361 - uint32_t get_frequency(Cpm_regs ®s);
1.362 -
1.363 - // Other operations.
1.364 -
1.365 - void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.366 - uint8_t in_divider, uint8_t out_divider);
1.367 -};
1.368 -
1.369 -
1.370 -
1.371 -// Clock descriptions.
1.372 -
1.373 -class Clock : public Clock_base
1.374 -{
1.375 - Field _gate, _change_enable, _busy;
1.376 - Divider _divider;
1.377 -
1.378 - // Clock control.
1.379 -
1.380 - void change_disable(Cpm_regs ®s);
1.381 - void change_enable(Cpm_regs ®s);
1.382 - void wait_busy(Cpm_regs ®s);
1.383 -
1.384 -public:
1.385 - explicit Clock(Source source = Source::undefined,
1.386 - Field gate = Field::undefined,
1.387 - Field change_enable = Field::undefined,
1.388 - Field busy = Field::undefined,
1.389 - Divider divider = Divider::undefined)
1.390 - : Clock_base(source),
1.391 - _gate(gate), _change_enable(change_enable), _busy(busy), _divider(divider)
1.392 - {
1.393 - }
1.394 -
1.395 - // Clock control.
1.396 -
1.397 - int have_clock(Cpm_regs ®s);
1.398 - void start_clock(Cpm_regs ®s);
1.399 - void stop_clock(Cpm_regs ®s);
1.400 -
1.401 - // Clock divider.
1.402 -
1.403 - uint32_t get_divider(Cpm_regs ®s);
1.404 - void set_divider(Cpm_regs ®s, uint32_t division);
1.405 -
1.406 - // Clock source.
1.407 -
1.408 - void set_source(Cpm_regs ®s, uint8_t source);
1.409 + virtual ~Clock_divided();
1.410
1.411 // Output frequency.
1.412
1.413 uint32_t get_frequency(Cpm_regs ®s);
1.414 };
1.415
1.416 +
1.417 +
1.418 +// PLL description.
1.419 +
1.420 +class Pll : public Clock_divided
1.421 +{
1.422 + // Value storage.
1.423 +
1.424 + Control_pll _control;
1.425 + Divider_pll _divider;
1.426 +
1.427 + virtual Control_base &_get_control() { return _control; }
1.428 + virtual Divider_base &_get_divider() { return _divider; }
1.429 +
1.430 +public:
1.431 + explicit Pll(Source source, Control_pll control, Divider_pll divider)
1.432 + : Clock_divided(source), _control(control), _divider(divider)
1.433 + {
1.434 + }
1.435 +
1.436 + virtual ~Pll();
1.437 +
1.438 + // General frequency modifiers.
1.439 +
1.440 + uint32_t get_multiplier(Cpm_regs ®s);
1.441 + void set_multiplier(Cpm_regs ®s, uint32_t multiplier);
1.442 + uint32_t get_input_divider(Cpm_regs ®s);
1.443 + void set_input_divider(Cpm_regs ®s, uint32_t divider);
1.444 + uint32_t get_output_divider(Cpm_regs ®s);
1.445 + void set_output_divider(Cpm_regs ®s, uint32_t divider);
1.446 +
1.447 + // Output frequency.
1.448 +
1.449 + uint32_t get_frequency(Cpm_regs ®s);
1.450 +
1.451 + // Other operations.
1.452 +
1.453 + void set_parameters(Cpm_regs ®s, uint32_t multiplier,
1.454 + uint32_t in_divider, uint32_t out_divider);
1.455 +};
1.456 +
1.457 +
1.458 +
1.459 +// Clock description.
1.460 +
1.461 +class Clock : public Clock_divided
1.462 +{
1.463 + // Value storage.
1.464 +
1.465 + Control _control;
1.466 + Divider _divider;
1.467 +
1.468 + virtual Control_base &_get_control() { return _control; }
1.469 + virtual Divider_base &_get_divider() { return _divider; }
1.470 +
1.471 +public:
1.472 + explicit Clock(Source source,
1.473 + Control control = Control::undefined,
1.474 + Divider divider = Divider::undefined)
1.475 + : Clock_divided(source), _control(control), _divider(divider)
1.476 + {
1.477 + }
1.478 +
1.479 + // Clock divider.
1.480 +
1.481 + uint32_t get_divider(Cpm_regs ®s);
1.482 + void set_divider(Cpm_regs ®s, uint32_t divider);
1.483 +};
1.484 +
1.485 +
1.486 +
1.487 +// I2S clock description.
1.488 +
1.489 +class Clock_divided_i2s : public Clock_divided
1.490 +{
1.491 + // Value storage.
1.492 +
1.493 + Control _control;
1.494 + Divider_i2s _divider;
1.495 +
1.496 + virtual Control_base &_get_control() { return _control; }
1.497 + virtual Divider_base &_get_divider() { return _divider; }
1.498 +
1.499 +public:
1.500 + explicit Clock_divided_i2s(Source source, Control control, Divider_i2s divider)
1.501 + : Clock_divided(source), _control(control), _divider(divider)
1.502 + {
1.503 + }
1.504 +};
1.505 +
1.506 #endif /* __cplusplus */