2.1 --- a/pkg/devices/lib/cpm/include/cpm-common.h Mon Sep 18 16:40:15 2023 +0200
2.2 +++ b/pkg/devices/lib/cpm/include/cpm-common.h Wed Sep 20 00:37:57 2023 +0200
2.3 @@ -149,6 +149,8 @@
2.4
2.5 uint8_t get_source(Cpm_regs ®s);
2.6 void set_source(Cpm_regs ®s, uint8_t source);
2.7 + enum Clock_identifiers get_source_clock(Cpm_regs ®s);
2.8 + void set_source_clock(Cpm_regs ®s, enum Clock_identifiers clock);
2.9
2.10 // Clock source frequency.
2.11
2.12 @@ -252,7 +254,7 @@
2.13
2.14 virtual int get_parameters(Cpm_regs ®s, uint32_t parameters[]) = 0;
2.15
2.16 - virtual void set_parameters(Cpm_regs ®s, uint32_t parameters[]) = 0;
2.17 + virtual int set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[]) = 0;
2.18 };
2.19
2.20
2.21 @@ -286,7 +288,7 @@
2.22 // Other operations.
2.23
2.24 int get_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.25 - void set_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.26 + int set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[]);
2.27 };
2.28
2.29
2.30 @@ -321,7 +323,7 @@
2.31 // Other operations.
2.32
2.33 int get_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.34 - void set_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.35 + int set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[]);
2.36 };
2.37
2.38
2.39 @@ -330,7 +332,7 @@
2.40
2.41 class Divider_i2s : public Divider_base
2.42 {
2.43 - Field _multiplier, _divider_N, _divider_D;
2.44 + Field _multiplier, _divider_N, _divider_D, _auto_N, _auto_D;
2.45
2.46 // General frequency modifiers.
2.47
2.48 @@ -339,10 +341,10 @@
2.49 uint32_t get_divider_D(Cpm_regs ®s);
2.50
2.51 public:
2.52 - explicit Divider_i2s(Field multiplier, Field divider_N,
2.53 - Field divider_D)
2.54 - : _multiplier(multiplier), _divider_N(divider_N),
2.55 - _divider_D(divider_D)
2.56 + explicit Divider_i2s(Field multiplier, Field divider_N, Field divider_D,
2.57 + Field auto_N, Field auto_D)
2.58 + : _multiplier(multiplier), _divider_N(divider_N), _divider_D(divider_D),
2.59 + _auto_N(auto_N), _auto_D(auto_D)
2.60 {
2.61 }
2.62
2.63 @@ -354,7 +356,7 @@
2.64
2.65 int get_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.66
2.67 - void set_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.68 + int set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[]);
2.69 };
2.70
2.71
2.72 @@ -456,6 +458,8 @@
2.73
2.74 virtual uint8_t get_source(Cpm_regs ®s);
2.75 virtual void set_source(Cpm_regs ®s, uint8_t source);
2.76 + enum Clock_identifiers get_source_clock(Cpm_regs ®s);
2.77 + void set_source_clock(Cpm_regs ®s, enum Clock_identifiers clock);
2.78
2.79 // Clock source frequency.
2.80
2.81 @@ -484,7 +488,7 @@
2.82 virtual ~Clock_divided_base();
2.83
2.84 virtual int get_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.85 - virtual void set_parameters(Cpm_regs ®s, uint32_t parameters[]);
2.86 + virtual int set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[]);
2.87
2.88 // Output frequency.
2.89
4.1 --- a/pkg/devices/lib/cpm/src/common.cc Mon Sep 18 16:40:15 2023 +0200
4.2 +++ b/pkg/devices/lib/cpm/src/common.cc Wed Sep 20 00:37:57 2023 +0200
4.3 @@ -23,6 +23,7 @@
4.4
4.5 #include "cpm-common.h"
4.6 #include <math.h>
4.7 +#include <stdio.h>
4.8
4.9
4.10
4.11 @@ -112,22 +113,26 @@
4.12 _source.set_field(regs, source);
4.13 }
4.14
4.15 +enum Clock_identifiers
4.16 +Source::get_source_clock(Cpm_regs ®s)
4.17 +{
4.18 + return get_input(get_number() == 1 ? 0 : get_source(regs));
4.19 +}
4.20 +
4.21 +void
4.22 +Source::set_source_clock(Cpm_regs ®s, enum Clock_identifiers clock)
4.23 +{
4.24 + for (int source = 0; source < _inputs.get_number(); source++)
4.25 + if (get_input(source) == clock)
4.26 + _source.set_field(regs, source);
4.27 +}
4.28 +
4.29 // Clock source frequencies.
4.30
4.31 uint32_t
4.32 Source::get_frequency(Cpm_regs ®s)
4.33 {
4.34 - // Clocks with one source yield that input frequency.
4.35 -
4.36 - if (get_number() == 1)
4.37 - return regs.get_clock(get_input(0))->get_frequency(regs);
4.38 -
4.39 - // With multiple sources, obtain the selected source for the clock.
4.40 -
4.41 - uint8_t source = get_source(regs);
4.42 - enum Clock_identifiers input = get_input(source);
4.43 -
4.44 - // Return the frequency of the source.
4.45 + enum Clock_identifiers input = get_source_clock(regs);
4.46
4.47 if (input != Clock_undefined)
4.48 return regs.get_clock(input)->get_frequency(regs);
4.49 @@ -291,10 +296,16 @@
4.50 return 1;
4.51 }
4.52
4.53 -void
4.54 -Divider::set_parameters(Cpm_regs ®s, uint32_t parameters[])
4.55 +int
4.56 +Divider::set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[])
4.57 {
4.58 - set_divider(regs, parameters[0]);
4.59 + if (num_parameters)
4.60 + {
4.61 + set_divider(regs, parameters[0]);
4.62 + return 1;
4.63 + }
4.64 +
4.65 + return 0;
4.66 }
4.67
4.68
4.69 @@ -367,12 +378,19 @@
4.70 return 3;
4.71 }
4.72
4.73 -void
4.74 -Divider_pll::set_parameters(Cpm_regs ®s, uint32_t parameters[])
4.75 +int
4.76 +Divider_pll::set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[])
4.77 {
4.78 - set_multiplier(regs, parameters[0]);
4.79 - set_input_divider(regs, parameters[1]);
4.80 - set_output_divider(regs, parameters[2]);
4.81 + if (num_parameters > 2)
4.82 + {
4.83 + set_multiplier(regs, parameters[0]);
4.84 + set_input_divider(regs, parameters[1]);
4.85 + set_output_divider(regs, parameters[2]);
4.86 +
4.87 + return 3;
4.88 + }
4.89 +
4.90 + return 0;
4.91 }
4.92
4.93
4.94 @@ -413,17 +431,43 @@
4.95 return 3;
4.96 }
4.97
4.98 -void
4.99 -Divider_i2s::set_parameters(Cpm_regs ®s, uint32_t parameters[])
4.100 +int
4.101 +Divider_i2s::set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[])
4.102 {
4.103 - // Test for N < 2M.
4.104 + if (num_parameters == 1)
4.105 + {
4.106 + // Set automatic N and D value calculation if only one parameter is given.
4.107 +
4.108 + _auto_N.set_field(regs, 0);
4.109 + _auto_D.set_field(regs, 0);
4.110 + _multiplier.set_field(regs, parameters[0]);
4.111 +
4.112 + return 1;
4.113 + }
4.114 + else if (num_parameters > 1)
4.115 + {
4.116 + // Test for N < 2M.
4.117
4.118 - if (parameters[1] < 2 * parameters[0] )
4.119 - return;
4.120 + if (parameters[1] < 2 * parameters[0])
4.121 + return 0;
4.122 +
4.123 + // Set automatic D value calculation if only two parameters are given.
4.124 +
4.125 + _auto_N.set_field(regs, 1);
4.126 + _auto_D.set_field(regs, (num_parameters == 2) ? 0 : 1);
4.127
4.128 - _multiplier.set_field(regs, parameters[0]);
4.129 - _divider_N.set_field(regs, parameters[1]);
4.130 - _divider_D.set_field(regs, parameters[2]);
4.131 + _multiplier.set_field(regs, parameters[0]);
4.132 + _divider_N.set_field(regs, parameters[1]);
4.133 +
4.134 + // Set D explicitly if given.
4.135 +
4.136 + if (num_parameters > 2)
4.137 + _divider_D.set_field(regs, parameters[2]);
4.138 +
4.139 + return num_parameters;
4.140 + }
4.141 +
4.142 + return 0;
4.143 }
4.144
4.145
4.146 @@ -546,6 +590,18 @@
4.147 _get_control().change_disable(regs);
4.148 }
4.149
4.150 +enum Clock_identifiers
4.151 +Clock_active::get_source_clock(Cpm_regs ®s)
4.152 +{
4.153 + return _source.get_source_clock(regs);
4.154 +}
4.155 +
4.156 +void
4.157 +Clock_active::set_source_clock(Cpm_regs ®s, enum Clock_identifiers clock)
4.158 +{
4.159 + _source.set_source_clock(regs, clock);
4.160 +}
4.161 +
4.162 // Clock source frequencies.
4.163
4.164 uint32_t
4.165 @@ -584,13 +640,15 @@
4.166 return _get_divider().get_parameters(regs, parameters);
4.167 }
4.168
4.169 -void
4.170 -Clock_divided_base::set_parameters(Cpm_regs ®s, uint32_t parameters[])
4.171 +int
4.172 +Clock_divided_base::set_parameters(Cpm_regs ®s, int num_parameters, uint32_t parameters[])
4.173 {
4.174 _get_control().change_enable(regs);
4.175 - _get_divider().set_parameters(regs, parameters);
4.176 + int n = _get_divider().set_parameters(regs, num_parameters, parameters);
4.177 _get_control().wait_busy(regs);
4.178 _get_control().change_disable(regs);
4.179 +
4.180 + return n;
4.181 }
4.182
4.183
4.184 @@ -604,13 +662,8 @@
4.185 uint32_t
4.186 Pll::get_frequency(Cpm_regs ®s)
4.187 {
4.188 - if (have_clock(regs))
4.189 - {
4.190 - if (!_control.pll_bypassed(regs))
4.191 - return _divider.get_frequency(regs, get_source_frequency(regs));
4.192 - else
4.193 - return get_source_frequency(regs);
4.194 - }
4.195 + if (!_control.pll_bypassed(regs))
4.196 + return _divider.get_frequency(regs, get_source_frequency(regs));
4.197 else
4.198 - return 0;
4.199 + return get_source_frequency(regs);
4.200 }
5.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Mon Sep 18 16:40:15 2023 +0200
5.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Wed Sep 20 00:37:57 2023 +0200
5.3 @@ -98,7 +98,7 @@
5.4 Clock_source_cdbus (Divider_cdbus, 3, 30), // CDCS
5.5 Clock_source_cim (Divider_cim, 3, 30), // CIMPCS
5.6 Clock_source_ddr (Divider_ddr, 3, 30), // DCS
5.7 - Clock_source_i2s (Divider0_i2s0, 1, 31), // I2PCS
5.8 + Clock_source_i2s (Divider0_i2s0, 1, 30), // I2PCS
5.9 Clock_source_lcd (Divider_lcd, 3, 30), // LPCS
5.10 Clock_source_mac (Divider_mac, 3, 30), // MACPCS
5.11 Clock_source_msc0 (Divider_msc0, 3, 30), // MPCS
5.12 @@ -126,7 +126,7 @@
5.13 Clock_change_enable_ahb2 (Clock_control, 1, 20),
5.14 Clock_change_enable_ddr (Divider_ddr, 1, 29),
5.15 Clock_change_enable_mac (Divider_mac, 1, 29),
5.16 - Clock_change_enable_i2s (Divider0_i2s0, 1, 29),
5.17 + // Clock_change_enable_i2s (Divider0_i2s0, 1, 29), // CE_I2S may not be change enable
5.18 Clock_change_enable_lcd (Divider_lcd, 1, 29),
5.19 Clock_change_enable_msc0 (Divider_msc0, 1, 29),
5.20 Clock_change_enable_msc1 (Divider_msc1, 1, 29),
5.21 @@ -162,6 +162,11 @@
5.22 Clock_divider_sfc (Divider_sfc, 0xff, 0), // SFCCDR
5.23 Clock_divider_ssi (Divider_ssi, 0xff, 0), // SSICDR
5.24
5.25 + Clock_divider_i2s0_n_auto (Divider1_i2s0, 1, 31), // I2S_NEN
5.26 + Clock_divider_i2s0_d_auto (Divider1_i2s0, 1, 30), // I2S_DEN
5.27 + Clock_divider_i2s1_n_auto (Divider1_i2s1, 1, 31), // I2S_NEN
5.28 + Clock_divider_i2s1_d_auto (Divider1_i2s1, 1, 30), // I2S_DEN
5.29 +
5.30 Clock_gate_main (Clock_control, 1, 23), // GATE_SCLKA
5.31 Clock_gate_ddr (Clock_gate0, 1, 31), // DDR
5.32 Clock_gate_ahb0 (Clock_gate0, 1, 29), // AHB0
5.33 @@ -237,8 +242,9 @@
5.34 #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__})
5.35
5.36 static Mux mux_external (Clock_external),
5.37 + mux_hclock0 (Clock_hclock0),
5.38 + mux_hclock2 (Clock_hclock2),
5.39 mux_pclock (Clock_pclock),
5.40 - mux_ahb2_apb (Clock_ahb2_apb),
5.41 mux_core (3, Clocks(Clock_none, Clock_main, Clock_pll_M)),
5.42 mux_bus (4, Clocks(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external)),
5.43 mux_dev (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E)),
5.44 @@ -255,9 +261,7 @@
5.45 // Note the use of extra parentheses due to the annoying C++ "most vexing parse"
5.46 // problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse
5.47
5.48 -static Clock clock_ahb2_apb(Source(mux_core, Clock_source_hclock2)),
5.49 -
5.50 - clock_dma((Source(mux_pclock)), (Control(Clock_gate_dma))),
5.51 +static Clock clock_dma((Source(mux_hclock2)), (Control(Clock_gate_dma))),
5.52
5.53 clock_i2c((Source(mux_pclock)), (Control(Clock_gate_i2c0))),
5.54
5.55 @@ -267,6 +271,10 @@
5.56
5.57 clock_main(Source(mux_core, Clock_source_main), Control(Clock_gate_main)),
5.58
5.59 + clock_mipi_csi((Source(mux_hclock0)), Control(Clock_gate_mipi_csi)),
5.60 +
5.61 + clock_otg((Source(mux_hclock2)), (Control(Clock_gate_otg))),
5.62 +
5.63 clock_timer((Source(mux_pclock)), (Control(Clock_gate_timer))),
5.64
5.65 clock_uart0((Source(mux_external)), (Control(Clock_gate_uart0))),
5.66 @@ -306,7 +314,7 @@
5.67 Control(Clock_gate_ahb0, Clock_change_enable_ahb0),
5.68 Divider(Clock_divider_hclock0)),
5.69
5.70 - clock_hclock2(Source(mux_ahb2_apb),
5.71 + clock_hclock2(Source(mux_core, Clock_source_hclock2),
5.72 Control(Clock_gate_apb0, Clock_change_enable_ahb2),
5.73 Divider(Clock_divider_hclock2)),
5.74
5.75 @@ -330,9 +338,9 @@
5.76 Control(Clock_gate_msc1, Clock_change_enable_msc1, Clock_busy_msc1),
5.77 Divider(Clock_divider_msc1)),
5.78
5.79 - clock_pclock((Source(mux_ahb2_apb)),
5.80 - (Control(Clock_gate_apb0)),
5.81 - (Divider(Clock_divider_pclock))),
5.82 + clock_pclock(Source(mux_core, Clock_source_hclock2),
5.83 + Control(Clock_gate_apb0, Clock_change_enable_ahb2),
5.84 + Divider(Clock_divider_pclock)),
5.85
5.86 clock_pwm(Source(mux_dev, Clock_source_pwm),
5.87 Control(Clock_gate_pwm, Clock_change_enable_pwm, Clock_busy_pwm),
5.88 @@ -352,14 +360,16 @@
5.89
5.90 static Clock_divided_i2s
5.91 clock_i2s0_rx(Source(mux_i2s, Clock_source_i2s),
5.92 - Control(Clock_gate_i2s0_rx, Clock_change_enable_i2s),
5.93 + Control(Clock_gate_i2s0_rx),
5.94 Divider_i2s(Clock_divider_i2s0_m, Clock_divider_i2s0_n,
5.95 - Clock_divider_i2s0_d)),
5.96 + Clock_divider_i2s0_d, Clock_divider_i2s0_n_auto,
5.97 + Clock_divider_i2s0_d_auto)),
5.98
5.99 clock_i2s0_tx(Source(mux_i2s, Clock_source_i2s),
5.100 - Control(Clock_gate_i2s0_tx, Clock_change_enable_i2s),
5.101 + Control(Clock_gate_i2s0_tx),
5.102 Divider_i2s(Clock_divider_i2s1_m, Clock_divider_i2s1_n,
5.103 - Clock_divider_i2s1_d));
5.104 + Clock_divider_i2s1_d, Clock_divider_i2s1_n_auto,
5.105 + Clock_divider_i2s1_d_auto));
5.106
5.107 static Pll clock_pll_A(Source(mux_external),
5.108 Control_pll(Pll_enable_A, Pll_stable_A, Pll_bypass_A),
5.109 @@ -381,7 +391,6 @@
5.110 // Clock register.
5.111
5.112 static Clock_base *clocks[Clock_identifier_count] = {
5.113 - &clock_ahb2_apb,
5.114 &clock_none, // Clock_aic_bitclk
5.115 &clock_none, // Clock_aic_pclk
5.116 &clock_can0,
5.117 @@ -407,10 +416,12 @@
5.118 &clock_lcd_pixel,
5.119 &clock_mac,
5.120 &clock_main,
5.121 + &clock_mipi_csi,
5.122 &clock_msc,
5.123 &clock_msc0,
5.124 &clock_msc1,
5.125 &clock_none,
5.126 + &clock_otg,
5.127 &clock_pclock,
5.128 &clock_pll_A,
5.129 &clock_pll_E,
5.130 @@ -485,13 +496,15 @@
5.131 return 0;
5.132 }
5.133
5.134 -void
5.135 -Cpm_x1600_chip::set_parameters(enum Clock_identifiers clock, uint32_t parameters[])
5.136 +int
5.137 +Cpm_x1600_chip::set_parameters(enum Clock_identifiers clock, int num_parameters, uint32_t parameters[])
5.138 {
5.139 Clock_divided_base *clk = dynamic_cast<Clock_divided_base *>(clocks[clock]);
5.140
5.141 if (clk != NULL)
5.142 - clk->set_parameters(_cpm_regs, parameters);
5.143 + return clk->set_parameters(_cpm_regs, num_parameters, parameters);
5.144 + else
5.145 + return 0;
5.146 }
5.147
5.148 uint8_t
5.149 @@ -505,6 +518,26 @@
5.150 return 0;
5.151 }
5.152
5.153 +enum Clock_identifiers
5.154 +Cpm_x1600_chip::get_source_clock(enum Clock_identifiers clock)
5.155 +{
5.156 + Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]);
5.157 +
5.158 + if (clk != NULL)
5.159 + return clk->get_source_clock(_cpm_regs);
5.160 + else
5.161 + return Clock_undefined;
5.162 +}
5.163 +
5.164 +void
5.165 +Cpm_x1600_chip::set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source)
5.166 +{
5.167 + Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]);
5.168 +
5.169 + if (clk != NULL)
5.170 + clk->set_source_clock(_cpm_regs, source);
5.171 +}
5.172 +
5.173 void
5.174 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source)
5.175 {
5.176 @@ -553,7 +586,7 @@
5.177
5.178 lcd->set_source(_cpm_regs, Source_mME_pll_M);
5.179 pll->start_clock(_cpm_regs);
5.180 - lcd->set_parameters(_cpm_regs, parameters);
5.181 + lcd->set_parameters(_cpm_regs, 1, parameters);
5.182 }
5.183 break;
5.184 }
5.185 @@ -606,10 +639,10 @@
5.186 return static_cast<Cpm_x1600_chip *>(cpm)->get_parameters(clock, parameters);
5.187 }
5.188
5.189 -void
5.190 -x1600_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[])
5.191 +int
5.192 +x1600_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[])
5.193 {
5.194 - return static_cast<Cpm_x1600_chip *>(cpm)->set_parameters(clock, parameters);
5.195 + return static_cast<Cpm_x1600_chip *>(cpm)->set_parameters(clock, num_parameters, parameters);
5.196 }
5.197
5.198 uint8_t
5.199 @@ -624,6 +657,18 @@
5.200 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source);
5.201 }
5.202
5.203 +enum Clock_identifiers
5.204 +x1600_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock)
5.205 +{
5.206 + return static_cast<Cpm_x1600_chip *>(cpm)->get_source_clock(clock);
5.207 +}
5.208 +
5.209 +void
5.210 +x1600_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source)
5.211 +{
5.212 + static_cast<Cpm_x1600_chip *>(cpm)->set_source_clock(clock, source);
5.213 +}
5.214 +
5.215 uint32_t
5.216 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock)
5.217 {