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