2.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Thu Sep 14 18:51:41 2023 +0200
2.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Fri Sep 15 00:31:43 2023 +0200
2.3 @@ -263,12 +263,107 @@
2.4
2.5
2.6
2.7 +// Common clock abstraction.
2.8 +
2.9 +class Clock_base
2.10 +{
2.11 +protected:
2.12 +
2.13 + // Clock sources and source selection.
2.14 +
2.15 + int num_inputs;
2.16 + enum Clock_identifiers *inputs;
2.17 + uint32_t source_reg;
2.18 + enum Clock_source_bits source_bit;
2.19 +
2.20 +public:
2.21 + explicit Clock_base(int num_inputs = 0,
2.22 + enum Clock_identifiers inputs[] = NULL,
2.23 + uint32_t source_reg = Reg_undefined,
2.24 + enum Clock_source_bits source_bit = Clock_source_undefined)
2.25 + : num_inputs(num_inputs), inputs(inputs),
2.26 + source_reg(source_reg), source_bit(source_bit)
2.27 + {
2.28 + }
2.29 +
2.30 + // Clock control.
2.31 +
2.32 + virtual int have_clock(Cpm_regs ®s);
2.33 + virtual void start_clock(Cpm_regs ®s);
2.34 + virtual void stop_clock(Cpm_regs ®s);
2.35 +
2.36 + // Clock divider.
2.37 +
2.38 + virtual uint32_t get_divider(Cpm_regs ®s);
2.39 + virtual void set_divider(Cpm_regs ®s, uint32_t division);
2.40 +
2.41 + // Clock source.
2.42 +
2.43 + virtual uint8_t get_source(Cpm_regs ®s);
2.44 + virtual void set_source(Cpm_regs ®s, uint8_t source);
2.45 +
2.46 + // Clock source frequency.
2.47 +
2.48 + virtual uint32_t get_source_frequency(Cpm_regs ®s);
2.49 +
2.50 + // Output frequency.
2.51 +
2.52 + virtual uint32_t get_frequency(Cpm_regs ®s);
2.53 +};
2.54 +
2.55 +
2.56 +
2.57 +// PLL descriptions.
2.58 +
2.59 +class Pll : public Clock_base
2.60 +{
2.61 + uint32_t control_reg;
2.62 + enum Pll_bypass_bits bypass_bit;
2.63 +
2.64 +public:
2.65 + explicit Pll(int num_inputs, enum Clock_identifiers inputs[],
2.66 + uint32_t control_reg, enum Pll_bypass_bits bypass_bit)
2.67 + : Clock_base(num_inputs, inputs), control_reg(control_reg), bypass_bit(bypass_bit)
2.68 + {
2.69 + }
2.70 +
2.71 + // PLL_specific control.
2.72 +
2.73 + int have_pll(Cpm_regs ®s);
2.74 + int pll_enabled(Cpm_regs ®s);
2.75 + int pll_bypassed(Cpm_regs ®s);
2.76 +
2.77 + // Clock control.
2.78 +
2.79 + int have_clock(Cpm_regs ®s);
2.80 + void start_clock(Cpm_regs ®s);
2.81 + void stop_clock(Cpm_regs ®s);
2.82 +
2.83 + // General frequency modifiers.
2.84 +
2.85 + uint16_t get_multiplier(Cpm_regs ®s);
2.86 + void set_multiplier(Cpm_regs ®s, uint16_t multiplier);
2.87 + uint8_t get_input_division(Cpm_regs ®s);
2.88 + void set_input_division(Cpm_regs ®s, uint8_t divider);
2.89 + uint8_t get_output_division(Cpm_regs ®s);
2.90 + void set_output_division(Cpm_regs ®s, uint8_t divider);
2.91 +
2.92 + // PLL output frequency.
2.93 +
2.94 + uint32_t get_frequency(Cpm_regs ®s);
2.95 +
2.96 + // Other operations.
2.97 +
2.98 + void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
2.99 + uint8_t in_divider, uint8_t out_divider);
2.100 +};
2.101 +
2.102 +
2.103 +
2.104 // Clock descriptions.
2.105
2.106 -struct Clock_desc
2.107 +class Clock : public Clock_base
2.108 {
2.109 - uint32_t source_reg;
2.110 - enum Clock_source_bits source_bit;
2.111 uint32_t gate_reg;
2.112 enum Clock_gate_bits gate_bit;
2.113 uint32_t change_enable_reg;
2.114 @@ -278,322 +373,665 @@
2.115 uint32_t divider_reg;
2.116 enum Clock_divider_bits divider_bit;
2.117 uint32_t divider_mask;
2.118 - int num_inputs;
2.119 - enum Clock_identifiers inputs[4];
2.120 -};
2.121
2.122 -#define Clock_desc_undefined {Reg_undefined, Clock_source_undefined, \
2.123 - Reg_undefined, Clock_gate_undefined, \
2.124 - Reg_undefined, Clock_change_enable_undefined, \
2.125 - Reg_undefined, Clock_busy_undefined, \
2.126 - Reg_undefined, Clock_divider_undefined, 0, \
2.127 - 0, {}}
2.128 -
2.129 -static struct Clock_desc clock_desc[Clock_identifier_count] = {
2.130 -
2.131 - /* Clock_ahb2_apb */ {Clock_control, Clock_source_hclock2,
2.132 - Reg_undefined, Clock_gate_undefined,
2.133 - Reg_undefined, Clock_change_enable_undefined,
2.134 - Reg_undefined, Clock_busy_undefined,
2.135 - Reg_undefined, Clock_divider_undefined, 0,
2.136 - 3, {Clock_none, Clock_main, Clock_pll_M}},
2.137 -
2.138 - /* Clock_aic_bitclk */ Clock_desc_undefined,
2.139 -
2.140 - /* Clock_aic_pclk */ Clock_desc_undefined,
2.141 -
2.142 - /* Clock_can0 */ {Can_divider0, Clock_source_can0,
2.143 - Clock_gate1, Clock_gate_can0,
2.144 - Can_divider0, Clock_change_enable_can0,
2.145 - Can_divider0, Clock_busy_can0,
2.146 - Can_divider0, Clock_divider_can0, 0xff,
2.147 - 4, {Clock_main, Clock_pll_M, Clock_pll_E, Clock_external}},
2.148 -
2.149 - /* Clock_can1 */ {Can_divider1, Clock_source_can1,
2.150 - Clock_gate1, Clock_gate_can1,
2.151 - Can_divider1, Clock_change_enable_can1,
2.152 - Can_divider1, Clock_busy_can1,
2.153 - Can_divider1, Clock_divider_can1, 0xff,
2.154 - 4, {Clock_main, Clock_pll_M, Clock_pll_E, Clock_external}},
2.155 -
2.156 - /* Clock_cdbus */ {Cdbus_divider, Clock_source_cdbus,
2.157 - Clock_gate1, Clock_gate_cdbus,
2.158 - Cdbus_divider, Clock_change_enable_cdbus,
2.159 - Cdbus_divider, Clock_busy_cdbus,
2.160 - Cdbus_divider, Clock_divider_cdbus, 0xff,
2.161 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.162 -
2.163 - /* Clock_cim */ {Cim_divider, Clock_source_cim,
2.164 - Clock_gate0, Clock_gate_cim,
2.165 - Cim_divider, Clock_change_enable_cim,
2.166 - Cim_divider, Clock_busy_cim,
2.167 - Cim_divider, Clock_divider_cim, 0xff,
2.168 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.169 -
2.170 - /* Clock_cpu */ {Clock_control, Clock_source_cpu,
2.171 - Reg_undefined, Clock_gate_undefined,
2.172 - Clock_control, Clock_change_enable_cpu,
2.173 - Clock_status, Clock_busy_cpu,
2.174 - Clock_control, Clock_divider_cpu, 0x0f,
2.175 - 3, {Clock_none, Clock_main, Clock_pll_M}},
2.176 -
2.177 - /* Clock_ddr */ {Ddr_divider, Clock_source_ddr,
2.178 - Clock_gate0, Clock_gate_ddr,
2.179 - Ddr_divider, Clock_change_enable_ddr,
2.180 - Ddr_divider, Clock_busy_ddr,
2.181 - Ddr_divider, Clock_divider_ddr, 0x0f,
2.182 - 3, {Clock_none, Clock_main, Clock_pll_M}},
2.183 -
2.184 - /* Clock_dma */ {Reg_undefined, Clock_source_undefined,
2.185 - Clock_gate0, Clock_gate_dma,
2.186 - Reg_undefined, Clock_change_enable_undefined,
2.187 - Reg_undefined, Clock_busy_undefined,
2.188 - Reg_undefined, Clock_divider_undefined, 0,
2.189 - 1, {Clock_pclock}},
2.190 + // Clock control.
2.191
2.192 - /* Clock_emac */ Clock_desc_undefined,
2.193 -
2.194 - /* Clock_external */ {Reg_undefined, Clock_source_undefined,
2.195 - Reg_undefined, Clock_gate_undefined,
2.196 - Reg_undefined, Clock_change_enable_undefined,
2.197 - Reg_undefined, Clock_busy_undefined,
2.198 - Reg_undefined, Clock_divider_undefined, 0,
2.199 - 0, {}},
2.200 -
2.201 - /* Clock_hclock0 */ {Clock_control, Clock_source_hclock0,
2.202 - Clock_gate0, Clock_gate_ahb0,
2.203 - Clock_control, Clock_change_enable_ahb0,
2.204 - Reg_undefined, Clock_busy_undefined,
2.205 - Clock_control, Clock_divider_hclock0, 0x0f,
2.206 - 3, {Clock_none, Clock_main, Clock_pll_M}},
2.207 -
2.208 - /* Clock_hclock2 */ {Reg_undefined, Clock_source_undefined,
2.209 - Clock_gate0, Clock_gate_apb0,
2.210 - Clock_control, Clock_change_enable_ahb2,
2.211 - Reg_undefined, Clock_busy_undefined,
2.212 - Clock_control, Clock_divider_hclock2, 0x0f,
2.213 - 1, {Clock_ahb2_apb}},
2.214 -
2.215 - /* Clock_hdmi */ Clock_desc_undefined,
2.216 -
2.217 - /* Clock_i2c */ {Reg_undefined, Clock_source_undefined,
2.218 - Clock_gate0, Clock_gate_i2c0,
2.219 - Reg_undefined, Clock_change_enable_undefined,
2.220 - Reg_undefined, Clock_busy_undefined,
2.221 - Reg_undefined, Clock_divider_undefined, 0,
2.222 - 1, {Clock_pclock}},
2.223 -
2.224 - /* Clock_i2c0 */ {Reg_undefined, Clock_source_undefined,
2.225 - Clock_gate0, Clock_gate_i2c0,
2.226 - Reg_undefined, Clock_change_enable_undefined,
2.227 - Reg_undefined, Clock_busy_undefined,
2.228 - Reg_undefined, Clock_divider_undefined, 0,
2.229 - 1, {Clock_pclock}},
2.230 -
2.231 - /* Clock_i2c1 */ {Reg_undefined, Clock_source_undefined,
2.232 - Clock_gate0, Clock_gate_i2c1,
2.233 - Reg_undefined, Clock_change_enable_undefined,
2.234 - Reg_undefined, Clock_busy_undefined,
2.235 - Reg_undefined, Clock_divider_undefined, 0,
2.236 - 1, {Clock_pclock}},
2.237 -
2.238 - /* Clock_i2s */ Clock_desc_undefined,
2.239 -
2.240 - /* Clock_i2s0_rx */ {I2s_divider0, Clock_source_i2s,
2.241 - Clock_gate1, Clock_gate_i2s0_rx,
2.242 - I2s_divider0, Clock_change_enable_i2s,
2.243 - Reg_undefined, Clock_busy_undefined,
2.244 - Reg_undefined, Clock_divider_undefined, 0, // NOTE: To define.
2.245 - 2, {Clock_main, Clock_pll_E}},
2.246 -
2.247 - /* Clock_i2s0_tx */ {I2s_divider0, Clock_source_i2s,
2.248 - Clock_gate1, Clock_gate_i2s0_tx,
2.249 - I2s_divider0, Clock_change_enable_i2s,
2.250 - Reg_undefined, Clock_busy_undefined,
2.251 - Reg_undefined, Clock_divider_undefined, 0, // NOTE: To define.
2.252 - 2, {Clock_main, Clock_pll_E}},
2.253 -
2.254 - /* Clock_kbc */ Clock_desc_undefined,
2.255 -
2.256 - /* Clock_lcd */ Clock_desc_undefined,
2.257 -
2.258 - /* Clock_lcd_pixel */ {Lcd_divider, Clock_source_lcd,
2.259 - Clock_gate0, Clock_gate_lcd_pixel,
2.260 - Lcd_divider, Clock_change_enable_lcd,
2.261 - Lcd_divider, Clock_busy_lcd,
2.262 - Lcd_divider, Clock_divider_lcd, 0xff,
2.263 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.264 + void change_disable(Cpm_regs ®s);
2.265 + void change_enable(Cpm_regs ®s);
2.266 + void wait_busy(Cpm_regs ®s);
2.267
2.268 - /* Clock_mac */ {Mac_divider, Clock_source_mac,
2.269 - Clock_gate1, Clock_gate_gmac0,
2.270 - Mac_divider, Clock_change_enable_mac,
2.271 - Mac_divider, Clock_busy_mac,
2.272 - Mac_divider, Clock_divider_mac, 0xff,
2.273 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.274 -
2.275 - /* Clock_main */ {Clock_control, Clock_source_main,
2.276 - Clock_control, Clock_gate_main,
2.277 - Reg_undefined, Clock_change_enable_undefined,
2.278 - Reg_undefined, Clock_busy_undefined,
2.279 - Reg_undefined, Clock_divider_undefined, 0,
2.280 - 3, {Clock_none, Clock_external, Clock_pll_A}},
2.281 -
2.282 - /* Clock_msc */ {Msc_divider0, Clock_source_msc0,
2.283 - Clock_gate0, Clock_gate_msc0,
2.284 - Msc_divider0, Clock_change_enable_msc0,
2.285 - Msc_divider0, Clock_busy_msc0,
2.286 - Msc_divider0, Clock_divider_msc0, 0xff,
2.287 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.288 -
2.289 - /* Clock_msc0 */ {Msc_divider0, Clock_source_msc0,
2.290 - Clock_gate0, Clock_gate_msc0,
2.291 - Msc_divider0, Clock_change_enable_msc0,
2.292 - Msc_divider0, Clock_busy_msc0,
2.293 - Msc_divider0, Clock_divider_msc0, 0xff,
2.294 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.295 -
2.296 - /* Clock_msc1 */ {Msc_divider1, Clock_source_msc1,
2.297 - Clock_gate0, Clock_gate_msc1,
2.298 - Msc_divider1, Clock_change_enable_msc1,
2.299 - Msc_divider1, Clock_busy_msc1,
2.300 - Msc_divider1, Clock_divider_msc1, 0xff,
2.301 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.302 -
2.303 - /* Clock_none */ {Reg_undefined, Clock_source_undefined,
2.304 - Reg_undefined, Clock_gate_undefined,
2.305 - Reg_undefined, Clock_change_enable_undefined,
2.306 - Reg_undefined, Clock_busy_undefined,
2.307 - Reg_undefined, Clock_divider_undefined, 0,
2.308 - 0, {}},
2.309 -
2.310 - /* Clock_pclock */ {Reg_undefined, Clock_source_undefined,
2.311 - Clock_gate0, Clock_gate_apb0,
2.312 - Reg_undefined, Clock_change_enable_undefined,
2.313 - Reg_undefined, Clock_busy_undefined,
2.314 - Clock_control, Clock_divider_pclock, 0x0f,
2.315 - 1, {Clock_ahb2_apb}},
2.316 -
2.317 - /* Clock_pll_A */ {Reg_undefined, Clock_source_undefined,
2.318 - Reg_undefined, Clock_gate_undefined,
2.319 - Reg_undefined, Clock_change_enable_undefined,
2.320 - Reg_undefined, Clock_busy_undefined,
2.321 - Reg_undefined, Clock_divider_undefined, 0,
2.322 - 1, {Clock_external}},
2.323 -
2.324 - /* Clock_pll_E */ {Reg_undefined, Clock_source_undefined,
2.325 - Reg_undefined, Clock_gate_undefined,
2.326 - Reg_undefined, Clock_change_enable_undefined,
2.327 - Reg_undefined, Clock_busy_undefined,
2.328 - Reg_undefined, Clock_divider_undefined, 0,
2.329 - 1, {Clock_external}},
2.330 -
2.331 - /* Clock_pll_M */ {Reg_undefined, Clock_source_undefined,
2.332 - Reg_undefined, Clock_gate_undefined,
2.333 - Reg_undefined, Clock_change_enable_undefined,
2.334 - Reg_undefined, Clock_busy_undefined,
2.335 - Reg_undefined, Clock_divider_undefined, 0,
2.336 - 1, {Clock_external}},
2.337 +public:
2.338 + explicit Clock(int num_inputs = 0,
2.339 + enum Clock_identifiers inputs[] = NULL,
2.340 + uint32_t source_reg = Reg_undefined,
2.341 + enum Clock_source_bits source_bit = Clock_source_undefined,
2.342 + uint32_t gate_reg = Reg_undefined,
2.343 + enum Clock_gate_bits gate_bit = Clock_gate_undefined,
2.344 + uint32_t change_enable_reg = Reg_undefined,
2.345 + enum Clock_change_enable_bits change_enable_bit = Clock_change_enable_undefined,
2.346 + uint32_t busy_reg = Reg_undefined,
2.347 + enum Clock_busy_bits busy_bit = Clock_busy_undefined,
2.348 + uint32_t divider_reg = Reg_undefined,
2.349 + enum Clock_divider_bits divider_bit = Clock_divider_undefined,
2.350 + uint32_t divider_mask = 0)
2.351 + : Clock_base(num_inputs, inputs, source_reg, source_bit),
2.352 + gate_reg(gate_reg), gate_bit(gate_bit),
2.353 + change_enable_reg(change_enable_reg), change_enable_bit(change_enable_bit),
2.354 + busy_reg(busy_reg), busy_bit(busy_bit),
2.355 + divider_reg(divider_reg), divider_bit(divider_bit), divider_mask(divider_mask)
2.356 + {
2.357 + }
2.358
2.359 - /* Clock_pwm */ {Pwm_divider, Clock_source_pwm,
2.360 - Clock_gate1, Clock_gate_pwm,
2.361 - Pwm_divider, Clock_change_enable_pwm,
2.362 - Pwm_divider, Clock_busy_pwm,
2.363 - Pwm_divider, Clock_divider_pwm, 0x0f,
2.364 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.365 -
2.366 - /* Clock_pwm0 */ {Pwm_divider, Clock_source_pwm,
2.367 - Clock_gate1, Clock_gate_pwm,
2.368 - Pwm_divider, Clock_change_enable_pwm,
2.369 - Pwm_divider, Clock_busy_pwm,
2.370 - Pwm_divider, Clock_divider_pwm, 0x0f,
2.371 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.372 -
2.373 - /* Clock_pwm1 */ Clock_desc_undefined,
2.374 + // Clock control.
2.375
2.376 - /* Clock_scc */ Clock_desc_undefined,
2.377 -
2.378 - /* Clock_sfc */ {Sfc_divider, Clock_source_sfc,
2.379 - Clock_gate0, Clock_gate_sfc,
2.380 - Sfc_divider, Clock_change_enable_sfc,
2.381 - Sfc_divider, Clock_busy_sfc,
2.382 - Sfc_divider, Clock_divider_sfc, 0xff,
2.383 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.384 -
2.385 - /* Clock_smb0 */ Clock_desc_undefined,
2.386 -
2.387 - /* Clock_smb1 */ Clock_desc_undefined,
2.388 -
2.389 - /* Clock_smb2 */ Clock_desc_undefined,
2.390 -
2.391 - /* Clock_smb3 */ Clock_desc_undefined,
2.392 -
2.393 - /* Clock_smb4 */ Clock_desc_undefined,
2.394 + int have_clock(Cpm_regs ®s);
2.395 + void start_clock(Cpm_regs ®s);
2.396 + void stop_clock(Cpm_regs ®s);
2.397
2.398 - /* Clock_ssi */ {Ssi_divider, Clock_source_ssi,
2.399 - Clock_gate0, Clock_gate_ssi0,
2.400 - Ssi_divider, Clock_change_enable_ssi,
2.401 - Ssi_divider, Clock_busy_ssi,
2.402 - Ssi_divider, Clock_divider_ssi, 0xff,
2.403 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
2.404 -
2.405 - /* Clock_timer */ {Reg_undefined, Clock_source_undefined,
2.406 - Clock_gate0, Clock_gate_timer,
2.407 - Reg_undefined, Clock_change_enable_undefined,
2.408 - Reg_undefined, Clock_busy_undefined,
2.409 - Reg_undefined, Clock_divider_undefined, 0,
2.410 - 1, {Clock_pclock}},
2.411 -
2.412 - /* Clock_uart0 */ {Reg_undefined, Clock_source_undefined,
2.413 - Clock_gate0, Clock_gate_uart0,
2.414 - Reg_undefined, Clock_change_enable_undefined,
2.415 - Reg_undefined, Clock_busy_undefined,
2.416 - Reg_undefined, Clock_divider_undefined, 0,
2.417 - 1, {Clock_external}},
2.418 + // Clock divider.
2.419
2.420 - /* Clock_uart1 */ {Reg_undefined, Clock_source_undefined,
2.421 - Clock_gate0, Clock_gate_uart1,
2.422 - Reg_undefined, Clock_change_enable_undefined,
2.423 - Reg_undefined, Clock_busy_undefined,
2.424 - Reg_undefined, Clock_divider_undefined, 0,
2.425 - 1, {Clock_external}},
2.426 + uint32_t get_divider(Cpm_regs ®s);
2.427 + void set_divider(Cpm_regs ®s, uint32_t division);
2.428
2.429 - /* Clock_uart2 */ {Reg_undefined, Clock_source_undefined,
2.430 - Clock_gate0, Clock_gate_uart2,
2.431 - Reg_undefined, Clock_change_enable_undefined,
2.432 - Reg_undefined, Clock_busy_undefined,
2.433 - Reg_undefined, Clock_divider_undefined, 0,
2.434 - 1, {Clock_external}},
2.435 + // Clock source.
2.436
2.437 - /* Clock_uart3 */ {Reg_undefined, Clock_source_undefined,
2.438 - Clock_gate1, Clock_gate_uart3,
2.439 - Reg_undefined, Clock_change_enable_undefined,
2.440 - Reg_undefined, Clock_busy_undefined,
2.441 - Reg_undefined, Clock_divider_undefined, 0,
2.442 - 1, {Clock_external}},
2.443 -
2.444 - /* Clock_udc */ Clock_desc_undefined,
2.445 -
2.446 - /* Clock_uhc */ Clock_desc_undefined,
2.447 -
2.448 - /* Clock_uprt */ Clock_desc_undefined,
2.449 + void set_source(Cpm_regs ®s, uint8_t source);
2.450 };
2.451
2.452
2.453
2.454 -// Convenience functions.
2.455 +// Clock instances.
2.456 +
2.457 +#define Clock_inputs(...) ((enum Clock_identifiers []) {__VA_ARGS__})
2.458 +
2.459 +Clock clock_ahb2_apb(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
2.460 + Clock_control, Clock_source_hclock2);
2.461 +
2.462 +Clock clock_aic_bitclk;
2.463 +
2.464 +Clock clock_aic_pclk;
2.465 +
2.466 +Clock clock_can0(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external),
2.467 + Can_divider0, Clock_source_can0,
2.468 + Clock_gate1, Clock_gate_can0,
2.469 + Can_divider0, Clock_change_enable_can0,
2.470 + Can_divider0, Clock_busy_can0,
2.471 + Can_divider0, Clock_divider_can0, 0xff);
2.472 +
2.473 +Clock clock_can1(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external),
2.474 + Can_divider1, Clock_source_can1,
2.475 + Clock_gate1, Clock_gate_can1,
2.476 + Can_divider1, Clock_change_enable_can1,
2.477 + Can_divider1, Clock_busy_can1,
2.478 + Can_divider1, Clock_divider_can1, 0xff);
2.479 +
2.480 +Clock clock_cdbus(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.481 + Cdbus_divider, Clock_source_cdbus,
2.482 + Clock_gate1, Clock_gate_cdbus,
2.483 + Cdbus_divider, Clock_change_enable_cdbus,
2.484 + Cdbus_divider, Clock_busy_cdbus,
2.485 + Cdbus_divider, Clock_divider_cdbus, 0xff);
2.486 +
2.487 +Clock clock_cim(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.488 + Cim_divider, Clock_source_cim,
2.489 + Clock_gate0, Clock_gate_cim,
2.490 + Cim_divider, Clock_change_enable_cim,
2.491 + Cim_divider, Clock_busy_cim,
2.492 + Cim_divider, Clock_divider_cim, 0xff);
2.493 +
2.494 +Clock clock_cpu(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
2.495 + Clock_control, Clock_source_cpu,
2.496 + Reg_undefined, Clock_gate_undefined,
2.497 + Clock_control, Clock_change_enable_cpu,
2.498 + Clock_status, Clock_busy_cpu,
2.499 + Clock_control, Clock_divider_cpu, 0x0f);
2.500 +
2.501 +Clock clock_ddr(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
2.502 + Ddr_divider, Clock_source_ddr,
2.503 + Clock_gate0, Clock_gate_ddr,
2.504 + Ddr_divider, Clock_change_enable_ddr,
2.505 + Ddr_divider, Clock_busy_ddr,
2.506 + Ddr_divider, Clock_divider_ddr, 0x0f);
2.507 +
2.508 +Clock clock_dma(1, Clock_inputs(Clock_pclock),
2.509 + Reg_undefined, Clock_source_undefined,
2.510 + Clock_gate0, Clock_gate_dma);
2.511 +
2.512 +Clock clock_emac;
2.513 +
2.514 +Clock clock_external;
2.515 +
2.516 +Clock clock_hclock0(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
2.517 + Clock_control, Clock_source_hclock0,
2.518 + Clock_gate0, Clock_gate_ahb0,
2.519 + Clock_control, Clock_change_enable_ahb0,
2.520 + Reg_undefined, Clock_busy_undefined,
2.521 + Clock_control, Clock_divider_hclock0, 0x0f);
2.522 +
2.523 +Clock clock_hclock2(1, Clock_inputs(Clock_ahb2_apb),
2.524 + Reg_undefined, Clock_source_undefined,
2.525 + Clock_gate0, Clock_gate_apb0,
2.526 + Clock_control, Clock_change_enable_ahb2,
2.527 + Reg_undefined, Clock_busy_undefined,
2.528 + Clock_control, Clock_divider_hclock2, 0x0f);
2.529 +
2.530 +Clock clock_hdmi;
2.531 +
2.532 +Clock clock_i2c(1, Clock_inputs(Clock_pclock),
2.533 + Reg_undefined, Clock_source_undefined,
2.534 + Clock_gate0, Clock_gate_i2c0);
2.535 +
2.536 +Clock clock_i2c0(1, Clock_inputs(Clock_pclock),
2.537 + Reg_undefined, Clock_source_undefined,
2.538 + Clock_gate0, Clock_gate_i2c0);
2.539 +
2.540 +Clock clock_i2c1(1, Clock_inputs(Clock_pclock),
2.541 + Reg_undefined, Clock_source_undefined,
2.542 + Clock_gate0, Clock_gate_i2c1);
2.543 +
2.544 +Clock clock_i2s;
2.545 +
2.546 +Clock clock_i2s0_rx(2, Clock_inputs(Clock_main, Clock_pll_E),
2.547 + I2s_divider0, Clock_source_i2s,
2.548 + Clock_gate1, Clock_gate_i2s0_rx,
2.549 + I2s_divider0, Clock_change_enable_i2s);
2.550 +
2.551 +Clock clock_i2s0_tx(2, Clock_inputs(Clock_main, Clock_pll_E),
2.552 + I2s_divider0, Clock_source_i2s,
2.553 + Clock_gate1, Clock_gate_i2s0_tx,
2.554 + I2s_divider0, Clock_change_enable_i2s);
2.555 +
2.556 +Clock clock_kbc;
2.557 +
2.558 +Clock clock_lcd;
2.559 +
2.560 +Clock clock_lcd_pixel(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.561 + Lcd_divider, Clock_source_lcd,
2.562 + Clock_gate0, Clock_gate_lcd_pixel,
2.563 + Lcd_divider, Clock_change_enable_lcd,
2.564 + Lcd_divider, Clock_busy_lcd,
2.565 + Lcd_divider, Clock_divider_lcd, 0xff);
2.566 +
2.567 +Clock clock_mac(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.568 + Mac_divider, Clock_source_mac,
2.569 + Clock_gate1, Clock_gate_gmac0,
2.570 + Mac_divider, Clock_change_enable_mac,
2.571 + Mac_divider, Clock_busy_mac,
2.572 + Mac_divider, Clock_divider_mac, 0xff);
2.573 +
2.574 +Clock clock_main(3, Clock_inputs(Clock_none, Clock_external, Clock_pll_A),
2.575 + Clock_control, Clock_source_main,
2.576 + Clock_control, Clock_gate_main);
2.577 +
2.578 +Clock clock_msc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.579 + Msc_divider0, Clock_source_msc0,
2.580 + Clock_gate0, Clock_gate_msc0,
2.581 + Msc_divider0, Clock_change_enable_msc0,
2.582 + Msc_divider0, Clock_busy_msc0,
2.583 + Msc_divider0, Clock_divider_msc0, 0xff);
2.584 +
2.585 +Clock clock_msc0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.586 + Msc_divider0, Clock_source_msc0,
2.587 + Clock_gate0, Clock_gate_msc0,
2.588 + Msc_divider0, Clock_change_enable_msc0,
2.589 + Msc_divider0, Clock_busy_msc0,
2.590 + Msc_divider0, Clock_divider_msc0, 0xff);
2.591 +
2.592 +Clock clock_msc1(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.593 + Msc_divider1, Clock_source_msc1,
2.594 + Clock_gate0, Clock_gate_msc1,
2.595 + Msc_divider1, Clock_change_enable_msc1,
2.596 + Msc_divider1, Clock_busy_msc1,
2.597 + Msc_divider1, Clock_divider_msc1, 0xff);
2.598 +
2.599 +Clock clock_none;
2.600
2.601 -static uint8_t get_clock_gate_bit(enum Clock_identifiers clock)
2.602 +Clock clock_pclock(1, Clock_inputs(Clock_ahb2_apb),
2.603 + Reg_undefined, Clock_source_undefined,
2.604 + Clock_gate0, Clock_gate_apb0,
2.605 + Reg_undefined, Clock_change_enable_undefined,
2.606 + Reg_undefined, Clock_busy_undefined,
2.607 + Clock_control, Clock_divider_pclock, 0x0f);
2.608 +
2.609 +Pll clock_pll_A(1, Clock_inputs(Clock_external),
2.610 + Pll_control_A, Pll_bypass_A);
2.611 +
2.612 +Pll clock_pll_E(1, Clock_inputs(Clock_external),
2.613 + Pll_control_E, Pll_bypass_E);
2.614 +
2.615 +Pll clock_pll_M(1, Clock_inputs(Clock_external),
2.616 + Pll_control_M, Pll_bypass_M);
2.617 +
2.618 +Clock clock_pwm(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.619 + Pwm_divider, Clock_source_pwm,
2.620 + Clock_gate1, Clock_gate_pwm,
2.621 + Pwm_divider, Clock_change_enable_pwm,
2.622 + Pwm_divider, Clock_busy_pwm,
2.623 + Pwm_divider, Clock_divider_pwm, 0x0f);
2.624 +
2.625 +Clock clock_pwm0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.626 + Pwm_divider, Clock_source_pwm,
2.627 + Clock_gate1, Clock_gate_pwm,
2.628 + Pwm_divider, Clock_change_enable_pwm,
2.629 + Pwm_divider, Clock_busy_pwm,
2.630 + Pwm_divider, Clock_divider_pwm, 0x0f);
2.631 +
2.632 +Clock clock_pwm1;
2.633 +
2.634 +Clock clock_scc;
2.635 +
2.636 +Clock clock_sfc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.637 + Sfc_divider, Clock_source_sfc,
2.638 + Clock_gate0, Clock_gate_sfc,
2.639 + Sfc_divider, Clock_change_enable_sfc,
2.640 + Sfc_divider, Clock_busy_sfc,
2.641 + Sfc_divider, Clock_divider_sfc, 0xff);
2.642 +
2.643 +Clock clock_smb0;
2.644 +
2.645 +Clock clock_smb1;
2.646 +
2.647 +Clock clock_smb2;
2.648 +
2.649 +Clock clock_smb3;
2.650 +
2.651 +Clock clock_smb4;
2.652 +
2.653 +Clock clock_ssi(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
2.654 + Ssi_divider, Clock_source_ssi,
2.655 + Clock_gate0, Clock_gate_ssi0,
2.656 + Ssi_divider, Clock_change_enable_ssi,
2.657 + Ssi_divider, Clock_busy_ssi,
2.658 + Ssi_divider, Clock_divider_ssi, 0xff);
2.659 +
2.660 +Clock clock_timer(1, Clock_inputs(Clock_pclock),
2.661 + Reg_undefined, Clock_source_undefined,
2.662 + Clock_gate0, Clock_gate_timer);
2.663 +
2.664 +Clock clock_uart0(1, Clock_inputs(Clock_external),
2.665 + Reg_undefined, Clock_source_undefined,
2.666 + Clock_gate0, Clock_gate_uart0);
2.667 +
2.668 +Clock clock_uart1(1, Clock_inputs(Clock_external),
2.669 + Reg_undefined, Clock_source_undefined,
2.670 + Clock_gate0, Clock_gate_uart1);
2.671 +
2.672 +Clock clock_uart2(1, Clock_inputs(Clock_external),
2.673 + Reg_undefined, Clock_source_undefined,
2.674 + Clock_gate0, Clock_gate_uart2);
2.675 +
2.676 +Clock clock_uart3(1, Clock_inputs(Clock_external),
2.677 + Reg_undefined, Clock_source_undefined,
2.678 + Clock_gate1, Clock_gate_uart3);
2.679 +
2.680 +Clock clock_udc;
2.681 +
2.682 +Clock clock_uhc;
2.683 +
2.684 +Clock clock_uprt;
2.685 +
2.686 +
2.687 +
2.688 +// Clock register.
2.689 +
2.690 +static Clock_base *clocks[Clock_identifier_count] = {
2.691 + &clock_ahb2_apb,
2.692 + &clock_aic_bitclk,
2.693 + &clock_aic_pclk,
2.694 + &clock_can0,
2.695 + &clock_can1,
2.696 + &clock_cdbus,
2.697 + &clock_cim,
2.698 + &clock_cpu,
2.699 + &clock_ddr,
2.700 + &clock_dma,
2.701 + &clock_emac,
2.702 + &clock_external,
2.703 + &clock_hclock0,
2.704 + &clock_hclock2,
2.705 + &clock_hdmi,
2.706 + &clock_i2c,
2.707 + &clock_i2c0,
2.708 + &clock_i2c1,
2.709 + &clock_i2s,
2.710 + &clock_i2s0_rx,
2.711 + &clock_i2s0_tx,
2.712 + &clock_kbc,
2.713 + &clock_lcd,
2.714 + &clock_lcd_pixel,
2.715 + &clock_mac,
2.716 + &clock_main,
2.717 + &clock_msc,
2.718 + &clock_msc0,
2.719 + &clock_msc1,
2.720 + &clock_none,
2.721 + &clock_pclock,
2.722 + &clock_pll_A,
2.723 + &clock_pll_E,
2.724 + &clock_pll_M,
2.725 + &clock_pwm,
2.726 + &clock_pwm0,
2.727 + &clock_pwm1,
2.728 + &clock_scc,
2.729 + &clock_sfc,
2.730 + &clock_smb0,
2.731 + &clock_smb1,
2.732 + &clock_smb2,
2.733 + &clock_smb3,
2.734 + &clock_smb4,
2.735 + &clock_ssi,
2.736 + &clock_timer,
2.737 + &clock_uart0,
2.738 + &clock_uart1,
2.739 + &clock_uart2,
2.740 + &clock_uart3,
2.741 + &clock_udc,
2.742 + &clock_uhc,
2.743 + &clock_uprt,
2.744 +};
2.745 +
2.746 +
2.747 +
2.748 +// Register access.
2.749 +
2.750 +Cpm_regs::Cpm_regs(l4_addr_t addr, uint32_t exclk_freq)
2.751 +: exclk_freq(exclk_freq)
2.752 {
2.753 - enum Clock_gate_bits bit = clock_desc[clock].gate_bit;
2.754 -
2.755 - return bit != Clock_gate_undefined ? (uint8_t) bit : 0;
2.756 + _regs = new Hw::Mmio_register_block<32>(addr);
2.757 }
2.758
2.759 -static uint32_t get_clock_gate_mask(enum Clock_identifiers clock)
2.760 +// Utility methods.
2.761 +
2.762 +uint32_t
2.763 +Cpm_regs::get_field(uint32_t reg, uint32_t mask, uint8_t shift)
2.764 +{
2.765 + return (_regs[reg] & (mask << shift)) >> shift;
2.766 +}
2.767 +
2.768 +void
2.769 +Cpm_regs::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value)
2.770 +{
2.771 + _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift);
2.772 +}
2.773 +
2.774 +
2.775 +
2.776 +// Clock control.
2.777 +
2.778 +int
2.779 +Clock_base::have_clock(Cpm_regs ®s)
2.780 +{
2.781 + (void) regs;
2.782 + return true;
2.783 +}
2.784 +
2.785 +void
2.786 +Clock_base::start_clock(Cpm_regs ®s)
2.787 +{
2.788 + (void) regs;
2.789 +}
2.790 +
2.791 +void
2.792 +Clock_base::stop_clock(Cpm_regs ®s)
2.793 +{
2.794 + (void) regs;
2.795 +}
2.796 +
2.797 +// Default divider.
2.798 +
2.799 +uint32_t
2.800 +Clock_base::get_divider(Cpm_regs ®s)
2.801 +{
2.802 + (void) regs;
2.803 + return 1;
2.804 +}
2.805 +
2.806 +void
2.807 +Clock_base::set_divider(Cpm_regs ®s, uint32_t division)
2.808 +{
2.809 + (void) regs;
2.810 + (void) division;
2.811 +}
2.812 +
2.813 +// Clock sources.
2.814 +
2.815 +uint8_t
2.816 +Clock_base::get_source(Cpm_regs ®s)
2.817 +{
2.818 + if (source_bit != Clock_source_undefined)
2.819 + return regs.get_field(source_reg, Source_mask, source_bit);
2.820 + else
2.821 + return 0;
2.822 +}
2.823 +
2.824 +void
2.825 +Clock_base::set_source(Cpm_regs ®s, uint8_t source)
2.826 +{
2.827 + if (source_bit == Clock_source_undefined)
2.828 + return;
2.829 +
2.830 + regs.set_field(source_reg, Source_mask, source_bit, source);
2.831 +}
2.832 +
2.833 +// Clock source frequencies.
2.834 +
2.835 +uint32_t
2.836 +Clock_base::get_source_frequency(Cpm_regs ®s)
2.837 +{
2.838 + // Return the external clock frequency without any input clock.
2.839 +
2.840 + if (num_inputs == 0)
2.841 + return regs.exclk_freq;
2.842 +
2.843 + // Clocks with one source yield that input frequency.
2.844 +
2.845 + else if (num_inputs == 1)
2.846 + return clocks[inputs[0]]->get_frequency(regs);
2.847 +
2.848 + // With multiple sources, obtain the selected source for the clock.
2.849 +
2.850 + uint8_t source = get_source(regs);
2.851 +
2.852 + // Return the frequency of the source.
2.853 +
2.854 + if (source < num_inputs)
2.855 + return clocks[inputs[source]]->get_frequency(regs);
2.856 + else
2.857 + return 0;
2.858 +}
2.859 +
2.860 +// Output clock frequencies.
2.861 +
2.862 +uint32_t
2.863 +Clock_base::get_frequency(Cpm_regs ®s)
2.864 +{
2.865 + return get_source_frequency(regs) / get_divider(regs);
2.866 +}
2.867 +
2.868 +
2.869 +
2.870 +// PLL-specific control.
2.871 +
2.872 +int
2.873 +Pll::have_pll(Cpm_regs ®s)
2.874 +{
2.875 + return regs.get_field(control_reg, 1, Pll_stable);
2.876 +}
2.877 +
2.878 +int
2.879 +Pll::pll_enabled(Cpm_regs ®s)
2.880 +{
2.881 + return regs.get_field(control_reg, 1, Pll_enabled);
2.882 +}
2.883 +
2.884 +int
2.885 +Pll::pll_bypassed(Cpm_regs ®s)
2.886 +{
2.887 + return regs.get_field(control_reg, 1, bypass_bit);
2.888 +}
2.889 +
2.890 +// Clock control.
2.891 +
2.892 +int
2.893 +Pll::have_clock(Cpm_regs ®s)
2.894 +{
2.895 + return have_pll(regs) && pll_enabled(regs);
2.896 +}
2.897 +
2.898 +void
2.899 +Pll::start_clock(Cpm_regs ®s)
2.900 +{
2.901 + regs.set_field(control_reg, 1, Pll_enabled, 1);
2.902 + while (!have_pll(regs));
2.903 +}
2.904 +
2.905 +void
2.906 +Pll::stop_clock(Cpm_regs ®s)
2.907 {
2.908 - enum Clock_gate_bits bit = clock_desc[clock].gate_bit;
2.909 + regs.set_field(control_reg, 1, Pll_enabled, 0);
2.910 + while (have_pll(regs));
2.911 +}
2.912 +
2.913 +// Feedback (13-bit) multiplier.
2.914 +
2.915 +uint16_t
2.916 +Pll::get_multiplier(Cpm_regs ®s)
2.917 +{
2.918 + return regs.get_field(control_reg, 0x1fff, Pll_multiplier) + 1;
2.919 +}
2.920 +
2.921 +void
2.922 +Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
2.923 +{
2.924 + regs.set_field(control_reg, 0x1fff, Pll_multiplier, multiplier - 1);
2.925 +}
2.926 +
2.927 +// Input (6-bit) divider.
2.928 +
2.929 +uint8_t
2.930 +Pll::get_input_division(Cpm_regs ®s)
2.931 +{
2.932 + return regs.get_field(control_reg, 0x3f, Pll_input_division) + 1;
2.933 +}
2.934 +
2.935 +void
2.936 +Pll::set_input_division(Cpm_regs ®s, uint8_t divider)
2.937 +{
2.938 + regs.set_field(control_reg, 0x3f, Pll_input_division, divider - 1);
2.939 +}
2.940 +
2.941 +// Output (dual 3-bit) dividers.
2.942 +
2.943 +uint8_t
2.944 +Pll::get_output_division(Cpm_regs ®s)
2.945 +{
2.946 + uint8_t d0 = regs.get_field(control_reg, 0x07, Pll_output_division0);
2.947 + uint8_t d1 = regs.get_field(control_reg, 0x07, Pll_output_division1);
2.948 +
2.949 + return d0 * d1;
2.950 +}
2.951 +
2.952 +void
2.953 +Pll::set_output_division(Cpm_regs ®s, uint8_t divider)
2.954 +{
2.955 + // Assert 1 as a minimum.
2.956 + // Divider 0 must be less than or equal to divider 1.
2.957 +
2.958 + uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
2.959 + uint8_t d1 = divider / d0;
2.960 +
2.961 + regs.set_field(control_reg, 0x07, Pll_output_division0, d0);
2.962 + regs.set_field(control_reg, 0x07, Pll_output_division1, d1);
2.963 +}
2.964 +
2.965 +uint32_t
2.966 +Pll::get_frequency(Cpm_regs ®s)
2.967 +{
2.968 + // Test for PLL enable and not PLL bypass.
2.969 +
2.970 + if (pll_enabled(regs))
2.971 + {
2.972 + if (!pll_bypassed(regs))
2.973 + return (get_source_frequency(regs) * get_multiplier(regs)) /
2.974 + (get_input_division(regs) * get_output_division(regs));
2.975 + else
2.976 + return get_source_frequency(regs);
2.977 + }
2.978 + else
2.979 + return 0;
2.980 +}
2.981 +
2.982 +void
2.983 +Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
2.984 +{
2.985 + set_multiplier(regs, multiplier);
2.986 + set_input_division(regs, in_divider);
2.987 + set_output_division(regs, out_divider);
2.988
2.989 - return bit != Clock_gate_undefined ? 1 : 0;
2.990 + if (pll_enabled(regs) && !pll_bypassed(regs))
2.991 + while (!have_pll(regs));
2.992 +}
2.993 +
2.994 +
2.995 +
2.996 +// Clock control.
2.997 +
2.998 +void
2.999 +Clock::change_disable(Cpm_regs ®s)
2.1000 +{
2.1001 + if (change_enable_bit != Clock_change_enable_undefined)
2.1002 + regs.set_field(change_enable_reg, 1, change_enable_bit, 0);
2.1003 +}
2.1004 +
2.1005 +void
2.1006 +Clock::change_enable(Cpm_regs ®s)
2.1007 +{
2.1008 + if (change_enable_bit != Clock_change_enable_undefined)
2.1009 + regs.set_field(change_enable_reg, 1, change_enable_bit, 1);
2.1010 +}
2.1011 +
2.1012 +int
2.1013 +Clock::have_clock(Cpm_regs ®s)
2.1014 +{
2.1015 + if (gate_bit != Clock_gate_undefined)
2.1016 + return !regs.get_field(gate_reg, 1, gate_bit);
2.1017 + else
2.1018 + return true;
2.1019 +}
2.1020 +
2.1021 +void
2.1022 +Clock::start_clock(Cpm_regs ®s)
2.1023 +{
2.1024 + if (gate_bit != Clock_gate_undefined)
2.1025 + regs.set_field(gate_reg, 1, gate_bit, 0);
2.1026 +}
2.1027 +
2.1028 +void
2.1029 +Clock::stop_clock(Cpm_regs ®s)
2.1030 +{
2.1031 + if (gate_bit != Clock_gate_undefined)
2.1032 + regs.set_field(gate_reg, 1, gate_bit, 1);
2.1033 +}
2.1034 +
2.1035 +void
2.1036 +Clock::wait_busy(Cpm_regs ®s)
2.1037 +{
2.1038 + if (busy_bit != Clock_busy_undefined)
2.1039 + while (regs.get_field(busy_reg, 1, busy_bit));
2.1040 +}
2.1041 +
2.1042 +
2.1043 +
2.1044 +// Clock dividers.
2.1045 +
2.1046 +uint32_t
2.1047 +Clock::get_divider(Cpm_regs ®s)
2.1048 +{
2.1049 + if (divider_bit != Clock_divider_undefined)
2.1050 + return regs.get_field(divider_reg, divider_mask, divider_bit) + 1;
2.1051 + else
2.1052 + return 1;
2.1053 +}
2.1054 +
2.1055 +void
2.1056 +Clock::set_divider(Cpm_regs ®s, uint32_t division)
2.1057 +{
2.1058 + if (divider_bit == Clock_divider_undefined)
2.1059 + return;
2.1060 +
2.1061 + change_enable(regs);
2.1062 + regs.set_field(divider_reg, divider_mask, divider_bit, division - 1);
2.1063 + wait_busy(regs);
2.1064 + change_disable(regs);
2.1065 +}
2.1066 +
2.1067 +void
2.1068 +Clock::set_source(Cpm_regs ®s, uint8_t source)
2.1069 +{
2.1070 + change_enable(regs);
2.1071 + Clock_base::set_source(regs, source);
2.1072 + wait_busy(regs);
2.1073 + change_disable(regs);
2.1074 }
2.1075
2.1076
2.1077 @@ -603,316 +1041,65 @@
2.1078 // definitions.
2.1079
2.1080 Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq)
2.1081 -: _exclk_freq(exclk_freq)
2.1082 +: _cpm_regs(addr, exclk_freq)
2.1083 {
2.1084 - _regs = new Hw::Mmio_register_block<32>(addr);
2.1085 -
2.1086 // add_cid("cpm");
2.1087 // add_cid("cpm-x1600");
2.1088 - // register_property("exclk_freq", &_exclk_freq);
2.1089 -}
2.1090 -
2.1091 -
2.1092 -
2.1093 -// Utility methods.
2.1094 -
2.1095 -uint32_t
2.1096 -Cpm_x1600_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift)
2.1097 -{
2.1098 - return (_regs[reg] & (mask << shift)) >> shift;
2.1099 -}
2.1100 -
2.1101 -void
2.1102 -Cpm_x1600_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value)
2.1103 -{
2.1104 - _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift);
2.1105 -}
2.1106 -
2.1107 -
2.1108 -
2.1109 -// Clock/timer control.
2.1110 -
2.1111 -void
2.1112 -Cpm_x1600_chip::change_disable(enum Clock_identifiers clock)
2.1113 -{
2.1114 - enum Clock_change_enable_bits bit = clock_desc[clock].change_enable_bit;
2.1115 -
2.1116 - if (bit != Clock_change_enable_undefined)
2.1117 - set_field(clock_desc[clock].change_enable_reg, 1, bit, 0);
2.1118 -}
2.1119 -
2.1120 -void
2.1121 -Cpm_x1600_chip::change_enable(enum Clock_identifiers clock)
2.1122 -{
2.1123 - enum Clock_change_enable_bits bit = clock_desc[clock].change_enable_bit;
2.1124 -
2.1125 - if (bit != Clock_change_enable_undefined)
2.1126 - set_field(clock_desc[clock].change_enable_reg, 1, bit, 1);
2.1127 + // register_property("exclk_freq", &exclk_freq);
2.1128 }
2.1129
2.1130 int
2.1131 Cpm_x1600_chip::have_clock(enum Clock_identifiers clock)
2.1132 {
2.1133 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
2.1134 - return !get_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
2.1135 - get_clock_gate_bit(clock));
2.1136 - else
2.1137 - return true;
2.1138 + return clocks[clock]->have_clock(_cpm_regs);
2.1139 }
2.1140
2.1141 void
2.1142 Cpm_x1600_chip::start_clock(enum Clock_identifiers clock)
2.1143 {
2.1144 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
2.1145 - set_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
2.1146 - get_clock_gate_bit(clock), 0);
2.1147 + clocks[clock]->start_clock(_cpm_regs);
2.1148 }
2.1149
2.1150 void
2.1151 Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock)
2.1152 {
2.1153 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
2.1154 - set_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
2.1155 - get_clock_gate_bit(clock), 1);
2.1156 -}
2.1157 -
2.1158 -void
2.1159 -Cpm_x1600_chip::wait_busy(enum Clock_identifiers clock)
2.1160 -{
2.1161 - enum Clock_busy_bits bit = clock_desc[clock].busy_bit;
2.1162 -
2.1163 - if (bit != Clock_busy_undefined)
2.1164 - while (get_field(clock_desc[clock].busy_reg, 1, bit));
2.1165 -}
2.1166 -
2.1167 -
2.1168 -
2.1169 -// PLL control.
2.1170 -
2.1171 -// Return whether the PLL is stable.
2.1172 -
2.1173 -int
2.1174 -Cpm_x1600_chip::have_pll(uint32_t pll_reg)
2.1175 -{
2.1176 - return get_field(pll_reg, 1, Pll_stable);
2.1177 -}
2.1178 -
2.1179 -int
2.1180 -Cpm_x1600_chip::pll_enabled(uint32_t pll_reg)
2.1181 -{
2.1182 - return get_field(pll_reg, 1, Pll_enabled);
2.1183 -}
2.1184 -
2.1185 -int
2.1186 -Cpm_x1600_chip::pll_bypassed(uint32_t pll_reg)
2.1187 -{
2.1188 - uint8_t bit;
2.1189 - unsigned mask = 1;
2.1190 -
2.1191 - switch (pll_reg)
2.1192 - {
2.1193 - case Pll_control_A: bit = Pll_bypass_A; break;
2.1194 - case Pll_control_M: bit = Pll_bypass_M; break;
2.1195 - case Pll_control_E: bit = Pll_bypass_E; break;
2.1196 - default: bit = 0; mask = 0; break;
2.1197 - }
2.1198 -
2.1199 - return get_field(Pll_control, mask, bit);
2.1200 -}
2.1201 -
2.1202 -void
2.1203 -Cpm_x1600_chip::pll_enable(uint32_t pll_reg)
2.1204 -{
2.1205 - set_field(pll_reg, 1, Pll_enabled, 1);
2.1206 - while (!have_pll(pll_reg));
2.1207 -}
2.1208 -
2.1209 -void
2.1210 -Cpm_x1600_chip::pll_disable(uint32_t pll_reg)
2.1211 -{
2.1212 - set_field(pll_reg, 1, Pll_enabled, 0);
2.1213 - while (have_pll(pll_reg));
2.1214 -}
2.1215 -
2.1216 -// Feedback (13-bit) multiplier.
2.1217 -
2.1218 -uint16_t
2.1219 -Cpm_x1600_chip::get_multiplier(uint32_t pll_reg)
2.1220 -{
2.1221 - return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1;
2.1222 + clocks[clock]->stop_clock(_cpm_regs);
2.1223 }
2.1224
2.1225 -void
2.1226 -Cpm_x1600_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier)
2.1227 -{
2.1228 - set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1);
2.1229 -}
2.1230 -
2.1231 -// Input (6-bit) divider.
2.1232 -
2.1233 -uint8_t
2.1234 -Cpm_x1600_chip::get_input_division(uint32_t pll_reg)
2.1235 -{
2.1236 - return get_field(pll_reg, 0x3f, Pll_input_division) + 1;
2.1237 -}
2.1238 -
2.1239 -void
2.1240 -Cpm_x1600_chip::set_input_division(uint32_t pll_reg, uint8_t divider)
2.1241 -{
2.1242 - set_field(pll_reg, 0x3f, Pll_input_division, divider - 1);
2.1243 -}
2.1244 -
2.1245 -// Output (dual 3-bit) dividers.
2.1246 -
2.1247 -uint8_t
2.1248 -Cpm_x1600_chip::get_output_division(uint32_t pll_reg)
2.1249 -{
2.1250 - uint8_t d0 = get_field(pll_reg, 0x07, Pll_output_division0);
2.1251 - uint8_t d1 = get_field(pll_reg, 0x07, Pll_output_division1);
2.1252 -
2.1253 - return d0 * d1;
2.1254 -}
2.1255 -
2.1256 -void
2.1257 -Cpm_x1600_chip::set_output_division(uint32_t pll_reg, uint8_t divider)
2.1258 -{
2.1259 - // Assert 1 as a minimum.
2.1260 - // Divider 0 must be less than or equal to divider 1.
2.1261 -
2.1262 - uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
2.1263 - uint8_t d1 = divider / d0;
2.1264 -
2.1265 - set_field(pll_reg, 0x07, Pll_output_division0, d0);
2.1266 - set_field(pll_reg, 0x07, Pll_output_division1, d1);
2.1267 -}
2.1268 -
2.1269 -uint32_t
2.1270 -Cpm_x1600_chip::get_pll_frequency(uint32_t pll_reg)
2.1271 -{
2.1272 - // Test for PLL enable and not PLL bypass.
2.1273 -
2.1274 - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
2.1275 - return (_exclk_freq * get_multiplier(pll_reg)) /
2.1276 - (get_input_division(pll_reg) * get_output_division(pll_reg));
2.1277 - else
2.1278 - return _exclk_freq;
2.1279 -}
2.1280 -
2.1281 -void
2.1282 -Cpm_x1600_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
2.1283 -{
2.1284 - set_multiplier(pll_reg, multiplier);
2.1285 - set_input_division(pll_reg, in_divider);
2.1286 - set_output_division(pll_reg, out_divider);
2.1287 -
2.1288 - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
2.1289 - while (!have_pll(pll_reg));
2.1290 -}
2.1291 -
2.1292 -
2.1293 -
2.1294 -// Clock dividers.
2.1295 -
2.1296 uint32_t
2.1297 Cpm_x1600_chip::get_divider(enum Clock_identifiers clock)
2.1298 {
2.1299 - if (clock_desc[clock].divider_bit != Clock_divider_undefined)
2.1300 - return get_field(clock_desc[clock].divider_reg, clock_desc[clock].divider_mask,
2.1301 - clock_desc[clock].divider_bit) + 1;
2.1302 - else
2.1303 - return 1;
2.1304 + return clocks[clock]->get_divider(_cpm_regs);
2.1305 }
2.1306
2.1307 void
2.1308 Cpm_x1600_chip::set_divider(enum Clock_identifiers clock, uint32_t division)
2.1309 {
2.1310 - if (clock_desc[clock].divider_bit == Clock_divider_undefined)
2.1311 - return;
2.1312 -
2.1313 - change_enable(clock);
2.1314 - set_field(clock_desc[clock].divider_reg, clock_desc[clock].divider_mask,
2.1315 - clock_desc[clock].divider_bit, division - 1);
2.1316 - wait_busy(clock);
2.1317 - change_disable(clock);
2.1318 + clocks[clock]->set_divider(_cpm_regs, division);
2.1319 }
2.1320
2.1321 -
2.1322 -
2.1323 -// Clock sources.
2.1324 -
2.1325 uint8_t
2.1326 Cpm_x1600_chip::get_source(enum Clock_identifiers clock)
2.1327 {
2.1328 - if (clock_desc[clock].source_bit != Clock_source_undefined)
2.1329 - return get_field(clock_desc[clock].source_reg, Source_mask, clock_desc[clock].source_bit);
2.1330 - else
2.1331 - return 0;
2.1332 + return clocks[clock]->get_source(_cpm_regs);
2.1333 }
2.1334
2.1335 void
2.1336 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source)
2.1337 {
2.1338 - if (clock_desc[clock].source_bit == Clock_source_undefined)
2.1339 - return;
2.1340 -
2.1341 - change_enable(clock);
2.1342 - set_field(clock_desc[clock].source_reg, Source_mask, clock_desc[clock].source_bit, source);
2.1343 - wait_busy(clock);
2.1344 - change_disable(clock);
2.1345 + clocks[clock]->set_source(_cpm_regs, source);
2.1346 }
2.1347
2.1348 -
2.1349 -
2.1350 -// Clock source frequencies.
2.1351 -
2.1352 uint32_t
2.1353 Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock)
2.1354 {
2.1355 - struct Clock_desc desc = clock_desc[clock];
2.1356 -
2.1357 - if (desc.num_inputs == 0)
2.1358 - {
2.1359 - switch (clock)
2.1360 - {
2.1361 - case Clock_external: return _exclk_freq;
2.1362 - default: return 0;
2.1363 - }
2.1364 - }
2.1365 -
2.1366 - // Clocks with one source yield that input frequency, although PLLs are
2.1367 - // handled specially.
2.1368 -
2.1369 - else if (desc.num_inputs == 1)
2.1370 - {
2.1371 - switch (clock)
2.1372 - {
2.1373 - case Clock_pll_A: return get_pll_frequency(Pll_control_A);
2.1374 - case Clock_pll_E: return get_pll_frequency(Pll_control_E);
2.1375 - case Clock_pll_M: return get_pll_frequency(Pll_control_M);
2.1376 - default: return get_frequency(desc.inputs[0]);
2.1377 - }
2.1378 - }
2.1379 -
2.1380 - // With multiple sources, obtain the selected source for the clock.
2.1381 -
2.1382 - uint8_t source = get_source(clock);
2.1383 -
2.1384 - // Return the frequency of the source.
2.1385 -
2.1386 - if (source < desc.num_inputs)
2.1387 - return get_frequency(desc.inputs[source]);
2.1388 - else
2.1389 - return 0;
2.1390 + return clocks[clock]->get_source_frequency(_cpm_regs);
2.1391 }
2.1392
2.1393 -
2.1394 -
2.1395 -// Output clock frequencies.
2.1396 -
2.1397 uint32_t
2.1398 Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock)
2.1399 {
2.1400 - return get_source_frequency(clock) / get_divider(clock);
2.1401 + return clocks[clock]->get_frequency(_cpm_regs);
2.1402 }
2.1403
2.1404 void
2.1405 @@ -924,19 +1111,33 @@
2.1406 // EPLL).
2.1407
2.1408 case Clock_lcd_pixel:
2.1409 + {
2.1410
2.1411 // Switch to the MPLL and attempt to set the divider.
2.1412
2.1413 - set_source(Clock_lcd_pixel, Source_mME_pll_M);
2.1414 - pll_enable(Pll_control_M);
2.1415 - set_divider(Clock_lcd_pixel, get_source_frequency(clock) / frequency);
2.1416 + Clock_base *lcd = clocks[Clock_lcd_pixel];
2.1417 + Clock_base *pll = clocks[Clock_pll_M];
2.1418 +
2.1419 + lcd->set_source(_cpm_regs, Source_mME_pll_M);
2.1420 + pll->start_clock(_cpm_regs);
2.1421 + lcd->set_divider(_cpm_regs, lcd->get_source_frequency(_cpm_regs) / frequency);
2.1422 break;
2.1423 + }
2.1424
2.1425 default:
2.1426 break;
2.1427 }
2.1428 }
2.1429
2.1430 +void
2.1431 +Cpm_x1600_chip::set_pll_parameters(enum Clock_identifiers clock, uint16_t multiplier,
2.1432 + uint8_t in_divider, uint8_t out_divider)
2.1433 +{
2.1434 + Pll *pll = dynamic_cast<Pll *>(clocks[clock]);
2.1435 +
2.1436 + pll->set_pll_parameters(_cpm_regs, multiplier, in_divider, out_divider);
2.1437 +}
2.1438 +
2.1439
2.1440
2.1441 // C language interface functions.
2.1442 @@ -968,8 +1169,6 @@
2.1443 static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock);
2.1444 }
2.1445
2.1446 -
2.1447 -
2.1448 uint32_t
2.1449 x1600_cpm_get_divider(void *cpm, enum Clock_identifiers clock)
2.1450 {
2.1451 @@ -982,8 +1181,6 @@
2.1452 return static_cast<Cpm_x1600_chip *>(cpm)->set_divider(clock, divider);
2.1453 }
2.1454
2.1455 -
2.1456 -
2.1457 uint8_t
2.1458 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock)
2.1459 {
2.1460 @@ -996,16 +1193,12 @@
2.1461 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source);
2.1462 }
2.1463
2.1464 -
2.1465 -
2.1466 uint32_t
2.1467 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock)
2.1468 {
2.1469 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock);
2.1470 }
2.1471
2.1472 -
2.1473 -
2.1474 uint32_t
2.1475 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock)
2.1476 {
2.1477 @@ -1018,10 +1211,8 @@
2.1478 static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency);
2.1479 }
2.1480
2.1481 -
2.1482 -
2.1483 void
2.1484 x1600_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
2.1485 {
2.1486 - static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider);
2.1487 + static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Clock_pll_M, multiplier, in_divider, out_divider);
2.1488 }