1.1 --- a/pkg/devices/lib/cpm/include/cpm-common.h Sat Sep 16 16:53:06 2023 +0200
1.2 +++ b/pkg/devices/lib/cpm/include/cpm-common.h Sat Sep 16 17:56:49 2023 +0200
1.3 @@ -118,6 +118,8 @@
1.4 enum Clock_identifiers get_input(int num);
1.5 };
1.6
1.7 +
1.8 +
1.9 class Source
1.10 {
1.11 Mux _inputs;
1.12 @@ -157,6 +159,83 @@
1.13
1.14
1.15
1.16 +// Frequency transformation.
1.17 +
1.18 +class Transform
1.19 +{
1.20 +public:
1.21 +
1.22 + // Output frequency.
1.23 +
1.24 + virtual uint32_t get_frequency(Cpm_regs ®s, uint32_t source_frequency) = 0;
1.25 +};
1.26 +
1.27 +
1.28 +
1.29 +class Divider : public Transform
1.30 +{
1.31 + Field _divider;
1.32 +
1.33 +public:
1.34 + explicit Divider(Field divider)
1.35 + : _divider(divider)
1.36 + {
1.37 + }
1.38 +
1.39 + explicit Divider()
1.40 + : _divider(Field::undefined)
1.41 + {
1.42 + }
1.43 +
1.44 + // Clock divider.
1.45 +
1.46 + uint32_t get_divider(Cpm_regs ®s);
1.47 + void set_divider(Cpm_regs ®s, uint32_t division);
1.48 +
1.49 + // Output frequency.
1.50 +
1.51 + uint32_t get_frequency(Cpm_regs ®s, uint32_t source_frequency);
1.52 +
1.53 + // Undefined divider.
1.54 +
1.55 + static Divider undefined;
1.56 +};
1.57 +
1.58 +
1.59 +
1.60 +class Divider_pll : public Transform
1.61 +{
1.62 + Field _multiplier, _input_division, _output_division0, _output_division1;
1.63 +
1.64 +public:
1.65 + explicit Divider_pll(Field multiplier, Field input_division,
1.66 + Field output_division0, Field output_division1)
1.67 + : _multiplier(multiplier), _input_division(input_division),
1.68 + _output_division0(output_division0), _output_division1(output_division1)
1.69 + {
1.70 + }
1.71 +
1.72 + // General frequency modifiers.
1.73 +
1.74 + uint16_t get_multiplier(Cpm_regs ®s);
1.75 + void set_multiplier(Cpm_regs ®s, uint16_t multiplier);
1.76 + uint8_t get_input_division(Cpm_regs ®s);
1.77 + void set_input_division(Cpm_regs ®s, uint8_t divider);
1.78 + uint8_t get_output_division(Cpm_regs ®s);
1.79 + void set_output_division(Cpm_regs ®s, uint8_t divider);
1.80 +
1.81 + // Output frequency.
1.82 +
1.83 + uint32_t get_frequency(Cpm_regs ®s, uint32_t source_frequency);
1.84 +
1.85 + // Other operations.
1.86 +
1.87 + void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.88 + uint8_t in_divider, uint8_t out_divider);
1.89 +};
1.90 +
1.91 +
1.92 +
1.93 // Common clock abstraction.
1.94
1.95 class Clock_base
1.96 @@ -201,17 +280,15 @@
1.97 class Pll : public Clock_base
1.98 {
1.99 Field _enable, _stable, _bypass;
1.100 - Field _multiplier, _input_division, _output_division0, _output_division1;
1.101 + Divider_pll _divider;
1.102
1.103 public:
1.104 explicit Pll(Source source,
1.105 Field enable, Field stable, Field bypass,
1.106 - Field multiplier, Field input_division,
1.107 - Field output_division0, Field output_division1)
1.108 + Divider_pll divider)
1.109 : Clock_base(source),
1.110 _enable(enable), _stable(stable), _bypass(bypass),
1.111 - _multiplier(multiplier), _input_division(input_division),
1.112 - _output_division0(output_division0), _output_division1(output_division1)
1.113 + _divider(divider)
1.114 {
1.115 }
1.116
1.117 @@ -252,7 +329,8 @@
1.118
1.119 class Clock : public Clock_base
1.120 {
1.121 - Field _gate, _change_enable, _busy, _divider;
1.122 + Field _gate, _change_enable, _busy;
1.123 + Divider _divider;
1.124
1.125 // Clock control.
1.126
1.127 @@ -265,7 +343,7 @@
1.128 Field gate = Field::undefined,
1.129 Field change_enable = Field::undefined,
1.130 Field busy = Field::undefined,
1.131 - Field divider = Field::undefined)
1.132 + Divider divider = Divider::undefined)
1.133 : Clock_base(source),
1.134 _gate(gate), _change_enable(change_enable), _busy(busy), _divider(divider)
1.135 {
1.136 @@ -285,6 +363,10 @@
1.137 // Clock source.
1.138
1.139 void set_source(Cpm_regs ®s, uint8_t source);
1.140 +
1.141 + // Output frequency.
1.142 +
1.143 + uint32_t get_frequency(Cpm_regs ®s);
1.144 };
1.145
1.146 #endif /* __cplusplus */
2.1 --- a/pkg/devices/lib/cpm/src/common.cc Sat Sep 16 16:53:06 2023 +0200
2.2 +++ b/pkg/devices/lib/cpm/src/common.cc Sat Sep 16 17:56:49 2023 +0200
2.3 @@ -146,6 +146,108 @@
2.4
2.5
2.6
2.7 +// Clock dividers.
2.8 +
2.9 +uint32_t
2.10 +Divider::get_divider(Cpm_regs ®s)
2.11 +{
2.12 + if (_divider.is_defined())
2.13 + return _divider.get_field(regs) + 1;
2.14 + else
2.15 + return 1;
2.16 +}
2.17 +
2.18 +void
2.19 +Divider::set_divider(Cpm_regs ®s, uint32_t division)
2.20 +{
2.21 + if (_divider.is_defined())
2.22 + _divider.set_field(regs, division - 1);
2.23 +}
2.24 +
2.25 +// Output clock frequencies.
2.26 +
2.27 +uint32_t
2.28 +Divider::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
2.29 +{
2.30 + return source_frequency / get_divider(regs);
2.31 +}
2.32 +
2.33 +// Undefined divider.
2.34 +
2.35 +Divider Divider::undefined;
2.36 +
2.37 +
2.38 +
2.39 +// Feedback (13-bit) multiplier.
2.40 +
2.41 +uint16_t
2.42 +Divider_pll::get_multiplier(Cpm_regs ®s)
2.43 +{
2.44 + return _multiplier.get_field(regs) + 1;
2.45 +}
2.46 +
2.47 +void
2.48 +Divider_pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
2.49 +{
2.50 + _multiplier.set_field(regs, multiplier - 1);
2.51 +}
2.52 +
2.53 +// Input (6-bit) divider.
2.54 +
2.55 +uint8_t
2.56 +Divider_pll::get_input_division(Cpm_regs ®s)
2.57 +{
2.58 + return _input_division.get_field(regs) + 1;
2.59 +}
2.60 +
2.61 +void
2.62 +Divider_pll::set_input_division(Cpm_regs ®s, uint8_t divider)
2.63 +{
2.64 + _input_division.set_field(regs, divider - 1);
2.65 +}
2.66 +
2.67 +// Output (dual 3-bit) dividers.
2.68 +
2.69 +uint8_t
2.70 +Divider_pll::get_output_division(Cpm_regs ®s)
2.71 +{
2.72 + uint8_t d0 = _output_division0.get_field(regs);
2.73 + uint8_t d1 = _output_division1.get_field(regs);
2.74 +
2.75 + return d0 * d1;
2.76 +}
2.77 +
2.78 +void
2.79 +Divider_pll::set_output_division(Cpm_regs ®s, uint8_t divider)
2.80 +{
2.81 + // Assert 1 as a minimum.
2.82 + // Divider 0 must be less than or equal to divider 1.
2.83 +
2.84 + uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
2.85 + uint8_t d1 = divider / d0;
2.86 +
2.87 + _output_division0.set_field(regs, d0);
2.88 + _output_division1.set_field(regs, d1);
2.89 +}
2.90 +
2.91 +uint32_t
2.92 +Divider_pll::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
2.93 +{
2.94 + return (source_frequency * get_multiplier(regs)) /
2.95 + (get_input_division(regs) * get_output_division(regs));
2.96 +}
2.97 +
2.98 +void
2.99 +Divider_pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
2.100 + uint8_t in_divider, uint8_t out_divider)
2.101 +{
2.102 + set_multiplier(regs, multiplier);
2.103 + set_input_division(regs, in_divider);
2.104 + set_output_division(regs, out_divider);
2.105 +}
2.106 +
2.107 +
2.108 +
2.109 // Clock control.
2.110
2.111 int
2.112 @@ -210,7 +312,7 @@
2.113 uint32_t
2.114 Clock_base::get_frequency(Cpm_regs ®s)
2.115 {
2.116 - return get_source_frequency(regs) / get_divider(regs);
2.117 + return get_source_frequency(regs);
2.118 }
2.119
2.120
2.121 @@ -262,13 +364,13 @@
2.122 uint16_t
2.123 Pll::get_multiplier(Cpm_regs ®s)
2.124 {
2.125 - return _multiplier.get_field(regs) + 1;
2.126 + return _divider.get_multiplier(regs);
2.127 }
2.128
2.129 void
2.130 Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
2.131 {
2.132 - _multiplier.set_field(regs, multiplier - 1);
2.133 + _divider.set_multiplier(regs, multiplier);
2.134 }
2.135
2.136 // Input (6-bit) divider.
2.137 @@ -276,13 +378,13 @@
2.138 uint8_t
2.139 Pll::get_input_division(Cpm_regs ®s)
2.140 {
2.141 - return _input_division.get_field(regs) + 1;
2.142 + return _divider.get_input_division(regs);
2.143 }
2.144
2.145 void
2.146 Pll::set_input_division(Cpm_regs ®s, uint8_t divider)
2.147 {
2.148 - _input_division.set_field(regs, divider - 1);
2.149 + _divider.set_input_division(regs, divider);
2.150 }
2.151
2.152 // Output (dual 3-bit) dividers.
2.153 @@ -290,23 +392,13 @@
2.154 uint8_t
2.155 Pll::get_output_division(Cpm_regs ®s)
2.156 {
2.157 - uint8_t d0 = _output_division0.get_field(regs);
2.158 - uint8_t d1 = _output_division1.get_field(regs);
2.159 -
2.160 - return d0 * d1;
2.161 + return _divider.get_output_division(regs);
2.162 }
2.163
2.164 void
2.165 Pll::set_output_division(Cpm_regs ®s, uint8_t divider)
2.166 {
2.167 - // Assert 1 as a minimum.
2.168 - // Divider 0 must be less than or equal to divider 1.
2.169 -
2.170 - uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
2.171 - uint8_t d1 = divider / d0;
2.172 -
2.173 - _output_division0.set_field(regs, d0);
2.174 - _output_division1.set_field(regs, d1);
2.175 + _divider.set_output_division(regs, divider);
2.176 }
2.177
2.178 uint32_t
2.179 @@ -317,8 +409,7 @@
2.180 if (pll_enabled(regs))
2.181 {
2.182 if (!pll_bypassed(regs))
2.183 - return (get_source_frequency(regs) * get_multiplier(regs)) /
2.184 - (get_input_division(regs) * get_output_division(regs));
2.185 + return _divider.get_frequency(regs, get_source_frequency(regs));
2.186 else
2.187 return get_source_frequency(regs);
2.188 }
2.189 @@ -327,11 +418,10 @@
2.190 }
2.191
2.192 void
2.193 -Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
2.194 +Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
2.195 + uint8_t in_divider, uint8_t out_divider)
2.196 {
2.197 - set_multiplier(regs, multiplier);
2.198 - set_input_division(regs, in_divider);
2.199 - set_output_division(regs, out_divider);
2.200 + set_pll_parameters(regs, multiplier, in_divider, out_divider);
2.201
2.202 if (pll_enabled(regs) && !pll_bypassed(regs))
2.203 while (!have_pll(regs));
2.204 @@ -385,27 +475,19 @@
2.205 while (_busy.get_field(regs));
2.206 }
2.207
2.208 -
2.209 -
2.210 // Clock dividers.
2.211
2.212 uint32_t
2.213 Clock::get_divider(Cpm_regs ®s)
2.214 {
2.215 - if (_divider.is_defined())
2.216 - return _divider.get_field(regs) + 1;
2.217 - else
2.218 - return 1;
2.219 + return _divider.get_divider(regs);
2.220 }
2.221
2.222 void
2.223 Clock::set_divider(Cpm_regs ®s, uint32_t division)
2.224 {
2.225 - if (!_divider.is_defined())
2.226 - return;
2.227 -
2.228 change_enable(regs);
2.229 - _divider.set_field(regs, division - 1);
2.230 + _divider.set_divider(regs, division);
2.231 wait_busy(regs);
2.232 change_disable(regs);
2.233 }
2.234 @@ -418,3 +500,11 @@
2.235 wait_busy(regs);
2.236 change_disable(regs);
2.237 }
2.238 +
2.239 +// Output clock frequencies.
2.240 +
2.241 +uint32_t
2.242 +Clock::get_frequency(Cpm_regs ®s)
2.243 +{
2.244 + return _divider.get_frequency(regs, get_source_frequency(regs));
2.245 +}
3.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Sat Sep 16 16:53:06 2023 +0200
3.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Sat Sep 16 17:56:49 2023 +0200
3.3 @@ -256,37 +256,37 @@
3.4 Clock_gate_can0,
3.5 Clock_change_enable_can0,
3.6 Clock_busy_can0,
3.7 - Clock_divider_can0);
3.8 + Divider(Clock_divider_can0));
3.9
3.10 Clock clock_can1(Source(mux_bus, Clock_source_can1),
3.11 Clock_gate_can1,
3.12 Clock_change_enable_can1,
3.13 Clock_busy_can1,
3.14 - Clock_divider_can1);
3.15 + Divider(Clock_divider_can1));
3.16
3.17 Clock clock_cdbus(Source(mux_dev, Clock_source_cdbus),
3.18 Clock_gate_cdbus,
3.19 Clock_change_enable_cdbus,
3.20 Clock_busy_cdbus,
3.21 - Clock_divider_cdbus);
3.22 + Divider(Clock_divider_cdbus));
3.23
3.24 Clock clock_cim(Source(mux_dev, Clock_source_cim),
3.25 Clock_gate_cim,
3.26 Clock_change_enable_cim,
3.27 Clock_busy_cim,
3.28 - Clock_divider_cim);
3.29 + Divider(Clock_divider_cim));
3.30
3.31 Clock clock_cpu(Source(mux_core, Clock_source_cpu),
3.32 Field::undefined,
3.33 Clock_change_enable_cpu,
3.34 Clock_busy_cpu,
3.35 - Clock_divider_cpu);
3.36 + Divider(Clock_divider_cpu));
3.37
3.38 Clock clock_ddr(Source(mux_core, Clock_source_ddr),
3.39 Clock_gate_ddr,
3.40 Clock_change_enable_ddr,
3.41 Clock_busy_ddr,
3.42 - Clock_divider_ddr);
3.43 + Divider(Clock_divider_ddr));
3.44
3.45 Clock clock_dma(Source(mux_pclock), Clock_gate_dma);
3.46
3.47 @@ -298,13 +298,13 @@
3.48 Clock_gate_ahb0,
3.49 Clock_change_enable_ahb0,
3.50 Field::undefined,
3.51 - Clock_divider_hclock0);
3.52 + Divider(Clock_divider_hclock0));
3.53
3.54 Clock clock_hclock2(Source(mux_ahb2_apb),
3.55 Clock_gate_apb0,
3.56 Clock_change_enable_ahb2,
3.57 Field::undefined,
3.58 - Clock_divider_hclock2);
3.59 + Divider(Clock_divider_hclock2));
3.60
3.61 Clock clock_hdmi;
3.62
3.63 @@ -332,13 +332,13 @@
3.64 Clock_gate_lcd_pixel,
3.65 Clock_change_enable_lcd,
3.66 Clock_busy_lcd,
3.67 - Clock_divider_lcd);
3.68 + Divider(Clock_divider_lcd));
3.69
3.70 Clock clock_mac(Source(mux_dev, Clock_source_mac),
3.71 Clock_gate_gmac0,
3.72 Clock_change_enable_mac,
3.73 Clock_busy_mac,
3.74 - Clock_divider_mac);
3.75 + Divider(Clock_divider_mac));
3.76
3.77 Clock clock_main(Source(mux_core, Clock_source_main),
3.78 Clock_gate_main);
3.79 @@ -347,19 +347,19 @@
3.80 Clock_gate_msc0,
3.81 Clock_change_enable_msc0,
3.82 Clock_busy_msc0,
3.83 - Clock_divider_msc0);
3.84 + Divider(Clock_divider_msc0));
3.85
3.86 Clock clock_msc0(Source(mux_dev, Clock_source_msc0),
3.87 Clock_gate_msc0,
3.88 Clock_change_enable_msc0,
3.89 Clock_busy_msc0,
3.90 - Clock_divider_msc0);
3.91 + Divider(Clock_divider_msc0));
3.92
3.93 Clock clock_msc1(Source(mux_dev, Clock_source_msc1),
3.94 Clock_gate_msc1,
3.95 Clock_change_enable_msc1,
3.96 Clock_busy_msc1,
3.97 - Clock_divider_msc1);
3.98 + Divider(Clock_divider_msc1));
3.99
3.100 Clock clock_none;
3.101
3.102 @@ -367,34 +367,34 @@
3.103 Clock_gate_apb0,
3.104 Field::undefined,
3.105 Field::undefined,
3.106 - Clock_divider_pclock);
3.107 + Divider(Clock_divider_pclock));
3.108
3.109 Pll clock_pll_A(Source(mux_external),
3.110 Pll_enable_A, Pll_stable_A, Pll_bypass_A,
3.111 - Pll_multiplier_A, Pll_input_division_A,
3.112 - Pll_output_division0_A, Pll_output_division1_A);
3.113 + Divider_pll(Pll_multiplier_A, Pll_input_division_A,
3.114 + Pll_output_division0_A, Pll_output_division1_A));
3.115
3.116 Pll clock_pll_E(Source(mux_external),
3.117 Pll_enable_E, Pll_stable_E, Pll_bypass_E,
3.118 - Pll_multiplier_E, Pll_input_division_E,
3.119 - Pll_output_division0_E, Pll_output_division1_E);
3.120 + Divider_pll(Pll_multiplier_E, Pll_input_division_E,
3.121 + Pll_output_division0_E, Pll_output_division1_E));
3.122
3.123 Pll clock_pll_M(Source(mux_external),
3.124 Pll_enable_M, Pll_stable_M, Pll_bypass_M,
3.125 - Pll_multiplier_M, Pll_input_division_M,
3.126 - Pll_output_division0_M, Pll_output_division1_M);
3.127 + Divider_pll(Pll_multiplier_M, Pll_input_division_M,
3.128 + Pll_output_division0_M, Pll_output_division1_M));
3.129
3.130 Clock clock_pwm(Source(mux_dev, Clock_source_pwm),
3.131 Clock_gate_pwm,
3.132 Clock_change_enable_pwm,
3.133 Clock_busy_pwm,
3.134 - Clock_divider_pwm);
3.135 + Divider(Clock_divider_pwm));
3.136
3.137 Clock clock_pwm0(Source(mux_dev, Clock_source_pwm),
3.138 Clock_gate_pwm,
3.139 Clock_change_enable_pwm,
3.140 Clock_busy_pwm,
3.141 - Clock_divider_pwm);
3.142 + Divider(Clock_divider_pwm));
3.143
3.144 Clock clock_pwm1;
3.145
3.146 @@ -404,7 +404,7 @@
3.147 Clock_gate_sfc,
3.148 Clock_change_enable_sfc,
3.149 Clock_busy_sfc,
3.150 - Clock_divider_sfc);
3.151 + Divider(Clock_divider_sfc));
3.152
3.153 Clock clock_smb0;
3.154
3.155 @@ -420,7 +420,7 @@
3.156 Clock_gate_ssi0,
3.157 Clock_change_enable_ssi,
3.158 Clock_busy_ssi,
3.159 - Clock_divider_ssi);
3.160 + Divider(Clock_divider_ssi));
3.161
3.162 Clock clock_timer(Source(mux_pclock), Clock_gate_timer);
3.163