6 #include "flash_layout.h"
10 #include "soc_watch.h"
13 #define get_ticks() _rdtsc()
19 static uint32_t ticks_per_us = SYS_TICKS_PER_US_32MHZ;
27 static void apply_flash_timings(uint32_t sys_ticks_per_us)
31 for (flash = QM_FLASH_0; flash < QM_FLASH_NUM; flash++) {
32 if (sys_ticks_per_us <= SYS_TICKS_PER_US_4MHZ) {
37 QM_FLASH[flash]->tmg_ctrl |= QM_FLASH_CLK_SLOW;
38 QM_FLASH[flash]->tmg_ctrl &= ~QM_FLASH_WAIT_STATE_MASK;
39 }
else if (sys_ticks_per_us <= SYS_TICKS_PER_US_16MHZ) {
40 QM_FLASH[flash]->tmg_ctrl &= ~QM_FLASH_CLK_SLOW;
45 QM_FLASH[flash]->tmg_ctrl &= ~QM_FLASH_WAIT_STATE_MASK;
47 QM_FLASH[flash]->tmg_ctrl &= ~QM_FLASH_CLK_SLOW;
52 QM_FLASH[flash]->tmg_ctrl =
53 (QM_FLASH[flash]->tmg_ctrl &
54 ~QM_FLASH_WAIT_STATE_MASK) |
55 (1 << QM_FLASH_WAIT_STATE_OFFSET);
66 uint32_t *sys_ticks_per_us,
71 *sys_ticks_per_us = SYS_TICKS_PER_US_32MHZ / BIT(div);
72 *trim = QM_FLASH_DATA_TRIM_CODE->osc_trim_32mhz;
76 *sys_ticks_per_us = SYS_TICKS_PER_US_16MHZ / BIT(div);
77 *trim = QM_FLASH_DATA_TRIM_CODE->osc_trim_16mhz;
81 *sys_ticks_per_us = SYS_TICKS_PER_US_8MHZ / BIT(div);
82 *trim = QM_FLASH_DATA_TRIM_CODE->osc_trim_8mhz;
86 *sys_ticks_per_us = SYS_TICKS_PER_US_4MHZ / BIT(div);
87 *trim = QM_FLASH_DATA_TRIM_CODE->osc_trim_4mhz;
91 *sys_ticks_per_us = 1;
95 *sys_ticks_per_us = SYS_TICKS_PER_US_XTAL / BIT(div);
102 QM_CHECK(div < CLK_SYS_DIV_NUM, -EINVAL);
107 uint32_t sys_ticks_per_us = 1;
113 uint32_t ccu_sys_clk_ctl =
114 QM_SCSS_CCU->ccu_sys_clk_ctl & CLK_SYS_CLK_DIV_DEF_MASK;
117 clk_sys_compute_new_frequency(mode, div, &sys_ticks_per_us, &trim);
125 apply_flash_timings(SYS_TICKS_PER_US_32MHZ);
157 if ((trim & QM_FLASH_TRIM_PRESENT_MASK) ==
158 QM_FLASH_TRIM_PRESENT) {
162 QM_SCSS_CCU->osc0_cfg1 &= ~OSC0_CFG1_SI_FREQ_SEL_MASK;
163 QM_SCSS_CCU->osc0_cfg1 |= (mode << OSC0_CFG1_SI_FREQ_SEL_OFFS);
165 QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_EN_SI_OSC;
167 while (!(QM_SCSS_CCU->osc0_stat1 & QM_OSC0_LOCK_SI)) {
170 QM_SCSS_CCU->osc0_cfg1 &= ~QM_OSC0_MODE_SEL;
172 QM_SCSS_CCU->ccu_sys_clk_ctl =
173 ccu_sys_clk_ctl | QM_CCU_SYS_CLK_SEL |
174 (div << QM_CCU_SYS_CLK_DIV_OFFSET);
176 QM_SCSS_CCU->osc0_cfg1 &= ~QM_OSC0_EN_CRYSTAL;
182 (QM_CCU_RTC_CLK_EN | (div << QM_CCU_SYS_CLK_DIV_OFFSET));
184 QM_SCSS_CCU->ccu_sys_clk_ctl =
185 (ccu_sys_clk_ctl & ~(QM_CCU_SYS_CLK_SEL));
189 QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_EN_CRYSTAL;
190 sys_ticks_per_us = SYS_TICKS_PER_US_XTAL / BIT(div);
191 while (!(QM_SCSS_CCU->osc0_stat1 & QM_OSC0_LOCK_XTAL)) {
193 QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_MODE_SEL;
194 QM_SCSS_CCU->ccu_sys_clk_ctl =
195 ccu_sys_clk_ctl | QM_CCU_SYS_CLK_SEL |
196 (div << QM_CCU_SYS_CLK_DIV_OFFSET);
197 QM_SCSS_CCU->osc0_cfg1 &= ~QM_OSC0_EN_SI_OSC;
201 QM_SCSS_CCU->ccu_sys_clk_ctl |= QM_CCU_SYS_CLK_DIV_EN;
202 ticks_per_us = (sys_ticks_per_us > 0 ? sys_ticks_per_us : 1);
207 apply_flash_timings(sys_ticks_per_us);
216 QM_CHECK(NULL != value, -EINVAL);
218 *value = (QM_SCSS_CCU->osc0_cfg1 & OSC0_CFG1_FTRIMOTP_MASK) >>
219 OSC0_CFG1_FTRIMOTP_OFFS;
227 QM_SCSS_CCU->osc0_cfg0 |= BIT(1);
230 QM_SCSS_CCU->osc0_cfg1 &= ~OSC0_CFG1_FTRIMOTP_MASK;
231 QM_SCSS_CCU->osc0_cfg1 |=
232 (value << OSC0_CFG1_FTRIMOTP_OFFS) & OSC0_CFG1_FTRIMOTP_MASK;
244 QM_SCSS_CCU->osc0_cfg0 &= ~BIT(1);
255 QM_CHECK((div - 1) <= QM_ADC_DIV_MAX, -EINVAL);
257 uint32_t reg = QM_SCSS_CCU->ccu_periph_clk_div_ctl0;
258 reg &= CLK_ADC_DIV_DEF_MASK;
259 reg |= ((div - 1) << QM_CCU_ADC_CLK_DIV_OFFSET);
260 QM_SCSS_CCU->ccu_periph_clk_div_ctl0 = reg;
270 QM_SCSS_CCU->ccu_periph_clk_div_ctl0 & CLK_PERIPH_DIV_DEF_MASK;
271 reg |= (div << QM_CCU_PERIPH_PCLK_DIV_OFFSET);
272 QM_SCSS_CCU->ccu_periph_clk_div_ctl0 = reg;
274 QM_SCSS_CCU->ccu_periph_clk_div_ctl0 |= QM_CCU_PERIPH_PCLK_DIV_EN;
284 QM_SCSS_CCU->ccu_gpio_db_clk_ctl & CLK_GPIO_DB_DIV_DEF_MASK;
285 reg |= (div << QM_CCU_GPIO_DB_DIV_OFFSET);
286 QM_SCSS_CCU->ccu_gpio_db_clk_ctl = reg;
288 QM_SCSS_CCU->ccu_gpio_db_clk_ctl |= QM_CCU_GPIO_DB_CLK_DIV_EN;
297 uint32_t reg = QM_SCSS_CCU->ccu_ext_clock_ctl & CLK_EXTERN_DIV_DEF_MASK;
298 reg |= (div << QM_CCU_EXTERN_DIV_OFFSET);
299 QM_SCSS_CCU->ccu_ext_clock_ctl = reg;
301 QM_SCSS_CCU->ccu_ext_clock_ctl |= QM_CCU_EXT_CLK_DIV_EN;
310 uint32_t reg = QM_SCSS_CCU->ccu_sys_clk_ctl & CLK_RTC_DIV_DEF_MASK;
311 reg |= (div << QM_CCU_RTC_CLK_DIV_OFFSET);
312 QM_SCSS_CCU->ccu_sys_clk_ctl = reg;
314 QM_SCSS_CCU->ccu_sys_clk_ctl |= QM_CCU_RTC_CLK_DIV_EN;
323 QM_SCSS_CCU->ccu_periph_clk_gate_ctl |= clocks;
325 #if (HAS_SW_SOCWATCH)
337 QM_SCSS_CCU->ccu_periph_clk_gate_ctl &= ~clocks;
339 #if (HAS_SW_SOCWATCH)
354 uint32_t timeout = ticks_per_us * microseconds;
355 unsigned long long tsc_start;
356 tsc_start = get_ticks();
358 while (get_ticks() - tsc_start < timeout) {
364 QM_SCSS_CCU->ccu_mlayer_ahb_ctl |= QM_CCU_DMA_CLK_EN;
371 QM_SCSS_CCU->ccu_mlayer_ahb_ctl &= ~QM_CCU_DMA_CLK_EN;
384 ((QM_SCSS_CCU->ccu_periph_clk_div_ctl0 &
385 CLK_PERIPH_DIV_DEF_MASK) >>
386 QM_CCU_PERIPH_PCLK_DIV_OFFSET);
clk_sys_mode_t
System clock mode type.
int clk_sys_set_mode(const clk_sys_mode_t mode, const clk_sys_div_t div)
Set clock mode and divisor.
Real Time Clock Divider = 32768.
int clk_rtc_set_div(const clk_rtc_div_t div)
Change divider value of RTC.
int clk_adc_set_div(const uint16_t div)
Change divider value of ADC clock.
int clk_periph_enable(const clk_periph_t clocks)
Enable clocks for peripherals / registers.
Peripheral Clock Divider = 8.
uint32_t get_i2c_clk_freq_in_mhz(void)
Get I2C clock frequency in MHz.
int clk_gpio_db_set_div(const clk_gpio_db_div_t div)
Change divider value of GPIO debounce clock.
Crystal Oscillator Clock.
int clk_dma_enable(void)
Enable the DMA clock.
Quark D2000 peripherals Enable.
0x018 Perip Clock Gate Ctl.
clk_sys_div_t
System clock divider type.
16MHz Hybrid Oscillator Clock.
int clk_trim_read(uint32_t *const value)
Read the silicon oscillator trim code for the current frequency.
clk_periph_div_t
Peripheral clock divider type.
32MHz Hybrid Oscillator Clock.
GPIO Clock Debounce Divider = 128.
External Crystal Clock Divider = 8.
clk_gpio_db_div_t
GPIO clock debounce divider type.
clk_rtc_div_t
RTC clock divider type.
void clk_sys_udelay(uint32_t microseconds)
Idle loop the processor for at least the value given in microseconds.
8MHz Hybrid Oscillator Clock.
uint32_t clk_sys_get_ticks_per_us(void)
Get number of system ticks per micro second.
int clk_periph_disable(const clk_periph_t clocks)
Disable clocks for peripherals / registers.
int clk_periph_set_div(const clk_periph_div_t div)
Change divider value of peripheral clock.
int clk_trim_apply(const uint32_t value)
Apply silicon oscillator trim code.
int clk_ext_set_div(const clk_ext_div_t div)
Change divider value of external clock.
int clk_dma_disable(void)
Disable the DMA clock.
4MHz Hybrid Oscillator Clock.
clk_periph_t
Peripheral clock register map.
clk_ext_div_t
External crystal clock divider type.