1.1 --- a/pkg/devices/lib/cpm/src/common.cc Sat Sep 16 16:53:06 2023 +0200
1.2 +++ b/pkg/devices/lib/cpm/src/common.cc Sat Sep 16 17:56:49 2023 +0200
1.3 @@ -146,6 +146,108 @@
1.4
1.5
1.6
1.7 +// Clock dividers.
1.8 +
1.9 +uint32_t
1.10 +Divider::get_divider(Cpm_regs ®s)
1.11 +{
1.12 + if (_divider.is_defined())
1.13 + return _divider.get_field(regs) + 1;
1.14 + else
1.15 + return 1;
1.16 +}
1.17 +
1.18 +void
1.19 +Divider::set_divider(Cpm_regs ®s, uint32_t division)
1.20 +{
1.21 + if (_divider.is_defined())
1.22 + _divider.set_field(regs, division - 1);
1.23 +}
1.24 +
1.25 +// Output clock frequencies.
1.26 +
1.27 +uint32_t
1.28 +Divider::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
1.29 +{
1.30 + return source_frequency / get_divider(regs);
1.31 +}
1.32 +
1.33 +// Undefined divider.
1.34 +
1.35 +Divider Divider::undefined;
1.36 +
1.37 +
1.38 +
1.39 +// Feedback (13-bit) multiplier.
1.40 +
1.41 +uint16_t
1.42 +Divider_pll::get_multiplier(Cpm_regs ®s)
1.43 +{
1.44 + return _multiplier.get_field(regs) + 1;
1.45 +}
1.46 +
1.47 +void
1.48 +Divider_pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
1.49 +{
1.50 + _multiplier.set_field(regs, multiplier - 1);
1.51 +}
1.52 +
1.53 +// Input (6-bit) divider.
1.54 +
1.55 +uint8_t
1.56 +Divider_pll::get_input_division(Cpm_regs ®s)
1.57 +{
1.58 + return _input_division.get_field(regs) + 1;
1.59 +}
1.60 +
1.61 +void
1.62 +Divider_pll::set_input_division(Cpm_regs ®s, uint8_t divider)
1.63 +{
1.64 + _input_division.set_field(regs, divider - 1);
1.65 +}
1.66 +
1.67 +// Output (dual 3-bit) dividers.
1.68 +
1.69 +uint8_t
1.70 +Divider_pll::get_output_division(Cpm_regs ®s)
1.71 +{
1.72 + uint8_t d0 = _output_division0.get_field(regs);
1.73 + uint8_t d1 = _output_division1.get_field(regs);
1.74 +
1.75 + return d0 * d1;
1.76 +}
1.77 +
1.78 +void
1.79 +Divider_pll::set_output_division(Cpm_regs ®s, uint8_t divider)
1.80 +{
1.81 + // Assert 1 as a minimum.
1.82 + // Divider 0 must be less than or equal to divider 1.
1.83 +
1.84 + uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
1.85 + uint8_t d1 = divider / d0;
1.86 +
1.87 + _output_division0.set_field(regs, d0);
1.88 + _output_division1.set_field(regs, d1);
1.89 +}
1.90 +
1.91 +uint32_t
1.92 +Divider_pll::get_frequency(Cpm_regs ®s, uint32_t source_frequency)
1.93 +{
1.94 + return (source_frequency * get_multiplier(regs)) /
1.95 + (get_input_division(regs) * get_output_division(regs));
1.96 +}
1.97 +
1.98 +void
1.99 +Divider_pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.100 + uint8_t in_divider, uint8_t out_divider)
1.101 +{
1.102 + set_multiplier(regs, multiplier);
1.103 + set_input_division(regs, in_divider);
1.104 + set_output_division(regs, out_divider);
1.105 +}
1.106 +
1.107 +
1.108 +
1.109 // Clock control.
1.110
1.111 int
1.112 @@ -210,7 +312,7 @@
1.113 uint32_t
1.114 Clock_base::get_frequency(Cpm_regs ®s)
1.115 {
1.116 - return get_source_frequency(regs) / get_divider(regs);
1.117 + return get_source_frequency(regs);
1.118 }
1.119
1.120
1.121 @@ -262,13 +364,13 @@
1.122 uint16_t
1.123 Pll::get_multiplier(Cpm_regs ®s)
1.124 {
1.125 - return _multiplier.get_field(regs) + 1;
1.126 + return _divider.get_multiplier(regs);
1.127 }
1.128
1.129 void
1.130 Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
1.131 {
1.132 - _multiplier.set_field(regs, multiplier - 1);
1.133 + _divider.set_multiplier(regs, multiplier);
1.134 }
1.135
1.136 // Input (6-bit) divider.
1.137 @@ -276,13 +378,13 @@
1.138 uint8_t
1.139 Pll::get_input_division(Cpm_regs ®s)
1.140 {
1.141 - return _input_division.get_field(regs) + 1;
1.142 + return _divider.get_input_division(regs);
1.143 }
1.144
1.145 void
1.146 Pll::set_input_division(Cpm_regs ®s, uint8_t divider)
1.147 {
1.148 - _input_division.set_field(regs, divider - 1);
1.149 + _divider.set_input_division(regs, divider);
1.150 }
1.151
1.152 // Output (dual 3-bit) dividers.
1.153 @@ -290,23 +392,13 @@
1.154 uint8_t
1.155 Pll::get_output_division(Cpm_regs ®s)
1.156 {
1.157 - uint8_t d0 = _output_division0.get_field(regs);
1.158 - uint8_t d1 = _output_division1.get_field(regs);
1.159 -
1.160 - return d0 * d1;
1.161 + return _divider.get_output_division(regs);
1.162 }
1.163
1.164 void
1.165 Pll::set_output_division(Cpm_regs ®s, uint8_t divider)
1.166 {
1.167 - // Assert 1 as a minimum.
1.168 - // Divider 0 must be less than or equal to divider 1.
1.169 -
1.170 - uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
1.171 - uint8_t d1 = divider / d0;
1.172 -
1.173 - _output_division0.set_field(regs, d0);
1.174 - _output_division1.set_field(regs, d1);
1.175 + _divider.set_output_division(regs, divider);
1.176 }
1.177
1.178 uint32_t
1.179 @@ -317,8 +409,7 @@
1.180 if (pll_enabled(regs))
1.181 {
1.182 if (!pll_bypassed(regs))
1.183 - return (get_source_frequency(regs) * get_multiplier(regs)) /
1.184 - (get_input_division(regs) * get_output_division(regs));
1.185 + return _divider.get_frequency(regs, get_source_frequency(regs));
1.186 else
1.187 return get_source_frequency(regs);
1.188 }
1.189 @@ -327,11 +418,10 @@
1.190 }
1.191
1.192 void
1.193 -Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
1.194 +Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.195 + uint8_t in_divider, uint8_t out_divider)
1.196 {
1.197 - set_multiplier(regs, multiplier);
1.198 - set_input_division(regs, in_divider);
1.199 - set_output_division(regs, out_divider);
1.200 + set_pll_parameters(regs, multiplier, in_divider, out_divider);
1.201
1.202 if (pll_enabled(regs) && !pll_bypassed(regs))
1.203 while (!have_pll(regs));
1.204 @@ -385,27 +475,19 @@
1.205 while (_busy.get_field(regs));
1.206 }
1.207
1.208 -
1.209 -
1.210 // Clock dividers.
1.211
1.212 uint32_t
1.213 Clock::get_divider(Cpm_regs ®s)
1.214 {
1.215 - if (_divider.is_defined())
1.216 - return _divider.get_field(regs) + 1;
1.217 - else
1.218 - return 1;
1.219 + return _divider.get_divider(regs);
1.220 }
1.221
1.222 void
1.223 Clock::set_divider(Cpm_regs ®s, uint32_t division)
1.224 {
1.225 - if (!_divider.is_defined())
1.226 - return;
1.227 -
1.228 change_enable(regs);
1.229 - _divider.set_field(regs, division - 1);
1.230 + _divider.set_divider(regs, division);
1.231 wait_busy(regs);
1.232 change_disable(regs);
1.233 }
1.234 @@ -418,3 +500,11 @@
1.235 wait_busy(regs);
1.236 change_disable(regs);
1.237 }
1.238 +
1.239 +// Output clock frequencies.
1.240 +
1.241 +uint32_t
1.242 +Clock::get_frequency(Cpm_regs ®s)
1.243 +{
1.244 + return _divider.get_frequency(regs, get_source_frequency(regs));
1.245 +}