paul@0 | 1 | /* |
paul@0 | 2 | * Clock and power management. This exposes the combined functionality |
paul@0 | 3 | * provided by the jz4780 and related SoCs. The power management |
paul@0 | 4 | * functionality could be exposed using a separate driver. |
paul@0 | 5 | * |
paul@0 | 6 | * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk> |
paul@0 | 7 | * |
paul@0 | 8 | * This program is free software; you can redistribute it and/or |
paul@0 | 9 | * modify it under the terms of the GNU General Public License as |
paul@0 | 10 | * published by the Free Software Foundation; either version 2 of |
paul@0 | 11 | * the License, or (at your option) any later version. |
paul@0 | 12 | * |
paul@0 | 13 | * This program is distributed in the hope that it will be useful, |
paul@0 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@0 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@0 | 16 | * GNU General Public License for more details. |
paul@0 | 17 | * |
paul@0 | 18 | * You should have received a copy of the GNU General Public License |
paul@0 | 19 | * along with this program; if not, write to the Free Software |
paul@0 | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@0 | 21 | * Boston, MA 02110-1301, USA |
paul@0 | 22 | */ |
paul@0 | 23 | |
paul@0 | 24 | #include <l4/devices/hw_mmio_register_block.h> |
paul@0 | 25 | #include "cpm-jz4780.h" |
paul@0 | 26 | |
paul@0 | 27 | |
paul@0 | 28 | |
paul@0 | 29 | enum Regs : unsigned |
paul@0 | 30 | { |
paul@0 | 31 | Clock_control = 0x000, // CPCCR |
paul@0 | 32 | Low_power_control = 0x004, // LCR |
paul@0 | 33 | Pll_control = 0x00c, // CPPCR |
paul@0 | 34 | Pll_control_A = 0x010, // CPAPCR |
paul@0 | 35 | Pll_control_M = 0x014, // CPMPCR |
paul@0 | 36 | Pll_control_E = 0x018, // CPEPCR |
paul@0 | 37 | Pll_control_V = 0x01c, // CPVPCR |
paul@0 | 38 | Clock_gate0 = 0x020, // CLKGR0 |
paul@0 | 39 | Clock_gate1 = 0x028, // CLKGR1 |
paul@0 | 40 | Sleep_control = 0x024, // OPCR (oscillator and power control) |
paul@0 | 41 | Ddr_divider = 0x02c, // DDRCDR |
paul@0 | 42 | I2s_divider0 = 0x060, // I2SCDR |
paul@0 | 43 | I2s_divider1 = 0x0a0, // I2S1CDR |
paul@0 | 44 | Lcd_divider0 = 0x054, // LP0CDR |
paul@0 | 45 | Lcd_divider1 = 0x064, // LP1CDR |
paul@0 | 46 | Msc_divider0 = 0x068, // MSC0CDR |
paul@0 | 47 | Msc_divider1 = 0x0a4, // MSC1CDR |
paul@0 | 48 | Msc_divider2 = 0x0a8, // MSC2CDR |
paul@0 | 49 | Uhc_divider = 0x06c, // UHCCDR |
paul@0 | 50 | Ssi_divider = 0x074, // SSICDR |
paul@0 | 51 | }; |
paul@0 | 52 | |
paul@0 | 53 | enum Clock_bits : unsigned |
paul@0 | 54 | { |
paul@0 | 55 | Clock_enable = 22, // CE_CPU |
paul@0 | 56 | Clock_pclock_divider = 16, // PDIV (slow APB peripherals) |
paul@0 | 57 | Clock_hclock2_divider = 12, // H2DIV (fast AHB peripherals) |
paul@0 | 58 | Clock_hclock0_divider = 8, // H0DIV (fast AHB peripherals) |
paul@0 | 59 | Clock_cpu_divider = 0, // CDIV |
paul@0 | 60 | }; |
paul@0 | 61 | |
paul@0 | 62 | enum Pll_bits : unsigned |
paul@0 | 63 | { |
paul@0 | 64 | Pll_multiplier = 19, // xPLLM |
paul@0 | 65 | Pll_input_division = 13, // xPLLN |
paul@0 | 66 | Pll_output_division = 9, // xPLLOD |
paul@0 | 67 | Pll_stable = 4, // xPLL_ON |
paul@0 | 68 | Pll_bypassed = 1, // xPLLBP |
paul@0 | 69 | Pll_enabled = 0, // xPLLEN |
paul@0 | 70 | }; |
paul@0 | 71 | |
paul@0 | 72 | enum Clock_source_bits : unsigned |
paul@0 | 73 | { |
paul@0 | 74 | Clock_source_main = 30, // SEL_SRC (output to SCLK_A) |
paul@0 | 75 | Clock_source_cpu = 28, // SEL_CPLL (output to CCLK) |
paul@0 | 76 | Clock_source_hclock0 = 26, // SEL_H0PLL (output to AHB0) |
paul@0 | 77 | Clock_source_hclock2 = 24, // SEL_H2PLL (output to AHB2) |
paul@0 | 78 | Clock_source_ddr = 30, // DCS |
paul@0 | 79 | Clock_source_i2s = 31, // I2CS |
paul@0 | 80 | Clock_source_lcd = 30, // LPCS |
paul@0 | 81 | }; |
paul@0 | 82 | |
paul@0 | 83 | enum Clock_sources : unsigned |
paul@0 | 84 | { |
paul@0 | 85 | Source_pll_A = 1, // APLL |
paul@0 | 86 | Source_external = 2, // EXCLK |
paul@0 | 87 | Source_realtime = 3, // RTCLK |
paul@0 | 88 | Source_main_frequency = 1, // SCLK_A |
paul@0 | 89 | Source_pll_M = 2, // MPLL |
paul@0 | 90 | Source_pll_E = 3, // EPLL |
paul@0 | 91 | Source_pll_V = 3, // VPLL |
paul@0 | 92 | }; |
paul@0 | 93 | |
paul@0 | 94 | enum Clock_gate_bits : unsigned |
paul@0 | 95 | { |
paul@0 | 96 | Clock_gate_lcd = 28, // LCD (in CLKGR0) |
paul@0 | 97 | Clock_gate_tve = 27, // TVE (in CLKGR0) |
paul@0 | 98 | Clock_gate_smb4 = 12, // SMB4 (in CLKGR1) |
paul@0 | 99 | Clock_gate_smb3 = 0, // SMB3 (in CLKGR1) |
paul@0 | 100 | Clock_gate_smb2 = 25, // SMB2 (in CLKGR0) |
paul@0 | 101 | Clock_gate_smb1 = 6, // SMB2 (in CLKGR0) |
paul@0 | 102 | Clock_gate_smb0 = 5, // SMB2 (in CLKGR0) |
paul@0 | 103 | }; |
paul@0 | 104 | |
paul@0 | 105 | enum Clock_gate_regs : unsigned |
paul@0 | 106 | { |
paul@0 | 107 | Clock_gate_reg_smb4 = Clock_gate1, |
paul@0 | 108 | Clock_gate_reg_smb3 = Clock_gate1, |
paul@0 | 109 | Clock_gate_reg_smb2 = Clock_gate0, |
paul@0 | 110 | Clock_gate_reg_smb1 = Clock_gate0, |
paul@0 | 111 | Clock_gate_reg_smb0 = Clock_gate0, |
paul@0 | 112 | }; |
paul@0 | 113 | |
paul@0 | 114 | enum Divider_bits : unsigned |
paul@0 | 115 | { |
paul@0 | 116 | Ddr_divider_value = 0, // DDRCDR |
paul@0 | 117 | Lcd_divider_value = 0, // LPCDR |
paul@0 | 118 | }; |
paul@0 | 119 | |
paul@0 | 120 | enum Lcd_clock_bits : unsigned |
paul@0 | 121 | { |
paul@0 | 122 | Lcd_change_enable = 0x1000, // CE_LCD |
paul@0 | 123 | Lcd_change_busy = 0x0800, // LCD_BUSY |
paul@0 | 124 | Lcd_clock_stop = 0x0400, // LCD_STOP |
paul@0 | 125 | }; |
paul@0 | 126 | |
paul@0 | 127 | |
paul@0 | 128 | |
paul@0 | 129 | // If implemented as a Hw::Device, various properties would be |
paul@0 | 130 | // initialised in the constructor and obtained from the device tree |
paul@0 | 131 | // definitions. |
paul@0 | 132 | |
paul@0 | 133 | Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq) |
paul@0 | 134 | : _exclk_freq(exclk_freq), _rtclk_freq(rtclk_freq) |
paul@0 | 135 | { |
paul@0 | 136 | _regs = new Hw::Mmio_register_block<32>(addr); |
paul@0 | 137 | |
paul@0 | 138 | // add_cid("cpm"); |
paul@0 | 139 | // add_cid("cpm-jz4780"); |
paul@0 | 140 | // register_property("exclk_freq", &_exclk_freq); |
paul@0 | 141 | } |
paul@0 | 142 | |
paul@0 | 143 | // Clock/timer control. |
paul@0 | 144 | // NOTE: For the time being, assume that the system is configured. |
paul@0 | 145 | |
paul@0 | 146 | int |
paul@0 | 147 | Cpm_jz4780_chip::have_clock() |
paul@0 | 148 | { |
paul@0 | 149 | // return !(_regs[Clock_gate] & (1 << Clock_gate_timer)); |
paul@0 | 150 | return 1; |
paul@0 | 151 | } |
paul@0 | 152 | |
paul@0 | 153 | void |
paul@0 | 154 | Cpm_jz4780_chip::start_clock() |
paul@0 | 155 | { |
paul@0 | 156 | // _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer); |
paul@0 | 157 | } |
paul@0 | 158 | |
paul@0 | 159 | |
paul@0 | 160 | |
paul@0 | 161 | // Utility methods. |
paul@0 | 162 | |
paul@0 | 163 | uint32_t |
paul@0 | 164 | Cpm_jz4780_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift) |
paul@0 | 165 | { |
paul@0 | 166 | return (_regs[reg] & (mask << shift)) >> shift; |
paul@0 | 167 | } |
paul@0 | 168 | |
paul@0 | 169 | void |
paul@0 | 170 | Cpm_jz4780_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) |
paul@0 | 171 | { |
paul@0 | 172 | _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); |
paul@0 | 173 | } |
paul@0 | 174 | |
paul@0 | 175 | // General clock divider access. |
paul@0 | 176 | |
paul@0 | 177 | uint8_t |
paul@0 | 178 | Cpm_jz4780_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift) |
paul@0 | 179 | { |
paul@0 | 180 | uint8_t d = get_field(reg, mask, shift); |
paul@0 | 181 | |
paul@0 | 182 | // NOTE: Value 14 stops the clock, 15 presumably resumes the clock. |
paul@0 | 183 | |
paul@0 | 184 | return (d < 14) ? d + 1 : 1; |
paul@0 | 185 | } |
paul@0 | 186 | |
paul@0 | 187 | |
paul@0 | 188 | |
paul@0 | 189 | // PLL control. |
paul@0 | 190 | |
paul@0 | 191 | // Return whether the PLL is stable. |
paul@0 | 192 | |
paul@0 | 193 | int |
paul@0 | 194 | Cpm_jz4780_chip::have_pll(uint32_t pll_reg) |
paul@0 | 195 | { |
paul@0 | 196 | return _regs[pll_reg] & (1 << Pll_stable); |
paul@0 | 197 | } |
paul@0 | 198 | |
paul@0 | 199 | int |
paul@0 | 200 | Cpm_jz4780_chip::pll_enabled(uint32_t pll_reg) |
paul@0 | 201 | { |
paul@0 | 202 | return _regs[pll_reg] & (1 << Pll_enabled); |
paul@0 | 203 | } |
paul@0 | 204 | |
paul@0 | 205 | int |
paul@0 | 206 | Cpm_jz4780_chip::pll_bypassed(uint32_t pll_reg) |
paul@0 | 207 | { |
paul@0 | 208 | return _regs[pll_reg] & (1 << Pll_bypassed); |
paul@0 | 209 | } |
paul@0 | 210 | |
paul@0 | 211 | // Feedback (13-bit) multiplier. |
paul@0 | 212 | |
paul@0 | 213 | uint16_t |
paul@0 | 214 | Cpm_jz4780_chip::get_multiplier(uint32_t pll_reg) |
paul@0 | 215 | { |
paul@0 | 216 | return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1; |
paul@0 | 217 | } |
paul@0 | 218 | |
paul@0 | 219 | void |
paul@0 | 220 | Cpm_jz4780_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier) |
paul@0 | 221 | { |
paul@0 | 222 | set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1); |
paul@0 | 223 | } |
paul@0 | 224 | |
paul@0 | 225 | // Input (6-bit) divider. |
paul@0 | 226 | |
paul@0 | 227 | uint8_t |
paul@0 | 228 | Cpm_jz4780_chip::get_input_division(uint32_t pll_reg) |
paul@0 | 229 | { |
paul@0 | 230 | return get_field(pll_reg, 0x3f, Pll_input_division) + 1; |
paul@0 | 231 | } |
paul@0 | 232 | |
paul@0 | 233 | void |
paul@0 | 234 | Cpm_jz4780_chip::set_input_division(uint32_t pll_reg, uint8_t divider) |
paul@0 | 235 | { |
paul@0 | 236 | set_field(pll_reg, 0x3f, Pll_input_division, divider - 1); |
paul@0 | 237 | } |
paul@0 | 238 | |
paul@0 | 239 | // Output divider. |
paul@0 | 240 | |
paul@0 | 241 | uint8_t |
paul@0 | 242 | Cpm_jz4780_chip::get_output_division(uint32_t pll_reg) |
paul@0 | 243 | { |
paul@0 | 244 | uint8_t d = get_field(pll_reg, 0x0f, Pll_output_division); |
paul@0 | 245 | |
paul@0 | 246 | // Zero yields a division of one. Otherwise enforce even results. |
paul@0 | 247 | |
paul@0 | 248 | return d == 0 ? 1 : (d + 1) & 0x0e; |
paul@0 | 249 | } |
paul@0 | 250 | |
paul@0 | 251 | void |
paul@0 | 252 | Cpm_jz4780_chip::set_output_division(uint32_t pll_reg, uint8_t divider) |
paul@0 | 253 | { |
paul@0 | 254 | uint8_t d = divider <= 1 ? 0 : (divider & 0x0e) - 1; |
paul@0 | 255 | |
paul@0 | 256 | set_field(pll_reg, 0x0f, Pll_output_division, d); |
paul@0 | 257 | } |
paul@0 | 258 | |
paul@0 | 259 | uint32_t |
paul@0 | 260 | Cpm_jz4780_chip::get_pll_frequency(uint32_t pll_reg) |
paul@0 | 261 | { |
paul@0 | 262 | // Test for PLL enable and not PLL bypass. |
paul@0 | 263 | |
paul@0 | 264 | if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) |
paul@0 | 265 | return (_exclk_freq * get_multiplier(pll_reg)) / |
paul@0 | 266 | (get_input_division(pll_reg) * get_output_division(pll_reg)); |
paul@0 | 267 | else |
paul@0 | 268 | return _exclk_freq; |
paul@0 | 269 | } |
paul@0 | 270 | |
paul@0 | 271 | void |
paul@0 | 272 | Cpm_jz4780_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) |
paul@0 | 273 | { |
paul@0 | 274 | set_multiplier(pll_reg, multiplier); |
paul@0 | 275 | set_input_division(pll_reg, in_divider); |
paul@0 | 276 | set_output_division(pll_reg, out_divider); |
paul@0 | 277 | |
paul@0 | 278 | if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) |
paul@0 | 279 | while (!have_pll(pll_reg)); |
paul@0 | 280 | } |
paul@0 | 281 | |
paul@0 | 282 | |
paul@0 | 283 | |
paul@0 | 284 | // CPU clock (CCLK) divider. |
paul@0 | 285 | |
paul@0 | 286 | uint8_t |
paul@0 | 287 | Cpm_jz4780_chip::get_cpu_divider() |
paul@0 | 288 | { |
paul@0 | 289 | return _get_divider(Clock_control, 0xf, Clock_cpu_divider); |
paul@0 | 290 | } |
paul@0 | 291 | |
paul@0 | 292 | // Fast peripheral clock (H0CLK) divider. |
paul@0 | 293 | |
paul@0 | 294 | uint8_t |
paul@0 | 295 | Cpm_jz4780_chip::get_hclock0_divider() |
paul@0 | 296 | { |
paul@0 | 297 | return _get_divider(Clock_control, 0xf, Clock_hclock0_divider); |
paul@0 | 298 | } |
paul@0 | 299 | |
paul@0 | 300 | // Fast peripheral clock (H2CLK) divider. |
paul@0 | 301 | |
paul@0 | 302 | uint8_t |
paul@0 | 303 | Cpm_jz4780_chip::get_hclock2_divider() |
paul@0 | 304 | { |
paul@0 | 305 | return _get_divider(Clock_control, 0xf, Clock_hclock2_divider); |
paul@0 | 306 | } |
paul@0 | 307 | |
paul@0 | 308 | // Slow peripheral clock (PCLK) divider. |
paul@0 | 309 | |
paul@0 | 310 | uint8_t |
paul@0 | 311 | Cpm_jz4780_chip::get_pclock_divider() |
paul@0 | 312 | { |
paul@0 | 313 | return _get_divider(Clock_control, 0xf, Clock_pclock_divider); |
paul@0 | 314 | } |
paul@0 | 315 | |
paul@0 | 316 | // LCD clock (LPCLK) divider for LCD0 pixel clock. |
paul@0 | 317 | |
paul@0 | 318 | uint8_t |
paul@0 | 319 | Cpm_jz4780_chip::get_lcd_pixel_divider() |
paul@0 | 320 | { |
paul@0 | 321 | return get_field(Lcd_divider0, 0xff, Lcd_divider_value) + 1; |
paul@0 | 322 | } |
paul@0 | 323 | |
paul@0 | 324 | // Memory clock (DDR_CLK) divider. |
paul@0 | 325 | |
paul@0 | 326 | uint8_t |
paul@0 | 327 | Cpm_jz4780_chip::get_memory_divider() |
paul@0 | 328 | { |
paul@0 | 329 | return _get_divider(Ddr_divider, 0xf, Ddr_divider_value); |
paul@0 | 330 | } |
paul@0 | 331 | |
paul@0 | 332 | // LCD pixel clock divider. |
paul@0 | 333 | // NOTE: This only supports the first LCD peripheral. |
paul@0 | 334 | |
paul@0 | 335 | void |
paul@0 | 336 | Cpm_jz4780_chip::set_lcd_pixel_divider(uint16_t division) |
paul@0 | 337 | { |
paul@0 | 338 | if ((division < 1) || (division > 256)) |
paul@0 | 339 | return; |
paul@0 | 340 | |
paul@0 | 341 | // Enable change. |
paul@0 | 342 | |
paul@0 | 343 | _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable; |
paul@0 | 344 | |
paul@0 | 345 | // Set the divider. |
paul@0 | 346 | |
paul@0 | 347 | set_field(Lcd_divider0, 0xff, Lcd_divider_value, division - 1); |
paul@0 | 348 | |
paul@0 | 349 | // Restart clock and disable change. |
paul@0 | 350 | |
paul@0 | 351 | while (_regs[Lcd_divider0] & Lcd_change_busy); |
paul@0 | 352 | _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~Lcd_change_enable; |
paul@0 | 353 | } |
paul@0 | 354 | |
paul@0 | 355 | |
paul@0 | 356 | |
paul@0 | 357 | // Clock gating control. |
paul@0 | 358 | |
paul@0 | 359 | void |
paul@0 | 360 | Cpm_jz4780_chip::start_lcd() |
paul@0 | 361 | { |
paul@0 | 362 | _regs[Clock_gate0] = _regs[Clock_gate0] & ~(1 << Clock_gate_lcd); |
paul@0 | 363 | } |
paul@0 | 364 | |
paul@0 | 365 | void |
paul@0 | 366 | Cpm_jz4780_chip::stop_lcd() |
paul@0 | 367 | { |
paul@0 | 368 | _regs[Clock_gate0] = _regs[Clock_gate0] | (1 << Clock_gate_lcd); |
paul@0 | 369 | } |
paul@0 | 370 | |
paul@0 | 371 | void |
paul@0 | 372 | Cpm_jz4780_chip::_update_i2c(uint8_t channel, int enable) |
paul@0 | 373 | { |
paul@0 | 374 | uint8_t bit; |
paul@0 | 375 | uint32_t reg; |
paul@0 | 376 | switch (channel) |
paul@0 | 377 | { |
paul@0 | 378 | case 0: bit = Clock_gate_smb0; reg = Clock_gate_reg_smb0; break; |
paul@0 | 379 | case 1: bit = Clock_gate_smb1; reg = Clock_gate_reg_smb1; break; |
paul@0 | 380 | case 2: bit = Clock_gate_smb2; reg = Clock_gate_reg_smb2; break; |
paul@0 | 381 | case 3: bit = Clock_gate_smb3; reg = Clock_gate_reg_smb3; break; |
paul@0 | 382 | case 4: bit = Clock_gate_smb4; reg = Clock_gate_reg_smb4; break; |
paul@0 | 383 | default: return; |
paul@0 | 384 | } |
paul@0 | 385 | if (enable) |
paul@0 | 386 | _regs[reg] = _regs[reg] & ~(1 << bit); |
paul@0 | 387 | else |
paul@0 | 388 | _regs[reg] = _regs[reg] | (1 << bit); |
paul@0 | 389 | } |
paul@0 | 390 | |
paul@0 | 391 | void |
paul@0 | 392 | Cpm_jz4780_chip::start_i2c(uint8_t channel) |
paul@0 | 393 | { |
paul@0 | 394 | _update_i2c(channel, 1); |
paul@0 | 395 | } |
paul@0 | 396 | |
paul@0 | 397 | void |
paul@0 | 398 | Cpm_jz4780_chip::stop_i2c(uint8_t channel) |
paul@0 | 399 | { |
paul@0 | 400 | _update_i2c(channel, 0); |
paul@0 | 401 | } |
paul@0 | 402 | |
paul@0 | 403 | |
paul@0 | 404 | |
paul@0 | 405 | // Clock sources. |
paul@0 | 406 | |
paul@0 | 407 | uint8_t |
paul@0 | 408 | Cpm_jz4780_chip::get_memory_source() |
paul@0 | 409 | { |
paul@0 | 410 | return get_field(Ddr_divider, 0x3, Clock_source_ddr); |
paul@0 | 411 | } |
paul@0 | 412 | |
paul@0 | 413 | uint32_t |
paul@0 | 414 | Cpm_jz4780_chip::get_memory_source_frequency() |
paul@0 | 415 | { |
paul@0 | 416 | switch (get_memory_source()) |
paul@0 | 417 | { |
paul@0 | 418 | case Source_main_frequency: |
paul@0 | 419 | return get_main_frequency(); |
paul@0 | 420 | case Source_pll_M: |
paul@0 | 421 | return get_pll_frequency(Pll_control_M); |
paul@0 | 422 | default: |
paul@0 | 423 | return 0; |
paul@0 | 424 | } |
paul@0 | 425 | } |
paul@0 | 426 | |
paul@0 | 427 | uint8_t |
paul@0 | 428 | Cpm_jz4780_chip::get_cpu_source() |
paul@0 | 429 | { |
paul@0 | 430 | return get_field(Clock_control, 0x3, Clock_source_cpu); |
paul@0 | 431 | } |
paul@0 | 432 | |
paul@0 | 433 | uint32_t |
paul@0 | 434 | Cpm_jz4780_chip::get_cpu_source_frequency() |
paul@0 | 435 | { |
paul@0 | 436 | switch (get_cpu_source()) |
paul@0 | 437 | { |
paul@0 | 438 | case Source_main_frequency: |
paul@0 | 439 | return get_main_frequency(); |
paul@0 | 440 | case Source_pll_M: |
paul@0 | 441 | return get_pll_frequency(Pll_control_M); |
paul@0 | 442 | case Source_pll_E: |
paul@0 | 443 | return get_pll_frequency(Pll_control_E); |
paul@0 | 444 | default: |
paul@0 | 445 | return 0; |
paul@0 | 446 | } |
paul@0 | 447 | } |
paul@0 | 448 | |
paul@0 | 449 | uint8_t |
paul@0 | 450 | Cpm_jz4780_chip::get_hclock0_source() |
paul@0 | 451 | { |
paul@0 | 452 | return get_field(Clock_control, 0x3, Clock_source_hclock0); |
paul@0 | 453 | } |
paul@0 | 454 | |
paul@0 | 455 | uint32_t |
paul@0 | 456 | Cpm_jz4780_chip::get_hclock0_source_frequency() |
paul@0 | 457 | { |
paul@0 | 458 | switch (get_hclock0_source()) |
paul@0 | 459 | { |
paul@0 | 460 | case Source_main_frequency: |
paul@0 | 461 | return get_main_frequency(); |
paul@0 | 462 | case Source_pll_M: |
paul@0 | 463 | return get_pll_frequency(Pll_control_M); |
paul@0 | 464 | case Source_pll_E: |
paul@0 | 465 | return get_pll_frequency(Pll_control_E); |
paul@0 | 466 | default: |
paul@0 | 467 | return 0; |
paul@0 | 468 | } |
paul@0 | 469 | } |
paul@0 | 470 | |
paul@0 | 471 | uint8_t |
paul@0 | 472 | Cpm_jz4780_chip::get_hclock2_source() |
paul@0 | 473 | { |
paul@0 | 474 | return get_field(Clock_control, 0x3, Clock_source_hclock2); |
paul@0 | 475 | } |
paul@0 | 476 | |
paul@0 | 477 | uint32_t |
paul@0 | 478 | Cpm_jz4780_chip::get_hclock2_source_frequency() |
paul@0 | 479 | { |
paul@0 | 480 | switch (get_hclock2_source()) |
paul@0 | 481 | { |
paul@0 | 482 | case Source_main_frequency: |
paul@0 | 483 | return get_main_frequency(); |
paul@0 | 484 | case Source_pll_M: |
paul@0 | 485 | return get_pll_frequency(Pll_control_M); |
paul@0 | 486 | case Source_realtime: |
paul@0 | 487 | return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code |
paul@0 | 488 | default: |
paul@0 | 489 | return 0; |
paul@0 | 490 | } |
paul@0 | 491 | } |
paul@0 | 492 | |
paul@0 | 493 | void |
paul@0 | 494 | Cpm_jz4780_chip::set_hclock2_source(uint8_t source) |
paul@0 | 495 | { |
paul@0 | 496 | set_field(Clock_control, 0x3, Clock_source_hclock2, source); |
paul@0 | 497 | } |
paul@0 | 498 | |
paul@0 | 499 | uint8_t |
paul@0 | 500 | Cpm_jz4780_chip::get_lcd_source() |
paul@0 | 501 | { |
paul@0 | 502 | return get_field(Lcd_divider0, 0x3, Clock_source_lcd); |
paul@0 | 503 | } |
paul@0 | 504 | |
paul@0 | 505 | uint32_t |
paul@0 | 506 | Cpm_jz4780_chip::get_lcd_source_frequency() |
paul@0 | 507 | { |
paul@0 | 508 | switch (get_lcd_source()) |
paul@0 | 509 | { |
paul@0 | 510 | case Source_main_frequency: |
paul@0 | 511 | return get_main_frequency(); |
paul@0 | 512 | case Source_pll_M: |
paul@0 | 513 | return get_pll_frequency(Pll_control_M); |
paul@0 | 514 | case Source_pll_V: |
paul@0 | 515 | return get_pll_frequency(Pll_control_V); |
paul@0 | 516 | default: |
paul@0 | 517 | return 0; |
paul@0 | 518 | } |
paul@0 | 519 | } |
paul@0 | 520 | |
paul@0 | 521 | void |
paul@0 | 522 | Cpm_jz4780_chip::set_lcd_source(uint8_t source) |
paul@0 | 523 | { |
paul@0 | 524 | // Stop clock and enable change. |
paul@0 | 525 | |
paul@0 | 526 | _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable | Lcd_clock_stop; |
paul@0 | 527 | |
paul@0 | 528 | // Set the source. |
paul@0 | 529 | |
paul@0 | 530 | set_field(Lcd_divider0, 0x03, Clock_source_lcd, source); |
paul@0 | 531 | |
paul@0 | 532 | // Restart clock and disable change. |
paul@0 | 533 | |
paul@0 | 534 | while (_regs[Lcd_divider0] & Lcd_change_busy); |
paul@0 | 535 | _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~(Lcd_change_enable | Lcd_clock_stop); |
paul@0 | 536 | } |
paul@0 | 537 | |
paul@0 | 538 | uint8_t |
paul@0 | 539 | Cpm_jz4780_chip::get_pclock_source() |
paul@0 | 540 | { |
paul@0 | 541 | return get_hclock2_source(); |
paul@0 | 542 | } |
paul@0 | 543 | |
paul@0 | 544 | uint32_t |
paul@0 | 545 | Cpm_jz4780_chip::get_pclock_source_frequency() |
paul@0 | 546 | { |
paul@0 | 547 | return get_hclock2_source_frequency(); |
paul@0 | 548 | } |
paul@0 | 549 | |
paul@0 | 550 | void |
paul@0 | 551 | Cpm_jz4780_chip::set_pclock_source(uint8_t source) |
paul@0 | 552 | { |
paul@0 | 553 | set_hclock2_source(source); |
paul@0 | 554 | } |
paul@0 | 555 | |
paul@0 | 556 | |
paul@0 | 557 | |
paul@0 | 558 | // Source frequency, used by various clock sources. |
paul@0 | 559 | |
paul@0 | 560 | uint8_t |
paul@0 | 561 | Cpm_jz4780_chip::get_main_source() |
paul@0 | 562 | { |
paul@0 | 563 | return get_field(Clock_control, 0x3, Clock_source_main); |
paul@0 | 564 | } |
paul@0 | 565 | |
paul@0 | 566 | uint32_t |
paul@0 | 567 | Cpm_jz4780_chip::get_main_frequency() |
paul@0 | 568 | { |
paul@0 | 569 | switch (get_main_source()) |
paul@0 | 570 | { |
paul@0 | 571 | case Source_pll_A: |
paul@0 | 572 | return get_pll_frequency(Pll_control_A); |
paul@0 | 573 | case Source_external: |
paul@0 | 574 | return _exclk_freq; |
paul@0 | 575 | case Source_realtime: |
paul@0 | 576 | return _rtclk_freq; |
paul@0 | 577 | default: |
paul@0 | 578 | return 0; |
paul@0 | 579 | } |
paul@0 | 580 | } |
paul@0 | 581 | |
paul@0 | 582 | // Clock frequency for the CPU. |
paul@0 | 583 | |
paul@0 | 584 | uint32_t |
paul@0 | 585 | Cpm_jz4780_chip::get_cpu_frequency() |
paul@0 | 586 | { |
paul@0 | 587 | return get_cpu_source_frequency() / get_cpu_divider(); |
paul@0 | 588 | } |
paul@0 | 589 | |
paul@0 | 590 | // Clock frequency for fast peripherals. |
paul@0 | 591 | |
paul@0 | 592 | uint32_t |
paul@0 | 593 | Cpm_jz4780_chip::get_hclock0_frequency() |
paul@0 | 594 | { |
paul@0 | 595 | return get_hclock0_source_frequency() / get_hclock0_divider(); |
paul@0 | 596 | } |
paul@0 | 597 | |
paul@0 | 598 | // Clock frequency for fast peripherals. |
paul@0 | 599 | |
paul@0 | 600 | uint32_t |
paul@0 | 601 | Cpm_jz4780_chip::get_hclock2_frequency() |
paul@0 | 602 | { |
paul@0 | 603 | return get_hclock2_source_frequency() / get_hclock2_divider(); |
paul@0 | 604 | } |
paul@0 | 605 | |
paul@0 | 606 | // Clock frequency for slow peripherals. |
paul@0 | 607 | |
paul@0 | 608 | uint32_t |
paul@0 | 609 | Cpm_jz4780_chip::get_pclock_frequency() |
paul@0 | 610 | { |
paul@0 | 611 | return get_pclock_source_frequency() / get_pclock_divider(); |
paul@0 | 612 | } |
paul@0 | 613 | |
paul@0 | 614 | // Clock frequency for the LCD0 controller. |
paul@0 | 615 | |
paul@0 | 616 | uint32_t |
paul@0 | 617 | Cpm_jz4780_chip::get_lcd_pixel_frequency() |
paul@0 | 618 | { |
paul@0 | 619 | return get_lcd_source_frequency() / get_lcd_pixel_divider(); |
paul@0 | 620 | } |
paul@0 | 621 | |
paul@0 | 622 | // Clock frequency for the memory. |
paul@0 | 623 | |
paul@0 | 624 | uint32_t |
paul@0 | 625 | Cpm_jz4780_chip::get_memory_frequency() |
paul@0 | 626 | { |
paul@0 | 627 | return get_memory_source_frequency() / get_memory_divider(); |
paul@0 | 628 | } |
paul@0 | 629 | |
paul@0 | 630 | uint32_t |
paul@0 | 631 | Cpm_jz4780_chip::get_apll_frequency() |
paul@0 | 632 | { |
paul@0 | 633 | return get_pll_frequency(Pll_control_A); |
paul@0 | 634 | } |
paul@0 | 635 | |
paul@0 | 636 | uint32_t |
paul@0 | 637 | Cpm_jz4780_chip::get_epll_frequency() |
paul@0 | 638 | { |
paul@0 | 639 | return get_pll_frequency(Pll_control_E); |
paul@0 | 640 | } |
paul@0 | 641 | |
paul@0 | 642 | uint32_t |
paul@0 | 643 | Cpm_jz4780_chip::get_mpll_frequency() |
paul@0 | 644 | { |
paul@0 | 645 | return get_pll_frequency(Pll_control_M); |
paul@0 | 646 | } |
paul@0 | 647 | |
paul@0 | 648 | uint32_t |
paul@0 | 649 | Cpm_jz4780_chip::get_vpll_frequency() |
paul@0 | 650 | { |
paul@0 | 651 | return get_pll_frequency(Pll_control_V); |
paul@0 | 652 | } |
paul@0 | 653 | |
paul@0 | 654 | |
paul@0 | 655 | |
paul@0 | 656 | // Set the pixel frequency. |
paul@0 | 657 | // Unlike the jz4740, HCLK/AHB0 is used as the device frequency, with the pixel |
paul@0 | 658 | // frequency being based on the selected clock source (SCLK_A, MPLL or VPLL). |
paul@0 | 659 | |
paul@0 | 660 | void |
paul@0 | 661 | Cpm_jz4780_chip::set_lcd_pixel_frequency(uint32_t pclk) |
paul@0 | 662 | { |
paul@0 | 663 | // Switch to the video PLL and attempt to set the divider. |
paul@0 | 664 | |
paul@0 | 665 | set_lcd_source(Source_pll_V); |
paul@0 | 666 | set_lcd_pixel_divider(get_lcd_source_frequency() / pclk); |
paul@0 | 667 | } |
paul@0 | 668 | |
paul@0 | 669 | // NOTE: Compatibility method. Probably needs reviewing. |
paul@0 | 670 | |
paul@0 | 671 | void |
paul@0 | 672 | Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio) |
paul@0 | 673 | { |
paul@0 | 674 | (void) ratio; |
paul@0 | 675 | set_lcd_pixel_frequency(pclk); |
paul@0 | 676 | } |
paul@0 | 677 | |
paul@0 | 678 | // NOTE: Empty method for compatibility. |
paul@0 | 679 | |
paul@0 | 680 | void |
paul@0 | 681 | Cpm_jz4780_chip::update_output_frequency() |
paul@0 | 682 | { |
paul@0 | 683 | } |
paul@0 | 684 | |
paul@0 | 685 | |
paul@0 | 686 | |
paul@0 | 687 | // C language interface functions. |
paul@0 | 688 | |
paul@0 | 689 | void |
paul@0 | 690 | *jz4780_cpm_init(l4_addr_t cpm_base) |
paul@0 | 691 | { |
paul@0 | 692 | /* Initialise the clock and power management peripheral with the |
paul@0 | 693 | register memory region and a 48MHz EXCLK frequency. */ |
paul@0 | 694 | |
paul@0 | 695 | return (void *) new Cpm_jz4780_chip(cpm_base, 48000000, 32768); |
paul@0 | 696 | } |
paul@0 | 697 | |
paul@0 | 698 | int |
paul@0 | 699 | jz4780_cpm_have_clock(void *cpm) |
paul@0 | 700 | { |
paul@0 | 701 | return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(); |
paul@0 | 702 | } |
paul@0 | 703 | |
paul@0 | 704 | void |
paul@0 | 705 | jz4780_cpm_start_clock(void *cpm) |
paul@0 | 706 | { |
paul@0 | 707 | static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(); |
paul@0 | 708 | } |
paul@0 | 709 | |
paul@0 | 710 | |
paul@0 | 711 | |
paul@0 | 712 | void |
paul@0 | 713 | jz4780_cpm_start_lcd(void *cpm) |
paul@0 | 714 | { |
paul@0 | 715 | static_cast<Cpm_jz4780_chip *>(cpm)->start_lcd(); |
paul@0 | 716 | } |
paul@0 | 717 | |
paul@0 | 718 | void |
paul@0 | 719 | jz4780_cpm_stop_lcd(void *cpm) |
paul@0 | 720 | { |
paul@0 | 721 | static_cast<Cpm_jz4780_chip *>(cpm)->stop_lcd(); |
paul@0 | 722 | } |
paul@0 | 723 | |
paul@0 | 724 | |
paul@0 | 725 | |
paul@0 | 726 | uint8_t |
paul@0 | 727 | jz4780_cpm_get_cpu_divider(void *cpm) |
paul@0 | 728 | { |
paul@0 | 729 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_divider(); |
paul@0 | 730 | } |
paul@0 | 731 | |
paul@0 | 732 | uint8_t |
paul@0 | 733 | jz4780_cpm_get_hclock0_divider(void *cpm) |
paul@0 | 734 | { |
paul@0 | 735 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_divider(); |
paul@0 | 736 | } |
paul@0 | 737 | |
paul@0 | 738 | uint8_t |
paul@0 | 739 | jz4780_cpm_get_hclock2_divider(void *cpm) |
paul@0 | 740 | { |
paul@0 | 741 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_divider(); |
paul@0 | 742 | } |
paul@0 | 743 | |
paul@0 | 744 | uint8_t |
paul@0 | 745 | jz4780_cpm_get_lcd_pixel_divider(void *cpm) |
paul@0 | 746 | { |
paul@0 | 747 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_divider(); |
paul@0 | 748 | } |
paul@0 | 749 | |
paul@0 | 750 | uint8_t |
paul@0 | 751 | jz4780_cpm_get_memory_divider(void *cpm) |
paul@0 | 752 | { |
paul@0 | 753 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_divider(); |
paul@0 | 754 | } |
paul@0 | 755 | |
paul@0 | 756 | uint8_t |
paul@0 | 757 | jz4780_cpm_get_pclock_divider(void *cpm) |
paul@0 | 758 | { |
paul@0 | 759 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_divider(); |
paul@0 | 760 | } |
paul@0 | 761 | |
paul@0 | 762 | |
paul@0 | 763 | |
paul@0 | 764 | uint8_t |
paul@0 | 765 | jz4780_cpm_get_hclock0_source(void *cpm) |
paul@0 | 766 | { |
paul@0 | 767 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source(); |
paul@0 | 768 | } |
paul@0 | 769 | |
paul@0 | 770 | uint8_t |
paul@0 | 771 | jz4780_cpm_get_hclock2_source(void *cpm) |
paul@0 | 772 | { |
paul@0 | 773 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source(); |
paul@0 | 774 | } |
paul@0 | 775 | |
paul@0 | 776 | uint8_t |
paul@0 | 777 | jz4780_cpm_get_lcd_source(void *cpm) |
paul@0 | 778 | { |
paul@0 | 779 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source(); |
paul@0 | 780 | } |
paul@0 | 781 | |
paul@0 | 782 | uint8_t |
paul@0 | 783 | jz4780_cpm_get_memory_source(void *cpm) |
paul@0 | 784 | { |
paul@0 | 785 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source(); |
paul@0 | 786 | } |
paul@0 | 787 | |
paul@0 | 788 | uint8_t |
paul@0 | 789 | jz4780_cpm_get_pclock_source(void *cpm) |
paul@0 | 790 | { |
paul@0 | 791 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source(); |
paul@0 | 792 | } |
paul@0 | 793 | |
paul@0 | 794 | void |
paul@0 | 795 | jz4780_cpm_set_pclock_source(void *cpm, uint8_t source) |
paul@0 | 796 | { |
paul@0 | 797 | static_cast<Cpm_jz4780_chip *>(cpm)->set_pclock_source(source); |
paul@0 | 798 | } |
paul@0 | 799 | |
paul@0 | 800 | |
paul@0 | 801 | |
paul@0 | 802 | uint32_t |
paul@0 | 803 | jz4780_cpm_get_hclock0_source_frequency(void *cpm) |
paul@0 | 804 | { |
paul@0 | 805 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source_frequency(); |
paul@0 | 806 | } |
paul@0 | 807 | |
paul@0 | 808 | uint32_t |
paul@0 | 809 | jz4780_cpm_get_hclock2_source_frequency(void *cpm) |
paul@0 | 810 | { |
paul@0 | 811 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source_frequency(); |
paul@0 | 812 | } |
paul@0 | 813 | |
paul@0 | 814 | uint32_t |
paul@0 | 815 | jz4780_cpm_get_lcd_source_frequency(void *cpm) |
paul@0 | 816 | { |
paul@0 | 817 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source_frequency(); |
paul@0 | 818 | } |
paul@0 | 819 | |
paul@0 | 820 | uint32_t |
paul@0 | 821 | jz4780_cpm_get_memory_source_frequency(void *cpm) |
paul@0 | 822 | { |
paul@0 | 823 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source_frequency(); |
paul@0 | 824 | } |
paul@0 | 825 | |
paul@0 | 826 | uint32_t |
paul@0 | 827 | jz4780_cpm_get_pclock_source_frequency(void *cpm) |
paul@0 | 828 | { |
paul@0 | 829 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source_frequency(); |
paul@0 | 830 | } |
paul@0 | 831 | |
paul@0 | 832 | |
paul@0 | 833 | |
paul@0 | 834 | uint8_t |
paul@0 | 835 | jz4780_cpm_get_main_source(void *cpm) |
paul@0 | 836 | { |
paul@0 | 837 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_source(); |
paul@0 | 838 | } |
paul@0 | 839 | |
paul@0 | 840 | uint32_t |
paul@0 | 841 | jz4780_cpm_get_main_frequency(void *cpm) |
paul@0 | 842 | { |
paul@0 | 843 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_frequency(); |
paul@0 | 844 | } |
paul@0 | 845 | |
paul@0 | 846 | uint32_t |
paul@0 | 847 | jz4780_cpm_get_cpu_frequency(void *cpm) |
paul@0 | 848 | { |
paul@0 | 849 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_frequency(); |
paul@0 | 850 | } |
paul@0 | 851 | |
paul@0 | 852 | uint32_t |
paul@0 | 853 | jz4780_cpm_get_hclock0_frequency(void *cpm) |
paul@0 | 854 | { |
paul@0 | 855 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_frequency(); |
paul@0 | 856 | } |
paul@0 | 857 | |
paul@0 | 858 | uint32_t |
paul@0 | 859 | jz4780_cpm_get_hclock2_frequency(void *cpm) |
paul@0 | 860 | { |
paul@0 | 861 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_frequency(); |
paul@0 | 862 | } |
paul@0 | 863 | |
paul@0 | 864 | uint32_t |
paul@0 | 865 | jz4780_cpm_get_lcd_pixel_frequency(void *cpm) |
paul@0 | 866 | { |
paul@0 | 867 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_frequency(); |
paul@0 | 868 | } |
paul@0 | 869 | |
paul@0 | 870 | uint32_t |
paul@0 | 871 | jz4780_cpm_get_memory_frequency(void *cpm) |
paul@0 | 872 | { |
paul@0 | 873 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_frequency(); |
paul@0 | 874 | } |
paul@0 | 875 | |
paul@0 | 876 | uint32_t |
paul@0 | 877 | jz4780_cpm_get_pclock_frequency(void *cpm) |
paul@0 | 878 | { |
paul@0 | 879 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_frequency(); |
paul@0 | 880 | } |
paul@0 | 881 | |
paul@0 | 882 | uint32_t |
paul@0 | 883 | jz4780_cpm_get_apll_frequency(void *cpm) |
paul@0 | 884 | { |
paul@0 | 885 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_apll_frequency(); |
paul@0 | 886 | } |
paul@0 | 887 | |
paul@0 | 888 | uint32_t |
paul@0 | 889 | jz4780_cpm_get_epll_frequency(void *cpm) |
paul@0 | 890 | { |
paul@0 | 891 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_epll_frequency(); |
paul@0 | 892 | } |
paul@0 | 893 | |
paul@0 | 894 | uint32_t |
paul@0 | 895 | jz4780_cpm_get_mpll_frequency(void *cpm) |
paul@0 | 896 | { |
paul@0 | 897 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_mpll_frequency(); |
paul@0 | 898 | } |
paul@0 | 899 | |
paul@0 | 900 | uint32_t |
paul@0 | 901 | jz4780_cpm_get_vpll_frequency(void *cpm) |
paul@0 | 902 | { |
paul@0 | 903 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_vpll_frequency(); |
paul@0 | 904 | } |
paul@0 | 905 | |
paul@0 | 906 | |
paul@0 | 907 | |
paul@0 | 908 | void |
paul@0 | 909 | jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk) |
paul@0 | 910 | { |
paul@0 | 911 | static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_pixel_frequency(pclk); |
paul@0 | 912 | } |
paul@0 | 913 | |
paul@0 | 914 | void |
paul@0 | 915 | jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) |
paul@0 | 916 | { |
paul@0 | 917 | static_cast<Cpm_jz4780_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider); |
paul@0 | 918 | } |