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@211 | 6 | * Copyright (C) 2017, 2018, 2020, 2021, 2023 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@211 | 29 | // Register locations. |
paul@211 | 30 | |
paul@0 | 31 | enum Regs : unsigned |
paul@0 | 32 | { |
paul@0 | 33 | Clock_control = 0x000, // CPCCR |
paul@0 | 34 | Low_power_control = 0x004, // LCR |
paul@211 | 35 | Clock_gate0 = 0x020, // CLKGR0 |
paul@211 | 36 | Clock_gate1 = 0x028, // CLKGR1 |
paul@211 | 37 | Sleep_control = 0x024, // OPCR (oscillator and power control) |
paul@211 | 38 | Clock_status = 0x0d4, // CPCSR |
paul@211 | 39 | |
paul@211 | 40 | Divider_bch = 0x0ac, // BCHCDR |
paul@211 | 41 | Divider_cim = 0x07c, // CIMCDR |
paul@211 | 42 | Divider_ddr = 0x02c, // DDRCDR |
paul@211 | 43 | Divider_gpu = 0x088, // GPUCDR |
paul@211 | 44 | Divider_hdmi = 0x08c, // HDMICDR |
paul@211 | 45 | Divider_i2s0 = 0x060, // I2SCDR |
paul@211 | 46 | Divider_i2s1 = 0x0a0, // I2S1CDR |
paul@211 | 47 | Divider_lcd0 = 0x054, // LP0CDR |
paul@211 | 48 | Divider_lcd1 = 0x064, // LP1CDR |
paul@211 | 49 | Divider_msc0 = 0x068, // MSC0CDR |
paul@211 | 50 | Divider_msc1 = 0x0a4, // MSC1CDR |
paul@211 | 51 | Divider_msc2 = 0x0a8, // MSC2CDR |
paul@211 | 52 | Divider_pcm = 0x084, // PCMCDR |
paul@211 | 53 | Divider_ssi = 0x074, // SSICDR |
paul@211 | 54 | Divider_uhc = 0x06c, // UHCCDR |
paul@211 | 55 | Divider_vpu = 0x030, // VPUCDR |
paul@211 | 56 | |
paul@211 | 57 | Cpm_interrupt = 0x0b0, // CPM_INTR |
paul@211 | 58 | Cpm_interrupt_en = 0x0b4, // CPM_INTRE |
paul@211 | 59 | Cpm_scratch = 0x034, // CPSPR |
paul@211 | 60 | Cpm_scratch_prot = 0x038, // CPSPPR |
paul@211 | 61 | |
paul@211 | 62 | Usb_param_control0 = 0x03c, // USBPCR |
paul@211 | 63 | Usb_reset_detect = 0x040, // USBRDT |
paul@211 | 64 | Usb_vbus_jitter = 0x044, // USBVBFIL |
paul@211 | 65 | Usb_param_control1 = 0x048, // USBPCR1 |
paul@211 | 66 | |
paul@0 | 67 | Pll_control = 0x00c, // CPPCR |
paul@0 | 68 | Pll_control_A = 0x010, // CPAPCR |
paul@0 | 69 | Pll_control_M = 0x014, // CPMPCR |
paul@0 | 70 | Pll_control_E = 0x018, // CPEPCR |
paul@0 | 71 | Pll_control_V = 0x01c, // CPVPCR |
paul@0 | 72 | }; |
paul@0 | 73 | |
paul@0 | 74 | |
paul@0 | 75 | |
paul@211 | 76 | // Register field definitions. |
paul@0 | 77 | |
paul@211 | 78 | static Field Clock_source_main (Clock_control, 3, 30), // SEL_SRC (output to SCLK_A) |
paul@211 | 79 | Clock_source_cpu (Clock_control, 3, 28), // SEL_CPLL (output to CCLK) |
paul@211 | 80 | Clock_source_hclock0 (Clock_control, 3, 26), // SEL_H0PLL (output to AHB0) |
paul@211 | 81 | Clock_source_hclock2 (Clock_control, 3, 24), // SEL_H2PLL (output to AHB2) |
paul@211 | 82 | Clock_source_bch (Divider_bch, 3, 30), // BPCS |
paul@211 | 83 | Clock_source_cim (Divider_cim, 1, 31), // CIMPCS |
paul@211 | 84 | Clock_source_ddr (Divider_ddr, 3, 30), // DCS |
paul@211 | 85 | Clock_source_gpu (Divider_gpu, 3, 30), // GPCS |
paul@211 | 86 | Clock_source_hdmi (Divider_hdmi, 3, 30), // HPCS |
paul@211 | 87 | Clock_source_i2s0 (Divider_i2s0, 3, 30), // I2CS, I2PCS |
paul@211 | 88 | Clock_source_i2s1 (Divider_i2s1, 3, 30), // I2CS, I2PCS |
paul@211 | 89 | Clock_source_lcd0 (Divider_lcd0, 3, 30), // LPCS |
paul@211 | 90 | Clock_source_lcd1 (Divider_lcd1, 3, 30), // LPCS |
paul@211 | 91 | Clock_source_msc (Divider_msc0, 3, 30), // MPCS |
paul@211 | 92 | Clock_source_pcm (Divider_pcm, 7, 29), // PCMS, PCMPCS |
paul@219 | 93 | Clock_source_ssi (Divider_ssi, 3, 30), // SCS, SPCS |
paul@211 | 94 | Clock_source_uhc (Divider_uhc, 3, 30), // UHCS |
paul@211 | 95 | Clock_source_vpu (Divider_vpu, 3, 30), // VCS |
paul@128 | 96 | |
paul@211 | 97 | Clock_busy_cpu (Clock_status, 1, 0), |
paul@211 | 98 | Clock_busy_hclock0 (Clock_status, 1, 1), |
paul@211 | 99 | Clock_busy_hclock2 (Clock_status, 1, 2), |
paul@211 | 100 | Clock_busy_bch (Divider_bch, 1, 28), |
paul@211 | 101 | Clock_busy_cim (Divider_cim, 1, 29), |
paul@211 | 102 | Clock_busy_ddr (Divider_ddr, 1, 28), |
paul@211 | 103 | Clock_busy_gpu (Divider_gpu, 1, 28), |
paul@211 | 104 | Clock_busy_hdmi (Divider_hdmi, 1, 28), |
paul@211 | 105 | Clock_busy_i2s0 (Divider_i2s0, 1, 28), |
paul@211 | 106 | Clock_busy_i2s1 (Divider_i2s1, 1, 28), |
paul@211 | 107 | Clock_busy_lcd0 (Divider_lcd0, 1, 27), |
paul@211 | 108 | Clock_busy_lcd1 (Divider_lcd1, 1, 27), |
paul@211 | 109 | Clock_busy_msc0 (Divider_msc0, 1, 28), |
paul@211 | 110 | Clock_busy_msc1 (Divider_msc1, 1, 28), |
paul@211 | 111 | Clock_busy_msc2 (Divider_msc2, 1, 28), |
paul@211 | 112 | Clock_busy_pcm (Divider_pcm, 1, 27), |
paul@211 | 113 | Clock_busy_ssi (Divider_ssi, 1, 28), |
paul@211 | 114 | Clock_busy_uhc (Divider_uhc, 1, 28), |
paul@211 | 115 | Clock_busy_vpu (Divider_vpu, 1, 28), |
paul@128 | 116 | |
paul@211 | 117 | Clock_change_enable_cpu (Clock_control, 1, 22), |
paul@211 | 118 | Clock_change_enable_ahb0 (Clock_control, 1, 21), |
paul@211 | 119 | Clock_change_enable_ahb2 (Clock_control, 1, 20), |
paul@211 | 120 | Clock_change_enable_bch (Divider_bch, 1, 29), |
paul@211 | 121 | Clock_change_enable_cim (Divider_cim, 1, 30), |
paul@211 | 122 | Clock_change_enable_ddr (Divider_ddr, 1, 29), |
paul@211 | 123 | Clock_change_enable_gpu (Divider_gpu, 1, 29), |
paul@211 | 124 | Clock_change_enable_hdmi (Divider_hdmi, 1, 29), |
paul@211 | 125 | Clock_change_enable_i2s0 (Divider_i2s0, 1, 29), |
paul@211 | 126 | Clock_change_enable_i2s1 (Divider_i2s1, 1, 29), |
paul@211 | 127 | Clock_change_enable_lcd0 (Divider_lcd0, 1, 28), |
paul@211 | 128 | Clock_change_enable_lcd1 (Divider_lcd1, 1, 28), |
paul@211 | 129 | Clock_change_enable_msc0 (Divider_msc0, 1, 29), |
paul@211 | 130 | Clock_change_enable_msc1 (Divider_msc1, 1, 29), |
paul@211 | 131 | Clock_change_enable_msc2 (Divider_msc2, 1, 29), |
paul@211 | 132 | Clock_change_enable_pcm (Divider_pcm, 1, 28), |
paul@211 | 133 | Clock_change_enable_ssi (Divider_ssi, 1, 29), |
paul@211 | 134 | Clock_change_enable_uhc (Divider_uhc, 1, 29), |
paul@211 | 135 | Clock_change_enable_vpu (Divider_vpu, 1, 29), |
paul@0 | 136 | |
paul@211 | 137 | Clock_divider_cpu (Clock_control, 0x0f, 0), // CDIV |
paul@211 | 138 | Clock_divider_hclock0 (Clock_control, 0x0f, 8), // H0DIV (fast AHB peripherals) |
paul@211 | 139 | Clock_divider_hclock2 (Clock_control, 0x0f, 12), // H2DIV (fast AHB peripherals) |
paul@211 | 140 | Clock_divider_l2cache (Clock_control, 0x0f, 4), // L2CDIV |
paul@211 | 141 | Clock_divider_pclock (Clock_control, 0x0f, 16), // PDIV (slow APB peripherals) |
paul@211 | 142 | Clock_divider_bch (Divider_bch, 0x0f, 0), // BCHCDR |
paul@211 | 143 | Clock_divider_cim (Divider_cim, 0xff, 0), // CIMCDR |
paul@211 | 144 | Clock_divider_ddr (Divider_ddr, 0x0f, 0), // DDRCDR |
paul@211 | 145 | Clock_divider_gpu (Divider_gpu, 0x0f, 0), // GPUCDR |
paul@211 | 146 | Clock_divider_hdmi (Divider_hdmi, 0xff, 0), // HDMICDR |
paul@211 | 147 | Clock_divider_i2s0 (Divider_i2s0, 0xff, 0), // I2SCDR |
paul@211 | 148 | Clock_divider_i2s1 (Divider_i2s1, 0xff, 0), // I2SCDR |
paul@211 | 149 | Clock_divider_lcd0 (Divider_lcd0, 0xff, 0), // LPCDR |
paul@211 | 150 | Clock_divider_lcd1 (Divider_lcd1, 0xff, 0), // LPCDR |
paul@211 | 151 | Clock_divider_msc0 (Divider_msc0, 0xff, 0), // MSC0CDR |
paul@211 | 152 | Clock_divider_msc1 (Divider_msc1, 0xff, 0), // MSC1CDR |
paul@211 | 153 | Clock_divider_msc2 (Divider_msc2, 0xff, 0), // MSC2CDR |
paul@211 | 154 | Clock_divider_pcm (Divider_pcm, 0xff, 0), // PCMCDR |
paul@211 | 155 | Clock_divider_ssi (Divider_ssi, 0xff, 0), // SSICDR |
paul@211 | 156 | Clock_divider_uhc (Divider_uhc, 0xff, 0), // UHCCDR |
paul@211 | 157 | Clock_divider_vpu (Divider_vpu, 0x0f, 0), // VPUCDR |
paul@0 | 158 | |
paul@211 | 159 | Clock_gate_main (Clock_control, 1, 23, true), // GATE_SCLKA |
paul@211 | 160 | Clock_gate_ddr (Clock_gate0, 3, 30, true), // DDR1, DDR0 |
paul@211 | 161 | Clock_gate_ipu (Clock_gate0, 1, 29, true), // IPU |
paul@211 | 162 | Clock_gate_lcd (Clock_gate0, 3, 27, true), // LCD, TVE |
paul@211 | 163 | Clock_gate_cim (Clock_gate0, 1, 26, true), // CIM |
paul@211 | 164 | Clock_gate_i2c2 (Clock_gate0, 1, 25, true), // SMB2 |
paul@211 | 165 | Clock_gate_uhc (Clock_gate0, 1, 24, true), // UHC |
paul@211 | 166 | Clock_gate_mac (Clock_gate0, 1, 23, true), // MAC |
paul@211 | 167 | Clock_gate_gps (Clock_gate0, 1, 22, true), // GPS |
paul@211 | 168 | Clock_gate_dma (Clock_gate0, 1, 21, true), // PDMA |
paul@219 | 169 | //Clock_gate_ssi2 (Clock_gate0, 1, 20, true), // SSI2 |
paul@211 | 170 | Clock_gate_ssi1 (Clock_gate0, 1, 19, true), // SSI1 |
paul@211 | 171 | Clock_gate_uart3 (Clock_gate0, 1, 18, true), // UART3 |
paul@211 | 172 | Clock_gate_uart2 (Clock_gate0, 1, 17, true), // UART2 |
paul@211 | 173 | Clock_gate_uart1 (Clock_gate0, 1, 16, true), // UART1 |
paul@211 | 174 | Clock_gate_uart0 (Clock_gate0, 1, 15, true), // UART0 |
paul@211 | 175 | Clock_gate_sadc (Clock_gate0, 1, 14, true), // SADC |
paul@211 | 176 | Clock_gate_kbc (Clock_gate0, 1, 13, true), // KBC |
paul@211 | 177 | Clock_gate_msc2 (Clock_gate0, 1, 12, true), // MSC2 |
paul@211 | 178 | Clock_gate_msc1 (Clock_gate0, 1, 11, true), // MSC1 |
paul@211 | 179 | Clock_gate_owi (Clock_gate0, 1, 10, true), // OWI |
paul@211 | 180 | Clock_gate_tssi0 (Clock_gate0, 1, 9, true), // TSSI0 |
paul@211 | 181 | Clock_gate_aic0 (Clock_gate0, 1, 8, true), // AIC0 |
paul@211 | 182 | Clock_gate_scc (Clock_gate0, 1, 7, true), // SCC |
paul@211 | 183 | Clock_gate_i2c1 (Clock_gate0, 1, 6, true), // SMB1 |
paul@211 | 184 | Clock_gate_i2c0 (Clock_gate0, 1, 5, true), // SMB0 |
paul@211 | 185 | Clock_gate_ssi0 (Clock_gate0, 1, 4, true), // SSI0 |
paul@211 | 186 | Clock_gate_msc0 (Clock_gate0, 1, 3, true), // MSC0 |
paul@211 | 187 | Clock_gate_otg0 (Clock_gate0, 1, 2, true), // OTG0 |
paul@211 | 188 | Clock_gate_bch (Clock_gate0, 1, 1, true), // BCH |
paul@211 | 189 | Clock_gate_nemc (Clock_gate0, 1, 0, true), // NEMC |
paul@211 | 190 | Clock_gate_p1 (Clock_gate1, 1, 15, true), // P1 |
paul@211 | 191 | Clock_gate_x2d (Clock_gate1, 1, 14, true), // X2D |
paul@211 | 192 | Clock_gate_des (Clock_gate1, 1, 13, true), // DES |
paul@211 | 193 | Clock_gate_i2c4 (Clock_gate1, 1, 12, true), // SMB4 |
paul@211 | 194 | Clock_gate_ahb_mon (Clock_gate1, 1, 11, true), // AHB_MON |
paul@211 | 195 | Clock_gate_uart4 (Clock_gate1, 1, 10, true), // UART4 |
paul@211 | 196 | Clock_gate_hdmi (Clock_gate1, 1, 9, true), // HDMI |
paul@211 | 197 | Clock_gate_otg1 (Clock_gate1, 1, 8, true), // OTG1 |
paul@211 | 198 | Clock_gate_gpvlc (Clock_gate1, 1, 7, true), // GPVLC |
paul@211 | 199 | Clock_gate_aic1 (Clock_gate1, 1, 6, true), // AIC1 |
paul@211 | 200 | Clock_gate_compress (Clock_gate1, 1, 5, true), // COMPRESS |
paul@211 | 201 | Clock_gate_gpu (Clock_gate1, 1, 4, true), // GPU |
paul@211 | 202 | Clock_gate_pcm (Clock_gate1, 1, 3, true), // PCM |
paul@211 | 203 | Clock_gate_vpu (Clock_gate1, 1, 2, true), // VPU |
paul@211 | 204 | Clock_gate_tssi1 (Clock_gate1, 1, 1, true), // TSSI1 |
paul@211 | 205 | Clock_gate_i2c3 (Clock_gate1, 1, 0, true), // I2C3 |
paul@0 | 206 | |
paul@211 | 207 | Pll_enable_A (Pll_control_A, 1, 0), // APLLEN |
paul@211 | 208 | Pll_enable_E (Pll_control_E, 1, 0), // EPLLEN |
paul@211 | 209 | Pll_enable_M (Pll_control_M, 1, 0), // MPLLEN |
paul@211 | 210 | Pll_enable_V (Pll_control_V, 1, 0), // VPLLEN |
paul@0 | 211 | |
paul@211 | 212 | Pll_stable_A (Pll_control_A, 1, 4), // APLL_ON |
paul@211 | 213 | Pll_stable_E (Pll_control_E, 1, 4), // EPLL_ON |
paul@211 | 214 | Pll_stable_M (Pll_control_M, 1, 4), // MPLL_ON |
paul@211 | 215 | Pll_stable_V (Pll_control_V, 1, 4), // VPLL_ON |
paul@211 | 216 | |
paul@211 | 217 | Pll_bypass_A (Pll_control_A, 1, 1), // APLL_BP |
paul@211 | 218 | Pll_bypass_E (Pll_control_E, 1, 1), // EPLL_BP |
paul@211 | 219 | Pll_bypass_M (Pll_control_M, 1, 1), // MPLL_BP |
paul@211 | 220 | Pll_bypass_V (Pll_control_V, 1, 1), // VPLL_BP |
paul@0 | 221 | |
paul@211 | 222 | Pll_multiplier_A (Pll_control_A, 0x1fff, 19), // APLLM |
paul@211 | 223 | Pll_multiplier_E (Pll_control_E, 0x1fff, 19), // EPLLM |
paul@211 | 224 | Pll_multiplier_M (Pll_control_M, 0x1fff, 19), // MPLLM |
paul@211 | 225 | Pll_multiplier_V (Pll_control_V, 0x1fff, 19), // VPLLM |
paul@0 | 226 | |
paul@211 | 227 | Pll_input_division_A (Pll_control_A, 0x3f, 13), // APLLN |
paul@211 | 228 | Pll_input_division_E (Pll_control_E, 0x3f, 13), // EPLLN |
paul@211 | 229 | Pll_input_division_M (Pll_control_M, 0x3f, 13), // MPLLN |
paul@211 | 230 | Pll_input_division_V (Pll_control_V, 0x3f, 13), // VPLLN |
paul@0 | 231 | |
paul@211 | 232 | Pll_output_division_A (Pll_control_A, 0x0f, 9), // APLLOD |
paul@211 | 233 | Pll_output_division_E (Pll_control_E, 0x0f, 9), // EPLLOD |
paul@211 | 234 | Pll_output_division_M (Pll_control_M, 0x0f, 9), // MPLLOD |
paul@211 | 235 | Pll_output_division_V (Pll_control_V, 0x0f, 9); // VPLLOD |
paul@0 | 236 | |
paul@0 | 237 | |
paul@0 | 238 | |
paul@211 | 239 | // Multiplexer instances. |
paul@0 | 240 | |
paul@211 | 241 | #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) |
paul@0 | 242 | |
paul@211 | 243 | static Mux mux_external (Clock_external), |
paul@0 | 244 | |
paul@211 | 245 | // Clocks being propagated to others. |
paul@0 | 246 | |
paul@211 | 247 | mux_clock_ssi (Clock_ssi), |
paul@211 | 248 | mux_clock_msc (Clock_msc), |
paul@211 | 249 | mux_hclock2 (Clock_hclock2), |
paul@211 | 250 | mux_hclock2_pclock (Clock_hclock2_pclock), |
paul@211 | 251 | mux_pclock (Clock_pclock), |
paul@67 | 252 | |
paul@211 | 253 | // Main bus and peripheral clock sources. |
paul@0 | 254 | |
paul@239 | 255 | mux_ahb2 (4, Clocks(Clock_none, Clock_main, Clock_pll_M, Clock_rtc_external)), |
paul@211 | 256 | mux_core (4, Clocks(Clock_none, Clock_main, Clock_pll_M, Clock_pll_E)), |
paul@239 | 257 | mux_main (4, Clocks(Clock_none, Clock_pll_A, Clock_external, Clock_rtc_external)), |
paul@0 | 258 | |
paul@211 | 259 | // Memory and device clock sources. |
paul@0 | 260 | |
paul@211 | 261 | mux_cim (2, Clocks(Clock_main, Clock_pll_M)), |
paul@211 | 262 | mux_dev (3, Clocks(Clock_none, Clock_main, Clock_pll_M)), |
paul@211 | 263 | mux_lcd (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_V)), |
paul@211 | 264 | mux_usb (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E /* , OTG PHY */)), |
paul@0 | 265 | |
paul@211 | 266 | // Clock selectors involving the external clock. |
paul@0 | 267 | |
paul@211 | 268 | mux_i2s (4, Clocks(Clock_external, Clock_external, Clock_main, Clock_pll_E)), |
paul@211 | 269 | mux_pcm (8, Clocks(Clock_external, Clock_external, Clock_external, Clock_external, |
paul@211 | 270 | Clock_main, Clock_pll_M, Clock_pll_E, Clock_pll_V)), |
paul@211 | 271 | mux_ssi (4, Clocks(Clock_external, Clock_external, Clock_main, Clock_pll_M)); |
paul@0 | 272 | |
paul@0 | 273 | |
paul@0 | 274 | |
paul@211 | 275 | // Clock instances. |
paul@0 | 276 | |
paul@211 | 277 | static Clock_null clock_none; |
paul@62 | 278 | |
paul@239 | 279 | static Clock_passive clock_external(48000000), |
paul@239 | 280 | clock_rtc_external(32768); |
paul@0 | 281 | |
paul@0 | 282 | |
paul@0 | 283 | |
paul@211 | 284 | // Note the use of extra parentheses due to the annoying C++ "most vexing parse" |
paul@211 | 285 | // problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse |
paul@0 | 286 | |
paul@211 | 287 | static Clock clock_ahb_mon((Source(mux_external)), (Control(Clock_gate_ahb_mon))), |
paul@211 | 288 | |
paul@211 | 289 | clock_compress((Source(mux_external)), (Control(Clock_gate_compress))), |
paul@0 | 290 | |
paul@211 | 291 | clock_des((Source(mux_external)), (Control(Clock_gate_des))), |
paul@211 | 292 | |
paul@211 | 293 | clock_dma((Source(mux_external)), (Control(Clock_gate_dma))), |
paul@211 | 294 | |
paul@211 | 295 | clock_gps((Source(mux_external)), (Control(Clock_gate_gps))), |
paul@211 | 296 | |
paul@211 | 297 | clock_gpvlc((Source(mux_external)), (Control(Clock_gate_gpvlc))), |
paul@211 | 298 | |
paul@211 | 299 | clock_i2c0((Source(mux_pclock)), (Control(Clock_gate_i2c0))), |
paul@0 | 300 | |
paul@211 | 301 | clock_i2c1((Source(mux_pclock)), (Control(Clock_gate_i2c1))), |
paul@211 | 302 | |
paul@211 | 303 | clock_i2c2((Source(mux_pclock)), (Control(Clock_gate_i2c2))), |
paul@211 | 304 | |
paul@211 | 305 | clock_i2c3((Source(mux_pclock)), (Control(Clock_gate_i2c3))), |
paul@211 | 306 | |
paul@211 | 307 | clock_i2c4((Source(mux_pclock)), (Control(Clock_gate_i2c4))), |
paul@0 | 308 | |
paul@211 | 309 | clock_i2s0(Source(mux_i2s, Clock_source_i2s0), Control(Clock_gate_aic0)), |
paul@211 | 310 | |
paul@211 | 311 | clock_i2s1(Source(mux_i2s, Clock_source_i2s1), Control(Clock_gate_aic1)), |
paul@211 | 312 | |
paul@211 | 313 | clock_ipu((Source(mux_external)), (Control(Clock_gate_ipu))), |
paul@211 | 314 | |
paul@211 | 315 | clock_kbc((Source(mux_external)), (Control(Clock_gate_kbc))), |
paul@211 | 316 | |
paul@211 | 317 | clock_lcd((Source(mux_external)), (Control(Clock_gate_lcd))), |
paul@0 | 318 | |
paul@211 | 319 | clock_main(Source(mux_main, Clock_source_main), Control(Clock_gate_main)), |
paul@211 | 320 | |
paul@211 | 321 | clock_mac((Source(mux_external)), (Control(Clock_gate_mac))), |
paul@211 | 322 | |
paul@211 | 323 | clock_msc((Source(mux_dev, Clock_source_msc))), |
paul@211 | 324 | |
paul@211 | 325 | clock_nemc((Source(mux_hclock2)), (Control(Clock_gate_nemc))), |
paul@0 | 326 | |
paul@211 | 327 | clock_otg0((Source(mux_external)), (Control(Clock_gate_otg0))), |
paul@211 | 328 | |
paul@211 | 329 | clock_otg1((Source(mux_external)), (Control(Clock_gate_otg1))), |
paul@211 | 330 | |
paul@211 | 331 | clock_owi((Source(mux_external)), (Control(Clock_gate_owi))), |
paul@211 | 332 | |
paul@211 | 333 | clock_sadc((Source(mux_external)), (Control(Clock_gate_sadc))), |
paul@211 | 334 | |
paul@211 | 335 | clock_scc((Source(mux_external)), (Control(Clock_gate_scc))), |
paul@0 | 336 | |
paul@211 | 337 | clock_tssi0((Source(mux_external)), (Control(Clock_gate_tssi0))), |
paul@211 | 338 | |
paul@211 | 339 | clock_tssi1((Source(mux_external)), (Control(Clock_gate_tssi1))), |
paul@211 | 340 | |
paul@211 | 341 | clock_uart0((Source(mux_external)), (Control(Clock_gate_uart0))), |
paul@211 | 342 | |
paul@211 | 343 | clock_uart1((Source(mux_external)), (Control(Clock_gate_uart1))), |
paul@211 | 344 | |
paul@211 | 345 | clock_uart2((Source(mux_external)), (Control(Clock_gate_uart2))), |
paul@0 | 346 | |
paul@211 | 347 | clock_uart3((Source(mux_external)), (Control(Clock_gate_uart3))), |
paul@211 | 348 | |
paul@215 | 349 | clock_uart4((Source(mux_external)), (Control(Clock_gate_uart4))), |
paul@215 | 350 | |
paul@211 | 351 | clock_x2d((Source(mux_external)), (Control(Clock_gate_x2d))), |
paul@0 | 352 | |
paul@211 | 353 | // Special parent clock for hclock2 and pclock. |
paul@211 | 354 | |
paul@211 | 355 | clock_hclock2_pclock(Source(mux_ahb2, Clock_source_hclock2)), |
paul@211 | 356 | |
paul@211 | 357 | // SSI channel clocks depending on a common parent divider. |
paul@0 | 358 | |
paul@211 | 359 | clock_ssi0((Source(mux_clock_ssi)), Control(Clock_gate_ssi0)), |
paul@211 | 360 | |
paul@219 | 361 | clock_ssi1((Source(mux_clock_ssi)), Control(Clock_gate_ssi1)); |
paul@62 | 362 | |
paul@211 | 363 | static Clock_divided |
paul@211 | 364 | clock_bch(Source(mux_core, Clock_source_bch), |
paul@211 | 365 | Control(Clock_gate_bch, Clock_change_enable_bch, Clock_busy_bch), |
paul@211 | 366 | Divider(Clock_divider_bch)), |
paul@211 | 367 | |
paul@211 | 368 | clock_cim(Source(mux_cim, Clock_source_cim), |
paul@211 | 369 | Control(Clock_gate_cim, Clock_change_enable_cim, Clock_busy_cim), |
paul@211 | 370 | Divider(Clock_divider_cim)), |
paul@62 | 371 | |
paul@211 | 372 | clock_cpu(Source(mux_core, Clock_source_cpu), |
paul@211 | 373 | Control(Field::undefined, Clock_change_enable_cpu, Clock_busy_cpu), |
paul@211 | 374 | Divider(Clock_divider_cpu)), |
paul@62 | 375 | |
paul@211 | 376 | clock_ddr(Source(mux_dev, Clock_source_ddr), |
paul@211 | 377 | Control(Clock_gate_ddr, Clock_change_enable_ddr, Clock_busy_ddr), |
paul@211 | 378 | Divider(Clock_divider_ddr)), |
paul@62 | 379 | |
paul@211 | 380 | clock_gpu(Source(mux_core, Clock_source_gpu), |
paul@211 | 381 | Control(Clock_gate_gpu, Clock_change_enable_gpu, Clock_busy_gpu), |
paul@211 | 382 | Divider(Clock_divider_gpu)), |
paul@62 | 383 | |
paul@211 | 384 | clock_hclock0(Source(mux_core, Clock_source_hclock0), |
paul@211 | 385 | Control(Field::undefined, Clock_change_enable_ahb0), |
paul@211 | 386 | Divider(Clock_divider_hclock0)), |
paul@211 | 387 | |
paul@211 | 388 | clock_hclock2(Source(mux_hclock2_pclock), |
paul@211 | 389 | Control(Field::undefined, Clock_change_enable_ahb2), |
paul@211 | 390 | Divider(Clock_divider_hclock2)), |
paul@0 | 391 | |
paul@211 | 392 | clock_hdmi(Source(mux_lcd, Clock_source_hdmi), |
paul@211 | 393 | Control(Clock_gate_hdmi, Clock_change_enable_hdmi, Clock_busy_hdmi), |
paul@211 | 394 | Divider(Clock_divider_hdmi)), |
paul@211 | 395 | |
paul@240 | 396 | clock_l2cache(Source(mux_core, Clock_source_cpu), |
paul@240 | 397 | Control(Field::undefined, Clock_change_enable_cpu, Clock_busy_cpu), |
paul@240 | 398 | Divider(Clock_divider_l2cache)), |
paul@240 | 399 | |
paul@211 | 400 | clock_lcd_pixel0(Source(mux_lcd, Clock_source_lcd0), |
paul@211 | 401 | Control(Clock_gate_lcd, Clock_change_enable_lcd0, Clock_busy_lcd0), |
paul@211 | 402 | Divider(Clock_divider_lcd0)), |
paul@0 | 403 | |
paul@211 | 404 | clock_lcd_pixel1(Source(mux_lcd, Clock_source_lcd1), |
paul@211 | 405 | Control(Clock_gate_lcd, Clock_change_enable_lcd1, Clock_busy_lcd1), |
paul@211 | 406 | Divider(Clock_divider_lcd1)), |
paul@67 | 407 | |
paul@211 | 408 | clock_msc0(Source(mux_clock_msc), |
paul@211 | 409 | Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), |
paul@211 | 410 | Divider(Clock_divider_msc0)), |
paul@0 | 411 | |
paul@211 | 412 | clock_msc1(Source(mux_clock_msc), |
paul@211 | 413 | Control(Clock_gate_msc1, Clock_change_enable_msc1, Clock_busy_msc1), |
paul@211 | 414 | Divider(Clock_divider_msc1)), |
paul@0 | 415 | |
paul@211 | 416 | clock_msc2(Source(mux_clock_msc), |
paul@211 | 417 | Control(Clock_gate_msc2, Clock_change_enable_msc2, Clock_busy_msc2), |
paul@211 | 418 | Divider(Clock_divider_msc2)), |
paul@0 | 419 | |
paul@211 | 420 | clock_pcm(Source(mux_pcm, Clock_source_pcm), |
paul@211 | 421 | Control(Clock_gate_pcm, Clock_change_enable_pcm, Clock_busy_pcm), |
paul@211 | 422 | Divider(Clock_divider_pcm)), |
paul@0 | 423 | |
paul@211 | 424 | clock_pclock(Source(mux_hclock2_pclock), |
paul@211 | 425 | Control(Field::undefined, Clock_change_enable_ahb2), |
paul@211 | 426 | Divider(Clock_divider_pclock)), |
paul@0 | 427 | |
paul@211 | 428 | clock_ssi(Source(mux_ssi, Clock_source_ssi), |
paul@211 | 429 | Control(Field::undefined, Clock_change_enable_ssi, Clock_busy_ssi), |
paul@211 | 430 | Divider(Clock_divider_ssi)), |
paul@0 | 431 | |
paul@211 | 432 | clock_uhc(Source(mux_usb, Clock_source_uhc), |
paul@211 | 433 | Control(Clock_gate_uhc, Clock_change_enable_uhc, Clock_busy_uhc), |
paul@213 | 434 | Divider(Clock_divider_uhc)), |
paul@0 | 435 | |
paul@213 | 436 | clock_vpu(Source(mux_core, Clock_source_vpu), |
paul@213 | 437 | Control(Clock_gate_vpu, Clock_change_enable_vpu, Clock_busy_vpu), |
paul@213 | 438 | Divider(Clock_divider_vpu)); |
paul@0 | 439 | |
paul@239 | 440 | static Clock_divided_fixed |
paul@239 | 441 | clock_external_div_512((Source(mux_external)), (Divider_fixed(512))); |
paul@239 | 442 | |
paul@211 | 443 | const double jz4780_pll_intermediate_min = 300000000, |
paul@211 | 444 | jz4780_pll_intermediate_max = 1500000000; |
paul@0 | 445 | |
paul@211 | 446 | static Pll clock_pll_A(Source(mux_external), |
paul@211 | 447 | Control_pll(Pll_enable_A, Pll_stable_A, Pll_bypass_A), |
paul@211 | 448 | Divider_pll(Pll_multiplier_A, Pll_input_division_A, |
paul@211 | 449 | Pll_output_division_A, |
paul@219 | 450 | jz4780_pll_intermediate_min, jz4780_pll_intermediate_max, |
paul@219 | 451 | true)), |
paul@0 | 452 | |
paul@211 | 453 | clock_pll_E(Source(mux_external), |
paul@211 | 454 | Control_pll(Pll_enable_E, Pll_stable_E, Pll_bypass_E), |
paul@211 | 455 | Divider_pll(Pll_multiplier_E, Pll_input_division_E, |
paul@211 | 456 | Pll_output_division_E, |
paul@219 | 457 | jz4780_pll_intermediate_min, jz4780_pll_intermediate_max, |
paul@219 | 458 | true)), |
paul@0 | 459 | |
paul@211 | 460 | clock_pll_M(Source(mux_external), |
paul@211 | 461 | Control_pll(Pll_enable_M, Pll_stable_M, Pll_bypass_M), |
paul@211 | 462 | Divider_pll(Pll_multiplier_M, Pll_input_division_M, |
paul@211 | 463 | Pll_output_division_M, |
paul@219 | 464 | jz4780_pll_intermediate_min, jz4780_pll_intermediate_max, |
paul@219 | 465 | true)), |
paul@0 | 466 | |
paul@211 | 467 | clock_pll_V(Source(mux_external), |
paul@211 | 468 | Control_pll(Pll_enable_V, Pll_stable_V, Pll_bypass_V), |
paul@211 | 469 | Divider_pll(Pll_multiplier_V, Pll_input_division_V, |
paul@211 | 470 | Pll_output_division_V, |
paul@219 | 471 | jz4780_pll_intermediate_min, jz4780_pll_intermediate_max, |
paul@219 | 472 | true)); |
paul@0 | 473 | |
paul@0 | 474 | |
paul@0 | 475 | |
paul@211 | 476 | // Clock register. |
paul@133 | 477 | |
paul@211 | 478 | static Clock_base *clocks[Clock_identifier_count] = { |
paul@211 | 479 | &clock_none, // Clock_aic |
paul@211 | 480 | &clock_none, // Clock_aic_bitclk |
paul@211 | 481 | &clock_none, // Clock_aic_pclk |
paul@211 | 482 | &clock_none, // Clock_can0 |
paul@211 | 483 | &clock_none, // Clock_can1 |
paul@211 | 484 | &clock_none, // Clock_cdbus |
paul@211 | 485 | &clock_cim, |
paul@211 | 486 | &clock_cpu, |
paul@211 | 487 | &clock_ddr, |
paul@211 | 488 | &clock_dma, |
paul@211 | 489 | &clock_none, // Clock_emac |
paul@211 | 490 | &clock_external, |
paul@239 | 491 | &clock_external_div_512, |
paul@211 | 492 | &clock_hclock0, |
paul@211 | 493 | &clock_hclock2, |
paul@211 | 494 | &clock_hclock2_pclock, |
paul@211 | 495 | &clock_hdmi, |
paul@211 | 496 | &clock_i2c0, |
paul@211 | 497 | &clock_i2c1, |
paul@211 | 498 | &clock_i2c2, |
paul@211 | 499 | &clock_i2c3, |
paul@211 | 500 | &clock_i2c4, |
paul@211 | 501 | &clock_i2s0, |
paul@211 | 502 | &clock_none, // Clock_i2s0_rx |
paul@211 | 503 | &clock_none, // Clock_i2s0_tx |
paul@211 | 504 | &clock_i2s1, |
paul@211 | 505 | &clock_none, // Clock_i2s1_rx |
paul@211 | 506 | &clock_none, // Clock_i2s1_tx |
paul@211 | 507 | &clock_none, // Clock_kbc |
paul@240 | 508 | &clock_l2cache, |
paul@211 | 509 | &clock_lcd, |
paul@211 | 510 | &clock_lcd_pixel0, |
paul@211 | 511 | &clock_lcd_pixel1, |
paul@211 | 512 | &clock_mac, |
paul@211 | 513 | &clock_main, |
paul@211 | 514 | &clock_none, // Clock_mipi_csi |
paul@211 | 515 | &clock_msc, |
paul@211 | 516 | &clock_msc0, |
paul@211 | 517 | &clock_msc1, |
paul@211 | 518 | &clock_msc2, |
paul@211 | 519 | &clock_none, // Clock_none |
paul@211 | 520 | &clock_otg0, |
paul@211 | 521 | &clock_otg1, |
paul@211 | 522 | &clock_pclock, |
paul@215 | 523 | &clock_pcm, |
paul@211 | 524 | &clock_pll_A, |
paul@211 | 525 | &clock_pll_E, |
paul@211 | 526 | &clock_pll_M, |
paul@211 | 527 | &clock_pll_V, |
paul@211 | 528 | &clock_none, // Clock_pwm0 |
paul@211 | 529 | &clock_none, // Clock_pwm1 |
paul@239 | 530 | &clock_external_div_512,// Clock_rtc |
paul@239 | 531 | &clock_rtc_external, |
paul@211 | 532 | &clock_scc, |
paul@211 | 533 | &clock_none, // Clock_sfc |
paul@211 | 534 | &clock_ssi, |
paul@211 | 535 | &clock_ssi0, |
paul@211 | 536 | &clock_ssi1, |
paul@219 | 537 | &clock_none, // Clock_ssi2 |
paul@211 | 538 | &clock_none, // Clock_timer |
paul@211 | 539 | &clock_uart0, |
paul@211 | 540 | &clock_uart1, |
paul@211 | 541 | &clock_uart2, |
paul@211 | 542 | &clock_uart3, |
paul@215 | 543 | &clock_uart4, |
paul@211 | 544 | &clock_none, // Clock_udc |
paul@211 | 545 | &clock_uhc, |
paul@211 | 546 | &clock_none, // Clock_uprt |
paul@213 | 547 | &clock_vpu, |
paul@211 | 548 | }; |
paul@133 | 549 | |
paul@211 | 550 | |
paul@133 | 551 | |
paul@211 | 552 | // Peripheral abstraction. |
paul@0 | 553 | |
paul@211 | 554 | Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr) |
paul@211 | 555 | : Cpm_chip(addr, clocks) |
paul@211 | 556 | { |
paul@0 | 557 | } |
paul@0 | 558 | |
paul@0 | 559 | |
paul@0 | 560 | |
paul@0 | 561 | // C language interface functions. |
paul@0 | 562 | |
paul@0 | 563 | void |
paul@0 | 564 | *jz4780_cpm_init(l4_addr_t cpm_base) |
paul@0 | 565 | { |
paul@211 | 566 | return (void *) new Cpm_jz4780_chip(cpm_base); |
paul@0 | 567 | } |
paul@0 | 568 | |
paul@214 | 569 | const char * |
paul@214 | 570 | jz4780_cpm_clock_type(void *cpm, enum Clock_identifiers clock) |
paul@214 | 571 | { |
paul@214 | 572 | return static_cast<Cpm_jz4780_chip *>(cpm)->clock_type(clock); |
paul@214 | 573 | } |
paul@214 | 574 | |
paul@0 | 575 | int |
paul@128 | 576 | jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock) |
paul@0 | 577 | { |
paul@128 | 578 | return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(clock); |
paul@0 | 579 | } |
paul@0 | 580 | |
paul@0 | 581 | void |
paul@128 | 582 | jz4780_cpm_start_clock(void *cpm, enum Clock_identifiers clock) |
paul@0 | 583 | { |
paul@128 | 584 | static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(clock); |
paul@62 | 585 | } |
paul@62 | 586 | |
paul@62 | 587 | void |
paul@128 | 588 | jz4780_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) |
paul@0 | 589 | { |
paul@128 | 590 | static_cast<Cpm_jz4780_chip *>(cpm)->stop_clock(clock); |
paul@0 | 591 | } |
paul@0 | 592 | |
paul@211 | 593 | int |
paul@211 | 594 | jz4780_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) |
paul@211 | 595 | { |
paul@211 | 596 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_parameters(clock, parameters); |
paul@0 | 597 | } |
paul@0 | 598 | |
paul@211 | 599 | int |
paul@211 | 600 | jz4780_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) |
paul@211 | 601 | { |
paul@211 | 602 | return static_cast<Cpm_jz4780_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); |
paul@0 | 603 | } |
paul@0 | 604 | |
paul@0 | 605 | uint8_t |
paul@211 | 606 | jz4780_cpm_get_source(void *cpm, enum Clock_identifiers clock) |
paul@211 | 607 | { |
paul@211 | 608 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_source(clock); |
paul@0 | 609 | } |
paul@0 | 610 | |
paul@0 | 611 | void |
paul@211 | 612 | jz4780_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) |
paul@211 | 613 | { |
paul@211 | 614 | static_cast<Cpm_jz4780_chip *>(cpm)->set_source(clock, source); |
paul@0 | 615 | } |
paul@0 | 616 | |
paul@211 | 617 | enum Clock_identifiers |
paul@211 | 618 | jz4780_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) |
paul@211 | 619 | { |
paul@211 | 620 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_source_clock(clock); |
paul@0 | 621 | } |
paul@0 | 622 | |
paul@211 | 623 | void |
paul@211 | 624 | jz4780_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) |
paul@211 | 625 | { |
paul@211 | 626 | static_cast<Cpm_jz4780_chip *>(cpm)->set_source_clock(clock, source); |
paul@0 | 627 | } |
paul@0 | 628 | |
paul@213 | 629 | uint64_t |
paul@211 | 630 | jz4780_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) |
paul@211 | 631 | { |
paul@211 | 632 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_source_frequency(clock); |
paul@0 | 633 | } |
paul@0 | 634 | |
paul@213 | 635 | uint64_t |
paul@160 | 636 | jz4780_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) |
paul@211 | 637 | { |
paul@133 | 638 | return static_cast<Cpm_jz4780_chip *>(cpm)->get_frequency(clock); |
paul@62 | 639 | } |
paul@62 | 640 | |
paul@211 | 641 | int |
paul@213 | 642 | jz4780_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) |
paul@0 | 643 | { |
paul@211 | 644 | return static_cast<Cpm_jz4780_chip *>(cpm)->set_frequency(clock, frequency); |
paul@64 | 645 | } |