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@62 | 6 | * Copyright (C) 2017, 2018, 2020 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@62 | 51 | |
paul@62 | 52 | // ... |
paul@62 | 53 | |
paul@62 | 54 | Hdmi_divider = 0x08c, // HDMICDR |
paul@62 | 55 | |
paul@62 | 56 | // ... |
paul@0 | 57 | }; |
paul@0 | 58 | |
paul@0 | 59 | enum Clock_bits : unsigned |
paul@0 | 60 | { |
paul@0 | 61 | Clock_enable = 22, // CE_CPU |
paul@0 | 62 | Clock_pclock_divider = 16, // PDIV (slow APB peripherals) |
paul@0 | 63 | Clock_hclock2_divider = 12, // H2DIV (fast AHB peripherals) |
paul@0 | 64 | Clock_hclock0_divider = 8, // H0DIV (fast AHB peripherals) |
paul@0 | 65 | Clock_cpu_divider = 0, // CDIV |
paul@0 | 66 | }; |
paul@0 | 67 | |
paul@0 | 68 | enum Pll_bits : unsigned |
paul@0 | 69 | { |
paul@0 | 70 | Pll_multiplier = 19, // xPLLM |
paul@0 | 71 | Pll_input_division = 13, // xPLLN |
paul@0 | 72 | Pll_output_division = 9, // xPLLOD |
paul@0 | 73 | Pll_stable = 4, // xPLL_ON |
paul@0 | 74 | Pll_bypassed = 1, // xPLLBP |
paul@0 | 75 | Pll_enabled = 0, // xPLLEN |
paul@0 | 76 | }; |
paul@0 | 77 | |
paul@0 | 78 | enum Clock_source_bits : unsigned |
paul@0 | 79 | { |
paul@0 | 80 | Clock_source_main = 30, // SEL_SRC (output to SCLK_A) |
paul@0 | 81 | Clock_source_cpu = 28, // SEL_CPLL (output to CCLK) |
paul@0 | 82 | Clock_source_hclock0 = 26, // SEL_H0PLL (output to AHB0) |
paul@0 | 83 | Clock_source_hclock2 = 24, // SEL_H2PLL (output to AHB2) |
paul@0 | 84 | Clock_source_ddr = 30, // DCS |
paul@0 | 85 | Clock_source_i2s = 31, // I2CS |
paul@0 | 86 | Clock_source_lcd = 30, // LPCS |
paul@62 | 87 | Clock_source_hdmi = 30, // HPCS |
paul@0 | 88 | }; |
paul@0 | 89 | |
paul@0 | 90 | enum Clock_sources : unsigned |
paul@0 | 91 | { |
paul@62 | 92 | // Main clock sources. |
paul@62 | 93 | |
paul@0 | 94 | Source_pll_A = 1, // APLL |
paul@0 | 95 | Source_external = 2, // EXCLK |
paul@0 | 96 | Source_realtime = 3, // RTCLK |
paul@62 | 97 | |
paul@62 | 98 | // Stoppable clock sources. |
paul@62 | 99 | |
paul@62 | 100 | Source_mux_stopped = 0, |
paul@62 | 101 | Source_mux_main = 1, // SCLK_A |
paul@62 | 102 | Source_mux_pll_M = 2, // MPLL |
paul@62 | 103 | Source_mux_pll_E = 3, // EPLL |
paul@62 | 104 | Source_mux_realtime = 3, // RTCLK (TCK) |
paul@62 | 105 | |
paul@62 | 106 | // Unstoppable clock sources. |
paul@62 | 107 | |
paul@62 | 108 | Source_main = 0, // SCLK_A |
paul@62 | 109 | Source_pll_M = 1, // MPLL |
paul@62 | 110 | Source_pll_E = 2, // EPLL |
paul@62 | 111 | Source_pll_V = 2, // VPLL |
paul@62 | 112 | Source_otg_phy = 3, // OTG_PHY |
paul@0 | 113 | }; |
paul@0 | 114 | |
paul@0 | 115 | enum Clock_gate_bits : unsigned |
paul@0 | 116 | { |
paul@0 | 117 | Clock_gate_lcd = 28, // LCD (in CLKGR0) |
paul@0 | 118 | Clock_gate_tve = 27, // TVE (in CLKGR0) |
paul@62 | 119 | Clock_gate_hdmi = 9, // HDMI (in CLKGR1) |
paul@0 | 120 | Clock_gate_smb4 = 12, // SMB4 (in CLKGR1) |
paul@0 | 121 | Clock_gate_smb3 = 0, // SMB3 (in CLKGR1) |
paul@0 | 122 | Clock_gate_smb2 = 25, // SMB2 (in CLKGR0) |
paul@0 | 123 | Clock_gate_smb1 = 6, // SMB2 (in CLKGR0) |
paul@0 | 124 | Clock_gate_smb0 = 5, // SMB2 (in CLKGR0) |
paul@0 | 125 | }; |
paul@0 | 126 | |
paul@0 | 127 | enum Clock_gate_regs : unsigned |
paul@0 | 128 | { |
paul@0 | 129 | Clock_gate_reg_smb4 = Clock_gate1, |
paul@0 | 130 | Clock_gate_reg_smb3 = Clock_gate1, |
paul@0 | 131 | Clock_gate_reg_smb2 = Clock_gate0, |
paul@0 | 132 | Clock_gate_reg_smb1 = Clock_gate0, |
paul@0 | 133 | Clock_gate_reg_smb0 = Clock_gate0, |
paul@0 | 134 | }; |
paul@0 | 135 | |
paul@0 | 136 | enum Divider_bits : unsigned |
paul@0 | 137 | { |
paul@0 | 138 | Ddr_divider_value = 0, // DDRCDR |
paul@62 | 139 | Hdmi_divider_value = 0, // HDMICDR |
paul@0 | 140 | Lcd_divider_value = 0, // LPCDR |
paul@0 | 141 | }; |
paul@0 | 142 | |
paul@62 | 143 | enum Lcd_clock_values : unsigned |
paul@0 | 144 | { |
paul@62 | 145 | Lcd_change_enable = 0x10000000, // CE_LCD |
paul@62 | 146 | Lcd_change_busy = 0x08000000, // LCD_BUSY |
paul@62 | 147 | Lcd_clock_stop = 0x04000000, // LCD_STOP |
paul@62 | 148 | }; |
paul@62 | 149 | |
paul@62 | 150 | enum Hdmi_divider_values : unsigned |
paul@62 | 151 | { |
paul@62 | 152 | Hdmi_select_mask = 0xc0000000, // HPCS |
paul@62 | 153 | Hdmi_change_enable = 0x20000000, // CE_HDMI |
paul@62 | 154 | Hdmi_change_busy = 0x10000000, // HDMI_BUSY |
paul@62 | 155 | Hdmi_clock_stop = 0x08000000, // HDMI_STOP |
paul@0 | 156 | }; |
paul@0 | 157 | |
paul@0 | 158 | |
paul@0 | 159 | |
paul@0 | 160 | // If implemented as a Hw::Device, various properties would be |
paul@0 | 161 | // initialised in the constructor and obtained from the device tree |
paul@0 | 162 | // definitions. |
paul@0 | 163 | |
paul@0 | 164 | Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq) |
paul@0 | 165 | : _exclk_freq(exclk_freq), _rtclk_freq(rtclk_freq) |
paul@0 | 166 | { |
paul@0 | 167 | _regs = new Hw::Mmio_register_block<32>(addr); |
paul@0 | 168 | |
paul@0 | 169 | // add_cid("cpm"); |
paul@0 | 170 | // add_cid("cpm-jz4780"); |
paul@0 | 171 | // register_property("exclk_freq", &_exclk_freq); |
paul@0 | 172 | } |
paul@0 | 173 | |
paul@0 | 174 | // Clock/timer control. |
paul@0 | 175 | // NOTE: For the time being, assume that the system is configured. |
paul@0 | 176 | |
paul@0 | 177 | int |
paul@0 | 178 | Cpm_jz4780_chip::have_clock() |
paul@0 | 179 | { |
paul@0 | 180 | // return !(_regs[Clock_gate] & (1 << Clock_gate_timer)); |
paul@0 | 181 | return 1; |
paul@0 | 182 | } |
paul@0 | 183 | |
paul@0 | 184 | void |
paul@0 | 185 | Cpm_jz4780_chip::start_clock() |
paul@0 | 186 | { |
paul@0 | 187 | // _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer); |
paul@0 | 188 | } |
paul@0 | 189 | |
paul@0 | 190 | |
paul@0 | 191 | |
paul@0 | 192 | // Utility methods. |
paul@0 | 193 | |
paul@0 | 194 | uint32_t |
paul@0 | 195 | Cpm_jz4780_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift) |
paul@0 | 196 | { |
paul@0 | 197 | return (_regs[reg] & (mask << shift)) >> shift; |
paul@0 | 198 | } |
paul@0 | 199 | |
paul@0 | 200 | void |
paul@0 | 201 | Cpm_jz4780_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) |
paul@0 | 202 | { |
paul@0 | 203 | _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); |
paul@0 | 204 | } |
paul@0 | 205 | |
paul@0 | 206 | // General clock divider access. |
paul@0 | 207 | |
paul@0 | 208 | uint8_t |
paul@0 | 209 | Cpm_jz4780_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift) |
paul@0 | 210 | { |
paul@0 | 211 | uint8_t d = get_field(reg, mask, shift); |
paul@0 | 212 | |
paul@0 | 213 | // NOTE: Value 14 stops the clock, 15 presumably resumes the clock. |
paul@0 | 214 | |
paul@0 | 215 | return (d < 14) ? d + 1 : 1; |
paul@0 | 216 | } |
paul@0 | 217 | |
paul@0 | 218 | |
paul@0 | 219 | |
paul@0 | 220 | // PLL control. |
paul@0 | 221 | |
paul@0 | 222 | // Return whether the PLL is stable. |
paul@0 | 223 | |
paul@0 | 224 | int |
paul@0 | 225 | Cpm_jz4780_chip::have_pll(uint32_t pll_reg) |
paul@0 | 226 | { |
paul@0 | 227 | return _regs[pll_reg] & (1 << Pll_stable); |
paul@0 | 228 | } |
paul@0 | 229 | |
paul@0 | 230 | int |
paul@0 | 231 | Cpm_jz4780_chip::pll_enabled(uint32_t pll_reg) |
paul@0 | 232 | { |
paul@0 | 233 | return _regs[pll_reg] & (1 << Pll_enabled); |
paul@0 | 234 | } |
paul@0 | 235 | |
paul@0 | 236 | int |
paul@0 | 237 | Cpm_jz4780_chip::pll_bypassed(uint32_t pll_reg) |
paul@0 | 238 | { |
paul@0 | 239 | return _regs[pll_reg] & (1 << Pll_bypassed); |
paul@0 | 240 | } |
paul@0 | 241 | |
paul@0 | 242 | // Feedback (13-bit) multiplier. |
paul@0 | 243 | |
paul@0 | 244 | uint16_t |
paul@0 | 245 | Cpm_jz4780_chip::get_multiplier(uint32_t pll_reg) |
paul@0 | 246 | { |
paul@0 | 247 | return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1; |
paul@0 | 248 | } |
paul@0 | 249 | |
paul@0 | 250 | void |
paul@0 | 251 | Cpm_jz4780_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier) |
paul@0 | 252 | { |
paul@0 | 253 | set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1); |
paul@0 | 254 | } |
paul@0 | 255 | |
paul@0 | 256 | // Input (6-bit) divider. |
paul@0 | 257 | |
paul@0 | 258 | uint8_t |
paul@0 | 259 | Cpm_jz4780_chip::get_input_division(uint32_t pll_reg) |
paul@0 | 260 | { |
paul@0 | 261 | return get_field(pll_reg, 0x3f, Pll_input_division) + 1; |
paul@0 | 262 | } |
paul@0 | 263 | |
paul@0 | 264 | void |
paul@0 | 265 | Cpm_jz4780_chip::set_input_division(uint32_t pll_reg, uint8_t divider) |
paul@0 | 266 | { |
paul@0 | 267 | set_field(pll_reg, 0x3f, Pll_input_division, divider - 1); |
paul@0 | 268 | } |
paul@0 | 269 | |
paul@0 | 270 | // Output divider. |
paul@0 | 271 | |
paul@0 | 272 | uint8_t |
paul@0 | 273 | Cpm_jz4780_chip::get_output_division(uint32_t pll_reg) |
paul@0 | 274 | { |
paul@0 | 275 | uint8_t d = get_field(pll_reg, 0x0f, Pll_output_division); |
paul@0 | 276 | |
paul@0 | 277 | // Zero yields a division of one. Otherwise enforce even results. |
paul@0 | 278 | |
paul@0 | 279 | return d == 0 ? 1 : (d + 1) & 0x0e; |
paul@0 | 280 | } |
paul@0 | 281 | |
paul@0 | 282 | void |
paul@0 | 283 | Cpm_jz4780_chip::set_output_division(uint32_t pll_reg, uint8_t divider) |
paul@0 | 284 | { |
paul@0 | 285 | uint8_t d = divider <= 1 ? 0 : (divider & 0x0e) - 1; |
paul@0 | 286 | |
paul@0 | 287 | set_field(pll_reg, 0x0f, Pll_output_division, d); |
paul@0 | 288 | } |
paul@0 | 289 | |
paul@0 | 290 | uint32_t |
paul@0 | 291 | Cpm_jz4780_chip::get_pll_frequency(uint32_t pll_reg) |
paul@0 | 292 | { |
paul@0 | 293 | // Test for PLL enable and not PLL bypass. |
paul@0 | 294 | |
paul@0 | 295 | if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) |
paul@0 | 296 | return (_exclk_freq * get_multiplier(pll_reg)) / |
paul@0 | 297 | (get_input_division(pll_reg) * get_output_division(pll_reg)); |
paul@0 | 298 | else |
paul@0 | 299 | return _exclk_freq; |
paul@0 | 300 | } |
paul@0 | 301 | |
paul@0 | 302 | void |
paul@0 | 303 | Cpm_jz4780_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) |
paul@0 | 304 | { |
paul@0 | 305 | set_multiplier(pll_reg, multiplier); |
paul@0 | 306 | set_input_division(pll_reg, in_divider); |
paul@0 | 307 | set_output_division(pll_reg, out_divider); |
paul@0 | 308 | |
paul@0 | 309 | if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) |
paul@0 | 310 | while (!have_pll(pll_reg)); |
paul@0 | 311 | } |
paul@0 | 312 | |
paul@0 | 313 | |
paul@0 | 314 | |
paul@0 | 315 | // CPU clock (CCLK) divider. |
paul@0 | 316 | |
paul@0 | 317 | uint8_t |
paul@0 | 318 | Cpm_jz4780_chip::get_cpu_divider() |
paul@0 | 319 | { |
paul@0 | 320 | return _get_divider(Clock_control, 0xf, Clock_cpu_divider); |
paul@0 | 321 | } |
paul@0 | 322 | |
paul@0 | 323 | // Fast peripheral clock (H0CLK) divider. |
paul@0 | 324 | |
paul@0 | 325 | uint8_t |
paul@0 | 326 | Cpm_jz4780_chip::get_hclock0_divider() |
paul@0 | 327 | { |
paul@0 | 328 | return _get_divider(Clock_control, 0xf, Clock_hclock0_divider); |
paul@0 | 329 | } |
paul@0 | 330 | |
paul@0 | 331 | // Fast peripheral clock (H2CLK) divider. |
paul@0 | 332 | |
paul@0 | 333 | uint8_t |
paul@0 | 334 | Cpm_jz4780_chip::get_hclock2_divider() |
paul@0 | 335 | { |
paul@0 | 336 | return _get_divider(Clock_control, 0xf, Clock_hclock2_divider); |
paul@0 | 337 | } |
paul@0 | 338 | |
paul@0 | 339 | // Slow peripheral clock (PCLK) divider. |
paul@0 | 340 | |
paul@0 | 341 | uint8_t |
paul@0 | 342 | Cpm_jz4780_chip::get_pclock_divider() |
paul@0 | 343 | { |
paul@0 | 344 | return _get_divider(Clock_control, 0xf, Clock_pclock_divider); |
paul@0 | 345 | } |
paul@0 | 346 | |
paul@62 | 347 | // HDMI clock divider. |
paul@62 | 348 | |
paul@62 | 349 | uint8_t |
paul@62 | 350 | Cpm_jz4780_chip::get_hdmi_divider() |
paul@62 | 351 | { |
paul@62 | 352 | return get_field(Hdmi_divider, 0xff, Hdmi_divider_value) + 1; |
paul@62 | 353 | } |
paul@62 | 354 | |
paul@0 | 355 | // LCD clock (LPCLK) divider for LCD0 pixel clock. |
paul@0 | 356 | |
paul@0 | 357 | uint8_t |
paul@0 | 358 | Cpm_jz4780_chip::get_lcd_pixel_divider() |
paul@0 | 359 | { |
paul@0 | 360 | return get_field(Lcd_divider0, 0xff, Lcd_divider_value) + 1; |
paul@0 | 361 | } |
paul@0 | 362 | |
paul@0 | 363 | // Memory clock (DDR_CLK) divider. |
paul@0 | 364 | |
paul@0 | 365 | uint8_t |
paul@0 | 366 | Cpm_jz4780_chip::get_memory_divider() |
paul@0 | 367 | { |
paul@0 | 368 | return _get_divider(Ddr_divider, 0xf, Ddr_divider_value); |
paul@0 | 369 | } |
paul@0 | 370 | |
paul@62 | 371 | // HDMI clock divider. |
paul@62 | 372 | |
paul@62 | 373 | void |
paul@62 | 374 | Cpm_jz4780_chip::set_hdmi_divider(uint16_t division) |
paul@62 | 375 | { |
paul@62 | 376 | if ((division < 1) || (division > 256)) |
paul@62 | 377 | return; |
paul@62 | 378 | |
paul@62 | 379 | // Enable change. |
paul@62 | 380 | |
paul@62 | 381 | _regs[Hdmi_divider] = _regs[Hdmi_divider] | Hdmi_change_enable; |
paul@62 | 382 | |
paul@62 | 383 | // Set the divider. |
paul@62 | 384 | |
paul@62 | 385 | set_field(Hdmi_divider, 0xff, Hdmi_divider_value, division - 1); |
paul@62 | 386 | |
paul@62 | 387 | // Restart clock and disable change. |
paul@62 | 388 | |
paul@62 | 389 | while (_regs[Hdmi_divider] & Hdmi_change_busy); |
paul@62 | 390 | _regs[Hdmi_divider] = _regs[Hdmi_divider] & ~Hdmi_change_enable; |
paul@62 | 391 | } |
paul@62 | 392 | |
paul@0 | 393 | // LCD pixel clock divider. |
paul@0 | 394 | // NOTE: This only supports the first LCD peripheral. |
paul@0 | 395 | |
paul@0 | 396 | void |
paul@0 | 397 | Cpm_jz4780_chip::set_lcd_pixel_divider(uint16_t division) |
paul@0 | 398 | { |
paul@0 | 399 | if ((division < 1) || (division > 256)) |
paul@0 | 400 | return; |
paul@0 | 401 | |
paul@0 | 402 | // Enable change. |
paul@0 | 403 | |
paul@0 | 404 | _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable; |
paul@0 | 405 | |
paul@0 | 406 | // Set the divider. |
paul@0 | 407 | |
paul@0 | 408 | set_field(Lcd_divider0, 0xff, Lcd_divider_value, division - 1); |
paul@0 | 409 | |
paul@0 | 410 | // Restart clock and disable change. |
paul@0 | 411 | |
paul@0 | 412 | while (_regs[Lcd_divider0] & Lcd_change_busy); |
paul@0 | 413 | _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~Lcd_change_enable; |
paul@0 | 414 | } |
paul@0 | 415 | |
paul@0 | 416 | |
paul@0 | 417 | |
paul@0 | 418 | // Clock gating control. |
paul@0 | 419 | |
paul@0 | 420 | void |
paul@62 | 421 | Cpm_jz4780_chip::start_hdmi() |
paul@62 | 422 | { |
paul@62 | 423 | _regs[Clock_gate1] = _regs[Clock_gate1] & ~(1 << Clock_gate_hdmi); |
paul@62 | 424 | } |
paul@62 | 425 | |
paul@62 | 426 | void |
paul@62 | 427 | Cpm_jz4780_chip::stop_hdmi() |
paul@62 | 428 | { |
paul@62 | 429 | _regs[Clock_gate1] = _regs[Clock_gate1] | (1 << Clock_gate_hdmi); |
paul@62 | 430 | } |
paul@62 | 431 | |
paul@62 | 432 | void |
paul@0 | 433 | Cpm_jz4780_chip::start_lcd() |
paul@0 | 434 | { |
paul@0 | 435 | _regs[Clock_gate0] = _regs[Clock_gate0] & ~(1 << Clock_gate_lcd); |
paul@0 | 436 | } |
paul@0 | 437 | |
paul@0 | 438 | void |
paul@0 | 439 | Cpm_jz4780_chip::stop_lcd() |
paul@0 | 440 | { |
paul@0 | 441 | _regs[Clock_gate0] = _regs[Clock_gate0] | (1 << Clock_gate_lcd); |
paul@0 | 442 | } |
paul@0 | 443 | |
paul@0 | 444 | void |
paul@0 | 445 | Cpm_jz4780_chip::_update_i2c(uint8_t channel, int enable) |
paul@0 | 446 | { |
paul@0 | 447 | uint8_t bit; |
paul@0 | 448 | uint32_t reg; |
paul@0 | 449 | switch (channel) |
paul@0 | 450 | { |
paul@0 | 451 | case 0: bit = Clock_gate_smb0; reg = Clock_gate_reg_smb0; break; |
paul@0 | 452 | case 1: bit = Clock_gate_smb1; reg = Clock_gate_reg_smb1; break; |
paul@0 | 453 | case 2: bit = Clock_gate_smb2; reg = Clock_gate_reg_smb2; break; |
paul@0 | 454 | case 3: bit = Clock_gate_smb3; reg = Clock_gate_reg_smb3; break; |
paul@0 | 455 | case 4: bit = Clock_gate_smb4; reg = Clock_gate_reg_smb4; break; |
paul@0 | 456 | default: return; |
paul@0 | 457 | } |
paul@0 | 458 | if (enable) |
paul@0 | 459 | _regs[reg] = _regs[reg] & ~(1 << bit); |
paul@0 | 460 | else |
paul@0 | 461 | _regs[reg] = _regs[reg] | (1 << bit); |
paul@0 | 462 | } |
paul@0 | 463 | |
paul@0 | 464 | void |
paul@0 | 465 | Cpm_jz4780_chip::start_i2c(uint8_t channel) |
paul@0 | 466 | { |
paul@0 | 467 | _update_i2c(channel, 1); |
paul@0 | 468 | } |
paul@0 | 469 | |
paul@0 | 470 | void |
paul@0 | 471 | Cpm_jz4780_chip::stop_i2c(uint8_t channel) |
paul@0 | 472 | { |
paul@0 | 473 | _update_i2c(channel, 0); |
paul@0 | 474 | } |
paul@0 | 475 | |
paul@0 | 476 | |
paul@0 | 477 | |
paul@0 | 478 | // Clock sources. |
paul@0 | 479 | |
paul@0 | 480 | uint8_t |
paul@0 | 481 | Cpm_jz4780_chip::get_memory_source() |
paul@0 | 482 | { |
paul@0 | 483 | return get_field(Ddr_divider, 0x3, Clock_source_ddr); |
paul@0 | 484 | } |
paul@0 | 485 | |
paul@0 | 486 | uint32_t |
paul@0 | 487 | Cpm_jz4780_chip::get_memory_source_frequency() |
paul@0 | 488 | { |
paul@0 | 489 | switch (get_memory_source()) |
paul@0 | 490 | { |
paul@62 | 491 | case Source_mux_main: |
paul@0 | 492 | return get_main_frequency(); |
paul@62 | 493 | case Source_mux_pll_M: |
paul@0 | 494 | return get_pll_frequency(Pll_control_M); |
paul@0 | 495 | default: |
paul@0 | 496 | return 0; |
paul@0 | 497 | } |
paul@0 | 498 | } |
paul@0 | 499 | |
paul@0 | 500 | uint8_t |
paul@0 | 501 | Cpm_jz4780_chip::get_cpu_source() |
paul@0 | 502 | { |
paul@0 | 503 | return get_field(Clock_control, 0x3, Clock_source_cpu); |
paul@0 | 504 | } |
paul@0 | 505 | |
paul@0 | 506 | uint32_t |
paul@0 | 507 | Cpm_jz4780_chip::get_cpu_source_frequency() |
paul@0 | 508 | { |
paul@0 | 509 | switch (get_cpu_source()) |
paul@0 | 510 | { |
paul@62 | 511 | case Source_mux_main: |
paul@0 | 512 | return get_main_frequency(); |
paul@62 | 513 | case Source_mux_pll_M: |
paul@0 | 514 | return get_pll_frequency(Pll_control_M); |
paul@62 | 515 | case Source_mux_pll_E: |
paul@0 | 516 | return get_pll_frequency(Pll_control_E); |
paul@0 | 517 | default: |
paul@0 | 518 | return 0; |
paul@0 | 519 | } |
paul@0 | 520 | } |
paul@0 | 521 | |
paul@0 | 522 | uint8_t |
paul@0 | 523 | Cpm_jz4780_chip::get_hclock0_source() |
paul@0 | 524 | { |
paul@0 | 525 | return get_field(Clock_control, 0x3, Clock_source_hclock0); |
paul@0 | 526 | } |
paul@0 | 527 | |
paul@0 | 528 | uint32_t |
paul@0 | 529 | Cpm_jz4780_chip::get_hclock0_source_frequency() |
paul@0 | 530 | { |
paul@0 | 531 | switch (get_hclock0_source()) |
paul@0 | 532 | { |
paul@62 | 533 | case Source_mux_main: |
paul@0 | 534 | return get_main_frequency(); |
paul@62 | 535 | case Source_mux_pll_M: |
paul@0 | 536 | return get_pll_frequency(Pll_control_M); |
paul@62 | 537 | case Source_mux_pll_E: |
paul@0 | 538 | return get_pll_frequency(Pll_control_E); |
paul@0 | 539 | default: |
paul@0 | 540 | return 0; |
paul@0 | 541 | } |
paul@0 | 542 | } |
paul@0 | 543 | |
paul@0 | 544 | uint8_t |
paul@0 | 545 | Cpm_jz4780_chip::get_hclock2_source() |
paul@0 | 546 | { |
paul@0 | 547 | return get_field(Clock_control, 0x3, Clock_source_hclock2); |
paul@0 | 548 | } |
paul@0 | 549 | |
paul@0 | 550 | uint32_t |
paul@0 | 551 | Cpm_jz4780_chip::get_hclock2_source_frequency() |
paul@0 | 552 | { |
paul@0 | 553 | switch (get_hclock2_source()) |
paul@0 | 554 | { |
paul@62 | 555 | case Source_mux_main: |
paul@0 | 556 | return get_main_frequency(); |
paul@62 | 557 | case Source_mux_pll_M: |
paul@0 | 558 | return get_pll_frequency(Pll_control_M); |
paul@62 | 559 | case Source_mux_realtime: |
paul@0 | 560 | return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code |
paul@0 | 561 | default: |
paul@0 | 562 | return 0; |
paul@0 | 563 | } |
paul@0 | 564 | } |
paul@0 | 565 | |
paul@0 | 566 | void |
paul@0 | 567 | Cpm_jz4780_chip::set_hclock2_source(uint8_t source) |
paul@0 | 568 | { |
paul@0 | 569 | set_field(Clock_control, 0x3, Clock_source_hclock2, source); |
paul@0 | 570 | } |
paul@0 | 571 | |
paul@0 | 572 | uint8_t |
paul@62 | 573 | Cpm_jz4780_chip::get_hdmi_source() |
paul@62 | 574 | { |
paul@62 | 575 | return get_field(Hdmi_divider, 0x3, Clock_source_hdmi); |
paul@62 | 576 | } |
paul@62 | 577 | |
paul@62 | 578 | uint32_t |
paul@62 | 579 | Cpm_jz4780_chip::get_hdmi_source_frequency() |
paul@62 | 580 | { |
paul@62 | 581 | switch (get_hdmi_source()) |
paul@62 | 582 | { |
paul@62 | 583 | case Source_main: |
paul@62 | 584 | return get_main_frequency(); |
paul@62 | 585 | case Source_pll_M: |
paul@62 | 586 | return get_pll_frequency(Pll_control_M); |
paul@62 | 587 | case Source_pll_V: |
paul@62 | 588 | return get_pll_frequency(Pll_control_V); |
paul@62 | 589 | default: |
paul@62 | 590 | return 0; |
paul@62 | 591 | } |
paul@62 | 592 | } |
paul@62 | 593 | |
paul@62 | 594 | void |
paul@62 | 595 | Cpm_jz4780_chip::set_hdmi_source(uint8_t source) |
paul@62 | 596 | { |
paul@62 | 597 | // Stop clock and enable change. |
paul@62 | 598 | |
paul@62 | 599 | _regs[Hdmi_divider] = _regs[Hdmi_divider] | Hdmi_change_enable | Hdmi_clock_stop; |
paul@62 | 600 | |
paul@62 | 601 | // Set the source. |
paul@62 | 602 | |
paul@62 | 603 | set_field(Hdmi_divider, 0x03, Clock_source_hdmi, source); |
paul@62 | 604 | |
paul@62 | 605 | // Restart clock and disable change. |
paul@62 | 606 | |
paul@62 | 607 | while (_regs[Hdmi_divider] & Hdmi_change_busy); |
paul@62 | 608 | _regs[Hdmi_divider] = _regs[Hdmi_divider] & ~(Hdmi_change_enable | Hdmi_clock_stop); |
paul@62 | 609 | } |
paul@62 | 610 | |
paul@62 | 611 | uint8_t |
paul@0 | 612 | Cpm_jz4780_chip::get_lcd_source() |
paul@0 | 613 | { |
paul@0 | 614 | return get_field(Lcd_divider0, 0x3, Clock_source_lcd); |
paul@0 | 615 | } |
paul@0 | 616 | |
paul@0 | 617 | uint32_t |
paul@0 | 618 | Cpm_jz4780_chip::get_lcd_source_frequency() |
paul@0 | 619 | { |
paul@0 | 620 | switch (get_lcd_source()) |
paul@0 | 621 | { |
paul@62 | 622 | case Source_main: |
paul@0 | 623 | return get_main_frequency(); |
paul@0 | 624 | case Source_pll_M: |
paul@0 | 625 | return get_pll_frequency(Pll_control_M); |
paul@0 | 626 | case Source_pll_V: |
paul@0 | 627 | return get_pll_frequency(Pll_control_V); |
paul@0 | 628 | default: |
paul@0 | 629 | return 0; |
paul@0 | 630 | } |
paul@0 | 631 | } |
paul@0 | 632 | |
paul@0 | 633 | void |
paul@0 | 634 | Cpm_jz4780_chip::set_lcd_source(uint8_t source) |
paul@0 | 635 | { |
paul@0 | 636 | // Stop clock and enable change. |
paul@0 | 637 | |
paul@0 | 638 | _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable | Lcd_clock_stop; |
paul@0 | 639 | |
paul@0 | 640 | // Set the source. |
paul@0 | 641 | |
paul@0 | 642 | set_field(Lcd_divider0, 0x03, Clock_source_lcd, source); |
paul@0 | 643 | |
paul@0 | 644 | // Restart clock and disable change. |
paul@0 | 645 | |
paul@0 | 646 | while (_regs[Lcd_divider0] & Lcd_change_busy); |
paul@0 | 647 | _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~(Lcd_change_enable | Lcd_clock_stop); |
paul@0 | 648 | } |
paul@0 | 649 | |
paul@0 | 650 | uint8_t |
paul@0 | 651 | Cpm_jz4780_chip::get_pclock_source() |
paul@0 | 652 | { |
paul@0 | 653 | return get_hclock2_source(); |
paul@0 | 654 | } |
paul@0 | 655 | |
paul@0 | 656 | uint32_t |
paul@0 | 657 | Cpm_jz4780_chip::get_pclock_source_frequency() |
paul@0 | 658 | { |
paul@0 | 659 | return get_hclock2_source_frequency(); |
paul@0 | 660 | } |
paul@0 | 661 | |
paul@0 | 662 | void |
paul@0 | 663 | Cpm_jz4780_chip::set_pclock_source(uint8_t source) |
paul@0 | 664 | { |
paul@0 | 665 | set_hclock2_source(source); |
paul@0 | 666 | } |
paul@0 | 667 | |
paul@0 | 668 | |
paul@0 | 669 | |
paul@0 | 670 | // Source frequency, used by various clock sources. |
paul@0 | 671 | |
paul@0 | 672 | uint8_t |
paul@0 | 673 | Cpm_jz4780_chip::get_main_source() |
paul@0 | 674 | { |
paul@0 | 675 | return get_field(Clock_control, 0x3, Clock_source_main); |
paul@0 | 676 | } |
paul@0 | 677 | |
paul@0 | 678 | uint32_t |
paul@0 | 679 | Cpm_jz4780_chip::get_main_frequency() |
paul@0 | 680 | { |
paul@0 | 681 | switch (get_main_source()) |
paul@0 | 682 | { |
paul@0 | 683 | case Source_pll_A: |
paul@0 | 684 | return get_pll_frequency(Pll_control_A); |
paul@0 | 685 | case Source_external: |
paul@0 | 686 | return _exclk_freq; |
paul@0 | 687 | case Source_realtime: |
paul@0 | 688 | return _rtclk_freq; |
paul@0 | 689 | default: |
paul@0 | 690 | return 0; |
paul@0 | 691 | } |
paul@0 | 692 | } |
paul@0 | 693 | |
paul@0 | 694 | // Clock frequency for the CPU. |
paul@0 | 695 | |
paul@0 | 696 | uint32_t |
paul@0 | 697 | Cpm_jz4780_chip::get_cpu_frequency() |
paul@0 | 698 | { |
paul@0 | 699 | return get_cpu_source_frequency() / get_cpu_divider(); |
paul@0 | 700 | } |
paul@0 | 701 | |
paul@0 | 702 | // Clock frequency for fast peripherals. |
paul@0 | 703 | |
paul@0 | 704 | uint32_t |
paul@0 | 705 | Cpm_jz4780_chip::get_hclock0_frequency() |
paul@0 | 706 | { |
paul@0 | 707 | return get_hclock0_source_frequency() / get_hclock0_divider(); |
paul@0 | 708 | } |
paul@0 | 709 | |
paul@0 | 710 | // Clock frequency for fast peripherals. |
paul@0 | 711 | |
paul@0 | 712 | uint32_t |
paul@0 | 713 | Cpm_jz4780_chip::get_hclock2_frequency() |
paul@0 | 714 | { |
paul@0 | 715 | return get_hclock2_source_frequency() / get_hclock2_divider(); |
paul@0 | 716 | } |
paul@0 | 717 | |
paul@0 | 718 | // Clock frequency for slow peripherals. |
paul@0 | 719 | |
paul@0 | 720 | uint32_t |
paul@0 | 721 | Cpm_jz4780_chip::get_pclock_frequency() |
paul@0 | 722 | { |
paul@0 | 723 | return get_pclock_source_frequency() / get_pclock_divider(); |
paul@0 | 724 | } |
paul@0 | 725 | |
paul@62 | 726 | // Clock frequency for the HDMI peripheral. |
paul@62 | 727 | |
paul@62 | 728 | uint32_t |
paul@62 | 729 | Cpm_jz4780_chip::get_hdmi_frequency() |
paul@62 | 730 | { |
paul@62 | 731 | return get_hdmi_source_frequency() / get_hdmi_divider(); |
paul@62 | 732 | } |
paul@62 | 733 | |
paul@0 | 734 | // Clock frequency for the LCD0 controller. |
paul@0 | 735 | |
paul@0 | 736 | uint32_t |
paul@0 | 737 | Cpm_jz4780_chip::get_lcd_pixel_frequency() |
paul@0 | 738 | { |
paul@0 | 739 | return get_lcd_source_frequency() / get_lcd_pixel_divider(); |
paul@0 | 740 | } |
paul@0 | 741 | |
paul@0 | 742 | // Clock frequency for the memory. |
paul@0 | 743 | |
paul@0 | 744 | uint32_t |
paul@0 | 745 | Cpm_jz4780_chip::get_memory_frequency() |
paul@0 | 746 | { |
paul@0 | 747 | return get_memory_source_frequency() / get_memory_divider(); |
paul@0 | 748 | } |
paul@0 | 749 | |
paul@0 | 750 | uint32_t |
paul@0 | 751 | Cpm_jz4780_chip::get_apll_frequency() |
paul@0 | 752 | { |
paul@0 | 753 | return get_pll_frequency(Pll_control_A); |
paul@0 | 754 | } |
paul@0 | 755 | |
paul@0 | 756 | uint32_t |
paul@0 | 757 | Cpm_jz4780_chip::get_epll_frequency() |
paul@0 | 758 | { |
paul@0 | 759 | return get_pll_frequency(Pll_control_E); |
paul@0 | 760 | } |
paul@0 | 761 | |
paul@0 | 762 | uint32_t |
paul@0 | 763 | Cpm_jz4780_chip::get_mpll_frequency() |
paul@0 | 764 | { |
paul@0 | 765 | return get_pll_frequency(Pll_control_M); |
paul@0 | 766 | } |
paul@0 | 767 | |
paul@0 | 768 | uint32_t |
paul@0 | 769 | Cpm_jz4780_chip::get_vpll_frequency() |
paul@0 | 770 | { |
paul@0 | 771 | return get_pll_frequency(Pll_control_V); |
paul@0 | 772 | } |
paul@0 | 773 | |
paul@0 | 774 | |
paul@0 | 775 | |
paul@62 | 776 | void |
paul@62 | 777 | Cpm_jz4780_chip::set_hdmi_frequency(uint32_t pclk) |
paul@62 | 778 | { |
paul@62 | 779 | // Switch to the video PLL and attempt to set the divider. |
paul@62 | 780 | |
paul@62 | 781 | set_hdmi_source(Source_pll_V); |
paul@62 | 782 | set_hdmi_divider(get_hdmi_source_frequency() / pclk); |
paul@62 | 783 | } |
paul@62 | 784 | |
paul@0 | 785 | // Set the pixel frequency. |
paul@0 | 786 | // Unlike the jz4740, HCLK/AHB0 is used as the device frequency, with the pixel |
paul@0 | 787 | // frequency being based on the selected clock source (SCLK_A, MPLL or VPLL). |
paul@0 | 788 | |
paul@0 | 789 | void |
paul@0 | 790 | Cpm_jz4780_chip::set_lcd_pixel_frequency(uint32_t pclk) |
paul@0 | 791 | { |
paul@0 | 792 | // Switch to the video PLL and attempt to set the divider. |
paul@0 | 793 | |
paul@0 | 794 | set_lcd_source(Source_pll_V); |
paul@0 | 795 | set_lcd_pixel_divider(get_lcd_source_frequency() / pclk); |
paul@0 | 796 | } |
paul@0 | 797 | |
paul@0 | 798 | // NOTE: Compatibility method. Probably needs reviewing. |
paul@64 | 799 | // NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock. |
paul@0 | 800 | |
paul@0 | 801 | void |
paul@0 | 802 | Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio) |
paul@0 | 803 | { |
paul@0 | 804 | (void) ratio; |
paul@0 | 805 | set_lcd_pixel_frequency(pclk); |
paul@0 | 806 | } |
paul@0 | 807 | |
paul@0 | 808 | // NOTE: Empty method for compatibility. |
paul@64 | 809 | // NOTE: It could potentially be combined with start_lcd. |
paul@0 | 810 | |
paul@0 | 811 | void |
paul@0 | 812 | Cpm_jz4780_chip::update_output_frequency() |
paul@0 | 813 | { |
paul@0 | 814 | } |
paul@0 | 815 | |
paul@0 | 816 | |
paul@0 | 817 | |
paul@0 | 818 | // C language interface functions. |
paul@0 | 819 | |
paul@0 | 820 | void |
paul@0 | 821 | *jz4780_cpm_init(l4_addr_t cpm_base) |
paul@0 | 822 | { |
paul@0 | 823 | /* Initialise the clock and power management peripheral with the |
paul@0 | 824 | register memory region and a 48MHz EXCLK frequency. */ |
paul@0 | 825 | |
paul@0 | 826 | return (void *) new Cpm_jz4780_chip(cpm_base, 48000000, 32768); |
paul@0 | 827 | } |
paul@0 | 828 | |
paul@0 | 829 | int |
paul@0 | 830 | jz4780_cpm_have_clock(void *cpm) |
paul@0 | 831 | { |
paul@0 | 832 | return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(); |
paul@0 | 833 | } |
paul@0 | 834 | |
paul@0 | 835 | void |
paul@0 | 836 | jz4780_cpm_start_clock(void *cpm) |
paul@0 | 837 | { |
paul@0 | 838 | static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(); |
paul@0 | 839 | } |
paul@0 | 840 | |
paul@0 | 841 | |
paul@0 | 842 | |
paul@0 | 843 | void |
paul@62 | 844 | jz4780_cpm_start_hdmi(void *cpm) |
paul@62 | 845 | { |
paul@62 | 846 | static_cast<Cpm_jz4780_chip *>(cpm)->start_hdmi(); |
paul@62 | 847 | } |
paul@62 | 848 | |
paul@62 | 849 | void |
paul@62 | 850 | jz4780_cpm_stop_hdmi(void *cpm) |
paul@62 | 851 | { |
paul@62 | 852 | static_cast<Cpm_jz4780_chip *>(cpm)->stop_hdmi(); |
paul@62 | 853 | } |
paul@62 | 854 | |
paul@62 | 855 | void |
paul@0 | 856 | jz4780_cpm_start_lcd(void *cpm) |
paul@0 | 857 | { |
paul@0 | 858 | static_cast<Cpm_jz4780_chip *>(cpm)->start_lcd(); |
paul@0 | 859 | } |
paul@0 | 860 | |
paul@0 | 861 | void |
paul@0 | 862 | jz4780_cpm_stop_lcd(void *cpm) |
paul@0 | 863 | { |
paul@0 | 864 | static_cast<Cpm_jz4780_chip *>(cpm)->stop_lcd(); |
paul@0 | 865 | } |
paul@0 | 866 | |
paul@0 | 867 | |
paul@0 | 868 | |
paul@0 | 869 | uint8_t |
paul@0 | 870 | jz4780_cpm_get_cpu_divider(void *cpm) |
paul@0 | 871 | { |
paul@0 | 872 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_divider(); |
paul@0 | 873 | } |
paul@0 | 874 | |
paul@0 | 875 | uint8_t |
paul@0 | 876 | jz4780_cpm_get_hclock0_divider(void *cpm) |
paul@0 | 877 | { |
paul@0 | 878 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_divider(); |
paul@0 | 879 | } |
paul@0 | 880 | |
paul@0 | 881 | uint8_t |
paul@0 | 882 | jz4780_cpm_get_hclock2_divider(void *cpm) |
paul@0 | 883 | { |
paul@0 | 884 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_divider(); |
paul@0 | 885 | } |
paul@0 | 886 | |
paul@0 | 887 | uint8_t |
paul@62 | 888 | jz4780_cpm_get_hdmi_divider(void *cpm) |
paul@62 | 889 | { |
paul@62 | 890 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hdmi_divider(); |
paul@62 | 891 | } |
paul@62 | 892 | |
paul@62 | 893 | uint8_t |
paul@0 | 894 | jz4780_cpm_get_lcd_pixel_divider(void *cpm) |
paul@0 | 895 | { |
paul@0 | 896 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_divider(); |
paul@0 | 897 | } |
paul@0 | 898 | |
paul@0 | 899 | uint8_t |
paul@0 | 900 | jz4780_cpm_get_memory_divider(void *cpm) |
paul@0 | 901 | { |
paul@0 | 902 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_divider(); |
paul@0 | 903 | } |
paul@0 | 904 | |
paul@0 | 905 | uint8_t |
paul@0 | 906 | jz4780_cpm_get_pclock_divider(void *cpm) |
paul@0 | 907 | { |
paul@0 | 908 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_divider(); |
paul@0 | 909 | } |
paul@0 | 910 | |
paul@0 | 911 | |
paul@0 | 912 | |
paul@0 | 913 | uint8_t |
paul@0 | 914 | jz4780_cpm_get_hclock0_source(void *cpm) |
paul@0 | 915 | { |
paul@0 | 916 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source(); |
paul@0 | 917 | } |
paul@0 | 918 | |
paul@0 | 919 | uint8_t |
paul@0 | 920 | jz4780_cpm_get_hclock2_source(void *cpm) |
paul@0 | 921 | { |
paul@0 | 922 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source(); |
paul@0 | 923 | } |
paul@0 | 924 | |
paul@0 | 925 | uint8_t |
paul@62 | 926 | jz4780_cpm_get_hdmi_source(void *cpm) |
paul@62 | 927 | { |
paul@62 | 928 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hdmi_source(); |
paul@62 | 929 | } |
paul@62 | 930 | |
paul@62 | 931 | uint8_t |
paul@0 | 932 | jz4780_cpm_get_lcd_source(void *cpm) |
paul@0 | 933 | { |
paul@0 | 934 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source(); |
paul@0 | 935 | } |
paul@0 | 936 | |
paul@0 | 937 | uint8_t |
paul@0 | 938 | jz4780_cpm_get_memory_source(void *cpm) |
paul@0 | 939 | { |
paul@0 | 940 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source(); |
paul@0 | 941 | } |
paul@0 | 942 | |
paul@0 | 943 | uint8_t |
paul@0 | 944 | jz4780_cpm_get_pclock_source(void *cpm) |
paul@0 | 945 | { |
paul@0 | 946 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source(); |
paul@0 | 947 | } |
paul@0 | 948 | |
paul@0 | 949 | void |
paul@0 | 950 | jz4780_cpm_set_pclock_source(void *cpm, uint8_t source) |
paul@0 | 951 | { |
paul@0 | 952 | static_cast<Cpm_jz4780_chip *>(cpm)->set_pclock_source(source); |
paul@0 | 953 | } |
paul@0 | 954 | |
paul@0 | 955 | |
paul@0 | 956 | |
paul@0 | 957 | uint32_t |
paul@0 | 958 | jz4780_cpm_get_hclock0_source_frequency(void *cpm) |
paul@0 | 959 | { |
paul@0 | 960 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source_frequency(); |
paul@0 | 961 | } |
paul@0 | 962 | |
paul@0 | 963 | uint32_t |
paul@0 | 964 | jz4780_cpm_get_hclock2_source_frequency(void *cpm) |
paul@0 | 965 | { |
paul@0 | 966 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source_frequency(); |
paul@0 | 967 | } |
paul@0 | 968 | |
paul@0 | 969 | uint32_t |
paul@62 | 970 | jz4780_cpm_get_hdmi_source_frequency(void *cpm) |
paul@62 | 971 | { |
paul@62 | 972 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hdmi_source_frequency(); |
paul@62 | 973 | } |
paul@62 | 974 | |
paul@62 | 975 | uint32_t |
paul@0 | 976 | jz4780_cpm_get_lcd_source_frequency(void *cpm) |
paul@0 | 977 | { |
paul@0 | 978 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source_frequency(); |
paul@0 | 979 | } |
paul@0 | 980 | |
paul@0 | 981 | uint32_t |
paul@0 | 982 | jz4780_cpm_get_memory_source_frequency(void *cpm) |
paul@0 | 983 | { |
paul@0 | 984 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source_frequency(); |
paul@0 | 985 | } |
paul@0 | 986 | |
paul@0 | 987 | uint32_t |
paul@0 | 988 | jz4780_cpm_get_pclock_source_frequency(void *cpm) |
paul@0 | 989 | { |
paul@0 | 990 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source_frequency(); |
paul@0 | 991 | } |
paul@0 | 992 | |
paul@0 | 993 | |
paul@0 | 994 | |
paul@0 | 995 | uint8_t |
paul@0 | 996 | jz4780_cpm_get_main_source(void *cpm) |
paul@0 | 997 | { |
paul@0 | 998 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_source(); |
paul@0 | 999 | } |
paul@0 | 1000 | |
paul@0 | 1001 | uint32_t |
paul@0 | 1002 | jz4780_cpm_get_main_frequency(void *cpm) |
paul@0 | 1003 | { |
paul@0 | 1004 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_frequency(); |
paul@0 | 1005 | } |
paul@0 | 1006 | |
paul@0 | 1007 | uint32_t |
paul@0 | 1008 | jz4780_cpm_get_cpu_frequency(void *cpm) |
paul@0 | 1009 | { |
paul@0 | 1010 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_frequency(); |
paul@0 | 1011 | } |
paul@0 | 1012 | |
paul@0 | 1013 | uint32_t |
paul@0 | 1014 | jz4780_cpm_get_hclock0_frequency(void *cpm) |
paul@0 | 1015 | { |
paul@0 | 1016 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_frequency(); |
paul@0 | 1017 | } |
paul@0 | 1018 | |
paul@0 | 1019 | uint32_t |
paul@0 | 1020 | jz4780_cpm_get_hclock2_frequency(void *cpm) |
paul@0 | 1021 | { |
paul@0 | 1022 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_frequency(); |
paul@0 | 1023 | } |
paul@0 | 1024 | |
paul@0 | 1025 | uint32_t |
paul@62 | 1026 | jz4780_cpm_get_hdmi_frequency(void *cpm) |
paul@62 | 1027 | { |
paul@62 | 1028 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_hdmi_frequency(); |
paul@62 | 1029 | } |
paul@62 | 1030 | |
paul@62 | 1031 | uint32_t |
paul@0 | 1032 | jz4780_cpm_get_lcd_pixel_frequency(void *cpm) |
paul@0 | 1033 | { |
paul@0 | 1034 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_frequency(); |
paul@0 | 1035 | } |
paul@0 | 1036 | |
paul@0 | 1037 | uint32_t |
paul@0 | 1038 | jz4780_cpm_get_memory_frequency(void *cpm) |
paul@0 | 1039 | { |
paul@0 | 1040 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_frequency(); |
paul@0 | 1041 | } |
paul@0 | 1042 | |
paul@0 | 1043 | uint32_t |
paul@0 | 1044 | jz4780_cpm_get_pclock_frequency(void *cpm) |
paul@0 | 1045 | { |
paul@0 | 1046 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_frequency(); |
paul@0 | 1047 | } |
paul@0 | 1048 | |
paul@0 | 1049 | uint32_t |
paul@0 | 1050 | jz4780_cpm_get_apll_frequency(void *cpm) |
paul@0 | 1051 | { |
paul@0 | 1052 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_apll_frequency(); |
paul@0 | 1053 | } |
paul@0 | 1054 | |
paul@0 | 1055 | uint32_t |
paul@0 | 1056 | jz4780_cpm_get_epll_frequency(void *cpm) |
paul@0 | 1057 | { |
paul@0 | 1058 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_epll_frequency(); |
paul@0 | 1059 | } |
paul@0 | 1060 | |
paul@0 | 1061 | uint32_t |
paul@0 | 1062 | jz4780_cpm_get_mpll_frequency(void *cpm) |
paul@0 | 1063 | { |
paul@0 | 1064 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_mpll_frequency(); |
paul@0 | 1065 | } |
paul@0 | 1066 | |
paul@0 | 1067 | uint32_t |
paul@0 | 1068 | jz4780_cpm_get_vpll_frequency(void *cpm) |
paul@0 | 1069 | { |
paul@0 | 1070 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_vpll_frequency(); |
paul@0 | 1071 | } |
paul@0 | 1072 | |
paul@0 | 1073 | |
paul@0 | 1074 | |
paul@0 | 1075 | void |
paul@62 | 1076 | jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk) |
paul@62 | 1077 | { |
paul@62 | 1078 | static_cast<Cpm_jz4780_chip *>(cpm)->set_hdmi_frequency(pclk); |
paul@62 | 1079 | } |
paul@62 | 1080 | |
paul@62 | 1081 | void |
paul@0 | 1082 | jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk) |
paul@0 | 1083 | { |
paul@0 | 1084 | static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_pixel_frequency(pclk); |
paul@0 | 1085 | } |
paul@0 | 1086 | |
paul@0 | 1087 | void |
paul@64 | 1088 | jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio) |
paul@64 | 1089 | { |
paul@64 | 1090 | static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_frequencies(pclk, ratio); |
paul@64 | 1091 | } |
paul@64 | 1092 | |
paul@64 | 1093 | void |
paul@0 | 1094 | jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) |
paul@0 | 1095 | { |
paul@0 | 1096 | static_cast<Cpm_jz4780_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider); |
paul@0 | 1097 | } |