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