github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_mimxrt1062_clock.go (about) 1 //go:build mimxrt1062 2 3 package runtime 4 5 import ( 6 "device/nxp" 7 ) 8 9 // Core clock frequencies (Hz) 10 const ( 11 CORE_FREQ = 600000000 // 600 MHz 12 OSC_FREQ = 24000000 // 24 MHz 13 ) 14 15 // Note from Teensyduino (cores/teensy4/startup.c): 16 // 17 // | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(), 18 // | micros(). SysTick can run from either the ARM core clock, or from an 19 // | "external" clock. NXP documents it as "24 MHz XTALOSC can be the external 20 // | clock source of SYSTICK" (RT1052 ref manual, rev 1, page 411). However, 21 // | NXP actually hid an undocumented divide-by-240 circuit in the hardware, so 22 // | the external clock is really 100 kHz. We use this clock rather than the 23 // | ARM clock, to allow SysTick to maintain correct timing even when we change 24 // | the ARM clock to run at different speeds. 25 const SYSTICK_FREQ = 100000 // 100 kHz 26 27 var ( 28 ArmPllConfig = nxp.ClockConfigArmPll{ 29 LoopDivider: 100, // PLL loop divider, Fout=Fin*50 30 Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N 31 } 32 SysPllConfig = nxp.ClockConfigSysPll{ 33 LoopDivider: 1, // PLL loop divider, Fout=Fin*(20+LOOP*2+NUMER/DENOM) 34 Numerator: 0, // 30-bit NUMER of fractional loop divider 35 Denominator: 1, // 30-bit DENOM of fractional loop divider 36 Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N 37 } 38 Usb1PllConfig = nxp.ClockConfigUsbPll{ 39 Instance: 1, // USB PLL instance 40 LoopDivider: 0, // PLL loop divider, Fout=Fin*20 41 Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N 42 } 43 Usb2PllConfig = nxp.ClockConfigUsbPll{ 44 Instance: 2, // USB PLL instance 45 LoopDivider: 0, // PLL loop divider, Fout=Fin*20 46 Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N 47 } 48 ) 49 50 // initClocks configures the core, buses, and all peripherals' clock source mux 51 // and dividers for runtime. The clock gates for individual peripherals are all 52 // disabled prior to configuration and must be enabled afterwards using one of 53 // these `enable*Clocks()` functions or the respective peripheral clocks' 54 // `Enable()` method from the "device/nxp" package. 55 func initClocks() { 56 // disable low-power mode so that __WFI doesn't lock up at runtime. 57 // see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2, 58 // 2019MAR01), chapter 14 59 nxp.ClockModeRun.Set() 60 61 // enable and use 1MHz clock output 62 nxp.XTALOSC24M.OSC_CONFIG2.SetBits(nxp.XTALOSC24M_OSC_CONFIG2_ENABLE_1M_Msk) 63 nxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk) 64 65 // initialize external 24 MHz clock 66 nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_XTAL_24M_PWD_Msk) // power 67 for !nxp.XTALOSC24M.LOWPWR_CTRL.HasBits(nxp.XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_Msk) { 68 } 69 nxp.CCM_ANALOG.MISC0_SET.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) // detect freq 70 for !nxp.CCM_ANALOG.MISC0.HasBits(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_Msk) { 71 } 72 nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) 73 74 // initialize internal RC OSC 24 MHz, and switch clock source to external OSC 75 nxp.XTALOSC24M.LOWPWR_CTRL.SetBits(nxp.XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_Msk) 76 nxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk) 77 78 // set oscillator ready counter value 79 nxp.CCM.CCR.Set((nxp.CCM.CCR.Get() & ^uint32(nxp.CCM_CCR_OSCNT_Msk)) | 80 ((127 << nxp.CCM_CCR_OSCNT_Pos) & nxp.CCM_CCR_OSCNT_Msk)) 81 82 // set PERIPH2_CLK and PERIPH to provide stable clock before PLLs initialed 83 nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC24M 84 nxp.MuxIpPeriph.Mux(1) // PERIPH select PERIPH_CLK2 85 86 // set VDD_SOC to 1.275V, necessary to config AHB to 600 MHz 87 nxp.DCDC.REG3.Set((nxp.DCDC.REG3.Get() & ^uint32(nxp.DCDC_REG3_TRG_Msk)) | 88 ((13 << nxp.DCDC_REG3_TRG_Pos) & nxp.DCDC_REG3_TRG_Msk)) 89 90 // wait until DCDC_STS_DC_OK bit is asserted 91 for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) { 92 } 93 94 nxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1) 95 96 nxp.ClockIpAdc1.Enable(false) // disable ADC 97 nxp.ClockIpAdc2.Enable(false) // 98 99 nxp.ClockIpXbar1.Enable(false) // disable XBAR 100 nxp.ClockIpXbar2.Enable(false) // 101 nxp.ClockIpXbar3.Enable(false) // 102 103 nxp.DivIpIpg.Div(3) // divide IPG_PODF (DIV4) 104 nxp.DivIpArm.Div(1) // divide ARM_PODF (DIV2) 105 nxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1) 106 107 nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT 108 nxp.ClockIpGpt1S.Enable(false) // 109 nxp.ClockIpGpt2.Enable(false) // 110 nxp.ClockIpGpt2S.Enable(false) // 111 nxp.ClockIpPit.Enable(false) // 112 113 nxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1) 114 115 nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1 116 nxp.DivIpUsdhc1.Div(1) // divide USDHC1_PODF (DIV2) 117 nxp.MuxIpUsdhc1.Mux(1) // USDHC1 select PLL2_PFD0 118 nxp.ClockIpUsdhc2.Enable(false) // disable USDHC2 119 nxp.DivIpUsdhc2.Div(1) // divide USDHC2_PODF (DIV2) 120 nxp.MuxIpUsdhc2.Mux(1) // USDHC2 select PLL2_PFD0 121 122 nxp.ClockIpSemc.Enable(false) // disable SEMC 123 nxp.DivIpSemc.Div(1) // divide SEMC_PODF (DIV2) 124 nxp.MuxIpSemcAlt.Mux(0) // SEMC_ALT select PLL2_PFD2 125 nxp.MuxIpSemc.Mux(1) // SEMC select SEMC_ALT 126 127 if false { 128 // TODO: external flash is on this bus, configured via DCD block 129 nxp.ClockIpFlexSpi.Enable(false) // disable FLEXSPI 130 nxp.DivIpFlexSpi.Div(0) // divide FLEXSPI_PODF (DIV1) 131 nxp.MuxIpFlexSpi.Mux(2) // FLEXSPI select PLL2_PFD2 132 } 133 nxp.ClockIpFlexSpi2.Enable(false) // disable FLEXSPI2 134 nxp.DivIpFlexSpi2.Div(0) // divide FLEXSPI2_PODF (DIV1) 135 nxp.MuxIpFlexSpi2.Mux(0) // FLEXSPI2 select PLL2_PFD2 136 137 nxp.ClockIpCsi.Enable(false) // disable CSI 138 nxp.DivIpCsi.Div(1) // divide CSI_PODF (DIV2) 139 nxp.MuxIpCsi.Mux(0) // CSI select OSC24M 140 141 nxp.ClockIpLpspi1.Enable(false) // disable LPSPI 142 nxp.ClockIpLpspi2.Enable(false) // 143 nxp.ClockIpLpspi3.Enable(false) // 144 nxp.ClockIpLpspi4.Enable(false) // 145 nxp.DivIpLpspi.Div(3) // divide LPSPI_PODF (DIV4) 146 nxp.MuxIpLpspi.Mux(2) // LPSPI select PLL2 147 148 nxp.ClockIpTrace.Enable(false) // disable TRACE 149 nxp.DivIpTrace.Div(3) // divide TRACE_PODF (DIV4) 150 nxp.MuxIpTrace.Mux(0) // TRACE select PLL2_MAIN 151 152 nxp.ClockIpSai1.Enable(false) // disable SAI1 153 nxp.DivIpSai1Pre.Div(3) // divide SAI1_CLK_PRED (DIV4) 154 nxp.DivIpSai1.Div(1) // divide SAI1_CLK_PODF (DIV2) 155 nxp.MuxIpSai1.Mux(0) // SAI1 select PLL3_PFD2 156 nxp.ClockIpSai2.Enable(false) // disable SAI2 157 nxp.DivIpSai2Pre.Div(3) // divide SAI2_CLK_PRED (DIV4) 158 nxp.DivIpSai2.Div(1) // divide SAI2_CLK_PODF (DIV2) 159 nxp.MuxIpSai2.Mux(0) // SAI2 select PLL3_PFD2 160 nxp.ClockIpSai3.Enable(false) // disable SAI3 161 nxp.DivIpSai3Pre.Div(3) // divide SAI3_CLK_PRED (DIV4) 162 nxp.DivIpSai3.Div(1) // divide SAI3_CLK_PODF (DIV2) 163 nxp.MuxIpSai3.Mux(0) // SAI3 select PLL3_PFD2 164 165 nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C 166 nxp.ClockIpLpi2c2.Enable(false) // 167 nxp.ClockIpLpi2c3.Enable(false) // 168 nxp.ClockIpLpi2c4.Enable(false) // 169 nxp.DivIpLpi2c.Div(0) // divide LPI2C_CLK_PODF (DIV1) 170 nxp.MuxIpLpi2c.Mux(1) // LPI2C select OSC 171 172 nxp.ClockIpCan1.Enable(false) // disable CAN 173 nxp.ClockIpCan2.Enable(false) // 174 nxp.ClockIpCan3.Enable(false) // 175 nxp.ClockIpCan1S.Enable(false) // 176 nxp.ClockIpCan2S.Enable(false) // 177 nxp.ClockIpCan3S.Enable(false) // 178 nxp.DivIpCan.Div(1) // divide CAN_CLK_PODF (DIV2) 179 nxp.MuxIpCan.Mux(2) // CAN select PLL3_SW_80M 180 181 nxp.ClockIpLpuart1.Enable(false) // disable UART 182 nxp.ClockIpLpuart2.Enable(false) // 183 nxp.ClockIpLpuart3.Enable(false) // 184 nxp.ClockIpLpuart4.Enable(false) // 185 nxp.ClockIpLpuart5.Enable(false) // 186 nxp.ClockIpLpuart6.Enable(false) // 187 nxp.ClockIpLpuart7.Enable(false) // 188 nxp.ClockIpLpuart8.Enable(false) // 189 nxp.DivIpUart.Div(0) // divide UART_CLK_PODF (DIV1) 190 nxp.MuxIpUart.Mux(1) // UART select OSC 191 192 nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF 193 nxp.DivIpLcdifPre.Div(1) // divide LCDIF_PRED (DIV2) 194 nxp.DivIpLcdif.Div(3) // divide LCDIF_CLK_PODF (DIV4) 195 nxp.MuxIpLcdifPre.Mux(5) // LCDIF_PRE select PLL3_PFD1 196 197 nxp.ClockIpSpdif.Enable(false) // disable SPDIF 198 nxp.DivIpSpdif0Pre.Div(1) // divide SPDIF0_CLK_PRED (DIV2) 199 nxp.DivIpSpdif0.Div(7) // divide SPDIF0_CLK_PODF (DIV8) 200 nxp.MuxIpSpdif.Mux(3) // SPDIF select PLL3_SW 201 202 nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1 203 nxp.DivIpFlexio1Pre.Div(1) // divide FLEXIO1_CLK_PRED (DIV2) 204 nxp.DivIpFlexio1.Div(7) // divide FLEXIO1_CLK_PODF (DIV8) 205 nxp.MuxIpFlexio1.Mux(3) // FLEXIO1 select PLL3_SW 206 nxp.ClockIpFlexio2.Enable(false) // disable FLEXIO2 207 nxp.DivIpFlexio2Pre.Div(1) // divide FLEXIO2_CLK_PRED (DIV2) 208 nxp.DivIpFlexio2.Div(7) // divide FLEXIO2_CLK_PODF (DIV8) 209 nxp.MuxIpFlexio2.Mux(3) // FLEXIO2 select PLL3_SW 210 211 nxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN 212 213 ArmPllConfig.Configure() // init ARM PLL 214 // SYS PLL (PLL2) @ 528 MHz 215 // PFD0 = 396 MHz -> USDHC1/USDHC2(DIV2)=198 MHz 216 // PFD1 = 594 MHz -> (currently unused) 217 // PFD2 = 327.72 MHz -> SEMC(DIV2)=163.86 MHz, FlexSPI/FlexSPI2=327.72 MHz 218 // PFD3 = 454.73 MHz -> (currently unused) 219 SysPllConfig.Configure(24, 16, 29, 16) // init SYS PLL and PFDs 220 221 // USB1 PLL (PLL3) @ 480 MHz 222 // PFD0 -> (currently unused) 223 // PFD1 -> (currently unused) 224 // PFD2 -> (currently unused) 225 // PFD3 -> (currently unused) 226 Usb1PllConfig.Configure() // init USB1 PLL and PFDs 227 Usb2PllConfig.Configure() // init USB2 PLL 228 229 nxp.MuxIpPrePeriph.Mux(3) // PRE_PERIPH select ARM_PLL 230 nxp.MuxIpPeriph.Mux(0) // PERIPH select PRE_PERIPH 231 nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC 232 nxp.MuxIpPerclk.Mux(1) // PERCLK select OSC 233 234 // set LVDS1 clock source 235 nxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) | 236 ((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) 237 238 // set CLOCK_OUT1 divider 239 nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) | 240 ((0 << nxp.CCM_CCOSR_CLKO1_DIV_Pos) & nxp.CCM_CCOSR_CLKO1_DIV_Msk)) 241 // set CLOCK_OUT1 source 242 nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_SEL_Msk)) | 243 ((1 << nxp.CCM_CCOSR_CLKO1_SEL_Pos) & nxp.CCM_CCOSR_CLKO1_SEL_Msk)) 244 // set CLOCK_OUT2 divider 245 nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_DIV_Msk)) | 246 ((0 << nxp.CCM_CCOSR_CLKO2_DIV_Pos) & nxp.CCM_CCOSR_CLKO2_DIV_Msk)) 247 // set CLOCK_OUT2 source 248 nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_SEL_Msk)) | 249 ((18 << nxp.CCM_CCOSR_CLKO2_SEL_Pos) & nxp.CCM_CCOSR_CLKO2_SEL_Msk)) 250 251 nxp.CCM.CCOSR.ClearBits(nxp.CCM_CCOSR_CLK_OUT_SEL_Msk) // set CLK_OUT1 drives CLK_OUT 252 nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO1_EN_Msk) // enable CLK_OUT1 253 nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2 254 255 nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR 256 nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC 257 // set GPT1 High frequency reference clock source 258 nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk) 259 // set GPT2 High frequency reference clock source 260 nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk) 261 262 nxp.ClockIpGpio1.Enable(false) // disable GPIO 263 nxp.ClockIpGpio2.Enable(false) // 264 nxp.ClockIpGpio3.Enable(false) // 265 nxp.ClockIpGpio4.Enable(false) // 266 } 267 268 func enableTimerClocks() { 269 nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT 270 nxp.ClockIpGpt1S.Enable(true) // 271 nxp.ClockIpGpt2.Enable(true) // 272 nxp.ClockIpGpt2S.Enable(true) // 273 nxp.ClockIpPit.Enable(true) // 274 } 275 276 func enablePinClocks() { 277 nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC 278 nxp.ClockIpIomuxc.Enable(true) // 279 280 nxp.ClockIpGpio1.Enable(true) // enable GPIO 281 nxp.ClockIpGpio2.Enable(true) // 282 nxp.ClockIpGpio3.Enable(true) // 283 nxp.ClockIpGpio4.Enable(true) // 284 } 285 286 func enablePeripheralClocks() { 287 nxp.ClockIpAdc1.Enable(true) // enable ADC 288 nxp.ClockIpAdc2.Enable(true) // 289 290 nxp.ClockIpXbar1.Enable(true) // enable XBAR 291 nxp.ClockIpXbar2.Enable(true) // 292 nxp.ClockIpXbar3.Enable(true) // 293 294 nxp.ClockIpUsdhc1.Enable(true) // enable USDHC 295 nxp.ClockIpUsdhc2.Enable(true) // 296 297 nxp.ClockIpSemc.Enable(true) // enable SEMC 298 299 nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2 300 301 nxp.ClockIpLpspi1.Enable(true) // enable LPSPI 302 nxp.ClockIpLpspi2.Enable(true) // 303 nxp.ClockIpLpspi3.Enable(true) // 304 nxp.ClockIpLpspi4.Enable(true) // 305 306 nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C 307 nxp.ClockIpLpi2c2.Enable(true) // 308 nxp.ClockIpLpi2c3.Enable(true) // 309 nxp.ClockIpLpi2c4.Enable(true) // 310 311 nxp.ClockIpCan1.Enable(true) // enable CAN 312 nxp.ClockIpCan2.Enable(true) // 313 nxp.ClockIpCan3.Enable(true) // 314 nxp.ClockIpCan1S.Enable(true) // 315 nxp.ClockIpCan2S.Enable(true) // 316 nxp.ClockIpCan3S.Enable(true) // 317 318 nxp.ClockIpLpuart1.Enable(true) // enable UART 319 nxp.ClockIpLpuart2.Enable(true) // 320 nxp.ClockIpLpuart3.Enable(true) // 321 nxp.ClockIpLpuart4.Enable(true) // 322 nxp.ClockIpLpuart5.Enable(true) // 323 nxp.ClockIpLpuart6.Enable(true) // 324 nxp.ClockIpLpuart7.Enable(true) // 325 nxp.ClockIpLpuart8.Enable(true) // 326 327 nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO 328 nxp.ClockIpFlexio2.Enable(true) // 329 }