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 Ddr_divider = 0x02c, // DDRCDR 42 Mac_divider = 0x054, // MACCDR 43 I2s_divider0 = 0x060, // I2SCDR 44 I2s_divider1 = 0x070, // I2S1CDR 45 Lcd_divider = 0x064, // LPCDR 46 Msc_divider0 = 0x068, // MSC0CDR 47 Msc_divider1 = 0x0a4, // MSC1CDR 48 Sfc_divider = 0x074, // SFCCDR 49 Ssi_divider = 0x05c, // SSICDR 50 Cim_divider = 0x078, // CIMCDR 51 Pwm_divider = 0x06c, // PWMCDR 52 Can_divider0 = 0x0a0, // CAN0CDR 53 Can_divider1 = 0x0a8, // CAN1CDR 54 Cdbus_divider = 0x0ac, // CDBUSCDR 55 Macphy0_divider = 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 // Special value 75 76 Reg_undefined = 0xfff, 77 }; 78 79 enum Clock_source_bits : unsigned 80 { 81 // Clock_control 82 83 Clock_source_main = 30, // SEL_SRC (output to SCLK_A) 84 Clock_source_cpu = 28, // SEL_CPLL (output to CCLK) 85 Clock_source_hclock0 = 26, // SEL_H0PLL (output to AHB0) 86 Clock_source_hclock2 = 24, // SEL_H2PLL (output to AHB2) 87 88 // Divider registers 89 90 Clock_source_can0 = 30, // CA0CS 91 Clock_source_can1 = 30, // CA1CS 92 Clock_source_cdbus = 30, // CDCS 93 Clock_source_cim = 30, // CIMPCS 94 Clock_source_ddr = 30, // DCS 95 Clock_source_i2s = 31, // I2PCS 96 Clock_source_lcd = 30, // LPCS 97 Clock_source_mac = 30, // MACPCS 98 Clock_source_msc0 = 30, // MPCS 99 Clock_source_msc1 = 30, // MPCS 100 Clock_source_pwm = 30, // PWMPCS 101 Clock_source_sfc = 30, // SFCS 102 Clock_source_ssi = 30, // SPCS 103 104 // Special value 105 106 Clock_source_undefined = 32, 107 }; 108 109 enum Clock_source_values : unsigned 110 { 111 Source_mME_main = 0, 112 Source_mME_pll_M = 1, 113 Source_mME_pll_E = 2, 114 115 // Special value 116 117 Source_mask = 0x3, 118 }; 119 120 enum Clock_gate_bits : unsigned 121 { 122 // Clock_control 123 124 Clock_gate_main = 23, // GATE_SCLKA 125 126 // Clock_gate0 127 128 Clock_gate_ddr = 31, // DDR 129 Clock_gate_ahb0 = 29, // AHB0 130 Clock_gate_apb0 = 28, // APB0 131 Clock_gate_rtc = 27, // RTC 132 Clock_gate_aes = 24, // AES 133 Clock_gate_lcd_pixel = 23, // LCD 134 Clock_gate_cim = 22, // CIM 135 Clock_gate_dma = 21, // PDMA 136 Clock_gate_ost = 20, // OST 137 Clock_gate_ssi0 = 19, // SSI0 138 Clock_gate_timer = 18, // TCU 139 Clock_gate_dtrng = 17, // DTRNG 140 Clock_gate_uart2 = 16, // UART2 141 Clock_gate_uart1 = 15, // UART1 142 Clock_gate_uart0 = 14, // UART0 143 Clock_gate_sadc = 13, // SADC 144 Clock_gate_audio = 11, // AUDIO 145 Clock_gate_ssi_slv = 10, // SSI_SLV 146 Clock_gate_i2c1 = 8, // I2C1 147 Clock_gate_i2c0 = 7, // I2C0 148 Clock_gate_msc1 = 5, // MSC1 149 Clock_gate_msc0 = 4, // MSC0 150 Clock_gate_otg = 3, // OTG 151 Clock_gate_sfc = 2, // SFC 152 Clock_gate_efuse = 1, // EFUSE 153 Clock_gate_nemc = 0, // NEMC 154 155 // Clock_gate1 156 157 Clock_gate_arb = 30, // ARB 158 Clock_gate_mipi_csi = 28, // MIPI_CSI 159 Clock_gate_intc = 26, // INTC 160 Clock_gate_gmac0 = 23, // GMAC0 161 Clock_gate_uart3 = 16, // UART3 162 Clock_gate_i2s0_tx = 9, // I2S0_dev_tclk 163 Clock_gate_i2s0_rx = 8, // I2S0_dev_rclk 164 Clock_gate_hash = 6, // HASH 165 Clock_gate_pwm = 5, // PWM 166 Clock_gate_cdbus = 2, // CDBUS 167 Clock_gate_can1 = 1, // CAN1 168 Clock_gate_can0 = 0, // CAN0 169 170 // Special value 171 172 Clock_gate_undefined = 32, 173 }; 174 175 enum Clock_change_enable_bits : unsigned 176 { 177 Clock_change_enable_cpu = 22, 178 Clock_change_enable_ahb0 = 21, 179 Clock_change_enable_ahb2 = 20, 180 Clock_change_enable_ddr = 29, 181 Clock_change_enable_mac = 29, 182 Clock_change_enable_i2s = 29, 183 Clock_change_enable_lcd = 29, 184 Clock_change_enable_msc0 = 29, 185 Clock_change_enable_msc1 = 29, 186 Clock_change_enable_sfc = 29, 187 Clock_change_enable_ssi = 29, 188 Clock_change_enable_cim = 29, 189 Clock_change_enable_pwm = 29, 190 Clock_change_enable_can0 = 29, 191 Clock_change_enable_can1 = 29, 192 Clock_change_enable_cdbus = 29, 193 194 // Special value 195 196 Clock_change_enable_undefined = 32, 197 }; 198 199 enum Clock_busy_bits : unsigned 200 { 201 Clock_busy_cpu = 0, 202 Clock_busy_ddr = 28, 203 Clock_busy_mac = 28, 204 Clock_busy_lcd = 28, 205 Clock_busy_msc0 = 28, 206 Clock_busy_msc1 = 28, 207 Clock_busy_sfc = 28, 208 Clock_busy_ssi = 28, 209 Clock_busy_cim = 28, 210 Clock_busy_pwm = 28, 211 Clock_busy_can0 = 28, 212 Clock_busy_can1 = 28, 213 Clock_busy_cdbus = 28, 214 215 // Special value 216 217 Clock_busy_undefined = 32, 218 }; 219 220 enum Clock_divider_bits : unsigned 221 { 222 Clock_divider_can0 = 0, // CAN0CDR 223 Clock_divider_can1 = 0, // CAN1CDR 224 Clock_divider_cdbus = 0, // CDBUSCDR 225 Clock_divider_cim = 0, // CIMCDR 226 Clock_divider_cpu = 0, // CDIV 227 Clock_divider_ddr = 0, // DDRCDR 228 Clock_divider_hclock0 = 8, // H0DIV (fast AHB peripherals) 229 Clock_divider_hclock2 = 12, // H2DIV (fast AHB peripherals) 230 Clock_divider_l2cache = 4, // L2CDIV 231 Clock_divider_lcd = 0, // LPCDR 232 Clock_divider_mac = 0, // MACCDR 233 Clock_divider_msc0 = 0, // MSC0CDR 234 Clock_divider_msc1 = 0, // MSC1CDR 235 Clock_divider_pclock = 16, // PDIV (slow APB peripherals) 236 Clock_divider_pwm = 0, // PWMCDR 237 Clock_divider_sfc = 0, // SFCCDR 238 Clock_divider_ssi = 0, // SSICDR 239 240 // Special value 241 242 Clock_divider_undefined = 32, 243 }; 244 245 enum Pll_bits : unsigned 246 { 247 // Pll_control_A, Pll_control_M, Pll_control_E 248 249 Pll_multiplier = 20, // xPLLM 250 Pll_input_division = 14, // xPLLN 251 Pll_output_division1 = 11, // xPLLOD1 252 Pll_output_division0 = 8, // xPLLOD0 253 Pll_stable = 3, // xPLL_ON 254 Pll_enabled = 0, // xPLLEN 255 }; 256 257 enum Pll_bypass_bits : unsigned 258 { 259 Pll_bypass_A = 30, // APLL_BP 260 Pll_bypass_M = 28, // MPLL_BP 261 Pll_bypass_E = 26, // EPLL_BP 262 }; 263 264 265 266 // Common clock abstraction. 267 268 class Clock_base 269 { 270 protected: 271 272 // Clock sources and source selection. 273 274 int num_inputs; 275 enum Clock_identifiers *inputs; 276 uint32_t source_reg; 277 enum Clock_source_bits source_bit; 278 279 public: 280 explicit Clock_base(int num_inputs = 0, 281 enum Clock_identifiers inputs[] = NULL, 282 uint32_t source_reg = Reg_undefined, 283 enum Clock_source_bits source_bit = Clock_source_undefined) 284 : num_inputs(num_inputs), inputs(inputs), 285 source_reg(source_reg), source_bit(source_bit) 286 { 287 } 288 289 // Clock control. 290 291 virtual int have_clock(Cpm_regs ®s); 292 virtual void start_clock(Cpm_regs ®s); 293 virtual void stop_clock(Cpm_regs ®s); 294 295 // Clock divider. 296 297 virtual uint32_t get_divider(Cpm_regs ®s); 298 virtual void set_divider(Cpm_regs ®s, uint32_t division); 299 300 // Clock source. 301 302 virtual uint8_t get_source(Cpm_regs ®s); 303 virtual void set_source(Cpm_regs ®s, uint8_t source); 304 305 // Clock source frequency. 306 307 virtual uint32_t get_source_frequency(Cpm_regs ®s); 308 309 // Output frequency. 310 311 virtual uint32_t get_frequency(Cpm_regs ®s); 312 }; 313 314 315 316 // PLL descriptions. 317 318 class Pll : public Clock_base 319 { 320 uint32_t control_reg; 321 enum Pll_bypass_bits bypass_bit; 322 323 public: 324 explicit Pll(int num_inputs, enum Clock_identifiers inputs[], 325 uint32_t control_reg, enum Pll_bypass_bits bypass_bit) 326 : Clock_base(num_inputs, inputs), control_reg(control_reg), bypass_bit(bypass_bit) 327 { 328 } 329 330 // PLL_specific control. 331 332 int have_pll(Cpm_regs ®s); 333 int pll_enabled(Cpm_regs ®s); 334 int pll_bypassed(Cpm_regs ®s); 335 336 // Clock control. 337 338 int have_clock(Cpm_regs ®s); 339 void start_clock(Cpm_regs ®s); 340 void stop_clock(Cpm_regs ®s); 341 342 // General frequency modifiers. 343 344 uint16_t get_multiplier(Cpm_regs ®s); 345 void set_multiplier(Cpm_regs ®s, uint16_t multiplier); 346 uint8_t get_input_division(Cpm_regs ®s); 347 void set_input_division(Cpm_regs ®s, uint8_t divider); 348 uint8_t get_output_division(Cpm_regs ®s); 349 void set_output_division(Cpm_regs ®s, uint8_t divider); 350 351 // PLL output frequency. 352 353 uint32_t get_frequency(Cpm_regs ®s); 354 355 // Other operations. 356 357 void set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, 358 uint8_t in_divider, uint8_t out_divider); 359 }; 360 361 362 363 // Clock descriptions. 364 365 class Clock : public Clock_base 366 { 367 uint32_t gate_reg; 368 enum Clock_gate_bits gate_bit; 369 uint32_t change_enable_reg; 370 enum Clock_change_enable_bits change_enable_bit; 371 uint32_t busy_reg; 372 enum Clock_busy_bits busy_bit; 373 uint32_t divider_reg; 374 enum Clock_divider_bits divider_bit; 375 uint32_t divider_mask; 376 377 // Clock control. 378 379 void change_disable(Cpm_regs ®s); 380 void change_enable(Cpm_regs ®s); 381 void wait_busy(Cpm_regs ®s); 382 383 public: 384 explicit Clock(int num_inputs = 0, 385 enum Clock_identifiers inputs[] = NULL, 386 uint32_t source_reg = Reg_undefined, 387 enum Clock_source_bits source_bit = Clock_source_undefined, 388 uint32_t gate_reg = Reg_undefined, 389 enum Clock_gate_bits gate_bit = Clock_gate_undefined, 390 uint32_t change_enable_reg = Reg_undefined, 391 enum Clock_change_enable_bits change_enable_bit = Clock_change_enable_undefined, 392 uint32_t busy_reg = Reg_undefined, 393 enum Clock_busy_bits busy_bit = Clock_busy_undefined, 394 uint32_t divider_reg = Reg_undefined, 395 enum Clock_divider_bits divider_bit = Clock_divider_undefined, 396 uint32_t divider_mask = 0) 397 : Clock_base(num_inputs, inputs, source_reg, source_bit), 398 gate_reg(gate_reg), gate_bit(gate_bit), 399 change_enable_reg(change_enable_reg), change_enable_bit(change_enable_bit), 400 busy_reg(busy_reg), busy_bit(busy_bit), 401 divider_reg(divider_reg), divider_bit(divider_bit), divider_mask(divider_mask) 402 { 403 } 404 405 // Clock control. 406 407 int have_clock(Cpm_regs ®s); 408 void start_clock(Cpm_regs ®s); 409 void stop_clock(Cpm_regs ®s); 410 411 // Clock divider. 412 413 uint32_t get_divider(Cpm_regs ®s); 414 void set_divider(Cpm_regs ®s, uint32_t division); 415 416 // Clock source. 417 418 void set_source(Cpm_regs ®s, uint8_t source); 419 }; 420 421 422 423 // Clock instances. 424 425 #define Clock_inputs(...) ((enum Clock_identifiers []) {__VA_ARGS__}) 426 427 Clock clock_ahb2_apb(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M), 428 Clock_control, Clock_source_hclock2); 429 430 Clock clock_aic_bitclk; 431 432 Clock clock_aic_pclk; 433 434 Clock clock_can0(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external), 435 Can_divider0, Clock_source_can0, 436 Clock_gate1, Clock_gate_can0, 437 Can_divider0, Clock_change_enable_can0, 438 Can_divider0, Clock_busy_can0, 439 Can_divider0, Clock_divider_can0, 0xff); 440 441 Clock clock_can1(4, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external), 442 Can_divider1, Clock_source_can1, 443 Clock_gate1, Clock_gate_can1, 444 Can_divider1, Clock_change_enable_can1, 445 Can_divider1, Clock_busy_can1, 446 Can_divider1, Clock_divider_can1, 0xff); 447 448 Clock clock_cdbus(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 449 Cdbus_divider, Clock_source_cdbus, 450 Clock_gate1, Clock_gate_cdbus, 451 Cdbus_divider, Clock_change_enable_cdbus, 452 Cdbus_divider, Clock_busy_cdbus, 453 Cdbus_divider, Clock_divider_cdbus, 0xff); 454 455 Clock clock_cim(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 456 Cim_divider, Clock_source_cim, 457 Clock_gate0, Clock_gate_cim, 458 Cim_divider, Clock_change_enable_cim, 459 Cim_divider, Clock_busy_cim, 460 Cim_divider, Clock_divider_cim, 0xff); 461 462 Clock clock_cpu(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M), 463 Clock_control, Clock_source_cpu, 464 Reg_undefined, Clock_gate_undefined, 465 Clock_control, Clock_change_enable_cpu, 466 Clock_status, Clock_busy_cpu, 467 Clock_control, Clock_divider_cpu, 0x0f); 468 469 Clock clock_ddr(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M), 470 Ddr_divider, Clock_source_ddr, 471 Clock_gate0, Clock_gate_ddr, 472 Ddr_divider, Clock_change_enable_ddr, 473 Ddr_divider, Clock_busy_ddr, 474 Ddr_divider, Clock_divider_ddr, 0x0f); 475 476 Clock clock_dma(1, Clock_inputs(Clock_pclock), 477 Reg_undefined, Clock_source_undefined, 478 Clock_gate0, Clock_gate_dma); 479 480 Clock clock_emac; 481 482 Clock clock_external; 483 484 Clock clock_hclock0(3, Clock_inputs(Clock_none, Clock_main, Clock_pll_M), 485 Clock_control, Clock_source_hclock0, 486 Clock_gate0, Clock_gate_ahb0, 487 Clock_control, Clock_change_enable_ahb0, 488 Reg_undefined, Clock_busy_undefined, 489 Clock_control, Clock_divider_hclock0, 0x0f); 490 491 Clock clock_hclock2(1, Clock_inputs(Clock_ahb2_apb), 492 Reg_undefined, Clock_source_undefined, 493 Clock_gate0, Clock_gate_apb0, 494 Clock_control, Clock_change_enable_ahb2, 495 Reg_undefined, Clock_busy_undefined, 496 Clock_control, Clock_divider_hclock2, 0x0f); 497 498 Clock clock_hdmi; 499 500 Clock clock_i2c(1, Clock_inputs(Clock_pclock), 501 Reg_undefined, Clock_source_undefined, 502 Clock_gate0, Clock_gate_i2c0); 503 504 Clock clock_i2c0(1, Clock_inputs(Clock_pclock), 505 Reg_undefined, Clock_source_undefined, 506 Clock_gate0, Clock_gate_i2c0); 507 508 Clock clock_i2c1(1, Clock_inputs(Clock_pclock), 509 Reg_undefined, Clock_source_undefined, 510 Clock_gate0, Clock_gate_i2c1); 511 512 Clock clock_i2s; 513 514 Clock clock_i2s0_rx(2, Clock_inputs(Clock_main, Clock_pll_E), 515 I2s_divider0, Clock_source_i2s, 516 Clock_gate1, Clock_gate_i2s0_rx, 517 I2s_divider0, Clock_change_enable_i2s); 518 519 Clock clock_i2s0_tx(2, Clock_inputs(Clock_main, Clock_pll_E), 520 I2s_divider0, Clock_source_i2s, 521 Clock_gate1, Clock_gate_i2s0_tx, 522 I2s_divider0, Clock_change_enable_i2s); 523 524 Clock clock_kbc; 525 526 Clock clock_lcd; 527 528 Clock clock_lcd_pixel(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 529 Lcd_divider, Clock_source_lcd, 530 Clock_gate0, Clock_gate_lcd_pixel, 531 Lcd_divider, Clock_change_enable_lcd, 532 Lcd_divider, Clock_busy_lcd, 533 Lcd_divider, Clock_divider_lcd, 0xff); 534 535 Clock clock_mac(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 536 Mac_divider, Clock_source_mac, 537 Clock_gate1, Clock_gate_gmac0, 538 Mac_divider, Clock_change_enable_mac, 539 Mac_divider, Clock_busy_mac, 540 Mac_divider, Clock_divider_mac, 0xff); 541 542 Clock clock_main(3, Clock_inputs(Clock_none, Clock_external, Clock_pll_A), 543 Clock_control, Clock_source_main, 544 Clock_control, Clock_gate_main); 545 546 Clock clock_msc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 547 Msc_divider0, Clock_source_msc0, 548 Clock_gate0, Clock_gate_msc0, 549 Msc_divider0, Clock_change_enable_msc0, 550 Msc_divider0, Clock_busy_msc0, 551 Msc_divider0, Clock_divider_msc0, 0xff); 552 553 Clock clock_msc0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 554 Msc_divider0, Clock_source_msc0, 555 Clock_gate0, Clock_gate_msc0, 556 Msc_divider0, Clock_change_enable_msc0, 557 Msc_divider0, Clock_busy_msc0, 558 Msc_divider0, Clock_divider_msc0, 0xff); 559 560 Clock clock_msc1(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 561 Msc_divider1, Clock_source_msc1, 562 Clock_gate0, Clock_gate_msc1, 563 Msc_divider1, Clock_change_enable_msc1, 564 Msc_divider1, Clock_busy_msc1, 565 Msc_divider1, Clock_divider_msc1, 0xff); 566 567 Clock clock_none; 568 569 Clock clock_pclock(1, Clock_inputs(Clock_ahb2_apb), 570 Reg_undefined, Clock_source_undefined, 571 Clock_gate0, Clock_gate_apb0, 572 Reg_undefined, Clock_change_enable_undefined, 573 Reg_undefined, Clock_busy_undefined, 574 Clock_control, Clock_divider_pclock, 0x0f); 575 576 Pll clock_pll_A(1, Clock_inputs(Clock_external), 577 Pll_control_A, Pll_bypass_A); 578 579 Pll clock_pll_E(1, Clock_inputs(Clock_external), 580 Pll_control_E, Pll_bypass_E); 581 582 Pll clock_pll_M(1, Clock_inputs(Clock_external), 583 Pll_control_M, Pll_bypass_M); 584 585 Clock clock_pwm(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 586 Pwm_divider, Clock_source_pwm, 587 Clock_gate1, Clock_gate_pwm, 588 Pwm_divider, Clock_change_enable_pwm, 589 Pwm_divider, Clock_busy_pwm, 590 Pwm_divider, Clock_divider_pwm, 0x0f); 591 592 Clock clock_pwm0(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 593 Pwm_divider, Clock_source_pwm, 594 Clock_gate1, Clock_gate_pwm, 595 Pwm_divider, Clock_change_enable_pwm, 596 Pwm_divider, Clock_busy_pwm, 597 Pwm_divider, Clock_divider_pwm, 0x0f); 598 599 Clock clock_pwm1; 600 601 Clock clock_scc; 602 603 Clock clock_sfc(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 604 Sfc_divider, Clock_source_sfc, 605 Clock_gate0, Clock_gate_sfc, 606 Sfc_divider, Clock_change_enable_sfc, 607 Sfc_divider, Clock_busy_sfc, 608 Sfc_divider, Clock_divider_sfc, 0xff); 609 610 Clock clock_smb0; 611 612 Clock clock_smb1; 613 614 Clock clock_smb2; 615 616 Clock clock_smb3; 617 618 Clock clock_smb4; 619 620 Clock clock_ssi(3, Clock_inputs(Clock_main, Clock_pll_M, Clock_pll_E), 621 Ssi_divider, Clock_source_ssi, 622 Clock_gate0, Clock_gate_ssi0, 623 Ssi_divider, Clock_change_enable_ssi, 624 Ssi_divider, Clock_busy_ssi, 625 Ssi_divider, Clock_divider_ssi, 0xff); 626 627 Clock clock_timer(1, Clock_inputs(Clock_pclock), 628 Reg_undefined, Clock_source_undefined, 629 Clock_gate0, Clock_gate_timer); 630 631 Clock clock_uart0(1, Clock_inputs(Clock_external), 632 Reg_undefined, Clock_source_undefined, 633 Clock_gate0, Clock_gate_uart0); 634 635 Clock clock_uart1(1, Clock_inputs(Clock_external), 636 Reg_undefined, Clock_source_undefined, 637 Clock_gate0, Clock_gate_uart1); 638 639 Clock clock_uart2(1, Clock_inputs(Clock_external), 640 Reg_undefined, Clock_source_undefined, 641 Clock_gate0, Clock_gate_uart2); 642 643 Clock clock_uart3(1, Clock_inputs(Clock_external), 644 Reg_undefined, Clock_source_undefined, 645 Clock_gate1, Clock_gate_uart3); 646 647 Clock clock_udc; 648 649 Clock clock_uhc; 650 651 Clock clock_uprt; 652 653 654 655 // Clock register. 656 657 static Clock_base *clocks[Clock_identifier_count] = { 658 &clock_ahb2_apb, 659 &clock_aic_bitclk, 660 &clock_aic_pclk, 661 &clock_can0, 662 &clock_can1, 663 &clock_cdbus, 664 &clock_cim, 665 &clock_cpu, 666 &clock_ddr, 667 &clock_dma, 668 &clock_emac, 669 &clock_external, 670 &clock_hclock0, 671 &clock_hclock2, 672 &clock_hdmi, 673 &clock_i2c, 674 &clock_i2c0, 675 &clock_i2c1, 676 &clock_i2s, 677 &clock_i2s0_rx, 678 &clock_i2s0_tx, 679 &clock_kbc, 680 &clock_lcd, 681 &clock_lcd_pixel, 682 &clock_mac, 683 &clock_main, 684 &clock_msc, 685 &clock_msc0, 686 &clock_msc1, 687 &clock_none, 688 &clock_pclock, 689 &clock_pll_A, 690 &clock_pll_E, 691 &clock_pll_M, 692 &clock_pwm, 693 &clock_pwm0, 694 &clock_pwm1, 695 &clock_scc, 696 &clock_sfc, 697 &clock_smb0, 698 &clock_smb1, 699 &clock_smb2, 700 &clock_smb3, 701 &clock_smb4, 702 &clock_ssi, 703 &clock_timer, 704 &clock_uart0, 705 &clock_uart1, 706 &clock_uart2, 707 &clock_uart3, 708 &clock_udc, 709 &clock_uhc, 710 &clock_uprt, 711 }; 712 713 714 715 // Register access. 716 717 Cpm_regs::Cpm_regs(l4_addr_t addr, uint32_t exclk_freq) 718 : exclk_freq(exclk_freq) 719 { 720 _regs = new Hw::Mmio_register_block<32>(addr); 721 } 722 723 // Utility methods. 724 725 uint32_t 726 Cpm_regs::get_field(uint32_t reg, uint32_t mask, uint8_t shift) 727 { 728 return (_regs[reg] & (mask << shift)) >> shift; 729 } 730 731 void 732 Cpm_regs::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) 733 { 734 _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); 735 } 736 737 738 739 // Clock control. 740 741 int 742 Clock_base::have_clock(Cpm_regs ®s) 743 { 744 (void) regs; 745 return true; 746 } 747 748 void 749 Clock_base::start_clock(Cpm_regs ®s) 750 { 751 (void) regs; 752 } 753 754 void 755 Clock_base::stop_clock(Cpm_regs ®s) 756 { 757 (void) regs; 758 } 759 760 // Default divider. 761 762 uint32_t 763 Clock_base::get_divider(Cpm_regs ®s) 764 { 765 (void) regs; 766 return 1; 767 } 768 769 void 770 Clock_base::set_divider(Cpm_regs ®s, uint32_t division) 771 { 772 (void) regs; 773 (void) division; 774 } 775 776 // Clock sources. 777 778 uint8_t 779 Clock_base::get_source(Cpm_regs ®s) 780 { 781 if (source_bit != Clock_source_undefined) 782 return regs.get_field(source_reg, Source_mask, source_bit); 783 else 784 return 0; 785 } 786 787 void 788 Clock_base::set_source(Cpm_regs ®s, uint8_t source) 789 { 790 if (source_bit == Clock_source_undefined) 791 return; 792 793 regs.set_field(source_reg, Source_mask, source_bit, source); 794 } 795 796 // Clock source frequencies. 797 798 uint32_t 799 Clock_base::get_source_frequency(Cpm_regs ®s) 800 { 801 // Return the external clock frequency without any input clock. 802 803 if (num_inputs == 0) 804 return regs.exclk_freq; 805 806 // Clocks with one source yield that input frequency. 807 808 else if (num_inputs == 1) 809 return clocks[inputs[0]]->get_frequency(regs); 810 811 // With multiple sources, obtain the selected source for the clock. 812 813 uint8_t source = get_source(regs); 814 815 // Return the frequency of the source. 816 817 if (source < num_inputs) 818 return clocks[inputs[source]]->get_frequency(regs); 819 else 820 return 0; 821 } 822 823 // Output clock frequencies. 824 825 uint32_t 826 Clock_base::get_frequency(Cpm_regs ®s) 827 { 828 return get_source_frequency(regs) / get_divider(regs); 829 } 830 831 832 833 // PLL-specific control. 834 835 int 836 Pll::have_pll(Cpm_regs ®s) 837 { 838 return regs.get_field(control_reg, 1, Pll_stable); 839 } 840 841 int 842 Pll::pll_enabled(Cpm_regs ®s) 843 { 844 return regs.get_field(control_reg, 1, Pll_enabled); 845 } 846 847 int 848 Pll::pll_bypassed(Cpm_regs ®s) 849 { 850 return regs.get_field(control_reg, 1, bypass_bit); 851 } 852 853 // Clock control. 854 855 int 856 Pll::have_clock(Cpm_regs ®s) 857 { 858 return have_pll(regs) && pll_enabled(regs); 859 } 860 861 void 862 Pll::start_clock(Cpm_regs ®s) 863 { 864 regs.set_field(control_reg, 1, Pll_enabled, 1); 865 while (!have_pll(regs)); 866 } 867 868 void 869 Pll::stop_clock(Cpm_regs ®s) 870 { 871 regs.set_field(control_reg, 1, Pll_enabled, 0); 872 while (have_pll(regs)); 873 } 874 875 // Feedback (13-bit) multiplier. 876 877 uint16_t 878 Pll::get_multiplier(Cpm_regs ®s) 879 { 880 return regs.get_field(control_reg, 0x1fff, Pll_multiplier) + 1; 881 } 882 883 void 884 Pll::set_multiplier(Cpm_regs ®s, uint16_t multiplier) 885 { 886 regs.set_field(control_reg, 0x1fff, Pll_multiplier, multiplier - 1); 887 } 888 889 // Input (6-bit) divider. 890 891 uint8_t 892 Pll::get_input_division(Cpm_regs ®s) 893 { 894 return regs.get_field(control_reg, 0x3f, Pll_input_division) + 1; 895 } 896 897 void 898 Pll::set_input_division(Cpm_regs ®s, uint8_t divider) 899 { 900 regs.set_field(control_reg, 0x3f, Pll_input_division, divider - 1); 901 } 902 903 // Output (dual 3-bit) dividers. 904 905 uint8_t 906 Pll::get_output_division(Cpm_regs ®s) 907 { 908 uint8_t d0 = regs.get_field(control_reg, 0x07, Pll_output_division0); 909 uint8_t d1 = regs.get_field(control_reg, 0x07, Pll_output_division1); 910 911 return d0 * d1; 912 } 913 914 void 915 Pll::set_output_division(Cpm_regs ®s, uint8_t divider) 916 { 917 // Assert 1 as a minimum. 918 // Divider 0 must be less than or equal to divider 1. 919 920 uint8_t d0 = (uint8_t) floor(sqrt(divider ? divider : 1)); 921 uint8_t d1 = divider / d0; 922 923 regs.set_field(control_reg, 0x07, Pll_output_division0, d0); 924 regs.set_field(control_reg, 0x07, Pll_output_division1, d1); 925 } 926 927 uint32_t 928 Pll::get_frequency(Cpm_regs ®s) 929 { 930 // Test for PLL enable and not PLL bypass. 931 932 if (pll_enabled(regs)) 933 { 934 if (!pll_bypassed(regs)) 935 return (get_source_frequency(regs) * get_multiplier(regs)) / 936 (get_input_division(regs) * get_output_division(regs)); 937 else 938 return get_source_frequency(regs); 939 } 940 else 941 return 0; 942 } 943 944 void 945 Pll::set_pll_parameters(Cpm_regs ®s, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) 946 { 947 set_multiplier(regs, multiplier); 948 set_input_division(regs, in_divider); 949 set_output_division(regs, out_divider); 950 951 if (pll_enabled(regs) && !pll_bypassed(regs)) 952 while (!have_pll(regs)); 953 } 954 955 956 957 // Clock control. 958 959 void 960 Clock::change_disable(Cpm_regs ®s) 961 { 962 if (change_enable_bit != Clock_change_enable_undefined) 963 regs.set_field(change_enable_reg, 1, change_enable_bit, 0); 964 } 965 966 void 967 Clock::change_enable(Cpm_regs ®s) 968 { 969 if (change_enable_bit != Clock_change_enable_undefined) 970 regs.set_field(change_enable_reg, 1, change_enable_bit, 1); 971 } 972 973 int 974 Clock::have_clock(Cpm_regs ®s) 975 { 976 if (gate_bit != Clock_gate_undefined) 977 return !regs.get_field(gate_reg, 1, gate_bit); 978 else 979 return true; 980 } 981 982 void 983 Clock::start_clock(Cpm_regs ®s) 984 { 985 if (gate_bit != Clock_gate_undefined) 986 regs.set_field(gate_reg, 1, gate_bit, 0); 987 } 988 989 void 990 Clock::stop_clock(Cpm_regs ®s) 991 { 992 if (gate_bit != Clock_gate_undefined) 993 regs.set_field(gate_reg, 1, gate_bit, 1); 994 } 995 996 void 997 Clock::wait_busy(Cpm_regs ®s) 998 { 999 if (busy_bit != Clock_busy_undefined) 1000 while (regs.get_field(busy_reg, 1, busy_bit)); 1001 } 1002 1003 1004 1005 // Clock dividers. 1006 1007 uint32_t 1008 Clock::get_divider(Cpm_regs ®s) 1009 { 1010 if (divider_bit != Clock_divider_undefined) 1011 return regs.get_field(divider_reg, divider_mask, divider_bit) + 1; 1012 else 1013 return 1; 1014 } 1015 1016 void 1017 Clock::set_divider(Cpm_regs ®s, uint32_t division) 1018 { 1019 if (divider_bit == Clock_divider_undefined) 1020 return; 1021 1022 change_enable(regs); 1023 regs.set_field(divider_reg, divider_mask, divider_bit, division - 1); 1024 wait_busy(regs); 1025 change_disable(regs); 1026 } 1027 1028 void 1029 Clock::set_source(Cpm_regs ®s, uint8_t source) 1030 { 1031 change_enable(regs); 1032 Clock_base::set_source(regs, source); 1033 wait_busy(regs); 1034 change_disable(regs); 1035 } 1036 1037 1038 1039 // If implemented as a Hw::Device, various properties would be 1040 // initialised in the constructor and obtained from the device tree 1041 // definitions. 1042 1043 Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq) 1044 : _cpm_regs(addr, exclk_freq) 1045 { 1046 // add_cid("cpm"); 1047 // add_cid("cpm-x1600"); 1048 // register_property("exclk_freq", &exclk_freq); 1049 } 1050 1051 int 1052 Cpm_x1600_chip::have_clock(enum Clock_identifiers clock) 1053 { 1054 return clocks[clock]->have_clock(_cpm_regs); 1055 } 1056 1057 void 1058 Cpm_x1600_chip::start_clock(enum Clock_identifiers clock) 1059 { 1060 clocks[clock]->start_clock(_cpm_regs); 1061 } 1062 1063 void 1064 Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock) 1065 { 1066 clocks[clock]->stop_clock(_cpm_regs); 1067 } 1068 1069 uint32_t 1070 Cpm_x1600_chip::get_divider(enum Clock_identifiers clock) 1071 { 1072 return clocks[clock]->get_divider(_cpm_regs); 1073 } 1074 1075 void 1076 Cpm_x1600_chip::set_divider(enum Clock_identifiers clock, uint32_t division) 1077 { 1078 clocks[clock]->set_divider(_cpm_regs, division); 1079 } 1080 1081 uint8_t 1082 Cpm_x1600_chip::get_source(enum Clock_identifiers clock) 1083 { 1084 return clocks[clock]->get_source(_cpm_regs); 1085 } 1086 1087 void 1088 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source) 1089 { 1090 clocks[clock]->set_source(_cpm_regs, source); 1091 } 1092 1093 uint32_t 1094 Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock) 1095 { 1096 return clocks[clock]->get_source_frequency(_cpm_regs); 1097 } 1098 1099 uint32_t 1100 Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock) 1101 { 1102 return clocks[clock]->get_frequency(_cpm_regs); 1103 } 1104 1105 void 1106 Cpm_x1600_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) 1107 { 1108 switch (clock) 1109 { 1110 // The pixel frequency is based on the selected clock source (SCLK_A, MPLL or 1111 // EPLL). 1112 1113 case Clock_lcd_pixel: 1114 { 1115 1116 // Switch to the MPLL and attempt to set the divider. 1117 1118 Clock_base *lcd = clocks[Clock_lcd_pixel]; 1119 Clock_base *pll = clocks[Clock_pll_M]; 1120 1121 lcd->set_source(_cpm_regs, Source_mME_pll_M); 1122 pll->start_clock(_cpm_regs); 1123 lcd->set_divider(_cpm_regs, lcd->get_source_frequency(_cpm_regs) / frequency); 1124 break; 1125 } 1126 1127 default: 1128 break; 1129 } 1130 } 1131 1132 void 1133 Cpm_x1600_chip::set_pll_parameters(enum Clock_identifiers clock, uint16_t multiplier, 1134 uint8_t in_divider, uint8_t out_divider) 1135 { 1136 Pll *pll = dynamic_cast<Pll *>(clocks[clock]); 1137 1138 pll->set_pll_parameters(_cpm_regs, multiplier, in_divider, out_divider); 1139 } 1140 1141 1142 1143 // C language interface functions. 1144 1145 void 1146 *x1600_cpm_init(l4_addr_t cpm_base) 1147 { 1148 /* Initialise the clock and power management peripheral with the 1149 register memory region and a 24MHz EXCLK frequency. */ 1150 1151 return (void *) new Cpm_x1600_chip(cpm_base, 24000000); 1152 } 1153 1154 int 1155 x1600_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 1156 { 1157 return static_cast<Cpm_x1600_chip *>(cpm)->have_clock(clock); 1158 } 1159 1160 void 1161 x1600_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 1162 { 1163 static_cast<Cpm_x1600_chip *>(cpm)->start_clock(clock); 1164 } 1165 1166 void 1167 x1600_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 1168 { 1169 static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock); 1170 } 1171 1172 uint32_t 1173 x1600_cpm_get_divider(void *cpm, enum Clock_identifiers clock) 1174 { 1175 return static_cast<Cpm_x1600_chip *>(cpm)->get_divider(clock); 1176 } 1177 1178 void 1179 x1600_cpm_set_divider(void *cpm, enum Clock_identifiers clock, uint32_t divider) 1180 { 1181 return static_cast<Cpm_x1600_chip *>(cpm)->set_divider(clock, divider); 1182 } 1183 1184 uint8_t 1185 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock) 1186 { 1187 return static_cast<Cpm_x1600_chip *>(cpm)->get_source(clock); 1188 } 1189 1190 void 1191 x1600_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 1192 { 1193 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source); 1194 } 1195 1196 uint32_t 1197 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 1198 { 1199 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock); 1200 } 1201 1202 uint32_t 1203 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 1204 { 1205 return static_cast<Cpm_x1600_chip *>(cpm)->get_frequency(clock); 1206 } 1207 1208 void 1209 x1600_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency) 1210 { 1211 static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency); 1212 } 1213 1214 void 1215 x1600_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) 1216 { 1217 static_cast<Cpm_x1600_chip *>(cpm)->set_pll_parameters(Clock_pll_M, multiplier, in_divider, out_divider); 1218 }