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