paul@0 | 1 | /* |
paul@0 | 2 | * Clock and power management. This exposes the combined functionality |
paul@0 | 3 | * provided by the jz4730. The power management functionality could be exposed |
paul@0 | 4 | * using a separate driver. |
paul@0 | 5 | * |
paul@284 | 6 | * Copyright (C) 2017, 2018, 2020, 2021, 2023, |
paul@284 | 7 | * 2024 Paul Boddie <paul@boddie.org.uk> |
paul@0 | 8 | * |
paul@0 | 9 | * This program is free software; you can redistribute it and/or |
paul@0 | 10 | * modify it under the terms of the GNU General Public License as |
paul@0 | 11 | * published by the Free Software Foundation; either version 2 of |
paul@0 | 12 | * the License, or (at your option) any later version. |
paul@0 | 13 | * |
paul@0 | 14 | * This program is distributed in the hope that it will be useful, |
paul@0 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@0 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@0 | 17 | * GNU General Public License for more details. |
paul@0 | 18 | * |
paul@0 | 19 | * You should have received a copy of the GNU General Public License |
paul@0 | 20 | * along with this program; if not, write to the Free Software |
paul@0 | 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@0 | 22 | * Boston, MA 02110-1301, USA |
paul@0 | 23 | */ |
paul@0 | 24 | |
paul@0 | 25 | #include <l4/devices/hw_mmio_register_block.h> |
paul@0 | 26 | #include "cpm-jz4730.h" |
paul@0 | 27 | |
paul@0 | 28 | |
paul@0 | 29 | |
paul@0 | 30 | enum Regs : unsigned |
paul@0 | 31 | { |
paul@0 | 32 | Clock_control = 0x000, // CFCR (CPCCR in JZ4740) |
paul@0 | 33 | Pll_control = 0x010, // PLCR1 (CPPCR in JZ4740) |
paul@284 | 34 | Exclk_oscillator = 0x01c, // OCR |
paul@0 | 35 | Clock_gate = 0x020, // MSCR (CLKGR in JZ4740) |
paul@0 | 36 | Sleep_control = 0x024, // SCR |
paul@0 | 37 | Lcd_divider = 0x060, // CFCR2 |
paul@0 | 38 | }; |
paul@0 | 39 | |
paul@284 | 40 | |
paul@284 | 41 | |
paul@284 | 42 | // Encoded value tables. |
paul@284 | 43 | |
paul@284 | 44 | static const uint32_t dv[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 1, 1, 1, 1, 1, 1}; |
paul@284 | 45 | static const uint32_t plldv[] = {1, 2, 2, 4}; |
paul@284 | 46 | |
paul@284 | 47 | |
paul@284 | 48 | |
paul@284 | 49 | // Register field definitions. |
paul@0 | 50 | |
paul@284 | 51 | static Field Clock_source_ssi (Clock_control, 1, 31), // SCS |
paul@284 | 52 | Clock_source_lcd (Clock_control, 1, 30), // LCS |
paul@284 | 53 | Clock_source_i2s (Clock_control, 1, 29), // I2CS |
paul@284 | 54 | Clock_source_usb (Clock_control, 1, 28), // UCS |
paul@284 | 55 | Clock_source_msc (Clock_control, 1, 24), // MCS |
paul@284 | 56 | Clock_source_rtc (Exclk_oscillator, 1, 8), // O2SE |
paul@284 | 57 | |
paul@284 | 58 | Clock_change_enable (Clock_control, 1, 20), // UPE |
paul@284 | 59 | |
paul@284 | 60 | Clock_divider_cpu (Clock_control, 0x0f, 0, dv), // CFR |
paul@284 | 61 | Clock_divider_hclock (Clock_control, 0x0f, 4, dv), // HFR |
paul@284 | 62 | Clock_divider_pclock (Clock_control, 0x0f, 8, dv), // PFR |
paul@284 | 63 | Clock_divider_lcd (Clock_control, 0x0f, 12, false, 1), // LFR |
paul@284 | 64 | Clock_divider_mclock (Clock_control, 0x0f, 16, dv), // MFR |
paul@284 | 65 | Clock_divider_usb (Clock_control, 0x07, 25, false, 1), // UFR |
paul@284 | 66 | Clock_divider_lcd_pixel (Lcd_divider, 0x1ff, 0), // PXFR |
paul@0 | 67 | |
paul@284 | 68 | Clock_gate_uprt (Clock_gate, 1, 25, true), |
paul@284 | 69 | Clock_gate_udc (Clock_gate, 1, 24, true), |
paul@284 | 70 | Clock_gate_cim (Clock_gate, 1, 23, true), |
paul@284 | 71 | Clock_gate_kbc (Clock_gate, 1, 22, true), |
paul@284 | 72 | Clock_gate_emac (Clock_gate, 1, 21, true), |
paul@284 | 73 | Clock_gate_uart3 (Clock_gate, 1, 20, true), |
paul@284 | 74 | Clock_gate_aic_bitclk (Clock_gate, 1, 18, true), |
paul@284 | 75 | Clock_gate_scc (Clock_gate, 1, 14, true), |
paul@284 | 76 | Clock_gate_msc (Clock_gate, 1, 13, true), |
paul@284 | 77 | Clock_gate_ssi (Clock_gate, 1, 12, true), |
paul@284 | 78 | Clock_gate_pwm1 (Clock_gate, 1, 11, true), |
paul@284 | 79 | Clock_gate_pwm0 (Clock_gate, 1, 10, true), |
paul@284 | 80 | Clock_gate_aic_pclk (Clock_gate, 1, 9, true), |
paul@284 | 81 | Clock_gate_i2c (Clock_gate, 1, 8, true), |
paul@284 | 82 | Clock_gate_lcd (Clock_gate, 1, 7, true), |
paul@284 | 83 | Clock_gate_uhc (Clock_gate, 1, 6, true), |
paul@284 | 84 | Clock_gate_dmac (Clock_gate, 1, 5, true), |
paul@284 | 85 | Clock_gate_timer (Clock_gate, 1, 3, true), |
paul@284 | 86 | Clock_gate_uart2 (Clock_gate, 1, 2, true), |
paul@284 | 87 | Clock_gate_uart1 (Clock_gate, 1, 1, true), |
paul@284 | 88 | Clock_gate_uart0 (Clock_gate, 1, 0, true), |
paul@284 | 89 | Clock_gate_sdram (Clock_control, 1, 22), |
paul@284 | 90 | |
paul@284 | 91 | Pll_enable (Pll_control, 1, 8), // PLLEN |
paul@284 | 92 | Pll_stable (Pll_control, 1, 10), // PLLS |
paul@284 | 93 | Pll_bypass (Pll_control, 1, 9), // PLLBP |
paul@284 | 94 | |
paul@284 | 95 | // Multiplier and input divider yield 2-based values. |
paul@0 | 96 | |
paul@284 | 97 | Pll_multiplier (Pll_control, 0x1ff, 23, false, 2), // PLLFD |
paul@284 | 98 | Pll_input_division (Pll_control, 0x1f, 18, false, 2), // PLLRD |
paul@284 | 99 | Pll_output_division (Pll_control, 0x03, 16, plldv); // PLLOD |
paul@284 | 100 | |
paul@284 | 101 | |
paul@284 | 102 | |
paul@284 | 103 | // Multiplexer instances. |
paul@284 | 104 | |
paul@284 | 105 | #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) |
paul@284 | 106 | #define Specific(CLOCK) ((enum Clock_identifiers) (CLOCK)) |
paul@284 | 107 | |
paul@284 | 108 | static Mux mux_external (Clock_external), |
paul@284 | 109 | |
paul@284 | 110 | // Clocks being propagated to others. |
paul@284 | 111 | |
paul@284 | 112 | mux_core (Clock_pll), |
paul@284 | 113 | mux_mclock (Clock_mclock), |
paul@284 | 114 | mux_hclock (Clock_hclock0), |
paul@284 | 115 | mux_pclock (Clock_pclock), |
paul@284 | 116 | |
paul@284 | 117 | // Clock selection. |
paul@284 | 118 | |
paul@284 | 119 | mux_i2s (2, Clocks(Clock_pll, Specific(Clock_pll_div_2))), |
paul@284 | 120 | mux_lcd_pixel (2, Clocks(Clock_lcd_pixel0, Specific(Clock_lcd_pixel_in))), |
paul@284 | 121 | mux_msc (2, Clocks(Specific(Clock_msc_16MHz), Specific(Clock_msc_24MHz))), |
paul@284 | 122 | mux_rtc (2, Clocks(Clock_external_div, Clock_rtc_external)), |
paul@284 | 123 | mux_ssi (2, Clocks(Clock_external, Clock_usb_phy)), |
paul@284 | 124 | mux_usb (2, Clocks(Specific(Clock_pll_usb), Specific(Clock_usb_phy_48MHz))); |
paul@0 | 125 | |
paul@0 | 126 | |
paul@0 | 127 | |
paul@284 | 128 | // Clock instances. |
paul@284 | 129 | // NOTE: Leaving the LCD pixel clock as a null clock. |
paul@0 | 130 | |
paul@284 | 131 | static Clock_null clock_none, |
paul@284 | 132 | clock_lcd_pixel_in; |
paul@0 | 133 | |
paul@284 | 134 | static Clock_passive clock_external(3686400), |
paul@284 | 135 | clock_mac(25000000), |
paul@284 | 136 | clock_msc_16MHz(16000000), |
paul@284 | 137 | clock_msc_24MHz(24000000), |
paul@284 | 138 | clock_rtc_external(32768), |
paul@284 | 139 | clock_usb_phy_48MHz(48000000); |
paul@128 | 140 | |
paul@284 | 141 | // Note the use of extra parentheses due to the annoying C++ "most vexing parse" |
paul@284 | 142 | // problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse |
paul@0 | 143 | |
paul@284 | 144 | static Clock |
paul@284 | 145 | clock_aic_bitclk((Source(mux_i2s)), Control(Clock_gate_aic_bitclk)), |
paul@284 | 146 | clock_aic_pclk((Source(mux_i2s)), Control(Clock_gate_aic_pclk)), |
paul@284 | 147 | clock_cim((Source(mux_hclock)), Control(Clock_gate_cim)), |
paul@284 | 148 | clock_dma((Source(mux_external)), Control(Clock_gate_dmac)), |
paul@284 | 149 | clock_emac((Source(mux_mclock)), Control(Clock_gate_emac)), |
paul@284 | 150 | clock_i2c0((Source(mux_external)), Control(Clock_gate_i2c)), |
paul@284 | 151 | clock_kbc((Source(mux_pclock)), Control(Clock_gate_kbc)), |
paul@284 | 152 | clock_msc0((Source(mux_msc)), Control(Clock_gate_msc)), |
paul@284 | 153 | clock_pwm0((Source(mux_external)), Control(Clock_gate_pwm0)), |
paul@284 | 154 | clock_pwm1((Source(mux_external)), Control(Clock_gate_pwm1)), |
paul@284 | 155 | clock_rtc((Source(mux_rtc))), |
paul@284 | 156 | clock_scc((Source(mux_external)), Control(Clock_gate_scc)), |
paul@284 | 157 | clock_sdram((Source(mux_mclock)), Control(Clock_gate_sdram)), |
paul@284 | 158 | clock_ssi0((Source(mux_ssi)), Control(Clock_gate_ssi)), |
paul@0 | 159 | |
paul@284 | 160 | // Timer propagates pclock but OST may select external |
paul@284 | 161 | // or rtc instead. |
paul@0 | 162 | |
paul@284 | 163 | clock_timer((Source(mux_pclock)), Control(Clock_gate_timer)), |
paul@284 | 164 | clock_uart0((Source(mux_external)), Control(Clock_gate_uart0)), |
paul@284 | 165 | clock_uart1((Source(mux_external)), Control(Clock_gate_uart1)), |
paul@284 | 166 | clock_uart2((Source(mux_external)), Control(Clock_gate_uart2)), |
paul@284 | 167 | clock_uart3((Source(mux_external)), Control(Clock_gate_uart3)), |
paul@284 | 168 | clock_udc((Source(mux_usb)), Control(Clock_gate_udc)), |
paul@284 | 169 | clock_uhc((Source(mux_usb)), Control(Clock_gate_uhc)), |
paul@284 | 170 | clock_uprt((Source(mux_external)), Control(Clock_gate_uprt)), |
paul@284 | 171 | clock_usb_phy((Source(mux_usb))); |
paul@0 | 172 | |
paul@284 | 173 | static Clock_divided |
paul@284 | 174 | clock_cpu(Source(mux_core), |
paul@284 | 175 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 176 | Divider(Clock_divider_cpu)), |
paul@284 | 177 | clock_hclock(Source(mux_core), |
paul@284 | 178 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 179 | Divider(Clock_divider_hclock)), |
paul@284 | 180 | clock_lcd(Source(mux_core), |
paul@284 | 181 | Control(Clock_gate_lcd, Clock_change_enable), |
paul@284 | 182 | Divider(Clock_divider_lcd)), |
paul@284 | 183 | clock_lcd_pixel(Source(mux_core), |
paul@284 | 184 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 185 | Divider(Clock_divider_lcd_pixel)), |
paul@284 | 186 | clock_mclock(Source(mux_core), |
paul@284 | 187 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 188 | Divider(Clock_divider_mclock)), |
paul@284 | 189 | clock_pclock(Source(mux_core), |
paul@284 | 190 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 191 | Divider(Clock_divider_pclock)), |
paul@284 | 192 | clock_pll_usb(Source(mux_core), |
paul@284 | 193 | Control(Field::undefined, Clock_change_enable), |
paul@284 | 194 | Divider(Clock_divider_usb)); |
paul@160 | 195 | |
paul@284 | 196 | static Clock_divided_fixed |
paul@284 | 197 | clock_external_div((Source(mux_external)), (Divider_fixed(128))), |
paul@284 | 198 | clock_pll_div_2((Source(mux_core)), (Divider_fixed(2))); |
paul@0 | 199 | |
paul@284 | 200 | const double jz4730_pll_intermediate_min = 100000000, |
paul@284 | 201 | jz4730_pll_intermediate_max = 500000000; |
paul@0 | 202 | |
paul@284 | 203 | static Pll clock_pll(Source(mux_external), |
paul@284 | 204 | Control_pll(Pll_enable, Pll_stable, Pll_bypass), |
paul@284 | 205 | Divider_pll(Pll_multiplier, Pll_input_division, |
paul@284 | 206 | Pll_output_division, |
paul@284 | 207 | jz4730_pll_intermediate_min, jz4730_pll_intermediate_max)); |
paul@0 | 208 | |
paul@0 | 209 | |
paul@0 | 210 | |
paul@284 | 211 | // Clock register. |
paul@0 | 212 | |
paul@284 | 213 | static Clock_base *clocks[Clock_jz4730_identifier_count] = { |
paul@284 | 214 | &clock_none, |
paul@114 | 215 | |
paul@284 | 216 | &clock_none, // Clock_aic |
paul@284 | 217 | &clock_aic_bitclk, |
paul@284 | 218 | &clock_aic_pclk, |
paul@284 | 219 | &clock_none, // Clock_can0 |
paul@284 | 220 | &clock_none, // Clock_can1 |
paul@284 | 221 | &clock_none, // Clock_cdbus |
paul@284 | 222 | &clock_cim, |
paul@284 | 223 | &clock_cpu, |
paul@284 | 224 | &clock_sdram, // Clock_ddr |
paul@284 | 225 | &clock_dma, |
paul@284 | 226 | &clock_emac, |
paul@284 | 227 | &clock_external, |
paul@284 | 228 | &clock_external_div, |
paul@284 | 229 | &clock_hclock, // Clock_hclock0 |
paul@284 | 230 | &clock_none, // Clock_hclock2 |
paul@284 | 231 | &clock_none, // Clock_hclock2_pclock |
paul@284 | 232 | &clock_none, // Clock_hdmi |
paul@284 | 233 | &clock_i2c0, |
paul@284 | 234 | &clock_none, // Clock_i2c1 |
paul@284 | 235 | &clock_none, // Clock_i2c2 |
paul@284 | 236 | &clock_none, // Clock_i2c3 |
paul@284 | 237 | &clock_none, // Clock_i2c4 |
paul@284 | 238 | &clock_none, // Clock_i2s0 |
paul@284 | 239 | &clock_none, // Clock_i2s0_rx |
paul@284 | 240 | &clock_none, // Clock_i2s0_tx |
paul@284 | 241 | &clock_none, // Clock_i2s1 |
paul@284 | 242 | &clock_none, // Clock_i2s1_rx |
paul@284 | 243 | &clock_none, // Clock_i2s1_tx |
paul@284 | 244 | &clock_none, // Clock_kbc |
paul@284 | 245 | &clock_none, // Clock_l2cache |
paul@284 | 246 | &clock_lcd, |
paul@284 | 247 | &clock_lcd_pixel, // Clock_lcd_pixel0 |
paul@284 | 248 | &clock_none, // Clock_lcd_pixel1 |
paul@284 | 249 | &clock_mac, |
paul@284 | 250 | &clock_none, // Clock_main |
paul@284 | 251 | &clock_none, // Clock_mipi_csi |
paul@284 | 252 | &clock_none, // Clock_msc |
paul@284 | 253 | &clock_msc0, |
paul@284 | 254 | &clock_none, // Clock_msc1 |
paul@284 | 255 | &clock_none, // Clock_msc2 |
paul@284 | 256 | &clock_none, // Clock_nemc |
paul@284 | 257 | &clock_none, // Clock_otg0 |
paul@284 | 258 | &clock_none, // Clock_otg1 |
paul@284 | 259 | &clock_pclock, |
paul@284 | 260 | &clock_none, // Clock_pcm |
paul@284 | 261 | &clock_pll, |
paul@284 | 262 | &clock_none, // Clock_pll_A |
paul@284 | 263 | &clock_none, // Clock_pll_E |
paul@284 | 264 | &clock_none, // Clock_pll_M |
paul@284 | 265 | &clock_none, // Clock_pll_V |
paul@284 | 266 | &clock_pwm0, |
paul@284 | 267 | &clock_pwm1, |
paul@284 | 268 | &clock_rtc, |
paul@284 | 269 | &clock_rtc_external, |
paul@284 | 270 | &clock_none, // Clock_sadc |
paul@284 | 271 | &clock_scc, |
paul@284 | 272 | &clock_none, // Clock_sfc |
paul@284 | 273 | &clock_none, // Clock_ssi |
paul@284 | 274 | &clock_ssi0, |
paul@284 | 275 | &clock_none, // Clock_ssi1 |
paul@284 | 276 | &clock_none, // Clock_ssi2 |
paul@284 | 277 | &clock_none, // Clock_timer |
paul@284 | 278 | &clock_uart0, |
paul@284 | 279 | &clock_uart1, |
paul@284 | 280 | &clock_uart2, |
paul@284 | 281 | &clock_uart3, |
paul@284 | 282 | &clock_none, // Clock_uart4 |
paul@284 | 283 | &clock_none, // Clock_udc |
paul@284 | 284 | &clock_uhc, |
paul@284 | 285 | &clock_uprt, |
paul@284 | 286 | &clock_usb_phy, |
paul@284 | 287 | &clock_none, // Clock_vpu |
paul@0 | 288 | |
paul@284 | 289 | /* JZ4730-specific clocks. */ |
paul@0 | 290 | |
paul@284 | 291 | &clock_lcd_pixel_in, |
paul@284 | 292 | &clock_msc_16MHz, |
paul@284 | 293 | &clock_msc_24MHz, |
paul@284 | 294 | &clock_pll_div_2, |
paul@284 | 295 | &clock_pll_usb, |
paul@284 | 296 | &clock_usb_phy_48MHz, |
paul@284 | 297 | }; |
paul@0 | 298 | |
paul@0 | 299 | |
paul@284 | 300 | // Peripheral abstraction. |
paul@0 | 301 | |
paul@284 | 302 | Cpm_jz4730_chip::Cpm_jz4730_chip(l4_addr_t addr) |
paul@284 | 303 | : Cpm_chip(addr, clocks) |
paul@284 | 304 | { |
paul@0 | 305 | } |
paul@0 | 306 | |
paul@284 | 307 | Cpm_chip * |
paul@284 | 308 | jz4730_cpm_chip(l4_addr_t cpm_base) |
paul@0 | 309 | { |
paul@284 | 310 | return new Cpm_jz4730_chip(cpm_base); |
paul@0 | 311 | } |
paul@0 | 312 | |
paul@0 | 313 | |
paul@0 | 314 | |
paul@0 | 315 | // C language interface functions. |
paul@0 | 316 | |
paul@284 | 317 | void * |
paul@284 | 318 | jz4730_cpm_init(l4_addr_t cpm_base) |
paul@0 | 319 | { |
paul@284 | 320 | return (void *) jz4730_cpm_chip(cpm_base); |
paul@284 | 321 | } |
paul@0 | 322 | |
paul@284 | 323 | const char * |
paul@284 | 324 | jz4730_cpm_clock_type(void *cpm, enum Clock_identifiers clock) |
paul@284 | 325 | { |
paul@284 | 326 | return static_cast<Cpm_chip *>(cpm)->clock_type(clock); |
paul@0 | 327 | } |
paul@0 | 328 | |
paul@0 | 329 | int |
paul@128 | 330 | jz4730_cpm_have_clock(void *cpm, enum Clock_identifiers clock) |
paul@0 | 331 | { |
paul@284 | 332 | return static_cast<Cpm_chip *>(cpm)->have_clock(clock); |
paul@0 | 333 | } |
paul@0 | 334 | |
paul@0 | 335 | void |
paul@128 | 336 | jz4730_cpm_start_clock(void *cpm, enum Clock_identifiers clock) |
paul@114 | 337 | { |
paul@284 | 338 | static_cast<Cpm_chip *>(cpm)->start_clock(clock); |
paul@114 | 339 | } |
paul@114 | 340 | |
paul@114 | 341 | void |
paul@128 | 342 | jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) |
paul@0 | 343 | { |
paul@284 | 344 | static_cast<Cpm_chip *>(cpm)->stop_clock(clock); |
paul@0 | 345 | } |
paul@0 | 346 | |
paul@284 | 347 | int |
paul@284 | 348 | jz4730_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) |
paul@284 | 349 | { |
paul@284 | 350 | return static_cast<Cpm_chip *>(cpm)->get_parameters(clock, parameters); |
paul@0 | 351 | } |
paul@0 | 352 | |
paul@284 | 353 | int |
paul@284 | 354 | jz4730_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) |
paul@284 | 355 | { |
paul@284 | 356 | return static_cast<Cpm_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); |
paul@0 | 357 | } |
paul@0 | 358 | |
paul@284 | 359 | uint8_t |
paul@284 | 360 | jz4730_cpm_get_source(void *cpm, enum Clock_identifiers clock) |
paul@284 | 361 | { |
paul@284 | 362 | return static_cast<Cpm_chip *>(cpm)->get_source(clock); |
paul@0 | 363 | } |
paul@0 | 364 | |
paul@0 | 365 | void |
paul@284 | 366 | jz4730_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) |
paul@284 | 367 | { |
paul@284 | 368 | static_cast<Cpm_chip *>(cpm)->set_source(clock, source); |
paul@284 | 369 | } |
paul@284 | 370 | |
paul@284 | 371 | enum Clock_identifiers |
paul@284 | 372 | jz4730_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) |
paul@284 | 373 | { |
paul@284 | 374 | return static_cast<Cpm_chip *>(cpm)->get_source_clock(clock); |
paul@284 | 375 | } |
paul@284 | 376 | |
paul@284 | 377 | void |
paul@284 | 378 | jz4730_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) |
paul@284 | 379 | { |
paul@284 | 380 | static_cast<Cpm_chip *>(cpm)->set_source_clock(clock, source); |
paul@284 | 381 | } |
paul@284 | 382 | |
paul@284 | 383 | uint64_t |
paul@284 | 384 | jz4730_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) |
paul@284 | 385 | { |
paul@284 | 386 | return static_cast<Cpm_chip *>(cpm)->get_source_frequency(clock); |
paul@284 | 387 | } |
paul@284 | 388 | |
paul@284 | 389 | uint64_t |
paul@284 | 390 | jz4730_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) |
paul@284 | 391 | { |
paul@284 | 392 | return static_cast<Cpm_chip *>(cpm)->get_frequency(clock); |
paul@284 | 393 | } |
paul@284 | 394 | |
paul@284 | 395 | int |
paul@284 | 396 | jz4730_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) |
paul@0 | 397 | { |
paul@284 | 398 | return static_cast<Cpm_chip *>(cpm)->set_frequency(clock, frequency); |
paul@0 | 399 | } |