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, // I2S0CDR 44 Divider1_i2s0 = 0x070, // I2S0CDR1 45 Divider0_i2s1 = 0x07c, // I2S1CDR (from X2000 manual) 46 Divider1_i2s1 = 0x080, // I2S1CDR1 (from X2000 manual) 47 Divider_lcd = 0x064, // LPCDR 48 Divider_msc0 = 0x068, // MSC0CDR 49 Divider_msc1 = 0x0a4, // MSC1CDR 50 Divider_sfc = 0x074, // SFCCDR 51 Divider_ssi = 0x05c, // SSICDR 52 Divider_cim = 0x078, // CIMCDR 53 Divider_pwm = 0x06c, // PWMCDR 54 Divider_can0 = 0x0a0, // CAN0CDR 55 Divider_can1 = 0x0a8, // CAN1CDR 56 Divider_cdbus = 0x0ac, // CDBUSCDR 57 Divider_macphy0 = 0x0e4, // MPHY0C 58 Cpm_interrupt = 0x0b0, // CPM_INTR 59 Cpm_interrupt_en = 0x0b4, // CPM_INTRE 60 Cpm_swi = 0x0bc, // CPM_SFTINT 61 Ddr_gate = 0x0d0, // DRCG 62 Cpm_scratch_prot = 0x038, // CPSPPR 63 Cpm_scratch = 0x034, // CPSPR 64 Usb_param_control0 = 0x03c, // USBPCR 65 Usb_reset_detect = 0x040, // USBRDT 66 Usb_vbus_jitter = 0x044, // USBVBFIL 67 Usb_param_control1 = 0x048, // USBPCR1 68 Pll_control = 0x00c, // CPPCR 69 Pll_control_A = 0x010, // CPAPCR 70 Pll_control_M = 0x014, // CPMPCR 71 Pll_control_E = 0x018, // CPEPCR 72 Pll_fraction_A = 0x084, // CPAPACR 73 Pll_fraction_M = 0x088, // CPMPACR 74 Pll_fraction_E = 0x08c, // CPEPACR 75 }; 76 77 enum Clock_source_values : unsigned 78 { 79 Source_mME_main = 0, 80 Source_mME_pll_M = 1, 81 Source_mME_pll_E = 2, 82 83 // Special value 84 85 Source_mask = 0x3, 86 }; 87 88 89 90 // Register field definitions. 91 92 static Field Clock_source_main (Clock_control, 3, 30), // SEL_SRC (output to SCLK_A) 93 Clock_source_cpu (Clock_control, 3, 28), // SEL_CPLL (output to CCLK) 94 Clock_source_hclock0 (Clock_control, 3, 26), // SEL_H0PLL (output to AHB0) 95 Clock_source_hclock2 (Clock_control, 3, 24), // SEL_H2PLL (output to AHB2) 96 Clock_source_can0 (Divider_can0, 3, 30), // CA0CS 97 Clock_source_can1 (Divider_can1, 3, 30), // CA1CS 98 Clock_source_cdbus (Divider_cdbus, 3, 30), // CDCS 99 Clock_source_cim (Divider_cim, 3, 30), // CIMPCS 100 Clock_source_ddr (Divider_ddr, 3, 30), // DCS 101 Clock_source_i2s (Divider0_i2s0, 1, 30), // I2PCS 102 Clock_source_lcd (Divider_lcd, 3, 30), // LPCS 103 Clock_source_mac (Divider_mac, 3, 30), // MACPCS 104 Clock_source_msc0 (Divider_msc0, 3, 30), // MPCS 105 Clock_source_msc1 (Divider_msc1, 3, 30), // MPCS 106 Clock_source_pwm (Divider_pwm, 3, 30), // PWMPCS 107 Clock_source_sfc (Divider_sfc, 3, 30), // SFCS 108 Clock_source_ssi (Divider_ssi, 3, 30), // SPCS 109 110 Clock_busy_cpu (Clock_status, 1, 0), 111 Clock_busy_ddr (Divider_ddr, 1, 28), 112 Clock_busy_mac (Divider_mac, 1, 28), 113 Clock_busy_lcd (Divider_lcd, 1, 28), 114 Clock_busy_msc0 (Divider_msc0, 1, 28), 115 Clock_busy_msc1 (Divider_msc1, 1, 28), 116 Clock_busy_sfc (Divider_sfc, 1, 28), 117 Clock_busy_ssi (Divider_ssi, 1, 28), 118 Clock_busy_cim (Divider_cim, 1, 28), 119 Clock_busy_pwm (Divider_pwm, 1, 28), 120 Clock_busy_can0 (Divider_can0, 1, 28), 121 Clock_busy_can1 (Divider_can1, 1, 28), 122 Clock_busy_cdbus (Divider_cdbus, 1, 28), 123 124 Clock_change_enable_cpu (Clock_control, 1, 22), 125 Clock_change_enable_ahb0 (Clock_control, 1, 21), 126 Clock_change_enable_ahb2 (Clock_control, 1, 20), 127 Clock_change_enable_ddr (Divider_ddr, 1, 29), 128 Clock_change_enable_mac (Divider_mac, 1, 29), 129 // Clock_change_enable_i2s (Divider0_i2s0, 1, 29), // CE_I2S may not be change enable 130 Clock_change_enable_lcd (Divider_lcd, 1, 29), 131 Clock_change_enable_msc0 (Divider_msc0, 1, 29), 132 Clock_change_enable_msc1 (Divider_msc1, 1, 29), 133 Clock_change_enable_sfc (Divider_sfc, 1, 29), 134 Clock_change_enable_ssi (Divider_ssi, 1, 29), 135 Clock_change_enable_cim (Divider_cim, 1, 29), 136 Clock_change_enable_pwm (Divider_pwm, 1, 29), 137 Clock_change_enable_can0 (Divider_can0, 1, 29), 138 Clock_change_enable_can1 (Divider_can1, 1, 29), 139 Clock_change_enable_cdbus (Divider_cdbus, 1, 29), 140 141 Clock_divider_can0 (Divider_can0, 0xff, 0), // CAN0CDR 142 Clock_divider_can1 (Divider_can1, 0xff, 0), // CAN1CDR 143 Clock_divider_cdbus (Divider_cdbus, 0xff, 0), // CDBUSCDR 144 Clock_divider_cim (Divider_cim, 0xff, 0), // CIMCDR 145 Clock_divider_cpu (Clock_control, 0x0f, 0), // CDIV 146 Clock_divider_ddr (Divider_ddr, 0x0f, 0), // DDRCDR 147 Clock_divider_hclock0 (Clock_control, 0x0f, 8), // H0DIV (fast AHB peripherals) 148 Clock_divider_hclock2 (Clock_control, 0x0f, 12), // H2DIV (fast AHB peripherals) 149 Clock_divider_i2s0_m (Divider0_i2s0, 0x1ff, 20), // I2SDIV_M 150 Clock_divider_i2s0_n (Divider0_i2s0, 0xfffff, 0), // I2SDIV_N 151 Clock_divider_i2s0_d (Divider1_i2s0, 0xfffff, 0), // I2SDIV_D 152 Clock_divider_i2s1_m (Divider0_i2s1, 0x1ff, 20), // I2SDIV_M 153 Clock_divider_i2s1_n (Divider0_i2s1, 0xfffff, 0), // I2SDIV_N 154 Clock_divider_i2s1_d (Divider1_i2s1, 0xfffff, 0), // I2SDIV_D 155 Clock_divider_l2cache (Clock_control, 0x0f, 4), // L2CDIV 156 Clock_divider_lcd (Divider_lcd, 0xff, 0), // LPCDR 157 Clock_divider_mac (Divider_mac, 0xff, 0), // MACCDR 158 Clock_divider_msc0 (Divider_msc0, 0xff, 0), // MSC0CDR 159 Clock_divider_msc1 (Divider_msc1, 0xff, 0), // MSC1CDR 160 Clock_divider_pclock (Clock_control, 0x0f, 16), // PDIV (slow APB peripherals) 161 Clock_divider_pwm (Divider_pwm, 0x0f, 0), // PWMCDR 162 Clock_divider_sfc (Divider_sfc, 0xff, 0), // SFCCDR 163 Clock_divider_ssi (Divider_ssi, 0xff, 0), // SSICDR 164 165 Clock_divider_i2s0_n_auto (Divider1_i2s0, 1, 31), // I2S_NEN 166 Clock_divider_i2s0_d_auto (Divider1_i2s0, 1, 30), // I2S_DEN 167 Clock_divider_i2s1_n_auto (Divider1_i2s1, 1, 31), // I2S_NEN 168 Clock_divider_i2s1_d_auto (Divider1_i2s1, 1, 30), // I2S_DEN 169 170 Clock_gate_main (Clock_control, 1, 23), // GATE_SCLKA 171 Clock_gate_ddr (Clock_gate0, 1, 31), // DDR 172 Clock_gate_ahb0 (Clock_gate0, 1, 29), // AHB0 173 Clock_gate_apb0 (Clock_gate0, 1, 28), // APB0 174 Clock_gate_rtc (Clock_gate0, 1, 27), // RTC 175 Clock_gate_aes (Clock_gate0, 1, 24), // AES 176 Clock_gate_lcd_pixel (Clock_gate0, 1, 23), // LCD 177 Clock_gate_cim (Clock_gate0, 1, 22), // CIM 178 Clock_gate_dma (Clock_gate0, 1, 21), // PDMA 179 Clock_gate_ost (Clock_gate0, 1, 20), // OST 180 Clock_gate_ssi0 (Clock_gate0, 1, 19), // SSI0 181 Clock_gate_timer (Clock_gate0, 1, 18), // TCU 182 Clock_gate_dtrng (Clock_gate0, 1, 17), // DTRNG 183 Clock_gate_uart2 (Clock_gate0, 1, 16), // UART2 184 Clock_gate_uart1 (Clock_gate0, 1, 15), // UART1 185 Clock_gate_uart0 (Clock_gate0, 1, 14), // UART0 186 Clock_gate_sadc (Clock_gate0, 1, 13), // SADC 187 Clock_gate_audio (Clock_gate0, 1, 11), // AUDIO 188 Clock_gate_ssi_slv (Clock_gate0, 1, 10), // SSI_SLV 189 Clock_gate_i2c1 (Clock_gate0, 1, 8), // I2C1 190 Clock_gate_i2c0 (Clock_gate0, 1, 7), // I2C0 191 Clock_gate_msc1 (Clock_gate0, 1, 5), // MSC1 192 Clock_gate_msc0 (Clock_gate0, 1, 4), // MSC0 193 Clock_gate_otg (Clock_gate0, 1, 3), // OTG 194 Clock_gate_sfc (Clock_gate0, 1, 2), // SFC 195 Clock_gate_efuse (Clock_gate0, 1, 1), // EFUSE 196 Clock_gate_nemc (Clock_gate0, 1, 0), // NEMC 197 Clock_gate_arb (Clock_gate1, 1, 30), // ARB 198 Clock_gate_mipi_csi (Clock_gate1, 1, 28), // MIPI_CSI 199 Clock_gate_intc (Clock_gate1, 1, 26), // INTC 200 Clock_gate_gmac0 (Clock_gate1, 1, 23), // GMAC0 201 Clock_gate_uart3 (Clock_gate1, 1, 16), // UART3 202 Clock_gate_i2s0_tx (Clock_gate1, 1, 9), // I2S0_dev_tclk 203 Clock_gate_i2s0_rx (Clock_gate1, 1, 8), // I2S0_dev_rclk 204 Clock_gate_hash (Clock_gate1, 1, 6), // HASH 205 Clock_gate_pwm (Clock_gate1, 1, 5), // PWM 206 Clock_gate_cdbus (Clock_gate1, 1, 2), // CDBUS 207 Clock_gate_can1 (Clock_gate1, 1, 1), // CAN1 208 Clock_gate_can0 (Clock_gate1, 1, 0), // CAN0 209 210 Pll_enable_A (Pll_control_A, 1, 0), // APLLEN 211 Pll_enable_E (Pll_control_E, 1, 0), // EPLLEN 212 Pll_enable_M (Pll_control_M, 1, 0), // MPLLEN 213 214 Pll_stable_A (Pll_control_A, 1, 3), // APLL_ON 215 Pll_stable_E (Pll_control_E, 1, 3), // EPLL_ON 216 Pll_stable_M (Pll_control_M, 1, 3), // MPLL_ON 217 218 Pll_bypass_A (Pll_control_A, 1, 30), // APLL_BP 219 Pll_bypass_E (Pll_control_E, 1, 26), // EPLL_BP 220 Pll_bypass_M (Pll_control_M, 1, 28), // MPLL_BP 221 222 Pll_multiplier_A (Pll_control_A, 0xfff, 20), // APLLM 223 Pll_multiplier_E (Pll_control_E, 0x3f, 20), // EPLLM (observed) 224 Pll_multiplier_M (Pll_control_M, 0xfff, 20), // MPLLM 225 226 Pll_input_division_A (Pll_control_A, 0x3f, 14), // APLLN 227 Pll_input_division_E (Pll_control_E, 0x3f, 14), // EPLLN 228 Pll_input_division_M (Pll_control_M, 0x3f, 14), // MPLLN 229 230 Pll_output_division1_A (Pll_control_A, 0x07, 11), // APLLOD1 231 Pll_output_division1_E (Pll_control_E, 0x07, 11), // EPLLOD1 232 Pll_output_division1_M (Pll_control_M, 0x07, 11), // MPLLOD1 233 234 Pll_output_division0_A (Pll_control_A, 0x07, 8), // APLLOD0 235 Pll_output_division0_E (Pll_control_E, 0x07, 8), // EPLLOD0 236 Pll_output_division0_M (Pll_control_M, 0x07, 8); // MPLLOD0 237 238 239 240 // Multiplexer instances. 241 242 #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) 243 244 static Mux mux_external (Clock_external), 245 mux_hclock0 (Clock_hclock0), 246 mux_hclock2 (Clock_hclock2), 247 mux_pclock (Clock_pclock), 248 mux_core (3, Clocks(Clock_none, Clock_main, Clock_pll_M)), 249 mux_bus (4, Clocks(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external)), 250 mux_dev (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E)), 251 mux_i2s (2, Clocks(Clock_main, Clock_pll_E)); 252 253 254 255 // Clock instances. 256 257 static Clock_null clock_none; 258 259 static Clock_passive clock_external; 260 261 // Note the use of extra parentheses due to the annoying C++ "most vexing parse" 262 // problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse 263 264 static Clock clock_dma((Source(mux_hclock2)), (Control(Clock_gate_dma))), 265 266 clock_i2c((Source(mux_pclock)), (Control(Clock_gate_i2c0))), 267 268 clock_i2c0((Source(mux_pclock)), (Control(Clock_gate_i2c0))), 269 270 clock_i2c1((Source(mux_pclock)), (Control(Clock_gate_i2c1))), 271 272 clock_main(Source(mux_core, Clock_source_main), Control(Clock_gate_main)), 273 274 clock_mipi_csi((Source(mux_hclock0)), Control(Clock_gate_mipi_csi)), 275 276 clock_otg((Source(mux_hclock2)), (Control(Clock_gate_otg))), 277 278 clock_timer((Source(mux_pclock)), (Control(Clock_gate_timer))), 279 280 clock_uart0((Source(mux_external)), (Control(Clock_gate_uart0))), 281 282 clock_uart1((Source(mux_external)), (Control(Clock_gate_uart1))), 283 284 clock_uart2((Source(mux_external)), (Control(Clock_gate_uart2))), 285 286 clock_uart3((Source(mux_external)), (Control(Clock_gate_uart3))); 287 288 static Clock_divided 289 clock_can0(Source(mux_bus, Clock_source_can0), 290 Control(Clock_gate_can0, Clock_change_enable_can0, Clock_busy_can0), 291 Divider(Clock_divider_can0)), 292 293 clock_can1(Source(mux_bus, Clock_source_can1), 294 Control(Clock_gate_can1, Clock_change_enable_can1, Clock_busy_can1), 295 Divider(Clock_divider_can1)), 296 297 clock_cdbus(Source(mux_dev, Clock_source_cdbus), 298 Control(Clock_gate_cdbus, Clock_change_enable_cdbus, Clock_busy_cdbus), 299 Divider(Clock_divider_cdbus)), 300 301 clock_cim(Source(mux_dev, Clock_source_cim), 302 Control(Clock_gate_cim, Clock_change_enable_cim, Clock_busy_cim), 303 Divider(Clock_divider_cim)), 304 305 clock_cpu(Source(mux_core, Clock_source_cpu), 306 Control(Field::undefined, Clock_change_enable_cpu, Clock_busy_cpu), 307 Divider(Clock_divider_cpu)), 308 309 clock_ddr(Source(mux_core, Clock_source_ddr), 310 Control(Clock_gate_ddr, Clock_change_enable_ddr, Clock_busy_ddr), 311 Divider(Clock_divider_ddr)), 312 313 clock_hclock0(Source(mux_core, Clock_source_hclock0), 314 Control(Clock_gate_ahb0, Clock_change_enable_ahb0), 315 Divider(Clock_divider_hclock0)), 316 317 clock_hclock2(Source(mux_core, Clock_source_hclock2), 318 Control(Clock_gate_apb0, Clock_change_enable_ahb2), 319 Divider(Clock_divider_hclock2)), 320 321 clock_lcd_pixel(Source(mux_dev, Clock_source_lcd), 322 Control(Clock_gate_lcd_pixel, Clock_change_enable_lcd, Clock_busy_lcd), 323 Divider(Clock_divider_lcd)), 324 325 clock_mac(Source(mux_dev, Clock_source_mac), 326 Control(Clock_gate_gmac0, Clock_change_enable_mac, Clock_busy_mac), 327 Divider(Clock_divider_mac)), 328 329 clock_msc(Source(mux_dev, Clock_source_msc0), 330 Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), 331 Divider(Clock_divider_msc0)), 332 333 clock_msc0(Source(mux_dev, Clock_source_msc0), 334 Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), 335 Divider(Clock_divider_msc0)), 336 337 clock_msc1(Source(mux_dev, Clock_source_msc1), 338 Control(Clock_gate_msc1, Clock_change_enable_msc1, Clock_busy_msc1), 339 Divider(Clock_divider_msc1)), 340 341 clock_pclock(Source(mux_core, Clock_source_hclock2), 342 Control(Clock_gate_apb0, Clock_change_enable_ahb2), 343 Divider(Clock_divider_pclock)), 344 345 clock_pwm(Source(mux_dev, Clock_source_pwm), 346 Control(Clock_gate_pwm, Clock_change_enable_pwm, Clock_busy_pwm), 347 Divider(Clock_divider_pwm)), 348 349 clock_pwm0(Source(mux_dev, Clock_source_pwm), 350 Control(Clock_gate_pwm, Clock_change_enable_pwm, Clock_busy_pwm), 351 Divider(Clock_divider_pwm)), 352 353 clock_sfc(Source(mux_dev, Clock_source_sfc), 354 Control(Clock_gate_sfc, Clock_change_enable_sfc, Clock_busy_sfc), 355 Divider(Clock_divider_sfc)), 356 357 clock_ssi(Source(mux_dev, Clock_source_ssi), 358 Control(Clock_gate_ssi0, Clock_change_enable_ssi, Clock_busy_ssi), 359 Divider(Clock_divider_ssi)); 360 361 static Clock_divided_i2s 362 clock_i2s0_rx(Source(mux_i2s, Clock_source_i2s), 363 Control(Clock_gate_i2s0_rx), 364 Divider_i2s(Clock_divider_i2s0_m, Clock_divider_i2s0_n, 365 Clock_divider_i2s0_d, Clock_divider_i2s0_n_auto, 366 Clock_divider_i2s0_d_auto)), 367 368 clock_i2s0_tx(Source(mux_i2s, Clock_source_i2s), 369 Control(Clock_gate_i2s0_tx), 370 Divider_i2s(Clock_divider_i2s1_m, Clock_divider_i2s1_n, 371 Clock_divider_i2s1_d, Clock_divider_i2s1_n_auto, 372 Clock_divider_i2s1_d_auto)); 373 374 static Pll clock_pll_A(Source(mux_external), 375 Control_pll(Pll_enable_A, Pll_stable_A, Pll_bypass_A), 376 Divider_pll(Pll_multiplier_A, Pll_input_division_A, 377 Pll_output_division0_A, Pll_output_division1_A)), 378 379 clock_pll_E(Source(mux_external), 380 Control_pll(Pll_enable_E, Pll_stable_E, Pll_bypass_E), 381 Divider_pll(Pll_multiplier_E, Pll_input_division_E, 382 Pll_output_division0_E, Pll_output_division1_E)), 383 384 clock_pll_M(Source(mux_external), 385 Control_pll(Pll_enable_M, Pll_stable_M, Pll_bypass_M), 386 Divider_pll(Pll_multiplier_M, Pll_input_division_M, 387 Pll_output_division0_M, Pll_output_division1_M)); 388 389 390 391 // Clock register. 392 393 static Clock_base *clocks[Clock_identifier_count] = { 394 &clock_none, // Clock_aic_bitclk 395 &clock_none, // Clock_aic_pclk 396 &clock_can0, 397 &clock_can1, 398 &clock_cdbus, 399 &clock_cim, 400 &clock_cpu, 401 &clock_ddr, 402 &clock_dma, 403 &clock_none, // Clock_emac 404 &clock_external, 405 &clock_hclock0, 406 &clock_hclock2, 407 &clock_none, // Clock_hdmi 408 &clock_i2c, 409 &clock_i2c0, 410 &clock_i2c1, 411 &clock_none, // Clock_i2s 412 &clock_i2s0_rx, 413 &clock_i2s0_tx, 414 &clock_none, // Clock_kbc 415 &clock_none, // Clock_lcd 416 &clock_lcd_pixel, 417 &clock_mac, 418 &clock_main, 419 &clock_mipi_csi, 420 &clock_msc, 421 &clock_msc0, 422 &clock_msc1, 423 &clock_none, 424 &clock_otg, 425 &clock_pclock, 426 &clock_pll_A, 427 &clock_pll_E, 428 &clock_pll_M, 429 &clock_pwm, 430 &clock_pwm0, 431 &clock_none, // Clock_pwm1 432 &clock_none, // Clock_scc 433 &clock_sfc, 434 &clock_none, // Clock_smb0 435 &clock_none, // Clock_smb1 436 &clock_none, // Clock_smb2 437 &clock_none, // Clock_smb3 438 &clock_none, // Clock_smb4 439 &clock_ssi, 440 &clock_timer, 441 &clock_uart0, 442 &clock_uart1, 443 &clock_uart2, 444 &clock_uart3, 445 &clock_none, // Clock_udc 446 &clock_none, // Clock_uhc 447 &clock_none, // Clock_uprt 448 }; 449 450 451 452 // If implemented as a Hw::Device, various properties would be 453 // initialised in the constructor and obtained from the device tree 454 // definitions. 455 456 Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq) 457 : _cpm_regs(addr, clocks, exclk_freq) 458 { 459 // add_cid("cpm"); 460 // add_cid("cpm-x1600"); 461 // register_property("exclk_freq", &exclk_freq); 462 } 463 464 const char * 465 Cpm_x1600_chip::clock_type(enum Clock_identifiers clock) 466 { 467 return clocks[clock]->clock_type(); 468 } 469 470 int 471 Cpm_x1600_chip::have_clock(enum Clock_identifiers clock) 472 { 473 return clocks[clock]->have_clock(_cpm_regs); 474 } 475 476 void 477 Cpm_x1600_chip::start_clock(enum Clock_identifiers clock) 478 { 479 clocks[clock]->start_clock(_cpm_regs); 480 } 481 482 void 483 Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock) 484 { 485 clocks[clock]->stop_clock(_cpm_regs); 486 } 487 488 int 489 Cpm_x1600_chip::get_parameters(enum Clock_identifiers clock, uint32_t parameters[]) 490 { 491 Clock_divided_base *clk = dynamic_cast<Clock_divided_base *>(clocks[clock]); 492 493 if (clk != NULL) 494 return clk->get_parameters(_cpm_regs, parameters); 495 else 496 return 0; 497 } 498 499 int 500 Cpm_x1600_chip::set_parameters(enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) 501 { 502 Clock_divided_base *clk = dynamic_cast<Clock_divided_base *>(clocks[clock]); 503 504 if (clk != NULL) 505 return clk->set_parameters(_cpm_regs, num_parameters, parameters); 506 else 507 return 0; 508 } 509 510 uint8_t 511 Cpm_x1600_chip::get_source(enum Clock_identifiers clock) 512 { 513 Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]); 514 515 if (clk != NULL) 516 return clk->get_source(_cpm_regs); 517 else 518 return 0; 519 } 520 521 enum Clock_identifiers 522 Cpm_x1600_chip::get_source_clock(enum Clock_identifiers clock) 523 { 524 Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]); 525 526 if (clk != NULL) 527 return clk->get_source_clock(_cpm_regs); 528 else 529 return Clock_undefined; 530 } 531 532 void 533 Cpm_x1600_chip::set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source) 534 { 535 Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]); 536 537 if (clk != NULL) 538 clk->set_source_clock(_cpm_regs, source); 539 } 540 541 void 542 Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source) 543 { 544 Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]); 545 546 if (clk != NULL) 547 clk->set_source(_cpm_regs, source); 548 } 549 550 uint32_t 551 Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock) 552 { 553 Clock_active *clk = dynamic_cast<Clock_active *>(clocks[clock]); 554 555 if (clk != NULL) 556 return clk->get_source_frequency(_cpm_regs); 557 else 558 return 0; 559 } 560 561 uint32_t 562 Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock) 563 { 564 return clocks[clock]->get_frequency(_cpm_regs); 565 } 566 567 int 568 Cpm_x1600_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) 569 { 570 Clock_divided_base *clk = dynamic_cast<Clock_divided_base *>(clocks[clock]); 571 572 if (clk != NULL) 573 return clk->set_frequency(_cpm_regs, frequency); 574 else 575 return 0; 576 } 577 578 579 580 // C language interface functions. 581 582 void 583 *x1600_cpm_init(l4_addr_t cpm_base) 584 { 585 /* Initialise the clock and power management peripheral with the 586 register memory region and a 24MHz EXCLK frequency. */ 587 588 return (void *) new Cpm_x1600_chip(cpm_base, 24000000); 589 } 590 591 const char * 592 x1600_cpm_clock_type(void *cpm, enum Clock_identifiers clock) 593 { 594 return static_cast<Cpm_x1600_chip *>(cpm)->clock_type(clock); 595 } 596 597 int 598 x1600_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 599 { 600 return static_cast<Cpm_x1600_chip *>(cpm)->have_clock(clock); 601 } 602 603 void 604 x1600_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 605 { 606 static_cast<Cpm_x1600_chip *>(cpm)->start_clock(clock); 607 } 608 609 void 610 x1600_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 611 { 612 static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock); 613 } 614 615 int 616 x1600_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) 617 { 618 return static_cast<Cpm_x1600_chip *>(cpm)->get_parameters(clock, parameters); 619 } 620 621 int 622 x1600_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) 623 { 624 return static_cast<Cpm_x1600_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 625 } 626 627 uint8_t 628 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock) 629 { 630 return static_cast<Cpm_x1600_chip *>(cpm)->get_source(clock); 631 } 632 633 void 634 x1600_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 635 { 636 static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source); 637 } 638 639 enum Clock_identifiers 640 x1600_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) 641 { 642 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_clock(clock); 643 } 644 645 void 646 x1600_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) 647 { 648 static_cast<Cpm_x1600_chip *>(cpm)->set_source_clock(clock, source); 649 } 650 651 uint32_t 652 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 653 { 654 return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock); 655 } 656 657 uint32_t 658 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 659 { 660 return static_cast<Cpm_x1600_chip *>(cpm)->get_frequency(clock); 661 } 662 663 int 664 x1600_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency) 665 { 666 return static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency); 667 }