1.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Thu Sep 14 18:51:41 2023 +0200
1.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Fri Sep 15 00:31:43 2023 +0200
1.3 @@ -263,12 +263,107 @@
1.4
1.5
1.6
1.7 +// Common clock abstraction.
1.8 +
1.9 +class Clock_base
1.10 +{
1.11 +protected:
1.12 +
1.13 + // Clock sources and source selection.
1.14 +
1.15 + int num_inputs;
1.16 + enum Clock_identifiers *inputs;
1.17 + uint32_t source_reg;
1.18 + enum Clock_source_bits source_bit;
1.19 +
1.20 +public:
1.21 + explicit Clock_base(int num_inputs = 0,
1.22 + enum Clock_identifiers inputs[] = NULL,
1.23 + uint32_t source_reg = Reg_undefined,
1.24 + enum Clock_source_bits source_bit = Clock_source_undefined)
1.25 + : num_inputs(num_inputs), inputs(inputs),
1.26 + source_reg(source_reg), source_bit(source_bit)
1.27 + {
1.28 + }
1.29 +
1.30 + // Clock control.
1.31 +
1.32 + virtual int have_clock(Cpm_regs ®s);
1.33 + virtual void start_clock(Cpm_regs ®s);
1.34 + virtual void stop_clock(Cpm_regs ®s);
1.35 +
1.36 + // Clock divider.
1.37 +
1.38 + virtual uint32_t get_divider(Cpm_regs ®s);
1.39 + virtual void set_divider(Cpm_regs ®s, uint32_t division);
1.40 +
1.41 + // Clock source.
1.42 +
1.43 + virtual uint8_t get_source(Cpm_regs ®s);
1.44 + virtual void set_source(Cpm_regs ®s, uint8_t source);
1.45 +
1.46 + // Clock source frequency.
1.47 +
1.48 + virtual uint32_t get_source_frequency(Cpm_regs ®s);
1.49 +
1.50 + // Output frequency.
1.51 +
1.52 + virtual uint32_t get_frequency(Cpm_regs ®s);
1.53 +};
1.54 +
1.55 +
1.56 +
1.57 +// PLL descriptions.
1.58 +
1.59 +class Pll : public Clock_base
1.60 +{
1.61 + uint32_t control_reg;
1.62 + enum Pll_bypass_bits bypass_bit;
1.63 +
1.64 +public:
1.65 + explicit Pll(int num_inputs, enum Clock_identifiers inputs[],
1.66 + uint32_t control_reg, enum Pll_bypass_bits bypass_bit)
1.67 + : Clock_base(num_inputs, inputs), control_reg(control_reg), bypass_bit(bypass_bit)
1.68 + {
1.69 + }
1.70 +
1.71 + // PLL_specific control.
1.72 +
1.73 + int have_pll(Cpm_regs ®s);
1.74 + int pll_enabled(Cpm_regs ®s);
1.75 + int pll_bypassed(Cpm_regs ®s);
1.76 +
1.77 + // Clock control.
1.78 +
1.79 + int have_clock(Cpm_regs ®s);
1.80 + void start_clock(Cpm_regs ®s);
1.81 + void stop_clock(Cpm_regs ®s);
1.82 +
1.83 + // General frequency modifiers.
1.84 +
1.85 + uint16_t get_multiplier(Cpm_regs ®s);
1.86 + void set_multiplier(Cpm_regs ®s, uint16_t multiplier);
1.87 + uint8_t get_input_division(Cpm_regs ®s);
1.88 + void set_input_division(Cpm_regs ®s, uint8_t divider);
1.89 + uint8_t get_output_division(Cpm_regs ®s);
1.90 + void set_output_division(Cpm_regs ®s, uint8_t divider);
1.91 +
1.92 + // PLL output frequency.
1.93 +
1.94 + uint32_t get_frequency(Cpm_regs ®s);
1.95 +
1.96 + // Other operations.
1.97 +
1.98 + void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier,
1.99 + uint8_t in_divider, uint8_t out_divider);
1.100 +};
1.101 +
1.102 +
1.103 +
1.104 // Clock descriptions.
1.105
1.106 -struct Clock_desc
1.107 +class Clock : public Clock_base
1.108 {
1.109 - uint32_t source_reg;
1.110 - enum Clock_source_bits source_bit;
1.111 uint32_t gate_reg;
1.112 enum Clock_gate_bits gate_bit;
1.113 uint32_t change_enable_reg;
1.114 @@ -278,322 +373,665 @@
1.115 uint32_t divider_reg;
1.116 enum Clock_divider_bits divider_bit;
1.117 uint32_t divider_mask;
1.118 - int num_inputs;
1.119 - enum Clock_identifiers inputs[4];
1.120 -};
1.121
1.122 -#define Clock_desc_undefined {Reg_undefined, Clock_source_undefined, \
1.123 - Reg_undefined, Clock_gate_undefined, \
1.124 - Reg_undefined, Clock_change_enable_undefined, \
1.125 - Reg_undefined, Clock_busy_undefined, \
1.126 - Reg_undefined, Clock_divider_undefined, 0, \
1.127 - 0, {}}
1.128 -
1.129 -static struct Clock_desc clock_desc[Clock_identifier_count] = {
1.130 -
1.131 - /* Clock_ahb2_apb */ {Clock_control, Clock_source_hclock2,
1.132 - Reg_undefined, Clock_gate_undefined,
1.133 - Reg_undefined, Clock_change_enable_undefined,
1.134 - Reg_undefined, Clock_busy_undefined,
1.135 - Reg_undefined, Clock_divider_undefined, 0,
1.136 - 3, {Clock_none, Clock_main, Clock_pll_M}},
1.137 -
1.138 - /* Clock_aic_bitclk */ Clock_desc_undefined,
1.139 -
1.140 - /* Clock_aic_pclk */ Clock_desc_undefined,
1.141 -
1.142 - /* Clock_can0 */ {Can_divider0, Clock_source_can0,
1.143 - Clock_gate1, Clock_gate_can0,
1.144 - Can_divider0, Clock_change_enable_can0,
1.145 - Can_divider0, Clock_busy_can0,
1.146 - Can_divider0, Clock_divider_can0, 0xff,
1.147 - 4, {Clock_main, Clock_pll_M, Clock_pll_E, Clock_external}},
1.148 -
1.149 - /* Clock_can1 */ {Can_divider1, Clock_source_can1,
1.150 - Clock_gate1, Clock_gate_can1,
1.151 - Can_divider1, Clock_change_enable_can1,
1.152 - Can_divider1, Clock_busy_can1,
1.153 - Can_divider1, Clock_divider_can1, 0xff,
1.154 - 4, {Clock_main, Clock_pll_M, Clock_pll_E, Clock_external}},
1.155 -
1.156 - /* Clock_cdbus */ {Cdbus_divider, Clock_source_cdbus,
1.157 - Clock_gate1, Clock_gate_cdbus,
1.158 - Cdbus_divider, Clock_change_enable_cdbus,
1.159 - Cdbus_divider, Clock_busy_cdbus,
1.160 - Cdbus_divider, Clock_divider_cdbus, 0xff,
1.161 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.162 -
1.163 - /* Clock_cim */ {Cim_divider, Clock_source_cim,
1.164 - Clock_gate0, Clock_gate_cim,
1.165 - Cim_divider, Clock_change_enable_cim,
1.166 - Cim_divider, Clock_busy_cim,
1.167 - Cim_divider, Clock_divider_cim, 0xff,
1.168 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.169 -
1.170 - /* Clock_cpu */ {Clock_control, Clock_source_cpu,
1.171 - Reg_undefined, Clock_gate_undefined,
1.172 - Clock_control, Clock_change_enable_cpu,
1.173 - Clock_status, Clock_busy_cpu,
1.174 - Clock_control, Clock_divider_cpu, 0x0f,
1.175 - 3, {Clock_none, Clock_main, Clock_pll_M}},
1.176 -
1.177 - /* Clock_ddr */ {Ddr_divider, Clock_source_ddr,
1.178 - Clock_gate0, Clock_gate_ddr,
1.179 - Ddr_divider, Clock_change_enable_ddr,
1.180 - Ddr_divider, Clock_busy_ddr,
1.181 - Ddr_divider, Clock_divider_ddr, 0x0f,
1.182 - 3, {Clock_none, Clock_main, Clock_pll_M}},
1.183 -
1.184 - /* Clock_dma */ {Reg_undefined, Clock_source_undefined,
1.185 - Clock_gate0, Clock_gate_dma,
1.186 - Reg_undefined, Clock_change_enable_undefined,
1.187 - Reg_undefined, Clock_busy_undefined,
1.188 - Reg_undefined, Clock_divider_undefined, 0,
1.189 - 1, {Clock_pclock}},
1.190 + // Clock control.
1.191
1.192 - /* Clock_emac */ Clock_desc_undefined,
1.193 -
1.194 - /* Clock_external */ {Reg_undefined, Clock_source_undefined,
1.195 - Reg_undefined, Clock_gate_undefined,
1.196 - Reg_undefined, Clock_change_enable_undefined,
1.197 - Reg_undefined, Clock_busy_undefined,
1.198 - Reg_undefined, Clock_divider_undefined, 0,
1.199 - 0, {}},
1.200 -
1.201 - /* Clock_hclock0 */ {Clock_control, Clock_source_hclock0,
1.202 - Clock_gate0, Clock_gate_ahb0,
1.203 - Clock_control, Clock_change_enable_ahb0,
1.204 - Reg_undefined, Clock_busy_undefined,
1.205 - Clock_control, Clock_divider_hclock0, 0x0f,
1.206 - 3, {Clock_none, Clock_main, Clock_pll_M}},
1.207 -
1.208 - /* Clock_hclock2 */ {Reg_undefined, Clock_source_undefined,
1.209 - Clock_gate0, Clock_gate_apb0,
1.210 - Clock_control, Clock_change_enable_ahb2,
1.211 - Reg_undefined, Clock_busy_undefined,
1.212 - Clock_control, Clock_divider_hclock2, 0x0f,
1.213 - 1, {Clock_ahb2_apb}},
1.214 -
1.215 - /* Clock_hdmi */ Clock_desc_undefined,
1.216 -
1.217 - /* Clock_i2c */ {Reg_undefined, Clock_source_undefined,
1.218 - Clock_gate0, Clock_gate_i2c0,
1.219 - Reg_undefined, Clock_change_enable_undefined,
1.220 - Reg_undefined, Clock_busy_undefined,
1.221 - Reg_undefined, Clock_divider_undefined, 0,
1.222 - 1, {Clock_pclock}},
1.223 -
1.224 - /* Clock_i2c0 */ {Reg_undefined, Clock_source_undefined,
1.225 - Clock_gate0, Clock_gate_i2c0,
1.226 - Reg_undefined, Clock_change_enable_undefined,
1.227 - Reg_undefined, Clock_busy_undefined,
1.228 - Reg_undefined, Clock_divider_undefined, 0,
1.229 - 1, {Clock_pclock}},
1.230 -
1.231 - /* Clock_i2c1 */ {Reg_undefined, Clock_source_undefined,
1.232 - Clock_gate0, Clock_gate_i2c1,
1.233 - Reg_undefined, Clock_change_enable_undefined,
1.234 - Reg_undefined, Clock_busy_undefined,
1.235 - Reg_undefined, Clock_divider_undefined, 0,
1.236 - 1, {Clock_pclock}},
1.237 -
1.238 - /* Clock_i2s */ Clock_desc_undefined,
1.239 -
1.240 - /* Clock_i2s0_rx */ {I2s_divider0, Clock_source_i2s,
1.241 - Clock_gate1, Clock_gate_i2s0_rx,
1.242 - I2s_divider0, Clock_change_enable_i2s,
1.243 - Reg_undefined, Clock_busy_undefined,
1.244 - Reg_undefined, Clock_divider_undefined, 0, // NOTE: To define.
1.245 - 2, {Clock_main, Clock_pll_E}},
1.246 -
1.247 - /* Clock_i2s0_tx */ {I2s_divider0, Clock_source_i2s,
1.248 - Clock_gate1, Clock_gate_i2s0_tx,
1.249 - I2s_divider0, Clock_change_enable_i2s,
1.250 - Reg_undefined, Clock_busy_undefined,
1.251 - Reg_undefined, Clock_divider_undefined, 0, // NOTE: To define.
1.252 - 2, {Clock_main, Clock_pll_E}},
1.253 -
1.254 - /* Clock_kbc */ Clock_desc_undefined,
1.255 -
1.256 - /* Clock_lcd */ Clock_desc_undefined,
1.257 -
1.258 - /* Clock_lcd_pixel */ {Lcd_divider, Clock_source_lcd,
1.259 - Clock_gate0, Clock_gate_lcd_pixel,
1.260 - Lcd_divider, Clock_change_enable_lcd,
1.261 - Lcd_divider, Clock_busy_lcd,
1.262 - Lcd_divider, Clock_divider_lcd, 0xff,
1.263 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.264 + void change_disable(Cpm_regs ®s);
1.265 + void change_enable(Cpm_regs ®s);
1.266 + void wait_busy(Cpm_regs ®s);
1.267
1.268 - /* Clock_mac */ {Mac_divider, Clock_source_mac,
1.269 - Clock_gate1, Clock_gate_gmac0,
1.270 - Mac_divider, Clock_change_enable_mac,
1.271 - Mac_divider, Clock_busy_mac,
1.272 - Mac_divider, Clock_divider_mac, 0xff,
1.273 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.274 -
1.275 - /* Clock_main */ {Clock_control, Clock_source_main,
1.276 - Clock_control, Clock_gate_main,
1.277 - Reg_undefined, Clock_change_enable_undefined,
1.278 - Reg_undefined, Clock_busy_undefined,
1.279 - Reg_undefined, Clock_divider_undefined, 0,
1.280 - 3, {Clock_none, Clock_external, Clock_pll_A}},
1.281 -
1.282 - /* Clock_msc */ {Msc_divider0, Clock_source_msc0,
1.283 - Clock_gate0, Clock_gate_msc0,
1.284 - Msc_divider0, Clock_change_enable_msc0,
1.285 - Msc_divider0, Clock_busy_msc0,
1.286 - Msc_divider0, Clock_divider_msc0, 0xff,
1.287 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.288 -
1.289 - /* Clock_msc0 */ {Msc_divider0, Clock_source_msc0,
1.290 - Clock_gate0, Clock_gate_msc0,
1.291 - Msc_divider0, Clock_change_enable_msc0,
1.292 - Msc_divider0, Clock_busy_msc0,
1.293 - Msc_divider0, Clock_divider_msc0, 0xff,
1.294 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.295 -
1.296 - /* Clock_msc1 */ {Msc_divider1, Clock_source_msc1,
1.297 - Clock_gate0, Clock_gate_msc1,
1.298 - Msc_divider1, Clock_change_enable_msc1,
1.299 - Msc_divider1, Clock_busy_msc1,
1.300 - Msc_divider1, Clock_divider_msc1, 0xff,
1.301 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.302 -
1.303 - /* Clock_none */ {Reg_undefined, Clock_source_undefined,
1.304 - Reg_undefined, Clock_gate_undefined,
1.305 - Reg_undefined, Clock_change_enable_undefined,
1.306 - Reg_undefined, Clock_busy_undefined,
1.307 - Reg_undefined, Clock_divider_undefined, 0,
1.308 - 0, {}},
1.309 -
1.310 - /* Clock_pclock */ {Reg_undefined, Clock_source_undefined,
1.311 - Clock_gate0, Clock_gate_apb0,
1.312 - Reg_undefined, Clock_change_enable_undefined,
1.313 - Reg_undefined, Clock_busy_undefined,
1.314 - Clock_control, Clock_divider_pclock, 0x0f,
1.315 - 1, {Clock_ahb2_apb}},
1.316 -
1.317 - /* Clock_pll_A */ {Reg_undefined, Clock_source_undefined,
1.318 - Reg_undefined, Clock_gate_undefined,
1.319 - Reg_undefined, Clock_change_enable_undefined,
1.320 - Reg_undefined, Clock_busy_undefined,
1.321 - Reg_undefined, Clock_divider_undefined, 0,
1.322 - 1, {Clock_external}},
1.323 -
1.324 - /* Clock_pll_E */ {Reg_undefined, Clock_source_undefined,
1.325 - Reg_undefined, Clock_gate_undefined,
1.326 - Reg_undefined, Clock_change_enable_undefined,
1.327 - Reg_undefined, Clock_busy_undefined,
1.328 - Reg_undefined, Clock_divider_undefined, 0,
1.329 - 1, {Clock_external}},
1.330 -
1.331 - /* Clock_pll_M */ {Reg_undefined, Clock_source_undefined,
1.332 - Reg_undefined, Clock_gate_undefined,
1.333 - Reg_undefined, Clock_change_enable_undefined,
1.334 - Reg_undefined, Clock_busy_undefined,
1.335 - Reg_undefined, Clock_divider_undefined, 0,
1.336 - 1, {Clock_external}},
1.337 +public:
1.338 + explicit Clock(int num_inputs = 0,
1.339 + enum Clock_identifiers inputs[] = NULL,
1.340 + uint32_t source_reg = Reg_undefined,
1.341 + enum Clock_source_bits source_bit = Clock_source_undefined,
1.342 + uint32_t gate_reg = Reg_undefined,
1.343 + enum Clock_gate_bits gate_bit = Clock_gate_undefined,
1.344 + uint32_t change_enable_reg = Reg_undefined,
1.345 + enum Clock_change_enable_bits change_enable_bit = Clock_change_enable_undefined,
1.346 + uint32_t busy_reg = Reg_undefined,
1.347 + enum Clock_busy_bits busy_bit = Clock_busy_undefined,
1.348 + uint32_t divider_reg = Reg_undefined,
1.349 + enum Clock_divider_bits divider_bit = Clock_divider_undefined,
1.350 + uint32_t divider_mask = 0)
1.351 + : Clock_base(num_inputs, inputs, source_reg, source_bit),
1.352 + gate_reg(gate_reg), gate_bit(gate_bit),
1.353 + change_enable_reg(change_enable_reg), change_enable_bit(change_enable_bit),
1.354 + busy_reg(busy_reg), busy_bit(busy_bit),
1.355 + divider_reg(divider_reg), divider_bit(divider_bit), divider_mask(divider_mask)
1.356 + {
1.357 + }
1.358
1.359 - /* Clock_pwm */ {Pwm_divider, Clock_source_pwm,
1.360 - Clock_gate1, Clock_gate_pwm,
1.361 - Pwm_divider, Clock_change_enable_pwm,
1.362 - Pwm_divider, Clock_busy_pwm,
1.363 - Pwm_divider, Clock_divider_pwm, 0x0f,
1.364 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.365 -
1.366 - /* Clock_pwm0 */ {Pwm_divider, Clock_source_pwm,
1.367 - Clock_gate1, Clock_gate_pwm,
1.368 - Pwm_divider, Clock_change_enable_pwm,
1.369 - Pwm_divider, Clock_busy_pwm,
1.370 - Pwm_divider, Clock_divider_pwm, 0x0f,
1.371 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.372 -
1.373 - /* Clock_pwm1 */ Clock_desc_undefined,
1.374 + // Clock control.
1.375
1.376 - /* Clock_scc */ Clock_desc_undefined,
1.377 -
1.378 - /* Clock_sfc */ {Sfc_divider, Clock_source_sfc,
1.379 - Clock_gate0, Clock_gate_sfc,
1.380 - Sfc_divider, Clock_change_enable_sfc,
1.381 - Sfc_divider, Clock_busy_sfc,
1.382 - Sfc_divider, Clock_divider_sfc, 0xff,
1.383 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.384 -
1.385 - /* Clock_smb0 */ Clock_desc_undefined,
1.386 -
1.387 - /* Clock_smb1 */ Clock_desc_undefined,
1.388 -
1.389 - /* Clock_smb2 */ Clock_desc_undefined,
1.390 -
1.391 - /* Clock_smb3 */ Clock_desc_undefined,
1.392 -
1.393 - /* Clock_smb4 */ Clock_desc_undefined,
1.394 + int have_clock(Cpm_regs ®s);
1.395 + void start_clock(Cpm_regs ®s);
1.396 + void stop_clock(Cpm_regs ®s);
1.397
1.398 - /* Clock_ssi */ {Ssi_divider, Clock_source_ssi,
1.399 - Clock_gate0, Clock_gate_ssi0,
1.400 - Ssi_divider, Clock_change_enable_ssi,
1.401 - Ssi_divider, Clock_busy_ssi,
1.402 - Ssi_divider, Clock_divider_ssi, 0xff,
1.403 - 3, {Clock_main, Clock_pll_M, Clock_pll_E}},
1.404 -
1.405 - /* Clock_timer */ {Reg_undefined, Clock_source_undefined,
1.406 - Clock_gate0, Clock_gate_timer,
1.407 - Reg_undefined, Clock_change_enable_undefined,
1.408 - Reg_undefined, Clock_busy_undefined,
1.409 - Reg_undefined, Clock_divider_undefined, 0,
1.410 - 1, {Clock_pclock}},
1.411 -
1.412 - /* Clock_uart0 */ {Reg_undefined, Clock_source_undefined,
1.413 - Clock_gate0, Clock_gate_uart0,
1.414 - Reg_undefined, Clock_change_enable_undefined,
1.415 - Reg_undefined, Clock_busy_undefined,
1.416 - Reg_undefined, Clock_divider_undefined, 0,
1.417 - 1, {Clock_external}},
1.418 + // Clock divider.
1.419
1.420 - /* Clock_uart1 */ {Reg_undefined, Clock_source_undefined,
1.421 - Clock_gate0, Clock_gate_uart1,
1.422 - Reg_undefined, Clock_change_enable_undefined,
1.423 - Reg_undefined, Clock_busy_undefined,
1.424 - Reg_undefined, Clock_divider_undefined, 0,
1.425 - 1, {Clock_external}},
1.426 + uint32_t get_divider(Cpm_regs ®s);
1.427 + void set_divider(Cpm_regs ®s, uint32_t division);
1.428
1.429 - /* Clock_uart2 */ {Reg_undefined, Clock_source_undefined,
1.430 - Clock_gate0, Clock_gate_uart2,
1.431 - Reg_undefined, Clock_change_enable_undefined,
1.432 - Reg_undefined, Clock_busy_undefined,
1.433 - Reg_undefined, Clock_divider_undefined, 0,
1.434 - 1, {Clock_external}},
1.435 + // Clock source.
1.436
1.437 - /* Clock_uart3 */ {Reg_undefined, Clock_source_undefined,
1.438 - Clock_gate1, Clock_gate_uart3,
1.439 - Reg_undefined, Clock_change_enable_undefined,
1.440 - Reg_undefined, Clock_busy_undefined,
1.441 - Reg_undefined, Clock_divider_undefined, 0,
1.442 - 1, {Clock_external}},
1.443 -
1.444 - /* Clock_udc */ Clock_desc_undefined,
1.445 -
1.446 - /* Clock_uhc */ Clock_desc_undefined,
1.447 -
1.448 - /* Clock_uprt */ Clock_desc_undefined,
1.449 + void set_source(Cpm_regs ®s, uint8_t source);
1.450 };
1.451
1.452
1.453
1.454 -// Convenience functions.
1.455 +// Clock instances.
1.456 +
1.457 +#define Clock_inputs(...) ((enum Clock_identifiers []) {__VA_ARGS__})
1.458 +
1.459 +Clock clock_ahb2_apb(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
1.460 + Clock_control, Clock_source_hclock2);
1.461 +
1.462 +Clock clock_aic_bitclk;
1.463 +
1.464 +Clock clock_aic_pclk;
1.465 +
1.466 +Clock clock_can0(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external),
1.467 + Can_divider0, Clock_source_can0,
1.468 + Clock_gate1, Clock_gate_can0,
1.469 + Can_divider0, Clock_change_enable_can0,
1.470 + Can_divider0, Clock_busy_can0,
1.471 + Can_divider0, Clock_divider_can0, 0xff);
1.472 +
1.473 +Clock clock_can1(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external),
1.474 + Can_divider1, Clock_source_can1,
1.475 + Clock_gate1, Clock_gate_can1,
1.476 + Can_divider1, Clock_change_enable_can1,
1.477 + Can_divider1, Clock_busy_can1,
1.478 + Can_divider1, Clock_divider_can1, 0xff);
1.479 +
1.480 +Clock clock_cdbus(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.481 + Cdbus_divider, Clock_source_cdbus,
1.482 + Clock_gate1, Clock_gate_cdbus,
1.483 + Cdbus_divider, Clock_change_enable_cdbus,
1.484 + Cdbus_divider, Clock_busy_cdbus,
1.485 + Cdbus_divider, Clock_divider_cdbus, 0xff);
1.486 +
1.487 +Clock clock_cim(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.488 + Cim_divider, Clock_source_cim,
1.489 + Clock_gate0, Clock_gate_cim,
1.490 + Cim_divider, Clock_change_enable_cim,
1.491 + Cim_divider, Clock_busy_cim,
1.492 + Cim_divider, Clock_divider_cim, 0xff);
1.493 +
1.494 +Clock clock_cpu(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
1.495 + Clock_control, Clock_source_cpu,
1.496 + Reg_undefined, Clock_gate_undefined,
1.497 + Clock_control, Clock_change_enable_cpu,
1.498 + Clock_status, Clock_busy_cpu,
1.499 + Clock_control, Clock_divider_cpu, 0x0f);
1.500 +
1.501 +Clock clock_ddr(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
1.502 + Ddr_divider, Clock_source_ddr,
1.503 + Clock_gate0, Clock_gate_ddr,
1.504 + Ddr_divider, Clock_change_enable_ddr,
1.505 + Ddr_divider, Clock_busy_ddr,
1.506 + Ddr_divider, Clock_divider_ddr, 0x0f);
1.507 +
1.508 +Clock clock_dma(1, Clock_inputs(Clock_pclock),
1.509 + Reg_undefined, Clock_source_undefined,
1.510 + Clock_gate0, Clock_gate_dma);
1.511 +
1.512 +Clock clock_emac;
1.513 +
1.514 +Clock clock_external;
1.515 +
1.516 +Clock clock_hclock0(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M),
1.517 + Clock_control, Clock_source_hclock0,
1.518 + Clock_gate0, Clock_gate_ahb0,
1.519 + Clock_control, Clock_change_enable_ahb0,
1.520 + Reg_undefined, Clock_busy_undefined,
1.521 + Clock_control, Clock_divider_hclock0, 0x0f);
1.522 +
1.523 +Clock clock_hclock2(1, Clock_inputs(Clock_ahb2_apb),
1.524 + Reg_undefined, Clock_source_undefined,
1.525 + Clock_gate0, Clock_gate_apb0,
1.526 + Clock_control, Clock_change_enable_ahb2,
1.527 + Reg_undefined, Clock_busy_undefined,
1.528 + Clock_control, Clock_divider_hclock2, 0x0f);
1.529 +
1.530 +Clock clock_hdmi;
1.531 +
1.532 +Clock clock_i2c(1, Clock_inputs(Clock_pclock),
1.533 + Reg_undefined, Clock_source_undefined,
1.534 + Clock_gate0, Clock_gate_i2c0);
1.535 +
1.536 +Clock clock_i2c0(1, Clock_inputs(Clock_pclock),
1.537 + Reg_undefined, Clock_source_undefined,
1.538 + Clock_gate0, Clock_gate_i2c0);
1.539 +
1.540 +Clock clock_i2c1(1, Clock_inputs(Clock_pclock),
1.541 + Reg_undefined, Clock_source_undefined,
1.542 + Clock_gate0, Clock_gate_i2c1);
1.543 +
1.544 +Clock clock_i2s;
1.545 +
1.546 +Clock clock_i2s0_rx(2, Clock_inputs(Clock_main, Clock_pll_E),
1.547 + I2s_divider0, Clock_source_i2s,
1.548 + Clock_gate1, Clock_gate_i2s0_rx,
1.549 + I2s_divider0, Clock_change_enable_i2s);
1.550 +
1.551 +Clock clock_i2s0_tx(2, Clock_inputs(Clock_main, Clock_pll_E),
1.552 + I2s_divider0, Clock_source_i2s,
1.553 + Clock_gate1, Clock_gate_i2s0_tx,
1.554 + I2s_divider0, Clock_change_enable_i2s);
1.555 +
1.556 +Clock clock_kbc;
1.557 +
1.558 +Clock clock_lcd;
1.559 +
1.560 +Clock clock_lcd_pixel(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.561 + Lcd_divider, Clock_source_lcd,
1.562 + Clock_gate0, Clock_gate_lcd_pixel,
1.563 + Lcd_divider, Clock_change_enable_lcd,
1.564 + Lcd_divider, Clock_busy_lcd,
1.565 + Lcd_divider, Clock_divider_lcd, 0xff);
1.566 +
1.567 +Clock clock_mac(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.568 + Mac_divider, Clock_source_mac,
1.569 + Clock_gate1, Clock_gate_gmac0,
1.570 + Mac_divider, Clock_change_enable_mac,
1.571 + Mac_divider, Clock_busy_mac,
1.572 + Mac_divider, Clock_divider_mac, 0xff);
1.573 +
1.574 +Clock clock_main(3, Clock_inputs(Clock_none, Clock_external, Clock_pll_A),
1.575 + Clock_control, Clock_source_main,
1.576 + Clock_control, Clock_gate_main);
1.577 +
1.578 +Clock clock_msc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.579 + Msc_divider0, Clock_source_msc0,
1.580 + Clock_gate0, Clock_gate_msc0,
1.581 + Msc_divider0, Clock_change_enable_msc0,
1.582 + Msc_divider0, Clock_busy_msc0,
1.583 + Msc_divider0, Clock_divider_msc0, 0xff);
1.584 +
1.585 +Clock clock_msc0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.586 + Msc_divider0, Clock_source_msc0,
1.587 + Clock_gate0, Clock_gate_msc0,
1.588 + Msc_divider0, Clock_change_enable_msc0,
1.589 + Msc_divider0, Clock_busy_msc0,
1.590 + Msc_divider0, Clock_divider_msc0, 0xff);
1.591 +
1.592 +Clock clock_msc1(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.593 + Msc_divider1, Clock_source_msc1,
1.594 + Clock_gate0, Clock_gate_msc1,
1.595 + Msc_divider1, Clock_change_enable_msc1,
1.596 + Msc_divider1, Clock_busy_msc1,
1.597 + Msc_divider1, Clock_divider_msc1, 0xff);
1.598 +
1.599 +Clock clock_none;
1.600
1.601 -static uint8_t get_clock_gate_bit(enum Clock_identifiers clock)
1.602 +Clock clock_pclock(1, Clock_inputs(Clock_ahb2_apb),
1.603 + Reg_undefined, Clock_source_undefined,
1.604 + Clock_gate0, Clock_gate_apb0,
1.605 + Reg_undefined, Clock_change_enable_undefined,
1.606 + Reg_undefined, Clock_busy_undefined,
1.607 + Clock_control, Clock_divider_pclock, 0x0f);
1.608 +
1.609 +Pll clock_pll_A(1, Clock_inputs(Clock_external),
1.610 + Pll_control_A, Pll_bypass_A);
1.611 +
1.612 +Pll clock_pll_E(1, Clock_inputs(Clock_external),
1.613 + Pll_control_E, Pll_bypass_E);
1.614 +
1.615 +Pll clock_pll_M(1, Clock_inputs(Clock_external),
1.616 + Pll_control_M, Pll_bypass_M);
1.617 +
1.618 +Clock clock_pwm(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.619 + Pwm_divider, Clock_source_pwm,
1.620 + Clock_gate1, Clock_gate_pwm,
1.621 + Pwm_divider, Clock_change_enable_pwm,
1.622 + Pwm_divider, Clock_busy_pwm,
1.623 + Pwm_divider, Clock_divider_pwm, 0x0f);
1.624 +
1.625 +Clock clock_pwm0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.626 + Pwm_divider, Clock_source_pwm,
1.627 + Clock_gate1, Clock_gate_pwm,
1.628 + Pwm_divider, Clock_change_enable_pwm,
1.629 + Pwm_divider, Clock_busy_pwm,
1.630 + Pwm_divider, Clock_divider_pwm, 0x0f);
1.631 +
1.632 +Clock clock_pwm1;
1.633 +
1.634 +Clock clock_scc;
1.635 +
1.636 +Clock clock_sfc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.637 + Sfc_divider, Clock_source_sfc,
1.638 + Clock_gate0, Clock_gate_sfc,
1.639 + Sfc_divider, Clock_change_enable_sfc,
1.640 + Sfc_divider, Clock_busy_sfc,
1.641 + Sfc_divider, Clock_divider_sfc, 0xff);
1.642 +
1.643 +Clock clock_smb0;
1.644 +
1.645 +Clock clock_smb1;
1.646 +
1.647 +Clock clock_smb2;
1.648 +
1.649 +Clock clock_smb3;
1.650 +
1.651 +Clock clock_smb4;
1.652 +
1.653 +Clock clock_ssi(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E),
1.654 + Ssi_divider, Clock_source_ssi,
1.655 + Clock_gate0, Clock_gate_ssi0,
1.656 + Ssi_divider, Clock_change_enable_ssi,
1.657 + Ssi_divider, Clock_busy_ssi,
1.658 + Ssi_divider, Clock_divider_ssi, 0xff);
1.659 +
1.660 +Clock clock_timer(1, Clock_inputs(Clock_pclock),
1.661 + Reg_undefined, Clock_source_undefined,
1.662 + Clock_gate0, Clock_gate_timer);
1.663 +
1.664 +Clock clock_uart0(1, Clock_inputs(Clock_external),
1.665 + Reg_undefined, Clock_source_undefined,
1.666 + Clock_gate0, Clock_gate_uart0);
1.667 +
1.668 +Clock clock_uart1(1, Clock_inputs(Clock_external),
1.669 + Reg_undefined, Clock_source_undefined,
1.670 + Clock_gate0, Clock_gate_uart1);
1.671 +
1.672 +Clock clock_uart2(1, Clock_inputs(Clock_external),
1.673 + Reg_undefined, Clock_source_undefined,
1.674 + Clock_gate0, Clock_gate_uart2);
1.675 +
1.676 +Clock clock_uart3(1, Clock_inputs(Clock_external),
1.677 + Reg_undefined, Clock_source_undefined,
1.678 + Clock_gate1, Clock_gate_uart3);
1.679 +
1.680 +Clock clock_udc;
1.681 +
1.682 +Clock clock_uhc;
1.683 +
1.684 +Clock clock_uprt;
1.685 +
1.686 +
1.687 +
1.688 +// Clock register.
1.689 +
1.690 +static Clock_base *clocks[Clock_identifier_count] = {
1.691 + &clock_ahb2_apb,
1.692 + &clock_aic_bitclk,
1.693 + &clock_aic_pclk,
1.694 + &clock_can0,
1.695 + &clock_can1,
1.696 + &clock_cdbus,
1.697 + &clock_cim,
1.698 + &clock_cpu,
1.699 + &clock_ddr,
1.700 + &clock_dma,
1.701 + &clock_emac,
1.702 + &clock_external,
1.703 + &clock_hclock0,
1.704 + &clock_hclock2,
1.705 + &clock_hdmi,
1.706 + &clock_i2c,
1.707 + &clock_i2c0,
1.708 + &clock_i2c1,
1.709 + &clock_i2s,
1.710 + &clock_i2s0_rx,
1.711 + &clock_i2s0_tx,
1.712 + &clock_kbc,
1.713 + &clock_lcd,
1.714 + &clock_lcd_pixel,
1.715 + &clock_mac,
1.716 + &clock_main,
1.717 + &clock_msc,
1.718 + &clock_msc0,
1.719 + &clock_msc1,
1.720 + &clock_none,
1.721 + &clock_pclock,
1.722 + &clock_pll_A,
1.723 + &clock_pll_E,
1.724 + &clock_pll_M,
1.725 + &clock_pwm,
1.726 + &clock_pwm0,
1.727 + &clock_pwm1,
1.728 + &clock_scc,
1.729 + &clock_sfc,
1.730 + &clock_smb0,
1.731 + &clock_smb1,
1.732 + &clock_smb2,
1.733 + &clock_smb3,
1.734 + &clock_smb4,
1.735 + &clock_ssi,
1.736 + &clock_timer,
1.737 + &clock_uart0,
1.738 + &clock_uart1,
1.739 + &clock_uart2,
1.740 + &clock_uart3,
1.741 + &clock_udc,
1.742 + &clock_uhc,
1.743 + &clock_uprt,
1.744 +};
1.745 +
1.746 +
1.747 +
1.748 +// Register access.
1.749 +
1.750 +Cpm_regs::Cpm_regs(l4_addr_t addr, uint32_t exclk_freq)
1.751 +: exclk_freq(exclk_freq)
1.752 {
1.753 - enum Clock_gate_bits bit = clock_desc[clock].gate_bit;
1.754 -
1.755 - return bit != Clock_gate_undefined ? (uint8_t) bit : 0;
1.756 + _regs = new Hw::Mmio_register_block<32>(addr);
1.757 }
1.758
1.759 -static uint32_t get_clock_gate_mask(enum Clock_identifiers clock)
1.760 +// Utility methods.
1.761 +
1.762 +uint32_t
1.763 +Cpm_regs::get_field(uint32_t reg, uint32_t mask, uint8_t shift)
1.764 +{
1.765 + return (_regs[reg] & (mask << shift)) >> shift;
1.766 +}
1.767 +
1.768 +void
1.769 +Cpm_regs::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value)
1.770 +{
1.771 + _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift);
1.772 +}
1.773 +
1.774 +
1.775 +
1.776 +// Clock control.
1.777 +
1.778 +int
1.779 +Clock_base::have_clock(Cpm_regs ®s)
1.780 +{
1.781 + (void) regs;
1.782 + return true;
1.783 +}
1.784 +
1.785 +void
1.786 +Clock_base::start_clock(Cpm_regs ®s)
1.787 +{
1.788 + (void) regs;
1.789 +}
1.790 +
1.791 +void
1.792 +Clock_base::stop_clock(Cpm_regs ®s)
1.793 +{
1.794 + (void) regs;
1.795 +}
1.796 +
1.797 +// Default divider.
1.798 +
1.799 +uint32_t
1.800 +Clock_base::get_divider(Cpm_regs ®s)
1.801 +{
1.802 + (void) regs;
1.803 + return 1;
1.804 +}
1.805 +
1.806 +void
1.807 +Clock_base::set_divider(Cpm_regs ®s, uint32_t division)
1.808 +{
1.809 + (void) regs;
1.810 + (void) division;
1.811 +}
1.812 +
1.813 +// Clock sources.
1.814 +
1.815 +uint8_t
1.816 +Clock_base::get_source(Cpm_regs ®s)
1.817 +{
1.818 + if (source_bit != Clock_source_undefined)
1.819 + return regs.get_field(source_reg, Source_mask, source_bit);
1.820 + else
1.821 + return 0;
1.822 +}
1.823 +
1.824 +void
1.825 +Clock_base::set_source(Cpm_regs ®s, uint8_t source)
1.826 +{
1.827 + if (source_bit == Clock_source_undefined)
1.828 + return;
1.829 +
1.830 + regs.set_field(source_reg, Source_mask, source_bit, source);
1.831 +}
1.832 +
1.833 +// Clock source frequencies.
1.834 +
1.835 +uint32_t
1.836 +Clock_base::get_source_frequency(Cpm_regs ®s)
1.837 +{
1.838 + // Return the external clock frequency without any input clock.
1.839 +
1.840 + if (num_inputs == 0)
1.841 + return regs.exclk_freq;
1.842 +
1.843 + // Clocks with one source yield that input frequency.
1.844 +
1.845 + else if (num_inputs == 1)
1.846 + return clocks[inputs[0]]->get_frequency(regs);
1.847 +
1.848 + // With multiple sources, obtain the selected source for the clock.
1.849 +
1.850 + uint8_t source = get_source(regs);
1.851 +
1.852 + // Return the frequency of the source.
1.853 +
1.854 + if (source < num_inputs)
1.855 + return clocks[inputs[source]]->get_frequency(regs);
1.856 + else
1.857 + return 0;
1.858 +}
1.859 +
1.860 +// Output clock frequencies.
1.861 +
1.862 +uint32_t
1.863 +Clock_base::get_frequency(Cpm_regs ®s)
1.864 +{
1.865 + return get_source_frequency(regs) / get_divider(regs);
1.866 +}
1.867 +
1.868 +
1.869 +
1.870 +// PLL-specific control.
1.871 +
1.872 +int
1.873 +Pll::have_pll(Cpm_regs ®s)
1.874 +{
1.875 + return regs.get_field(control_reg, 1, Pll_stable);
1.876 +}
1.877 +
1.878 +int
1.879 +Pll::pll_enabled(Cpm_regs ®s)
1.880 +{
1.881 + return regs.get_field(control_reg, 1, Pll_enabled);
1.882 +}
1.883 +
1.884 +int
1.885 +Pll::pll_bypassed(Cpm_regs ®s)
1.886 +{
1.887 + return regs.get_field(control_reg, 1, bypass_bit);
1.888 +}
1.889 +
1.890 +// Clock control.
1.891 +
1.892 +int
1.893 +Pll::have_clock(Cpm_regs ®s)
1.894 +{
1.895 + return have_pll(regs) && pll_enabled(regs);
1.896 +}
1.897 +
1.898 +void
1.899 +Pll::start_clock(Cpm_regs ®s)
1.900 +{
1.901 + regs.set_field(control_reg, 1, Pll_enabled, 1);
1.902 + while (!have_pll(regs));
1.903 +}
1.904 +
1.905 +void
1.906 +Pll::stop_clock(Cpm_regs ®s)
1.907 {
1.908 - enum Clock_gate_bits bit = clock_desc[clock].gate_bit;
1.909 + regs.set_field(control_reg, 1, Pll_enabled, 0);
1.910 + while (have_pll(regs));
1.911 +}
1.912 +
1.913 +// Feedback (13-bit) multiplier.
1.914 +
1.915 +uint16_t
1.916 +Pll::get_multiplier(Cpm_regs ®s)
1.917 +{
1.918 + return regs.get_field(control_reg, 0x1fff, Pll_multiplier) + 1;
1.919 +}
1.920 +
1.921 +void
1.922 +Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier)
1.923 +{
1.924 + regs.set_field(control_reg, 0x1fff, Pll_multiplier, multiplier - 1);
1.925 +}
1.926 +
1.927 +// Input (6-bit) divider.
1.928 +
1.929 +uint8_t
1.930 +Pll::get_input_division(Cpm_regs ®s)
1.931 +{
1.932 + return regs.get_field(control_reg, 0x3f, Pll_input_division) + 1;
1.933 +}
1.934 +
1.935 +void
1.936 +Pll::set_input_division(Cpm_regs ®s, uint8_t divider)
1.937 +{
1.938 + regs.set_field(control_reg, 0x3f, Pll_input_division, divider - 1);
1.939 +}
1.940 +
1.941 +// Output (dual 3-bit) dividers.
1.942 +
1.943 +uint8_t
1.944 +Pll::get_output_division(Cpm_regs ®s)
1.945 +{
1.946 + uint8_t d0 = regs.get_field(control_reg, 0x07, Pll_output_division0);
1.947 + uint8_t d1 = regs.get_field(control_reg, 0x07, Pll_output_division1);
1.948 +
1.949 + return d0 * d1;
1.950 +}
1.951 +
1.952 +void
1.953 +Pll::set_output_division(Cpm_regs ®s, uint8_t divider)
1.954 +{
1.955 + // Assert 1 as a minimum.
1.956 + // Divider 0 must be less than or equal to divider 1.
1.957 +
1.958 + uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
1.959 + uint8_t d1 = divider / d0;
1.960 +
1.961 + regs.set_field(control_reg, 0x07, Pll_output_division0, d0);
1.962 + regs.set_field(control_reg, 0x07, Pll_output_division1, d1);
1.963 +}
1.964 +
1.965 +uint32_t
1.966 +Pll::get_frequency(Cpm_regs ®s)
1.967 +{
1.968 + // Test for PLL enable and not PLL bypass.
1.969 +
1.970 + if (pll_enabled(regs))
1.971 + {
1.972 + if (!pll_bypassed(regs))
1.973 + return (get_source_frequency(regs) * get_multiplier(regs)) /
1.974 + (get_input_division(regs) * get_output_division(regs));
1.975 + else
1.976 + return get_source_frequency(regs);
1.977 + }
1.978 + else
1.979 + return 0;
1.980 +}
1.981 +
1.982 +void
1.983 +Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
1.984 +{
1.985 + set_multiplier(regs, multiplier);
1.986 + set_input_division(regs, in_divider);
1.987 + set_output_division(regs, out_divider);
1.988
1.989 - return bit != Clock_gate_undefined ? 1 : 0;
1.990 + if (pll_enabled(regs) && !pll_bypassed(regs))
1.991 + while (!have_pll(regs));
1.992 +}
1.993 +
1.994 +
1.995 +
1.996 +// Clock control.
1.997 +
1.998 +void
1.999 +Clock::change_disable(Cpm_regs ®s)
1.1000 +{
1.1001 + if (change_enable_bit != Clock_change_enable_undefined)
1.1002 + regs.set_field(change_enable_reg, 1, change_enable_bit, 0);
1.1003 +}
1.1004 +
1.1005 +void
1.1006 +Clock::change_enable(Cpm_regs ®s)
1.1007 +{
1.1008 + if (change_enable_bit != Clock_change_enable_undefined)
1.1009 + regs.set_field(change_enable_reg, 1, change_enable_bit, 1);
1.1010 +}
1.1011 +
1.1012 +int
1.1013 +Clock::have_clock(Cpm_regs ®s)
1.1014 +{
1.1015 + if (gate_bit != Clock_gate_undefined)
1.1016 + return !regs.get_field(gate_reg, 1, gate_bit);
1.1017 + else
1.1018 + return true;
1.1019 +}
1.1020 +
1.1021 +void
1.1022 +Clock::start_clock(Cpm_regs ®s)
1.1023 +{
1.1024 + if (gate_bit != Clock_gate_undefined)
1.1025 + regs.set_field(gate_reg, 1, gate_bit, 0);
1.1026 +}
1.1027 +
1.1028 +void
1.1029 +Clock::stop_clock(Cpm_regs ®s)
1.1030 +{
1.1031 + if (gate_bit != Clock_gate_undefined)
1.1032 + regs.set_field(gate_reg, 1, gate_bit, 1);
1.1033 +}
1.1034 +
1.1035 +void
1.1036 +Clock::wait_busy(Cpm_regs ®s)
1.1037 +{
1.1038 + if (busy_bit != Clock_busy_undefined)
1.1039 + while (regs.get_field(busy_reg, 1, busy_bit));
1.1040 +}
1.1041 +
1.1042 +
1.1043 +
1.1044 +// Clock dividers.
1.1045 +
1.1046 +uint32_t
1.1047 +Clock::get_divider(Cpm_regs ®s)
1.1048 +{
1.1049 + if (divider_bit != Clock_divider_undefined)
1.1050 + return regs.get_field(divider_reg, divider_mask, divider_bit) + 1;
1.1051 + else
1.1052 + return 1;
1.1053 +}
1.1054 +
1.1055 +void
1.1056 +Clock::set_divider(Cpm_regs ®s, uint32_t division)
1.1057 +{
1.1058 + if (divider_bit == Clock_divider_undefined)
1.1059 + return;
1.1060 +
1.1061 + change_enable(regs);
1.1062 + regs.set_field(divider_reg, divider_mask, divider_bit, division - 1);
1.1063 + wait_busy(regs);
1.1064 + change_disable(regs);
1.1065 +}
1.1066 +
1.1067 +void
1.1068 +Clock::set_source(Cpm_regs ®s, uint8_t source)
1.1069 +{
1.1070 + change_enable(regs);
1.1071 + Clock_base::set_source(regs, source);
1.1072 + wait_busy(regs);
1.1073 + change_disable(regs);
1.1074 }
1.1075
1.1076
1.1077 @@ -603,316 +1041,65 @@
1.1078 // definitions.
1.1079
1.1080 Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq)
1.1081 -: _exclk_freq(exclk_freq)
1.1082 +: _cpm_regs(addr, exclk_freq)
1.1083 {
1.1084 - _regs = new Hw::Mmio_register_block<32>(addr);
1.1085 -
1.1086 // add_cid("cpm");
1.1087 // add_cid("cpm-x1600");
1.1088 - // register_property("exclk_freq", &_exclk_freq);
1.1089 -}
1.1090 -
1.1091 -
1.1092 -
1.1093 -// Utility methods.
1.1094 -
1.1095 -uint32_t
1.1096 -Cpm_x1600_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift)
1.1097 -{
1.1098 - return (_regs[reg] & (mask << shift)) >> shift;
1.1099 -}
1.1100 -
1.1101 -void
1.1102 -Cpm_x1600_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value)
1.1103 -{
1.1104 - _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift);
1.1105 -}
1.1106 -
1.1107 -
1.1108 -
1.1109 -// Clock/timer control.
1.1110 -
1.1111 -void
1.1112 -Cpm_x1600_chip::change_disable(enum Clock_identifiers clock)
1.1113 -{
1.1114 - enum Clock_change_enable_bits bit = clock_desc[clock].change_enable_bit;
1.1115 -
1.1116 - if (bit != Clock_change_enable_undefined)
1.1117 - set_field(clock_desc[clock].change_enable_reg, 1, bit, 0);
1.1118 -}
1.1119 -
1.1120 -void
1.1121 -Cpm_x1600_chip::change_enable(enum Clock_identifiers clock)
1.1122 -{
1.1123 - enum Clock_change_enable_bits bit = clock_desc[clock].change_enable_bit;
1.1124 -
1.1125 - if (bit != Clock_change_enable_undefined)
1.1126 - set_field(clock_desc[clock].change_enable_reg, 1, bit, 1);
1.1127 + // register_property("exclk_freq", &exclk_freq);
1.1128 }
1.1129
1.1130 int
1.1131 Cpm_x1600_chip::have_clock(enum Clock_identifiers clock)
1.1132 {
1.1133 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
1.1134 - return !get_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
1.1135 - get_clock_gate_bit(clock));
1.1136 - else
1.1137 - return true;
1.1138 + return clocks[clock]->have_clock(_cpm_regs);
1.1139 }
1.1140
1.1141 void
1.1142 Cpm_x1600_chip::start_clock(enum Clock_identifiers clock)
1.1143 {
1.1144 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
1.1145 - set_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
1.1146 - get_clock_gate_bit(clock), 0);
1.1147 + clocks[clock]->start_clock(_cpm_regs);
1.1148 }
1.1149
1.1150 void
1.1151 Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock)
1.1152 {
1.1153 - if (clock_desc[clock].gate_bit != Clock_gate_undefined)
1.1154 - set_field(clock_desc[clock].gate_reg, get_clock_gate_mask(clock),
1.1155 - get_clock_gate_bit(clock), 1);
1.1156 -}
1.1157 -
1.1158 -void
1.1159 -Cpm_x1600_chip::wait_busy(enum Clock_identifiers clock)
1.1160 -{
1.1161 - enum Clock_busy_bits bit = clock_desc[clock].busy_bit;
1.1162 -
1.1163 - if (bit != Clock_busy_undefined)
1.1164 - while (get_field(clock_desc[clock].busy_reg, 1, bit));
1.1165 -}
1.1166 -
1.1167 -
1.1168 -
1.1169 -// PLL control.
1.1170 -
1.1171 -// Return whether the PLL is stable.
1.1172 -
1.1173 -int
1.1174 -Cpm_x1600_chip::have_pll(uint32_t pll_reg)
1.1175 -{
1.1176 - return get_field(pll_reg, 1, Pll_stable);
1.1177 -}
1.1178 -
1.1179 -int
1.1180 -Cpm_x1600_chip::pll_enabled(uint32_t pll_reg)
1.1181 -{
1.1182 - return get_field(pll_reg, 1, Pll_enabled);
1.1183 -}
1.1184 -
1.1185 -int
1.1186 -Cpm_x1600_chip::pll_bypassed(uint32_t pll_reg)
1.1187 -{
1.1188 - uint8_t bit;
1.1189 - unsigned mask = 1;
1.1190 -
1.1191 - switch (pll_reg)
1.1192 - {
1.1193 - case Pll_control_A: bit = Pll_bypass_A; break;
1.1194 - case Pll_control_M: bit = Pll_bypass_M; break;
1.1195 - case Pll_control_E: bit = Pll_bypass_E; break;
1.1196 - default: bit = 0; mask = 0; break;
1.1197 - }
1.1198 -
1.1199 - return get_field(Pll_control, mask, bit);
1.1200 -}
1.1201 -
1.1202 -void
1.1203 -Cpm_x1600_chip::pll_enable(uint32_t pll_reg)
1.1204 -{
1.1205 - set_field(pll_reg, 1, Pll_enabled, 1);
1.1206 - while (!have_pll(pll_reg));
1.1207 -}
1.1208 -
1.1209 -void
1.1210 -Cpm_x1600_chip::pll_disable(uint32_t pll_reg)
1.1211 -{
1.1212 - set_field(pll_reg, 1, Pll_enabled, 0);
1.1213 - while (have_pll(pll_reg));
1.1214 -}
1.1215 -
1.1216 -// Feedback (13-bit) multiplier.
1.1217 -
1.1218 -uint16_t
1.1219 -Cpm_x1600_chip::get_multiplier(uint32_t pll_reg)
1.1220 -{
1.1221 - return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1;
1.1222 + clocks[clock]->stop_clock(_cpm_regs);
1.1223 }
1.1224
1.1225 -void
1.1226 -Cpm_x1600_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier)
1.1227 -{
1.1228 - set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1);
1.1229 -}
1.1230 -
1.1231 -// Input (6-bit) divider.
1.1232 -
1.1233 -uint8_t
1.1234 -Cpm_x1600_chip::get_input_division(uint32_t pll_reg)
1.1235 -{
1.1236 - return get_field(pll_reg, 0x3f, Pll_input_division) + 1;
1.1237 -}
1.1238 -
1.1239 -void
1.1240 -Cpm_x1600_chip::set_input_division(uint32_t pll_reg, uint8_t divider)
1.1241 -{
1.1242 - set_field(pll_reg, 0x3f, Pll_input_division, divider - 1);
1.1243 -}
1.1244 -
1.1245 -// Output (dual 3-bit) dividers.
1.1246 -
1.1247 -uint8_t
1.1248 -Cpm_x1600_chip::get_output_division(uint32_t pll_reg)
1.1249 -{
1.1250 - uint8_t d0 = get_field(pll_reg, 0x07, Pll_output_division0);
1.1251 - uint8_t d1 = get_field(pll_reg, 0x07, Pll_output_division1);
1.1252 -
1.1253 - return d0 * d1;
1.1254 -}
1.1255 -
1.1256 -void
1.1257 -Cpm_x1600_chip::set_output_division(uint32_t pll_reg, uint8_t divider)
1.1258 -{
1.1259 - // Assert 1 as a minimum.
1.1260 - // Divider 0 must be less than or equal to divider 1.
1.1261 -
1.1262 - uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1));
1.1263 - uint8_t d1 = divider / d0;
1.1264 -
1.1265 - set_field(pll_reg, 0x07, Pll_output_division0, d0);
1.1266 - set_field(pll_reg, 0x07, Pll_output_division1, d1);
1.1267 -}
1.1268 -
1.1269 -uint32_t
1.1270 -Cpm_x1600_chip::get_pll_frequency(uint32_t pll_reg)
1.1271 -{
1.1272 - // Test for PLL enable and not PLL bypass.
1.1273 -
1.1274 - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
1.1275 - return (_exclk_freq * get_multiplier(pll_reg)) /
1.1276 - (get_input_division(pll_reg) * get_output_division(pll_reg));
1.1277 - else
1.1278 - return _exclk_freq;
1.1279 -}
1.1280 -
1.1281 -void
1.1282 -Cpm_x1600_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
1.1283 -{
1.1284 - set_multiplier(pll_reg, multiplier);
1.1285 - set_input_division(pll_reg, in_divider);
1.1286 - set_output_division(pll_reg, out_divider);
1.1287 -
1.1288 - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
1.1289 - while (!have_pll(pll_reg));
1.1290 -}
1.1291 -
1.1292 -
1.1293 -
1.1294 -// Clock dividers.
1.1295 -
1.1296 uint32_t
1.1297 Cpm_x1600_chip::get_divider(enum Clock_identifiers clock)
1.1298 {
1.1299 - if (clock_desc[clock].divider_bit != Clock_divider_undefined)
1.1300 - return get_field(clock_desc[clock].divider_reg, clock_desc[clock].divider_mask,
1.1301 - clock_desc[clock].divider_bit) + 1;
1.1302 - else
1.1303 - return 1;
1.1304 + return clocks[clock]->get_divider(_cpm_regs);
1.1305 }
1.1306
1.1307 void
1.1308 Cpm_x1600_chip::set_divider(enum Clock_identifiers clock, uint32_t division)
1.1309 {
1.1310 - if (clock_desc[clock].divider_bit == Clock_divider_undefined)
1.1311 - return;
1.1312 -
1.1313 - change_enable(clock);
1.1314 - set_field(clock_desc[clock].divider_reg, clock_desc[clock].divider_mask,
1.1315 - clock_desc[clock].divider_bit, division - 1);
1.1316 - wait_busy(clock);
1.1317 - change_disable(clock);
1.1318 + clocks[clock]->set_divider(_cpm_regs, division);
1.1319 }
1.1320
1.1321 -
1.1322 -
1.1323 -// Clock sources.
1.1324 -
1.1325 uint8_t
1.1326 Cpm_x1600_chip::get_source(enum Clock_identifiers clock)
1.1327 {
1.1328 - if (clock_desc[clock].source_bit != Clock_source_undefined)
1.1329 - return get_field(clock_desc[clock].source_reg, Source_mask, clock_desc[clock].source_bit);
1.1330 - else
1.1331 - return 0;
1.1332 + return clocks[clock]->get_source(_cpm_regs);
1.1333 }
1.1334
1.1335 void
1.1336 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source)
1.1337 {
1.1338 - if (clock_desc[clock].source_bit == Clock_source_undefined)
1.1339 - return;
1.1340 -
1.1341 - change_enable(clock);
1.1342 - set_field(clock_desc[clock].source_reg, Source_mask, clock_desc[clock].source_bit, source);
1.1343 - wait_busy(clock);
1.1344 - change_disable(clock);
1.1345 + clocks[clock]->set_source(_cpm_regs, source);
1.1346 }
1.1347
1.1348 -
1.1349 -
1.1350 -// Clock source frequencies.
1.1351 -
1.1352 uint32_t
1.1353 Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock)
1.1354 {
1.1355 - struct Clock_desc desc = clock_desc[clock];
1.1356 -
1.1357 - if (desc.num_inputs == 0)
1.1358 - {
1.1359 - switch (clock)
1.1360 - {
1.1361 - case Clock_external: return _exclk_freq;
1.1362 - default: return 0;
1.1363 - }
1.1364 - }
1.1365 -
1.1366 - // Clocks with one source yield that input frequency, although PLLs are
1.1367 - // handled specially.
1.1368 -
1.1369 - else if (desc.num_inputs == 1)
1.1370 - {
1.1371 - switch (clock)
1.1372 - {
1.1373 - case Clock_pll_A: return get_pll_frequency(Pll_control_A);
1.1374 - case Clock_pll_E: return get_pll_frequency(Pll_control_E);
1.1375 - case Clock_pll_M: return get_pll_frequency(Pll_control_M);
1.1376 - default: return get_frequency(desc.inputs[0]);
1.1377 - }
1.1378 - }
1.1379 -
1.1380 - // With multiple sources, obtain the selected source for the clock.
1.1381 -
1.1382 - uint8_t source = get_source(clock);
1.1383 -
1.1384 - // Return the frequency of the source.
1.1385 -
1.1386 - if (source < desc.num_inputs)
1.1387 - return get_frequency(desc.inputs[source]);
1.1388 - else
1.1389 - return 0;
1.1390 + return clocks[clock]->get_source_frequency(_cpm_regs);
1.1391 }
1.1392
1.1393 -
1.1394 -
1.1395 -// Output clock frequencies.
1.1396 -
1.1397 uint32_t
1.1398 Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock)
1.1399 {
1.1400 - return get_source_frequency(clock) / get_divider(clock);
1.1401 + return clocks[clock]->get_frequency(_cpm_regs);
1.1402 }
1.1403
1.1404 void
1.1405 @@ -924,19 +1111,33 @@
1.1406 // EPLL).
1.1407
1.1408 case Clock_lcd_pixel:
1.1409 + {
1.1410
1.1411 // Switch to the MPLL and attempt to set the divider.
1.1412
1.1413 - set_source(Clock_lcd_pixel, Source_mME_pll_M);
1.1414 - pll_enable(Pll_control_M);
1.1415 - set_divider(Clock_lcd_pixel, get_source_frequency(clock) / frequency);
1.1416 + Clock_base *lcd = clocks[Clock_lcd_pixel];
1.1417 + Clock_base *pll = clocks[Clock_pll_M];
1.1418 +
1.1419 + lcd->set_source(_cpm_regs, Source_mME_pll_M);
1.1420 + pll->start_clock(_cpm_regs);
1.1421 + lcd->set_divider(_cpm_regs, lcd->get_source_frequency(_cpm_regs) / frequency);
1.1422 break;
1.1423 + }
1.1424
1.1425 default:
1.1426 break;
1.1427 }
1.1428 }
1.1429
1.1430 +void
1.1431 +Cpm_x1600_chip::set_pll_parameters(enum Clock_identifiers clock, uint16_t multiplier,
1.1432 + uint8_t in_divider, uint8_t out_divider)
1.1433 +{
1.1434 + Pll *pll = dynamic_cast<Pll *>(clocks[clock]);
1.1435 +
1.1436 + pll->set_pll_parameters(_cpm_regs, multiplier, in_divider, out_divider);
1.1437 +}
1.1438 +
1.1439
1.1440
1.1441 // C language interface functions.
1.1442 @@ -968,8 +1169,6 @@
1.1443 static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock);
1.1444 }
1.1445
1.1446 -
1.1447 -
1.1448 uint32_t
1.1449 x1600_cpm_get_divider(void *cpm, enum Clock_identifiers clock)
1.1450 {
1.1451 @@ -982,8 +1181,6 @@
1.1452 return static_cast<Cpm_x1600_chip *>(cpm)->set_divider(clock, divider);
1.1453 }
1.1454
1.1455 -
1.1456 -
1.1457 uint8_t
1.1458 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock)
1.1459 {
1.1460 @@ -996,16 +1193,12 @@
1.1461 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source);
1.1462 }
1.1463
1.1464 -
1.1465 -
1.1466 uint32_t
1.1467 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock)
1.1468 {
1.1469 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock);
1.1470 }
1.1471
1.1472 -
1.1473 -
1.1474 uint32_t
1.1475 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock)
1.1476 {
1.1477 @@ -1018,10 +1211,8 @@
1.1478 static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency);
1.1479 }
1.1480
1.1481 -
1.1482 -
1.1483 void
1.1484 x1600_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
1.1485 {
1.1486 - static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider);
1.1487 + static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Clock_pll_M, multiplier, in_divider, out_divider);
1.1488 }