1 /* 2 * Clock and power management. This exposes the combined functionality 3 * provided by the X1600 and related SoCs. The power management 4 * functionality could be exposed using a separate driver. 5 * 6 * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA 22 */ 23 24 #include <l4/devices/hw_mmio_register_block.h> 25 #include "cpm-x1600.h" 26 #include <math.h> 27 #include <stdio.h> 28 29 30 31 // Register locations. 32 33 enum Regs : unsigned 34 { 35 Clock_control = 0x000, // CPCCR 36 Low_power_control = 0x004, // LCR 37 Clock_gate0 = 0x020, // CLKGR0 38 Clock_gate1 = 0x028, // CLKGR1 39 Sleep_control = 0x024, // OPCR (oscillator and power control) 40 Clock_status = 0x0d4, // CPCSR 41 Divider_ddr = 0x02c, // DDRCDR 42 Divider_mac = 0x054, // MACCDR 43 Divider0_i2s0 = 0x060, // I2SCDR 44 Divider1_i2s0 = 0x070, // I2S1CDR 45 Divider_lcd = 0x064, // LPCDR 46 Divider_msc0 = 0x068, // MSC0CDR 47 Divider_msc1 = 0x0a4, // MSC1CDR 48 Divider_sfc = 0x074, // SFCCDR 49 Divider_ssi = 0x05c, // SSICDR 50 Divider_cim = 0x078, // CIMCDR 51 Divider_pwm = 0x06c, // PWMCDR 52 Divider_can0 = 0x0a0, // CAN0CDR 53 Divider_can1 = 0x0a8, // CAN1CDR 54 Divider_cdbus = 0x0ac, // CDBUSCDR 55 Divider_macphy0 = 0x0e4, // MPHY0C 56 Cpm_interrupt = 0x0b0, // CPM_INTR 57 Cpm_interrupt_en = 0x0b4, // CPM_INTRE 58 Cpm_swi = 0x0bc, // CPM_SFTINT 59 Ddr_gate = 0x0d0, // DRCG 60 Cpm_scratch_prot = 0x038, // CPSPPR 61 Cpm_scratch = 0x034, // CPSPR 62 Usb_param_control0 = 0x03c, // USBPCR 63 Usb_reset_detect = 0x040, // USBRDT 64 Usb_vbus_jitter = 0x044, // USBVBFIL 65 Usb_param_control1 = 0x048, // USBPCR1 66 Pll_control = 0x00c, // CPPCR 67 Pll_control_A = 0x010, // CPAPCR 68 Pll_control_M = 0x014, // CPMPCR 69 Pll_control_E = 0x018, // CPEPCR 70 Pll_fraction_A = 0x084, // CPAPACR 71 Pll_fraction_M = 0x088, // CPMPACR 72 Pll_fraction_E = 0x08c, // CPEPACR 73 }; 74 75 enum Clock_source_values : unsigned 76 { 77 Source_mME_main = 0, 78 Source_mME_pll_M = 1, 79 Source_mME_pll_E = 2, 80 81 // Special value 82 83 Source_mask = 0x3, 84 }; 85 86 87 88 // Register field abstraction. 89 90 class Field 91 { 92 uint32_t reg; 93 uint32_t mask; 94 uint8_t bit; 95 bool defined; 96 97 public: 98 explicit Field() 99 : defined(false) 100 { 101 } 102 103 explicit Field(uint32_t reg, uint32_t mask, uint32_t bit) 104 : reg(reg), mask(mask), bit(bit), defined(true) 105 { 106 } 107 108 uint32_t get_field(Cpm_regs ®s); 109 void set_field(Cpm_regs ®s, uint32_t value); 110 bool is_defined() { return defined; } 111 }; 112 113 // Undefined fields. 114 115 Field Gate_undefined, Change_enable_undefined, Busy_undefined, Divider_undefined; 116 117 118 119 // Clock sources. 120 121 class Mux 122 { 123 int _num_inputs; 124 enum Clock_identifiers *_inputs, _input; 125 126 public: 127 explicit Mux(int num_inputs, enum Clock_identifiers inputs[]) 128 : _num_inputs(num_inputs), _inputs(inputs) 129 { 130 } 131 132 explicit Mux(enum Clock_identifiers input) 133 : _num_inputs(1), _inputs(&_input) 134 { 135 _input = input; 136 } 137 138 explicit Mux() 139 : _num_inputs(0), _inputs(NULL) 140 { 141 } 142 143 int get_number() { return _num_inputs; } 144 enum Clock_identifiers get_input(int num); 145 }; 146 147 class Source 148 { 149 Mux _inputs; 150 Field _source; 151 152 public: 153 explicit Source(Mux inputs, Field source) 154 : _inputs(inputs), _source(source) 155 { 156 } 157 158 explicit Source(Mux inputs) 159 : _inputs(inputs) 160 { 161 } 162 163 explicit Source() 164 { 165 } 166 167 int get_number() { return _inputs.get_number(); } 168 enum Clock_identifiers get_input(int num) { return _inputs.get_input(num); } 169 170 // Clock source. 171 172 uint8_t get_source(Cpm_regs ®s); 173 void set_source(Cpm_regs ®s, uint8_t source); 174 175 // Clock source frequency. 176 177 uint32_t get_frequency(Cpm_regs ®s); 178 }; 179 180 // Undefined sources. 181 182 Source Source_undefined; 183 184 185 186 // Common clock abstraction. 187 188 class Clock_base 189 { 190 Source _source; 191 192 public: 193 explicit Clock_base(Source source) 194 : _source(source) 195 { 196 } 197 198 // Clock control. 199 200 virtual int have_clock(Cpm_regs ®s); 201 virtual void start_clock(Cpm_regs ®s); 202 virtual void stop_clock(Cpm_regs ®s); 203 204 // Clock divider. 205 206 virtual uint32_t get_divider(Cpm_regs ®s); 207 virtual void set_divider(Cpm_regs ®s, uint32_t division); 208 209 // Clock source. 210 211 virtual uint8_t get_source(Cpm_regs ®s); 212 virtual void set_source(Cpm_regs ®s, uint8_t source); 213 214 // Clock source frequency. 215 216 virtual uint32_t get_source_frequency(Cpm_regs ®s); 217 218 // Output frequency. 219 220 virtual uint32_t get_frequency(Cpm_regs ®s); 221 }; 222 223 224 225 // PLL descriptions. 226 227 class Pll : public Clock_base 228 { 229 Field _enable, _stable, _bypass; 230 Field _multiplier, _input_division, _output_division0, _output_division1; 231 232 public: 233 explicit Pll(Source source, 234 Field enable, Field stable, Field bypass, 235 Field multiplier, Field input_division, 236 Field output_division0, Field output_division1) 237 : Clock_base(source), 238 _enable(enable), _stable(stable), _bypass(bypass), 239 _multiplier(multiplier), _input_division(input_division), 240 _output_division0(output_division0), _output_division1(output_division1) 241 { 242 } 243 244 // PLL_specific control. 245 246 int have_pll(Cpm_regs ®s); 247 int pll_enabled(Cpm_regs ®s); 248 int pll_bypassed(Cpm_regs ®s); 249 250 // Clock control. 251 252 int have_clock(Cpm_regs ®s); 253 void start_clock(Cpm_regs ®s); 254 void stop_clock(Cpm_regs ®s); 255 256 // General frequency modifiers. 257 258 uint16_t get_multiplier(Cpm_regs ®s); 259 void set_multiplier(Cpm_regs ®s, uint16_t multiplier); 260 uint8_t get_input_division(Cpm_regs ®s); 261 void set_input_division(Cpm_regs ®s, uint8_t divider); 262 uint8_t get_output_division(Cpm_regs ®s); 263 void set_output_division(Cpm_regs ®s, uint8_t divider); 264 265 // PLL output frequency. 266 267 uint32_t get_frequency(Cpm_regs ®s); 268 269 // Other operations. 270 271 void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, 272 uint8_t in_divider, uint8_t out_divider); 273 }; 274 275 276 277 // Clock descriptions. 278 279 class Clock : public Clock_base 280 { 281 Field _gate, _change_enable, _busy, _divider; 282 283 // Clock control. 284 285 void change_disable(Cpm_regs ®s); 286 void change_enable(Cpm_regs ®s); 287 void wait_busy(Cpm_regs ®s); 288 289 public: 290 explicit Clock(Source source = Source_undefined, 291 Field gate = Gate_undefined, 292 Field change_enable = Change_enable_undefined, 293 Field busy = Busy_undefined, 294 Field divider = Divider_undefined) 295 : Clock_base(source), 296 _gate(gate), _change_enable(change_enable), _busy(busy), _divider(divider) 297 { 298 } 299 300 // Clock control. 301 302 int have_clock(Cpm_regs ®s); 303 void start_clock(Cpm_regs ®s); 304 void stop_clock(Cpm_regs ®s); 305 306 // Clock divider. 307 308 uint32_t get_divider(Cpm_regs ®s); 309 void set_divider(Cpm_regs ®s, uint32_t division); 310 311 // Clock source. 312 313 void set_source(Cpm_regs ®s, uint8_t source); 314 }; 315 316 317 318 // Register field definitions. 319 320 Field Clock_source_main (Clock_control, 3, 30); // SEL_SRC (output to SCLK_A) 321 Field Clock_source_cpu (Clock_control, 3, 28); // SEL_CPLL (output to CCLK) 322 Field Clock_source_hclock0 (Clock_control, 3, 26); // SEL_H0PLL (output to AHB0) 323 Field Clock_source_hclock2 (Clock_control, 3, 24); // SEL_H2PLL (output to AHB2) 324 Field Clock_source_can0 (Divider_can0, 3, 30); // CA0CS 325 Field Clock_source_can1 (Divider_can1, 3, 30); // CA1CS 326 Field Clock_source_cdbus (Divider_cdbus, 3, 30); // CDCS 327 Field Clock_source_cim (Divider_cim, 3, 30); // CIMPCS 328 Field Clock_source_ddr (Divider_ddr, 3, 30); // DCS 329 Field Clock_source_i2s (Divider0_i2s0, 1, 31); // I2PCS 330 Field Clock_source_lcd (Divider_lcd, 3, 30); // LPCS 331 Field Clock_source_mac (Divider_mac, 3, 30); // MACPCS 332 Field Clock_source_msc0 (Divider_msc0, 3, 30); // MPCS 333 Field Clock_source_msc1 (Divider_msc1, 3, 30); // MPCS 334 Field Clock_source_pwm (Divider_pwm, 3, 30); // PWMPCS 335 Field Clock_source_sfc (Divider_sfc, 3, 30); // SFCS 336 Field Clock_source_ssi (Divider_ssi, 3, 30); // SPCS 337 338 Field Clock_busy_cpu (Clock_status, 1, 0); 339 Field Clock_busy_ddr (Divider_ddr, 1, 28); 340 Field Clock_busy_mac (Divider_mac, 1, 28); 341 Field Clock_busy_lcd (Divider_lcd, 1, 28); 342 Field Clock_busy_msc0 (Divider_msc0, 1, 28); 343 Field Clock_busy_msc1 (Divider_msc1, 1, 28); 344 Field Clock_busy_sfc (Divider_sfc, 1, 28); 345 Field Clock_busy_ssi (Divider_ssi, 1, 28); 346 Field Clock_busy_cim (Divider_cim, 1, 28); 347 Field Clock_busy_pwm (Divider_pwm, 1, 28); 348 Field Clock_busy_can0 (Divider_can0, 1, 28); 349 Field Clock_busy_can1 (Divider_can1, 1, 28); 350 Field Clock_busy_cdbus (Divider_cdbus, 1, 28); 351 352 Field Clock_change_enable_cpu (Clock_control, 1, 22); 353 Field Clock_change_enable_ahb0 (Clock_control, 1, 21); 354 Field Clock_change_enable_ahb2 (Clock_control, 1, 20); 355 Field Clock_change_enable_ddr (Divider_ddr, 1, 29); 356 Field Clock_change_enable_mac (Divider_mac, 1, 29); 357 Field Clock_change_enable_i2s (Divider0_i2s0, 1, 29); 358 Field Clock_change_enable_lcd (Divider_lcd, 1, 29); 359 Field Clock_change_enable_msc0 (Divider_msc0, 1, 29); 360 Field Clock_change_enable_msc1 (Divider_msc1, 1, 29); 361 Field Clock_change_enable_sfc (Divider_sfc, 1, 29); 362 Field Clock_change_enable_ssi (Divider_ssi, 1, 29); 363 Field Clock_change_enable_cim (Divider_cim, 1, 29); 364 Field Clock_change_enable_pwm (Divider_pwm, 1, 29); 365 Field Clock_change_enable_can0 (Divider_can0, 1, 29); 366 Field Clock_change_enable_can1 (Divider_can1, 1, 29); 367 Field Clock_change_enable_cdbus (Divider_cdbus, 1, 29); 368 369 Field Clock_divider_can0 (Divider_can0, 0xff, 0); // CAN0CDR 370 Field Clock_divider_can1 (Divider_can1, 0xff, 0); // CAN1CDR 371 Field Clock_divider_cdbus (Divider_cdbus, 0xff, 0); // CDBUSCDR 372 Field Clock_divider_cim (Divider_cim, 0xff, 0); // CIMCDR 373 Field Clock_divider_cpu (Clock_control, 0x0f, 0); // CDIV 374 Field Clock_divider_ddr (Divider_ddr, 0x0f, 0); // DDRCDR 375 Field Clock_divider_hclock0 (Clock_control, 0x0f, 8); // H0DIV (fast AHB peripherals) 376 Field Clock_divider_hclock2 (Clock_control, 0x0f, 12); // H2DIV (fast AHB peripherals) 377 Field Clock_divider_l2cache (Clock_control, 0x0f, 4); // L2CDIV 378 Field Clock_divider_lcd (Divider_lcd, 0xff, 0); // LPCDR 379 Field Clock_divider_mac (Divider_mac, 0xff, 0); // MACCDR 380 Field Clock_divider_msc0 (Divider_msc0, 0xff, 0); // MSC0CDR 381 Field Clock_divider_msc1 (Divider_msc1, 0xff, 0); // MSC1CDR 382 Field Clock_divider_pclock (Clock_control, 0x0f, 16); // PDIV (slow APB peripherals) 383 Field Clock_divider_pwm (Divider_pwm, 0x0f, 0); // PWMCDR 384 Field Clock_divider_sfc (Divider_sfc, 0xff, 0); // SFCCDR 385 Field Clock_divider_ssi (Divider_ssi, 0xff, 0); // SSICDR 386 387 Field Clock_gate_main (Clock_control, 1, 23); // GATE_SCLKA 388 Field Clock_gate_ddr (Clock_gate0, 1, 31); // DDR 389 Field Clock_gate_ahb0 (Clock_gate0, 1, 29); // AHB0 390 Field Clock_gate_apb0 (Clock_gate0, 1, 28); // APB0 391 Field Clock_gate_rtc (Clock_gate0, 1, 27); // RTC 392 Field Clock_gate_aes (Clock_gate0, 1, 24); // AES 393 Field Clock_gate_lcd_pixel (Clock_gate0, 1, 23); // LCD 394 Field Clock_gate_cim (Clock_gate0, 1, 22); // CIM 395 Field Clock_gate_dma (Clock_gate0, 1, 21); // PDMA 396 Field Clock_gate_ost (Clock_gate0, 1, 20); // OST 397 Field Clock_gate_ssi0 (Clock_gate0, 1, 19); // SSI0 398 Field Clock_gate_timer (Clock_gate0, 1, 18); // TCU 399 Field Clock_gate_dtrng (Clock_gate0, 1, 17); // DTRNG 400 Field Clock_gate_uart2 (Clock_gate0, 1, 16); // UART2 401 Field Clock_gate_uart1 (Clock_gate0, 1, 15); // UART1 402 Field Clock_gate_uart0 (Clock_gate0, 1, 14); // UART0 403 Field Clock_gate_sadc (Clock_gate0, 1, 13); // SADC 404 Field Clock_gate_audio (Clock_gate0, 1, 11); // AUDIO 405 Field Clock_gate_ssi_slv (Clock_gate0, 1, 10); // SSI_SLV 406 Field Clock_gate_i2c1 (Clock_gate0, 1, 8); // I2C1 407 Field Clock_gate_i2c0 (Clock_gate0, 1, 7); // I2C0 408 Field Clock_gate_msc1 (Clock_gate0, 1, 5); // MSC1 409 Field Clock_gate_msc0 (Clock_gate0, 1, 4); // MSC0 410 Field Clock_gate_otg (Clock_gate0, 1, 3); // OTG 411 Field Clock_gate_sfc (Clock_gate0, 1, 2); // SFC 412 Field Clock_gate_efuse (Clock_gate0, 1, 1); // EFUSE 413 Field Clock_gate_nemc (Clock_gate0, 1, 0); // NEMC 414 Field Clock_gate_arb (Clock_gate1, 1, 30); // ARB 415 Field Clock_gate_mipi_csi (Clock_gate1, 1, 28); // MIPI_CSI 416 Field Clock_gate_intc (Clock_gate1, 1, 26); // INTC 417 Field Clock_gate_gmac0 (Clock_gate1, 1, 23); // GMAC0 418 Field Clock_gate_uart3 (Clock_gate1, 1, 16); // UART3 419 Field Clock_gate_i2s0_tx (Clock_gate1, 1, 9); // I2S0_dev_tclk 420 Field Clock_gate_i2s0_rx (Clock_gate1, 1, 8); // I2S0_dev_rclk 421 Field Clock_gate_hash (Clock_gate1, 1, 6); // HASH 422 Field Clock_gate_pwm (Clock_gate1, 1, 5); // PWM 423 Field Clock_gate_cdbus (Clock_gate1, 1, 2); // CDBUS 424 Field Clock_gate_can1 (Clock_gate1, 1, 1); // CAN1 425 Field Clock_gate_can0 (Clock_gate1, 1, 0); // CAN0 426 427 Field Pll_enable_A (Pll_control_A, 1, 0); // APLLEN 428 Field Pll_enable_E (Pll_control_E, 1, 0); // EPLLEN 429 Field Pll_enable_M (Pll_control_M, 1, 0); // MPLLEN 430 431 Field Pll_stable_A (Pll_control_A, 1, 3); // APLL_ON 432 Field Pll_stable_E (Pll_control_E, 1, 3); // EPLL_ON 433 Field Pll_stable_M (Pll_control_M, 1, 3); // MPLL_ON 434 435 Field Pll_bypass_A (Pll_control_A, 1, 30); // APLL_BP 436 Field Pll_bypass_E (Pll_control_E, 1, 26); // EPLL_BP 437 Field Pll_bypass_M (Pll_control_M, 1, 28); // MPLL_BP 438 439 Field Pll_multiplier_A (Pll_control_A, 0x1fff, 20); // APLLM 440 Field Pll_multiplier_E (Pll_control_E, 0x1fff, 20); // EPLLM 441 Field Pll_multiplier_M (Pll_control_M, 0x1fff, 20); // MPLLM 442 443 Field Pll_input_division_A (Pll_control_A, 0x3f, 14); // APLLN 444 Field Pll_input_division_E (Pll_control_E, 0x3f, 14); // EPLLN 445 Field Pll_input_division_M (Pll_control_M, 0x3f, 14); // MPLLN 446 447 Field Pll_output_division1_A (Pll_control_A, 0x07, 11); // APLLOD1 448 Field Pll_output_division1_E (Pll_control_E, 0x07, 11); // EPLLOD1 449 Field Pll_output_division1_M (Pll_control_M, 0x07, 11); // MPLLOD1 450 451 Field Pll_output_division0_A (Pll_control_A, 0x07, 8); // APLLOD0 452 Field Pll_output_division0_E (Pll_control_E, 0x07, 8); // EPLLOD0 453 Field Pll_output_division0_M (Pll_control_M, 0x07, 8); // MPLLOD0 454 455 456 457 // Multiplexer instances. 458 459 #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) 460 461 Mux mux_external(Clock_external); 462 463 Mux mux_pclock(Clock_pclock); 464 465 Mux mux_ahb2_apb(Clock_ahb2_apb); 466 467 Mux mux_core(3, Clocks(Clock_none, Clock_main, Clock_pll_M)); 468 469 Mux mux_bus(4, Clocks(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external)); 470 471 Mux mux_dev(3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E)); 472 473 Mux mux_i2s(2, Clocks(Clock_main, Clock_pll_E)); 474 475 476 477 // Clock instances. 478 479 Clock clock_ahb2_apb(Source(mux_core, Clock_source_hclock2)); 480 481 Clock clock_aic_bitclk; 482 483 Clock clock_aic_pclk; 484 485 Clock clock_can0(Source(mux_bus, Clock_source_can0), 486 Clock_gate_can0, 487 Clock_change_enable_can0, 488 Clock_busy_can0, 489 Clock_divider_can0); 490 491 Clock clock_can1(Source(mux_bus, Clock_source_can1), 492 Clock_gate_can1, 493 Clock_change_enable_can1, 494 Clock_busy_can1, 495 Clock_divider_can1); 496 497 Clock clock_cdbus(Source(mux_dev, Clock_source_cdbus), 498 Clock_gate_cdbus, 499 Clock_change_enable_cdbus, 500 Clock_busy_cdbus, 501 Clock_divider_cdbus); 502 503 Clock clock_cim(Source(mux_dev, Clock_source_cim), 504 Clock_gate_cim, 505 Clock_change_enable_cim, 506 Clock_busy_cim, 507 Clock_divider_cim); 508 509 Clock clock_cpu(Source(mux_core, Clock_source_cpu), 510 Gate_undefined, 511 Clock_change_enable_cpu, 512 Clock_busy_cpu, 513 Clock_divider_cpu); 514 515 Clock clock_ddr(Source(mux_core, Clock_source_ddr), 516 Clock_gate_ddr, 517 Clock_change_enable_ddr, 518 Clock_busy_ddr, 519 Clock_divider_ddr); 520 521 Clock clock_dma(Source(mux_pclock), Clock_gate_dma); 522 523 Clock clock_emac; 524 525 Clock clock_external; 526 527 Clock clock_hclock0(Source(mux_core, Clock_source_hclock0), 528 Clock_gate_ahb0, 529 Clock_change_enable_ahb0, 530 Busy_undefined, 531 Clock_divider_hclock0); 532 533 Clock clock_hclock2(Source(mux_ahb2_apb), 534 Clock_gate_apb0, 535 Clock_change_enable_ahb2, 536 Busy_undefined, 537 Clock_divider_hclock2); 538 539 Clock clock_hdmi; 540 541 Clock clock_i2c(Source(mux_pclock), Clock_gate_i2c0); 542 543 Clock clock_i2c0(Source(mux_pclock), Clock_gate_i2c0); 544 545 Clock clock_i2c1(Source(mux_pclock), Clock_gate_i2c1); 546 547 Clock clock_i2s; 548 549 Clock clock_i2s0_rx(Source(mux_i2s, Clock_source_i2s), 550 Clock_gate_i2s0_rx, 551 Clock_change_enable_i2s); 552 553 Clock clock_i2s0_tx(Source(mux_i2s, Clock_source_i2s), 554 Clock_gate_i2s0_tx, 555 Clock_change_enable_i2s); 556 557 Clock clock_kbc; 558 559 Clock clock_lcd; 560 561 Clock clock_lcd_pixel(Source(mux_dev, Clock_source_lcd), 562 Clock_gate_lcd_pixel, 563 Clock_change_enable_lcd, 564 Clock_busy_lcd, 565 Clock_divider_lcd); 566 567 Clock clock_mac(Source(mux_dev, Clock_source_mac), 568 Clock_gate_gmac0, 569 Clock_change_enable_mac, 570 Clock_busy_mac, 571 Clock_divider_mac); 572 573 Clock clock_main(Source(mux_core, Clock_source_main), 574 Clock_gate_main); 575 576 Clock clock_msc(Source(mux_dev, Clock_source_msc0), 577 Clock_gate_msc0, 578 Clock_change_enable_msc0, 579 Clock_busy_msc0, 580 Clock_divider_msc0); 581 582 Clock clock_msc0(Source(mux_dev, Clock_source_msc0), 583 Clock_gate_msc0, 584 Clock_change_enable_msc0, 585 Clock_busy_msc0, 586 Clock_divider_msc0); 587 588 Clock clock_msc1(Source(mux_dev, Clock_source_msc1), 589 Clock_gate_msc1, 590 Clock_change_enable_msc1, 591 Clock_busy_msc1, 592 Clock_divider_msc1); 593 594 Clock clock_none; 595 596 Clock clock_pclock(Source(mux_ahb2_apb), 597 Clock_gate_apb0, 598 Change_enable_undefined, 599 Busy_undefined, 600 Clock_divider_pclock); 601 602 Pll clock_pll_A(Source(mux_external), 603 Pll_enable_A, Pll_stable_A, Pll_bypass_A, 604 Pll_multiplier_A, Pll_input_division_A, 605 Pll_output_division0_A, Pll_output_division1_A); 606 607 Pll clock_pll_E(Source(mux_external), 608 Pll_enable_E, Pll_stable_E, Pll_bypass_E, 609 Pll_multiplier_E, Pll_input_division_E, 610 Pll_output_division0_E, Pll_output_division1_E); 611 612 Pll clock_pll_M(Source(mux_external), 613 Pll_enable_M, Pll_stable_M, Pll_bypass_M, 614 Pll_multiplier_M, Pll_input_division_M, 615 Pll_output_division0_M, Pll_output_division1_M); 616 617 Clock clock_pwm(Source(mux_dev, Clock_source_pwm), 618 Clock_gate_pwm, 619 Clock_change_enable_pwm, 620 Clock_busy_pwm, 621 Clock_divider_pwm); 622 623 Clock clock_pwm0(Source(mux_dev, Clock_source_pwm), 624 Clock_gate_pwm, 625 Clock_change_enable_pwm, 626 Clock_busy_pwm, 627 Clock_divider_pwm); 628 629 Clock clock_pwm1; 630 631 Clock clock_scc; 632 633 Clock clock_sfc(Source(mux_dev, Clock_source_sfc), 634 Clock_gate_sfc, 635 Clock_change_enable_sfc, 636 Clock_busy_sfc, 637 Clock_divider_sfc); 638 639 Clock clock_smb0; 640 641 Clock clock_smb1; 642 643 Clock clock_smb2; 644 645 Clock clock_smb3; 646 647 Clock clock_smb4; 648 649 Clock clock_ssi(Source(mux_dev, Clock_source_ssi), 650 Clock_gate_ssi0, 651 Clock_change_enable_ssi, 652 Clock_busy_ssi, 653 Clock_divider_ssi); 654 655 Clock clock_timer(Source(mux_pclock), Clock_gate_timer); 656 657 Clock clock_uart0(Source(mux_external), Clock_gate_uart0); 658 659 Clock clock_uart1(Source(mux_external), Clock_gate_uart1); 660 661 Clock clock_uart2(Source(mux_external), Clock_gate_uart2); 662 663 Clock clock_uart3(Source(mux_external), Clock_gate_uart3); 664 665 Clock clock_udc; 666 667 Clock clock_uhc; 668 669 Clock clock_uprt; 670 671 672 673 // Clock register. 674 675 static Clock_base *clocks[Clock_identifier_count] = { 676 &clock_ahb2_apb, 677 &clock_aic_bitclk, 678 &clock_aic_pclk, 679 &clock_can0, 680 &clock_can1, 681 &clock_cdbus, 682 &clock_cim, 683 &clock_cpu, 684 &clock_ddr, 685 &clock_dma, 686 &clock_emac, 687 &clock_external, 688 &clock_hclock0, 689 &clock_hclock2, 690 &clock_hdmi, 691 &clock_i2c, 692 &clock_i2c0, 693 &clock_i2c1, 694 &clock_i2s, 695 &clock_i2s0_rx, 696 &clock_i2s0_tx, 697 &clock_kbc, 698 &clock_lcd, 699 &clock_lcd_pixel, 700 &clock_mac, 701 &clock_main, 702 &clock_msc, 703 &clock_msc0, 704 &clock_msc1, 705 &clock_none, 706 &clock_pclock, 707 &clock_pll_A, 708 &clock_pll_E, 709 &clock_pll_M, 710 &clock_pwm, 711 &clock_pwm0, 712 &clock_pwm1, 713 &clock_scc, 714 &clock_sfc, 715 &clock_smb0, 716 &clock_smb1, 717 &clock_smb2, 718 &clock_smb3, 719 &clock_smb4, 720 &clock_ssi, 721 &clock_timer, 722 &clock_uart0, 723 &clock_uart1, 724 &clock_uart2, 725 &clock_uart3, 726 &clock_udc, 727 &clock_uhc, 728 &clock_uprt, 729 }; 730 731 732 733 // Register access. 734 735 Cpm_regs::Cpm_regs(l4_addr_t addr, uint32_t exclk_freq) 736 : exclk_freq(exclk_freq) 737 { 738 _regs = new Hw::Mmio_register_block<32>(addr); 739 } 740 741 // Utility methods. 742 743 uint32_t 744 Cpm_regs::get_field(uint32_t reg, uint32_t mask, uint8_t shift) 745 { 746 return (_regs[reg] & (mask << shift)) >> shift; 747 } 748 749 void 750 Cpm_regs::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) 751 { 752 _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); 753 } 754 755 756 757 // Field methods. 758 759 uint32_t 760 Field::get_field(Cpm_regs ®s) 761 { 762 if (defined) 763 return regs.get_field(reg, mask, bit); 764 else 765 return 0; 766 } 767 768 void 769 Field::set_field(Cpm_regs ®s, uint32_t value) 770 { 771 if (defined) 772 regs.set_field(reg, mask, bit, value); 773 } 774 775 776 777 // Clock sources. 778 779 enum Clock_identifiers 780 Mux::get_input(int num) 781 { 782 if (num < _num_inputs) 783 return _inputs[num]; 784 else 785 return Clock_undefined; 786 } 787 788 // Clock sources. 789 790 uint8_t 791 Source::get_source(Cpm_regs ®s) 792 { 793 if (_source.is_defined()) 794 return _source.get_field(regs); 795 else 796 return 0; 797 } 798 799 void 800 Source::set_source(Cpm_regs ®s, uint8_t source) 801 { 802 if (!_source.is_defined()) 803 return; 804 805 _source.set_field(regs, source); 806 } 807 808 // Clock source frequencies. 809 810 uint32_t 811 Source::get_frequency(Cpm_regs ®s) 812 { 813 // Return the external clock frequency without any input clock. 814 815 if (get_number() == 0) 816 return regs.exclk_freq; 817 818 // Clocks with one source yield that input frequency. 819 820 else if (get_number() == 1) 821 return clocks[get_input(0)]->get_frequency(regs); 822 823 // With multiple sources, obtain the selected source for the clock. 824 825 uint8_t source = get_source(regs); 826 enum Clock_identifiers input = get_input(source); 827 828 // Return the frequency of the source. 829 830 if (input != Clock_undefined) 831 return clocks[input]->get_frequency(regs); 832 else 833 return 0; 834 } 835 836 837 838 // Clock control. 839 840 int 841 Clock_base::have_clock(Cpm_regs ®s) 842 { 843 (void) regs; 844 return true; 845 } 846 847 void 848 Clock_base::start_clock(Cpm_regs ®s) 849 { 850 (void) regs; 851 } 852 853 void 854 Clock_base::stop_clock(Cpm_regs ®s) 855 { 856 (void) regs; 857 } 858 859 // Default divider. 860 861 uint32_t 862 Clock_base::get_divider(Cpm_regs ®s) 863 { 864 (void) regs; 865 return 1; 866 } 867 868 void 869 Clock_base::set_divider(Cpm_regs ®s, uint32_t division) 870 { 871 (void) regs; 872 (void) division; 873 } 874 875 // Clock sources. 876 877 uint8_t 878 Clock_base::get_source(Cpm_regs ®s) 879 { 880 return _source.get_source(regs); 881 } 882 883 void 884 Clock_base::set_source(Cpm_regs ®s, uint8_t source) 885 { 886 _source.set_source(regs, source); 887 } 888 889 // Clock source frequencies. 890 891 uint32_t 892 Clock_base::get_source_frequency(Cpm_regs ®s) 893 { 894 return _source.get_frequency(regs); 895 } 896 897 // Output clock frequencies. 898 899 uint32_t 900 Clock_base::get_frequency(Cpm_regs ®s) 901 { 902 return get_source_frequency(regs) / get_divider(regs); 903 } 904 905 906 907 // PLL-specific control. 908 909 int 910 Pll::have_pll(Cpm_regs ®s) 911 { 912 return _stable.get_field(regs); 913 } 914 915 int 916 Pll::pll_enabled(Cpm_regs ®s) 917 { 918 return _enable.get_field(regs); 919 } 920 921 int 922 Pll::pll_bypassed(Cpm_regs ®s) 923 { 924 return _bypass.get_field(regs); 925 } 926 927 // Clock control. 928 929 int 930 Pll::have_clock(Cpm_regs ®s) 931 { 932 return have_pll(regs) && pll_enabled(regs); 933 } 934 935 void 936 Pll::start_clock(Cpm_regs ®s) 937 { 938 _enable.set_field(regs, 1); 939 while (!have_pll(regs)); 940 } 941 942 void 943 Pll::stop_clock(Cpm_regs ®s) 944 { 945 _enable.set_field(regs, 0); 946 while (have_pll(regs)); 947 } 948 949 // Feedback (13-bit) multiplier. 950 951 uint16_t 952 Pll::get_multiplier(Cpm_regs ®s) 953 { 954 return _multiplier.get_field(regs) + 1; 955 } 956 957 void 958 Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier) 959 { 960 _multiplier.set_field(regs, multiplier - 1); 961 } 962 963 // Input (6-bit) divider. 964 965 uint8_t 966 Pll::get_input_division(Cpm_regs ®s) 967 { 968 return _input_division.get_field(regs) + 1; 969 } 970 971 void 972 Pll::set_input_division(Cpm_regs ®s, uint8_t divider) 973 { 974 _input_division.set_field(regs, divider - 1); 975 } 976 977 // Output (dual 3-bit) dividers. 978 979 uint8_t 980 Pll::get_output_division(Cpm_regs ®s) 981 { 982 uint8_t d0 = _output_division0.get_field(regs); 983 uint8_t d1 = _output_division1.get_field(regs); 984 985 return d0 * d1; 986 } 987 988 void 989 Pll::set_output_division(Cpm_regs ®s, uint8_t divider) 990 { 991 // Assert 1 as a minimum. 992 // Divider 0 must be less than or equal to divider 1. 993 994 uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1)); 995 uint8_t d1 = divider / d0; 996 997 _output_division0.set_field(regs, d0); 998 _output_division1.set_field(regs, d1); 999 } 1000 1001 uint32_t 1002 Pll::get_frequency(Cpm_regs ®s) 1003 { 1004 // Test for PLL enable and not PLL bypass. 1005 1006 if (pll_enabled(regs)) 1007 { 1008 if (!pll_bypassed(regs)) 1009 return (get_source_frequency(regs) * get_multiplier(regs)) / 1010 (get_input_division(regs) * get_output_division(regs)); 1011 else 1012 return get_source_frequency(regs); 1013 } 1014 else 1015 return 0; 1016 } 1017 1018 void 1019 Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) 1020 { 1021 set_multiplier(regs, multiplier); 1022 set_input_division(regs, in_divider); 1023 set_output_division(regs, out_divider); 1024 1025 if (pll_enabled(regs) && !pll_bypassed(regs)) 1026 while (!have_pll(regs)); 1027 } 1028 1029 1030 1031 // Clock control. 1032 1033 void 1034 Clock::change_disable(Cpm_regs ®s) 1035 { 1036 if (_change_enable.is_defined()) 1037 _change_enable.set_field(regs, 0); 1038 } 1039 1040 void 1041 Clock::change_enable(Cpm_regs ®s) 1042 { 1043 if (_change_enable.is_defined()) 1044 _change_enable.set_field(regs, 1); 1045 } 1046 1047 int 1048 Clock::have_clock(Cpm_regs ®s) 1049 { 1050 if (_gate.is_defined()) 1051 return !_gate.get_field(regs); 1052 else 1053 return true; 1054 } 1055 1056 void 1057 Clock::start_clock(Cpm_regs ®s) 1058 { 1059 if (_gate.is_defined()) 1060 _gate.set_field(regs, 0); 1061 } 1062 1063 void 1064 Clock::stop_clock(Cpm_regs ®s) 1065 { 1066 if (_gate.is_defined()) 1067 _gate.set_field(regs, 1); 1068 } 1069 1070 void 1071 Clock::wait_busy(Cpm_regs ®s) 1072 { 1073 if (_busy.is_defined()) 1074 while (_busy.get_field(regs)); 1075 } 1076 1077 1078 1079 // Clock dividers. 1080 1081 uint32_t 1082 Clock::get_divider(Cpm_regs ®s) 1083 { 1084 if (_divider.is_defined()) 1085 return _divider.get_field(regs) + 1; 1086 else 1087 return 1; 1088 } 1089 1090 void 1091 Clock::set_divider(Cpm_regs ®s, uint32_t division) 1092 { 1093 if (!_divider.is_defined()) 1094 return; 1095 1096 change_enable(regs); 1097 _divider.set_field(regs, division - 1); 1098 wait_busy(regs); 1099 change_disable(regs); 1100 } 1101 1102 void 1103 Clock::set_source(Cpm_regs ®s, uint8_t source) 1104 { 1105 change_enable(regs); 1106 Clock_base::set_source(regs, source); 1107 wait_busy(regs); 1108 change_disable(regs); 1109 } 1110 1111 1112 1113 // If implemented as a Hw::Device, various properties would be 1114 // initialised in the constructor and obtained from the device tree 1115 // definitions. 1116 1117 Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq) 1118 : _cpm_regs(addr, exclk_freq) 1119 { 1120 // add_cid("cpm"); 1121 // add_cid("cpm-x1600"); 1122 // register_property("exclk_freq", &exclk_freq); 1123 } 1124 1125 int 1126 Cpm_x1600_chip::have_clock(enum Clock_identifiers clock) 1127 { 1128 return clocks[clock]->have_clock(_cpm_regs); 1129 } 1130 1131 void 1132 Cpm_x1600_chip::start_clock(enum Clock_identifiers clock) 1133 { 1134 clocks[clock]->start_clock(_cpm_regs); 1135 } 1136 1137 void 1138 Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock) 1139 { 1140 clocks[clock]->stop_clock(_cpm_regs); 1141 } 1142 1143 uint32_t 1144 Cpm_x1600_chip::get_divider(enum Clock_identifiers clock) 1145 { 1146 return clocks[clock]->get_divider(_cpm_regs); 1147 } 1148 1149 void 1150 Cpm_x1600_chip::set_divider(enum Clock_identifiers clock, uint32_t division) 1151 { 1152 clocks[clock]->set_divider(_cpm_regs, division); 1153 } 1154 1155 uint8_t 1156 Cpm_x1600_chip::get_source(enum Clock_identifiers clock) 1157 { 1158 return clocks[clock]->get_source(_cpm_regs); 1159 } 1160 1161 void 1162 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source) 1163 { 1164 clocks[clock]->set_source(_cpm_regs, source); 1165 } 1166 1167 uint32_t 1168 Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock) 1169 { 1170 return clocks[clock]->get_source_frequency(_cpm_regs); 1171 } 1172 1173 uint32_t 1174 Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock) 1175 { 1176 return clocks[clock]->get_frequency(_cpm_regs); 1177 } 1178 1179 void 1180 Cpm_x1600_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) 1181 { 1182 switch (clock) 1183 { 1184 // The pixel frequency is based on the selected clock source (SCLK_A, MPLL or 1185 // EPLL). 1186 1187 case Clock_lcd_pixel: 1188 { 1189 1190 // Switch to the MPLL and attempt to set the divider. 1191 1192 Clock_base *lcd = clocks[Clock_lcd_pixel]; 1193 Clock_base *pll = clocks[Clock_pll_M]; 1194 1195 lcd->set_source(_cpm_regs, Source_mME_pll_M); 1196 pll->start_clock(_cpm_regs); 1197 lcd->set_divider(_cpm_regs, lcd->get_source_frequency(_cpm_regs) / frequency); 1198 break; 1199 } 1200 1201 default: 1202 break; 1203 } 1204 } 1205 1206 void 1207 Cpm_x1600_chip::set_pll_parameters(enum Clock_identifiers clock, uint16_t multiplier, 1208 uint8_t in_divider, uint8_t out_divider) 1209 { 1210 Pll *pll = dynamic_cast<Pll *>(clocks[clock]); 1211 1212 pll->set_pll_parameters(_cpm_regs, multiplier, in_divider, out_divider); 1213 } 1214 1215 1216 1217 // C language interface functions. 1218 1219 void 1220 *x1600_cpm_init(l4_addr_t cpm_base) 1221 { 1222 /* Initialise the clock and power management peripheral with the 1223 register memory region and a 24MHz EXCLK frequency. */ 1224 1225 return (void *) new Cpm_x1600_chip(cpm_base, 24000000); 1226 } 1227 1228 int 1229 x1600_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 1230 { 1231 return static_cast<Cpm_x1600_chip *>(cpm)->have_clock(clock); 1232 } 1233 1234 void 1235 x1600_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 1236 { 1237 static_cast<Cpm_x1600_chip *>(cpm)->start_clock(clock); 1238 } 1239 1240 void 1241 x1600_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 1242 { 1243 static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock); 1244 } 1245 1246 uint32_t 1247 x1600_cpm_get_divider(void *cpm, enum Clock_identifiers clock) 1248 { 1249 return static_cast<Cpm_x1600_chip *>(cpm)->get_divider(clock); 1250 } 1251 1252 void 1253 x1600_cpm_set_divider(void *cpm, enum Clock_identifiers clock, uint32_t divider) 1254 { 1255 return static_cast<Cpm_x1600_chip *>(cpm)->set_divider(clock, divider); 1256 } 1257 1258 uint8_t 1259 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock) 1260 { 1261 return static_cast<Cpm_x1600_chip *>(cpm)->get_source(clock); 1262 } 1263 1264 void 1265 x1600_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 1266 { 1267 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source); 1268 } 1269 1270 uint32_t 1271 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 1272 { 1273 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock); 1274 } 1275 1276 uint32_t 1277 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 1278 { 1279 return static_cast<Cpm_x1600_chip *>(cpm)->get_frequency(clock); 1280 } 1281 1282 void 1283 x1600_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency) 1284 { 1285 static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency); 1286 } 1287 1288 void 1289 x1600_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) 1290 { 1291 static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Clock_pll_M, multiplier, in_divider, out_divider); 1292 }