diff options
author | Damien Le Moal <damien.lemoal@wdc.com> | 2019-01-03 08:32:25 +0300 |
---|---|---|
committer | Damien Le Moal <damien.lemoal@wdc.com> | 2019-01-03 08:32:25 +0300 |
commit | c37a8508d14dae5b0d09c74b5de905bc585abbe3 (patch) | |
tree | ecc447160fb368affdc0dee0c99c7201a9cb6b6b /platform/kendryte | |
parent | 4079df63a7a081c649a350eafd92af51d99df448 (diff) | |
download | opensbi-c37a8508d14dae5b0d09c74b5de905bc585abbe3.tar.xz |
platform: kendryte/k210: Simplify sysctl code
Simplify sysctl.c code to only the used CPU freqency function.
This reduces the size of the final firmware by 4KB.
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Diffstat (limited to 'platform/kendryte')
-rw-r--r-- | platform/kendryte/k210/sysctl.c | 1766 | ||||
-rw-r--r-- | platform/kendryte/k210/sysctl.h | 161 | ||||
-rw-r--r-- | platform/kendryte/k210/uarths.c | 2 |
3 files changed, 20 insertions, 1909 deletions
diff --git a/platform/kendryte/k210/sysctl.c b/platform/kendryte/k210/sysctl.c index 90aa0e2..5977e33 100644 --- a/platform/kendryte/k210/sysctl.c +++ b/platform/kendryte/k210/sysctl.c @@ -15,959 +15,18 @@ #include <sbi/riscv_encoding.h> #include "sysctl.h" -#define SYSCTRL_CLOCK_FREQ_IN0 (26000000UL) - -const u8 get_select_pll2[] = { - [SYSCTL_SOURCE_IN0] = 0, - [SYSCTL_SOURCE_PLL0] = 1, - [SYSCTL_SOURCE_PLL1] = 2, -}; - -const u8 get_source_pll2[] = { - [0] = SYSCTL_SOURCE_IN0, - [1] = SYSCTL_SOURCE_PLL0, - [2] = SYSCTL_SOURCE_PLL1, -}; - -const u8 get_select_aclk[] = { - [SYSCTL_SOURCE_IN0] = 0, - [SYSCTL_SOURCE_PLL0] = 1, -}; - -const u8 get_source_aclk[] = { - [0] = SYSCTL_SOURCE_IN0, - [1] = SYSCTL_SOURCE_PLL0, -}; - volatile sysctl_t *const sysctl = (volatile sysctl_t *)SYSCTL_BASE_ADDR; -u32 sysctl_get_git_id(void) -{ - return sysctl->git_id.git_id; -} - -u32 sysctl_get_freq(void) -{ - return sysctl->clk_freq.clk_freq; -} - -static void sysctl_reset_ctl(sysctl_reset_t reset, u8 rst_value) -{ - switch (reset) { - case SYSCTL_RESET_SOC: - sysctl->soft_reset.soft_reset = rst_value; - break; - case SYSCTL_RESET_ROM: - sysctl->peri_reset.rom_reset = rst_value; - break; - case SYSCTL_RESET_DMA: - sysctl->peri_reset.dma_reset = rst_value; - break; - case SYSCTL_RESET_AI: - sysctl->peri_reset.ai_reset = rst_value; - break; - case SYSCTL_RESET_DVP: - sysctl->peri_reset.dvp_reset = rst_value; - break; - case SYSCTL_RESET_FFT: - sysctl->peri_reset.fft_reset = rst_value; - break; - case SYSCTL_RESET_GPIO: - sysctl->peri_reset.gpio_reset = rst_value; - break; - case SYSCTL_RESET_SPI0: - sysctl->peri_reset.spi0_reset = rst_value; - break; - case SYSCTL_RESET_SPI1: - sysctl->peri_reset.spi1_reset = rst_value; - break; - case SYSCTL_RESET_SPI2: - sysctl->peri_reset.spi2_reset = rst_value; - break; - case SYSCTL_RESET_SPI3: - sysctl->peri_reset.spi3_reset = rst_value; - break; - case SYSCTL_RESET_I2S0: - sysctl->peri_reset.i2s0_reset = rst_value; - break; - case SYSCTL_RESET_I2S1: - sysctl->peri_reset.i2s1_reset = rst_value; - break; - case SYSCTL_RESET_I2S2: - sysctl->peri_reset.i2s2_reset = rst_value; - break; - case SYSCTL_RESET_I2C0: - sysctl->peri_reset.i2c0_reset = rst_value; - break; - case SYSCTL_RESET_I2C1: - sysctl->peri_reset.i2c1_reset = rst_value; - break; - case SYSCTL_RESET_I2C2: - sysctl->peri_reset.i2c2_reset = rst_value; - break; - case SYSCTL_RESET_UART1: - sysctl->peri_reset.uart1_reset = rst_value; - break; - case SYSCTL_RESET_UART2: - sysctl->peri_reset.uart2_reset = rst_value; - break; - case SYSCTL_RESET_UART3: - sysctl->peri_reset.uart3_reset = rst_value; - break; - case SYSCTL_RESET_AES: - sysctl->peri_reset.aes_reset = rst_value; - break; - case SYSCTL_RESET_FPIOA: - sysctl->peri_reset.fpioa_reset = rst_value; - break; - case SYSCTL_RESET_TIMER0: - sysctl->peri_reset.timer0_reset = rst_value; - break; - case SYSCTL_RESET_TIMER1: - sysctl->peri_reset.timer1_reset = rst_value; - break; - case SYSCTL_RESET_TIMER2: - sysctl->peri_reset.timer2_reset = rst_value; - break; - case SYSCTL_RESET_WDT0: - sysctl->peri_reset.wdt0_reset = rst_value; - break; - case SYSCTL_RESET_WDT1: - sysctl->peri_reset.wdt1_reset = rst_value; - break; - case SYSCTL_RESET_SHA: - sysctl->peri_reset.sha_reset = rst_value; - break; - case SYSCTL_RESET_RTC: - sysctl->peri_reset.rtc_reset = rst_value; - break; - - default: - break; - } -} - -void sysctl_reset(sysctl_reset_t reset) -{ - sysctl_reset_ctl(reset, 1); - sysctl_reset_ctl(reset, 0); -} - -static int sysctl_clock_bus_en(sysctl_clock_t clock, u8 en) -{ - /* - * The timer is under APB0, to prevent apb0_clk_en1 and apb0_clk_en0 - * on same register, we split it to peripheral and central two - * registers, to protect CPU close apb0 clock accidentally. - * - * The apb0_clk_en0 and apb0_clk_en1 have same function, - * one of them set, the APB0 clock enable. - */ - - /* The APB clock should carefully disable */ - if (en) { - switch (clock) { - /* - * These peripheral devices are under APB0 - * GPIO, UART1, UART2, UART3, SPI_SLAVE, I2S0, I2S1, - * I2S2, I2C0, I2C1, I2C2, FPIOA, SHA256, TIMER0, - * TIMER1, TIMER2 - */ - case SYSCTL_CLOCK_GPIO: - case SYSCTL_CLOCK_SPI2: - case SYSCTL_CLOCK_I2S0: - case SYSCTL_CLOCK_I2S1: - case SYSCTL_CLOCK_I2S2: - case SYSCTL_CLOCK_I2C0: - case SYSCTL_CLOCK_I2C1: - case SYSCTL_CLOCK_I2C2: - case SYSCTL_CLOCK_UART1: - case SYSCTL_CLOCK_UART2: - case SYSCTL_CLOCK_UART3: - case SYSCTL_CLOCK_FPIOA: - case SYSCTL_CLOCK_TIMER0: - case SYSCTL_CLOCK_TIMER1: - case SYSCTL_CLOCK_TIMER2: - case SYSCTL_CLOCK_SHA: - sysctl->clk_en_cent.apb0_clk_en = en; - break; - - /* - * These peripheral devices are under APB1 - * WDT, AES, OTP, DVP, SYSCTL - */ - case SYSCTL_CLOCK_AES: - case SYSCTL_CLOCK_WDT0: - case SYSCTL_CLOCK_WDT1: - case SYSCTL_CLOCK_OTP: - case SYSCTL_CLOCK_RTC: - sysctl->clk_en_cent.apb1_clk_en = en; - break; - - /* - * These peripheral devices are under APB2 - * SPI0, SPI1 - */ - case SYSCTL_CLOCK_SPI0: - case SYSCTL_CLOCK_SPI1: - sysctl->clk_en_cent.apb2_clk_en = en; - break; - - default: - break; - } - } - - return 0; -} - -static int sysctl_clock_device_en(sysctl_clock_t clock, u8 en) -{ - switch (clock) { - /* - * These devices are PLL - */ - case SYSCTL_CLOCK_PLL0: - sysctl->pll0.pll_out_en0 = en; - break; - case SYSCTL_CLOCK_PLL1: - sysctl->pll1.pll_out_en1 = en; - break; - case SYSCTL_CLOCK_PLL2: - sysctl->pll2.pll_out_en2 = en; - break; - - /* - * These devices are CPU, SRAM, APB bus, ROM, DMA, AI - */ - case SYSCTL_CLOCK_CPU: - sysctl->clk_en_cent.cpu_clk_en = en; - break; - case SYSCTL_CLOCK_SRAM0: - sysctl->clk_en_cent.sram0_clk_en = en; - break; - case SYSCTL_CLOCK_SRAM1: - sysctl->clk_en_cent.sram1_clk_en = en; - break; - case SYSCTL_CLOCK_APB0: - sysctl->clk_en_cent.apb0_clk_en = en; - break; - case SYSCTL_CLOCK_APB1: - sysctl->clk_en_cent.apb1_clk_en = en; - break; - case SYSCTL_CLOCK_APB2: - sysctl->clk_en_cent.apb2_clk_en = en; - break; - case SYSCTL_CLOCK_ROM: - sysctl->clk_en_peri.rom_clk_en = en; - break; - case SYSCTL_CLOCK_DMA: - sysctl->clk_en_peri.dma_clk_en = en; - break; - case SYSCTL_CLOCK_AI: - sysctl->clk_en_peri.ai_clk_en = en; - break; - case SYSCTL_CLOCK_DVP: - sysctl->clk_en_peri.dvp_clk_en = en; - break; - case SYSCTL_CLOCK_FFT: - sysctl->clk_en_peri.fft_clk_en = en; - break; - case SYSCTL_CLOCK_SPI3: - sysctl->clk_en_peri.spi3_clk_en = en; - break; - - /* - * These peripheral devices are under APB0 - * GPIO, UART1, UART2, UART3, SPI_SLAVE, I2S0, I2S1, - * I2S2, I2C0, I2C1, I2C2, FPIOA, SHA256, TIMER0, - * TIMER1, TIMER2 - */ - case SYSCTL_CLOCK_GPIO: - sysctl->clk_en_peri.gpio_clk_en = en; - break; - case SYSCTL_CLOCK_SPI2: - sysctl->clk_en_peri.spi2_clk_en = en; - break; - case SYSCTL_CLOCK_I2S0: - sysctl->clk_en_peri.i2s0_clk_en = en; - break; - case SYSCTL_CLOCK_I2S1: - sysctl->clk_en_peri.i2s1_clk_en = en; - break; - case SYSCTL_CLOCK_I2S2: - sysctl->clk_en_peri.i2s2_clk_en = en; - break; - case SYSCTL_CLOCK_I2C0: - sysctl->clk_en_peri.i2c0_clk_en = en; - break; - case SYSCTL_CLOCK_I2C1: - sysctl->clk_en_peri.i2c1_clk_en = en; - break; - case SYSCTL_CLOCK_I2C2: - sysctl->clk_en_peri.i2c2_clk_en = en; - break; - case SYSCTL_CLOCK_UART1: - sysctl->clk_en_peri.uart1_clk_en = en; - break; - case SYSCTL_CLOCK_UART2: - sysctl->clk_en_peri.uart2_clk_en = en; - break; - case SYSCTL_CLOCK_UART3: - sysctl->clk_en_peri.uart3_clk_en = en; - break; - case SYSCTL_CLOCK_FPIOA: - sysctl->clk_en_peri.fpioa_clk_en = en; - break; - case SYSCTL_CLOCK_TIMER0: - sysctl->clk_en_peri.timer0_clk_en = en; - break; - case SYSCTL_CLOCK_TIMER1: - sysctl->clk_en_peri.timer1_clk_en = en; - break; - case SYSCTL_CLOCK_TIMER2: - sysctl->clk_en_peri.timer2_clk_en = en; - break; - case SYSCTL_CLOCK_SHA: - sysctl->clk_en_peri.sha_clk_en = en; - break; - - /* - * These peripheral devices are under APB1 - * WDT, AES, OTP, DVP, SYSCTL - */ - case SYSCTL_CLOCK_AES: - sysctl->clk_en_peri.aes_clk_en = en; - break; - case SYSCTL_CLOCK_WDT0: - sysctl->clk_en_peri.wdt0_clk_en = en; - break; - case SYSCTL_CLOCK_WDT1: - sysctl->clk_en_peri.wdt1_clk_en = en; - break; - case SYSCTL_CLOCK_OTP: - sysctl->clk_en_peri.otp_clk_en = en; - break; - case SYSCTL_CLOCK_RTC: - sysctl->clk_en_peri.rtc_clk_en = en; - break; - - /* - * These peripheral devices are under APB2 - * SPI0, SPI1 - */ - case SYSCTL_CLOCK_SPI0: - sysctl->clk_en_peri.spi0_clk_en = en; - break; - case SYSCTL_CLOCK_SPI1: - sysctl->clk_en_peri.spi1_clk_en = en; - break; - - default: - break; - } - - return 0; -} - -int sysctl_clock_enable(sysctl_clock_t clock) -{ - if (clock >= SYSCTL_CLOCK_MAX) - return -1; - - sysctl_clock_bus_en(clock, 1); - sysctl_clock_device_en(clock, 1); - - return 0; -} - -int sysctl_clock_disable(sysctl_clock_t clock) -{ - if (clock >= SYSCTL_CLOCK_MAX) - return -1; - - sysctl_clock_bus_en(clock, 0); - sysctl_clock_device_en(clock, 0); - - return 0; -} - -int sysctl_clock_set_threshold(sysctl_threshold_t which, int threshold) -{ - int result = 0; - - switch (which) { - /* - * These threshold is 2 bit width - */ - case SYSCTL_THRESHOLD_ACLK: - sysctl->clk_sel0.aclk_divider_sel = (u8)threshold & 0x03; - break; - - /* - * These threshold is 3 bit width - */ - case SYSCTL_THRESHOLD_APB0: - sysctl->clk_sel0.apb0_clk_sel = (u8)threshold & 0x07; - break; - case SYSCTL_THRESHOLD_APB1: - sysctl->clk_sel0.apb1_clk_sel = (u8)threshold & 0x07; - break; - case SYSCTL_THRESHOLD_APB2: - sysctl->clk_sel0.apb2_clk_sel = (u8)threshold & 0x07; - break; - - /* - * These threshold is 4 bit width - */ - case SYSCTL_THRESHOLD_SRAM0: - sysctl->clk_th0.sram0_gclk_threshold = (u8)threshold & 0x0F; - break; - case SYSCTL_THRESHOLD_SRAM1: - sysctl->clk_th0.sram1_gclk_threshold = (u8)threshold & 0x0F; - break; - case SYSCTL_THRESHOLD_AI: - sysctl->clk_th0.ai_gclk_threshold = (u8)threshold & 0x0F; - break; - case SYSCTL_THRESHOLD_DVP: - sysctl->clk_th0.dvp_gclk_threshold = (u8)threshold & 0x0F; - break; - case SYSCTL_THRESHOLD_ROM: - sysctl->clk_th0.rom_gclk_threshold = (u8)threshold & 0x0F; - break; - - /* - * These threshold is 8 bit width - */ - case SYSCTL_THRESHOLD_SPI0: - sysctl->clk_th1.spi0_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_SPI1: - sysctl->clk_th1.spi1_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_SPI2: - sysctl->clk_th1.spi2_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_SPI3: - sysctl->clk_th1.spi3_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_TIMER0: - sysctl->clk_th2.timer0_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_TIMER1: - sysctl->clk_th2.timer1_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_TIMER2: - sysctl->clk_th2.timer2_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2S0_M: - sysctl->clk_th4.i2s0_mclk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2S1_M: - sysctl->clk_th4.i2s1_mclk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2S2_M: - sysctl->clk_th5.i2s2_mclk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2C0: - sysctl->clk_th5.i2c0_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2C1: - sysctl->clk_th5.i2c1_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_I2C2: - sysctl->clk_th5.i2c2_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_WDT0: - sysctl->clk_th6.wdt0_clk_threshold = (u8)threshold; - break; - case SYSCTL_THRESHOLD_WDT1: - sysctl->clk_th6.wdt1_clk_threshold = (u8)threshold; - break; - - /* - * These threshold is 16 bit width - */ - case SYSCTL_THRESHOLD_I2S0: - sysctl->clk_th3.i2s0_clk_threshold = (u16)threshold; - break; - case SYSCTL_THRESHOLD_I2S1: - sysctl->clk_th3.i2s1_clk_threshold = (u16)threshold; - break; - case SYSCTL_THRESHOLD_I2S2: - sysctl->clk_th4.i2s2_clk_threshold = (u16)threshold; - break; - - default: - result = -1; - break; - } - - return result; -} - -int sysctl_clock_get_threshold(sysctl_threshold_t which) -{ - int threshold = 0; - - switch (which) { - /* - * Select and get threshold value - */ - case SYSCTL_THRESHOLD_ACLK: - threshold = (int)sysctl->clk_sel0.aclk_divider_sel; - break; - case SYSCTL_THRESHOLD_APB0: - threshold = (int)sysctl->clk_sel0.apb0_clk_sel; - break; - case SYSCTL_THRESHOLD_APB1: - threshold = (int)sysctl->clk_sel0.apb1_clk_sel; - break; - case SYSCTL_THRESHOLD_APB2: - threshold = (int)sysctl->clk_sel0.apb2_clk_sel; - break; - case SYSCTL_THRESHOLD_SRAM0: - threshold = (int)sysctl->clk_th0.sram0_gclk_threshold; - break; - case SYSCTL_THRESHOLD_SRAM1: - threshold = (int)sysctl->clk_th0.sram1_gclk_threshold; - break; - case SYSCTL_THRESHOLD_AI: - threshold = (int)sysctl->clk_th0.ai_gclk_threshold; - break; - case SYSCTL_THRESHOLD_DVP: - threshold = (int)sysctl->clk_th0.dvp_gclk_threshold; - break; - case SYSCTL_THRESHOLD_ROM: - threshold = (int)sysctl->clk_th0.rom_gclk_threshold; - break; - case SYSCTL_THRESHOLD_SPI0: - threshold = (int)sysctl->clk_th1.spi0_clk_threshold; - break; - case SYSCTL_THRESHOLD_SPI1: - threshold = (int)sysctl->clk_th1.spi1_clk_threshold; - break; - case SYSCTL_THRESHOLD_SPI2: - threshold = (int)sysctl->clk_th1.spi2_clk_threshold; - break; - case SYSCTL_THRESHOLD_SPI3: - threshold = (int)sysctl->clk_th1.spi3_clk_threshold; - break; - case SYSCTL_THRESHOLD_TIMER0: - threshold = (int)sysctl->clk_th2.timer0_clk_threshold; - break; - case SYSCTL_THRESHOLD_TIMER1: - threshold = (int)sysctl->clk_th2.timer1_clk_threshold; - break; - case SYSCTL_THRESHOLD_TIMER2: - threshold = (int)sysctl->clk_th2.timer2_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2S0: - threshold = (int)sysctl->clk_th3.i2s0_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2S1: - threshold = (int)sysctl->clk_th3.i2s1_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2S2: - threshold = (int)sysctl->clk_th4.i2s2_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2S0_M: - threshold = (int)sysctl->clk_th4.i2s0_mclk_threshold; - break; - case SYSCTL_THRESHOLD_I2S1_M: - threshold = (int)sysctl->clk_th4.i2s1_mclk_threshold; - break; - case SYSCTL_THRESHOLD_I2S2_M: - threshold = (int)sysctl->clk_th5.i2s2_mclk_threshold; - break; - case SYSCTL_THRESHOLD_I2C0: - threshold = (int)sysctl->clk_th5.i2c0_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2C1: - threshold = (int)sysctl->clk_th5.i2c1_clk_threshold; - break; - case SYSCTL_THRESHOLD_I2C2: - threshold = (int)sysctl->clk_th5.i2c2_clk_threshold; - break; - case SYSCTL_THRESHOLD_WDT0: - threshold = (int)sysctl->clk_th6.wdt0_clk_threshold; - break; - case SYSCTL_THRESHOLD_WDT1: - threshold = (int)sysctl->clk_th6.wdt1_clk_threshold; - break; - - default: - break; - } - - return threshold; -} - -int sysctl_clock_set_clock_select(sysctl_clock_select_t which, int select) -{ - int result = 0; - - switch (which) { - /* - * These clock select is 1 bit width - */ - case SYSCTL_CLOCK_SELECT_PLL0_BYPASS: - sysctl->pll0.pll_bypass0 = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_PLL1_BYPASS: - sysctl->pll1.pll_bypass1 = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_PLL2_BYPASS: - sysctl->pll2.pll_bypass2 = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_ACLK: - sysctl->clk_sel0.aclk_sel = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_SPI3: - sysctl->clk_sel0.spi3_clk_sel = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_TIMER0: - sysctl->clk_sel0.timer0_clk_sel = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_TIMER1: - sysctl->clk_sel0.timer1_clk_sel = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_TIMER2: - sysctl->clk_sel0.timer2_clk_sel = select & 0x01; - break; - case SYSCTL_CLOCK_SELECT_SPI3_SAMPLE: - sysctl->clk_sel1.spi3_sample_clk_sel = select & 0x01; - break; - - /* - * These clock select is 2 bit width - */ - case SYSCTL_CLOCK_SELECT_PLL2: - sysctl->pll2.pll_ckin_sel2 = select & 0x03; - break; - - default: - result = -1; - break; - } - - return result; -} - -int sysctl_clock_get_clock_select(sysctl_clock_select_t which) -{ - int clock_select = 0; - - switch (which) { - /* - * Select and get clock select value - */ - case SYSCTL_CLOCK_SELECT_PLL0_BYPASS: - clock_select = (int)sysctl->pll0.pll_bypass0; - break; - case SYSCTL_CLOCK_SELECT_PLL1_BYPASS: - clock_select = (int)sysctl->pll1.pll_bypass1; - break; - case SYSCTL_CLOCK_SELECT_PLL2_BYPASS: - clock_select = (int)sysctl->pll2.pll_bypass2; - break; - case SYSCTL_CLOCK_SELECT_PLL2: - clock_select = (int)sysctl->pll2.pll_ckin_sel2; - break; - case SYSCTL_CLOCK_SELECT_ACLK: - clock_select = (int)sysctl->clk_sel0.aclk_sel; - break; - case SYSCTL_CLOCK_SELECT_SPI3: - clock_select = (int)sysctl->clk_sel0.spi3_clk_sel; - break; - case SYSCTL_CLOCK_SELECT_TIMER0: - clock_select = (int)sysctl->clk_sel0.timer0_clk_sel; - break; - case SYSCTL_CLOCK_SELECT_TIMER1: - clock_select = (int)sysctl->clk_sel0.timer1_clk_sel; - break; - case SYSCTL_CLOCK_SELECT_TIMER2: - clock_select = (int)sysctl->clk_sel0.timer2_clk_sel; - break; - case SYSCTL_CLOCK_SELECT_SPI3_SAMPLE: - clock_select = (int)sysctl->clk_sel1.spi3_sample_clk_sel; - break; - - default: - break; - } - - return clock_select; -} - -u32 sysctl_clock_source_get_freq(sysctl_clock_source_t input) -{ - u32 result; - - switch (input) { - case SYSCTL_SOURCE_IN0: - result = SYSCTRL_CLOCK_FREQ_IN0; - break; - case SYSCTL_SOURCE_PLL0: - result = sysctl_pll_get_freq(SYSCTL_PLL0); - break; - case SYSCTL_SOURCE_PLL1: - result = sysctl_pll_get_freq(SYSCTL_PLL1); - break; - case SYSCTL_SOURCE_PLL2: - result = sysctl_pll_get_freq(SYSCTL_PLL2); - break; - case SYSCTL_SOURCE_ACLK: - result = sysctl_clock_get_freq(SYSCTL_CLOCK_ACLK); - break; - default: - result = 0; - break; - } - - return result; -} - -static int sysctl_pll_is_lock(sysctl_pll_t pll) -{ - /* - * All bit enable means PLL lock - * - * struct pll_lock_t - * { - * u8 overflow : 1; - * u8 rfslip : 1; - * u8 fbslip : 1; - * }; - * - */ - - if (pll >= SYSCTL_PLL_MAX) - return 0; - - switch (pll) { - case SYSCTL_PLL0: - return sysctl->pll_lock.pll_lock0 == 3; - - case SYSCTL_PLL1: - return sysctl->pll_lock.pll_lock1 & 1; - - case SYSCTL_PLL2: - return sysctl->pll_lock.pll_lock2 & 1; - - default: - break; - } - - return 0; -} - -static int sysctl_pll_clear_slip(sysctl_pll_t pll) -{ - if (pll >= SYSCTL_PLL_MAX) - return -1; - - switch (pll) { - case SYSCTL_PLL0: - sysctl->pll_lock.pll_slip_clear0 = 1; - break; - - case SYSCTL_PLL1: - sysctl->pll_lock.pll_slip_clear1 = 1; - break; - - case SYSCTL_PLL2: - sysctl->pll_lock.pll_slip_clear2 = 1; - break; - - default: - break; - } - - return sysctl_pll_is_lock(pll) ? 0 : -1; -} - -int sysctl_pll_enable(sysctl_pll_t pll) -{ - /* - * ---+ - * PWRDN | - * +------------------------------------------------------------- - * ^ - * | - * | - * t1 - * +------------------+ - * RESET | | - * ----------+ +----------------------------------- - * ^ ^ ^ - * |<----- t_rst ---->|<---------- t_lock ---------->| - * | | | - * t2 t3 t4 - */ - - if (pll >= SYSCTL_PLL_MAX) - return -1; - - switch (pll) { - case SYSCTL_PLL0: - /* Do not bypass PLL */ - sysctl->pll0.pll_bypass0 = 0; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll0.pll_pwrd0 = 1; - /* - * Reset trigger of the PLL, connected RESET - * 0 is free - * 1 is reset - */ - sysctl->pll0.pll_reset0 = 0; - sysctl->pll0.pll_reset0 = 1; - asm volatile ("nop"); - asm volatile ("nop"); - sysctl->pll0.pll_reset0 = 0; - break; - - case SYSCTL_PLL1: - /* Do not bypass PLL */ - sysctl->pll1.pll_bypass1 = 0; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll1.pll_pwrd1 = 1; - /* - * Reset trigger of the PLL, connected RESET - * 0 is free - * 1 is reset - */ - sysctl->pll1.pll_reset1 = 0; - sysctl->pll1.pll_reset1 = 1; - asm volatile ("nop"); - asm volatile ("nop"); - sysctl->pll1.pll_reset1 = 0; - break; - - case SYSCTL_PLL2: - /* Do not bypass PLL */ - sysctl->pll2.pll_bypass2 = 0; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll2.pll_pwrd2 = 1; - /* - * Reset trigger of the PLL, connected RESET - * 0 is free - * 1 is reset - */ - sysctl->pll2.pll_reset2 = 0; - sysctl->pll2.pll_reset2 = 1; - asm volatile ("nop"); - asm volatile ("nop"); - sysctl->pll2.pll_reset2 = 0; - break; - - default: - break; - } - - return 0; -} - -int sysctl_pll_disable(sysctl_pll_t pll) -{ - if (pll >= SYSCTL_PLL_MAX) - return -1; - - switch (pll) { - case SYSCTL_PLL0: - /* Bypass PLL */ - sysctl->pll0.pll_bypass0 = 1; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll0.pll_pwrd0 = 0; - break; - - case SYSCTL_PLL1: - /* Bypass PLL */ - sysctl->pll1.pll_bypass1 = 1; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll1.pll_pwrd1 = 0; - break; - - case SYSCTL_PLL2: - /* Bypass PLL */ - sysctl->pll2.pll_bypass2 = 1; - /* - * Power on the PLL, negtive from PWRDN - * 0 is power off - * 1 is power on - */ - sysctl->pll2.pll_pwrd2 = 0; - break; - - default: - break; - } - - return 0; -} +#define SYSCTRL_CLOCK_FREQ_IN0 (26000000UL) -u32 sysctl_pll_get_freq(sysctl_pll_t pll) +static u32 sysctl_pll0_get_freq(void) { - u32 freq_in = 0; - u32 nr = 0, nf = 0, od = 0; - u8 select = 0; - - if (pll >= SYSCTL_PLL_MAX) - return 0; + u32 freq_in, nr, nf, od; - switch (pll) { - case SYSCTL_PLL0: - freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - nr = sysctl->pll0.clkr0 + 1; - nf = sysctl->pll0.clkf0 + 1; - od = sysctl->pll0.clkod0 + 1; - break; - - case SYSCTL_PLL1: - freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - nr = sysctl->pll1.clkr1 + 1; - nf = sysctl->pll1.clkf1 + 1; - od = sysctl->pll1.clkod1 + 1; - break; - - case SYSCTL_PLL2: - /* - * Get input freq accroding select register - */ - select = sysctl->pll2.pll_ckin_sel2; - if (select < sizeof(get_source_pll2)) - freq_in = sysctl_clock_source_get_freq(get_source_pll2[select]); - else - return 0; - - nr = sysctl->pll2.clkr2 + 1; - nf = sysctl->pll2.clkf2 + 1; - od = sysctl->pll2.clkod2 + 1; - break; - - default: - break; - } + freq_in = SYSCTRL_CLOCK_FREQ_IN0; + nr = sysctl->pll0.clkr0 + 1; + nf = sysctl->pll0.clkf0 + 1; + od = sysctl->pll0.clkod0 + 1; /* * Get final PLL output freq @@ -977,812 +36,19 @@ u32 sysctl_pll_get_freq(sysctl_pll_t pll) return ((u64)freq_in * (u64)nf) / ((u64)nr * (u64)od); } -#if 0 -static u32 sysctl_pll_source_set_freq(sysctl_pll_t pll, - sysctl_clock_source_t source, u32 freq) -{ - - const double vco_min = 3.5e+08; - const double vco_max = 1.75e+09; - const double ref_min = 1.36719e+07; - const double ref_max = 1.75e+09; - const int nr_min = 1; - const int nr_max = 16; - const int nf_min = 1; - const int nf_max = 64; - const int no_min = 1; - const int no_max = 16; - const int nb_min = 1; - const int nb_max = 64; - const int max_vco = 1; - const int ref_rng = 1; - int nr = 0; - int nrx = 0; - int nf = 0; - int nfi = 0; - int no = 0; - int noe = 0; - int not = 0; - int nor = 0; - int nore = 0; - int nb = 0; - int first = 0; - int firstx = 0; - int found = 0; - long long nfx = 0; - double fin = 0, fout = 0, fvco = 0; - double val = 0, nval = 0, err = 0, merr = 0, terr = 0; - int x_nrx = 0, x_no = 0, x_nb = 0; - long long x_nfx = 0; - double x_fvco = 0, x_err = 0; - sysctl_pll0_t pll0; - sysctl_pll1_t pll1; - sysctl_pll2_t pll2; - u32 freq_in = 0; - - if (pll >= SYSCTL_PLL_MAX) - return 0; - - if (source >= SYSCTL_SOURCE_MAX) - return 0; - - switch (pll) { - case SYSCTL_PLL0: - case SYSCTL_PLL1: - /* - * Check input clock source - */ - if (source != SYSCTL_SOURCE_IN0) - return 0; - freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - /* - * Check input clock freq - */ - if (freq_in == 0) - return 0; - break; - - case SYSCTL_PLL2: - /* - * Check input clock source - */ - if (source < sizeof(get_select_pll2)) - freq_in = sysctl_clock_source_get_freq(source); - /* - * Check input clock freq - */ - if (freq_in == 0) - return 0; - break; - - default: - return 0; - } - - /* - * Begin calculate PLL registers' value - */ - fin = freq_in; - fout = freq; - val = fout / fin; - terr = 0.5 / ((double)(nf_max / 2)); - first = firstx = 1; - if (terr != -2) { - first = 0; - if (terr == 0) - terr = 1e-16; - merr = fabs(terr); - } - found = 0; - for (nfi = val; nfi < nf_max; ++nfi) { - nr = rint(((double)nfi) / val); - if (nr == 0) - continue; - if ((ref_rng) && (nr < nr_min)) - continue; - if (fin / ((double)nr) > ref_max) - continue; - nrx = nr; - nf = nfx = nfi; - nval = ((double)nfx) / ((double)nr); - if (nf == 0) - nf = 1; - err = 1 - nval / val; - - if ((first) || (fabs(err) < merr * (1 + 1e-6)) || (fabs(err) < 1e-16)) { - not = floor(vco_max / fout); - for (no = (not > no_max) ? no_max : not; no > no_min; --no) { - if ((ref_rng) && ((nr / no) < nr_min)) - continue; - if ((nr % no) == 0) - break; - } - if ((nr % no) != 0) - continue; - nor = ((not > no_max) ? no_max : not) / no; - nore = nf_max / nf; - if (nor > nore) - nor = nore; - noe = ceil(vco_min / fout); - if (!max_vco) { - nore = (noe - 1) / no + 1; - nor = nore; - not = 0; /* force next if to fail */ - } - if ((((no * nor) < (not >> 1)) || ((no * nor) < noe)) && ((no * nor) < (nf_max / nf))) { - no = nf_max / nf; - if (no > no_max) - no = no_max; - if (no > not) - no = not; - nfx *= no; - nf *= no; - if ((no > 1) && (!firstx)) - continue; - /* wait for larger nf in later iterations */ - } else { - nrx /= no; - nfx *= nor; - nf *= nor; - no *= nor; - if (no > no_max) - continue; - if ((nor > 1) && (!firstx)) - continue; - /* wait for larger nf in later iterations */ - } - - nb = nfx; - if (nb < nb_min) - nb = nb_min; - if (nb > nb_max) - continue; - - fvco = fin / ((double)nrx) * ((double)nfx); - if (fvco < vco_min) - continue; - if (fvco > vco_max) - continue; - if (nf < nf_min) - continue; - if ((ref_rng) && (fin / ((double)nrx) < ref_min)) - continue; - if ((ref_rng) && (nrx > nr_max)) - continue; - if (!(((firstx) && (terr < 0)) || (fabs(err) < merr * (1 - 1e-6)) || ((max_vco) && (no > x_no)))) - continue; - if ((!firstx) && (terr >= 0) && (nrx > x_nrx)) - continue; - - found = 1; - x_no = no; - x_nrx = nrx; - x_nfx = nfx; - x_nb = nb; - x_fvco = fvco; - x_err = err; - first = firstx = 0; - merr = fabs(err); - if (terr != -1) - continue; - } - } - - if (!found) - return 0; - - nrx = x_nrx; - nfx = x_nfx; - no = x_no; - nb = x_nb; - fvco = x_fvco; - err = x_err; - if ((terr != -2) && (fabs(err) >= terr * (1 - 1e-6))) - return 0; - - /* - * Begin write PLL registers' value, - * Using atomic write method. - */ - switch (pll) { - case SYSCTL_PLL0: - /* Read register from bus */ - pll0 = sysctl->pll0; - /* Set register temporary value */ - pll0.clkr0 = nrx - 1; - pll0.clkf0 = nfx - 1; - pll0.clkod0 = no - 1; - pll0.bwadj0 = nb - 1; - /* Write register back to bus */ - sysctl->pll0 = pll0; - break; - - case SYSCTL_PLL1: - /* Read register from bus */ - pll1 = sysctl->pll1; - /* Set register temporary value */ - pll1.clkr1 = nrx - 1; - pll1.clkf1 = nfx - 1; - pll1.clkod1 = no - 1; - pll1.bwadj1 = nb - 1; - /* Write register back to bus */ - sysctl->pll1 = pll1; - break; - - case SYSCTL_PLL2: - /* Read register from bus */ - pll2 = sysctl->pll2; - /* Set register temporary value */ - if (source < sizeof(get_select_pll2)) - pll2.pll_ckin_sel2 = get_select_pll2[source]; - - pll2.clkr2 = nrx - 1; - pll2.clkf2 = nfx - 1; - pll2.clkod2 = no - 1; - pll2.bwadj2 = nb - 1; - /* Write register back to bus */ - sysctl->pll2 = pll2; - break; - - default: - return 0; - } - - return sysctl_pll_get_freq(pll); -} -#endif - -u32 sysctl_clock_get_freq(sysctl_clock_t clock) -{ - u32 source = 0; - u32 result = 0; - - switch (clock) { - /* - * The clock IN0 - */ - case SYSCTL_CLOCK_IN0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - result = source; - break; - - /* - * These clock directly under PLL clock domain - * They are using gated divider. - */ - case SYSCTL_CLOCK_PLL0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source; - break; - case SYSCTL_CLOCK_PLL1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL1); - result = source; - break; - case SYSCTL_CLOCK_PLL2: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2); - result = source; - break; - - /* - * These clock directly under ACLK clock domain - */ - case SYSCTL_CLOCK_CPU: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) / - (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK)); - break; - default: - break; - } - result = source; - break; - case SYSCTL_CLOCK_DMA: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) / - (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK)); - break; - default: - break; - } - result = source; - break; - case SYSCTL_CLOCK_FFT: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) / - (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK)); - break; - default: - break; - } - result = source; - break; - case SYSCTL_CLOCK_ACLK: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) / - (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK)); - break; - default: - break; - } - result = source; - break; - case SYSCTL_CLOCK_HCLK: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) / - (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK)); - break; - default: - break; - } - result = source; - break; - - /* - * These clock under ACLK clock domain. - * They are using gated divider. - */ - case SYSCTL_CLOCK_SRAM0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SRAM0) + 1); - break; - case SYSCTL_CLOCK_SRAM1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SRAM1) + 1); - break; - case SYSCTL_CLOCK_ROM: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ROM) + 1); - break; - case SYSCTL_CLOCK_DVP: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_DVP) + 1); - break; - - /* - * These clock under ACLK clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_APB0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB0) + 1); - break; - case SYSCTL_CLOCK_APB1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB1) + 1); - break; - case SYSCTL_CLOCK_APB2: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB2) + 1); - break; - - /* - * These clock under AI clock domain. - * They are using gated divider. - */ - case SYSCTL_CLOCK_AI: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL1); - result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_AI) + 1); - break; - - /* - * These clock under I2S clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_I2S0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S0) + 1) * 2); - break; - case SYSCTL_CLOCK_I2S1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S1) + 1) * 2); - break; - case SYSCTL_CLOCK_I2S2: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S2) + 1) * 2); - break; - - /* - * These clock under WDT clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_WDT0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_WDT0) + 1) * 2); - break; - case SYSCTL_CLOCK_WDT1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_WDT1) + 1) * 2); - break; - - /* - * These clock under PLL0 clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_SPI0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI0) + 1) * 2); - break; - case SYSCTL_CLOCK_SPI1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI1) + 1) * 2); - break; - case SYSCTL_CLOCK_SPI2: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI2) + 1) * 2); - break; - case SYSCTL_CLOCK_I2C0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C0) + 1) * 2); - break; - case SYSCTL_CLOCK_I2C1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C1) + 1) * 2); - break; - case SYSCTL_CLOCK_I2C2: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C2) + 1) * 2); - break; - - /* - * These clock under PLL0_SEL clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_SPI3: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_SPI3)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - break; - default: - break; - } - - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI3) + 1) * 2); - break; - case SYSCTL_CLOCK_TIMER0: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER0)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - break; - default: - break; - } - - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER0) + 1) * 2); - break; - case SYSCTL_CLOCK_TIMER1: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER1)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - break; - default: - break; - } - - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER1) + 1) * 2); - break; - case SYSCTL_CLOCK_TIMER2: - switch (sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER2)) { - case 0: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - break; - case 1: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0); - break; - default: - break; - } - - result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER2) + 1) * 2); - break; - - /* - * These clock under MISC clock domain. - * They are using even divider. - */ - - /* - * These clock under APB0 clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_GPIO: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - case SYSCTL_CLOCK_UART1: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - case SYSCTL_CLOCK_UART2: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - case SYSCTL_CLOCK_UART3: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - case SYSCTL_CLOCK_FPIOA: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - case SYSCTL_CLOCK_SHA: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0); - result = source; - break; - - /* - * These clock under APB1 clock domain. - * They are using even divider. - */ - case SYSCTL_CLOCK_AES: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1); - result = source; - break; - case SYSCTL_CLOCK_OTP: - source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1); - result = source; - break; - case SYSCTL_CLOCK_RTC: - source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0); - result = source; - break; - - /* - * These clock under APB2 clock domain. - * They are using even divider. - */ - default: - break; - } - - return result; -} - -int sysctl_dma_select(sysctl_dma_channel_t channel, sysctl_dma_select_t select) -{ - sysctl_dma_sel0_t dma_sel0; - sysctl_dma_sel1_t dma_sel1; - - /* Read register from bus */ - dma_sel0 = sysctl->dma_sel0; - dma_sel1 = sysctl->dma_sel1; - switch (channel) { - case SYSCTL_DMA_CHANNEL_0: - dma_sel0.dma_sel0 = select; - break; - - case SYSCTL_DMA_CHANNEL_1: - dma_sel0.dma_sel1 = select; - break; - - case SYSCTL_DMA_CHANNEL_2: - dma_sel0.dma_sel2 = select; - break; - - case SYSCTL_DMA_CHANNEL_3: - dma_sel0.dma_sel3 = select; - break; - - case SYSCTL_DMA_CHANNEL_4: - dma_sel0.dma_sel4 = select; - break; - - case SYSCTL_DMA_CHANNEL_5: - dma_sel1.dma_sel5 = select; - break; - - default: - return -1; - } - - /* Write register back to bus */ - sysctl->dma_sel0 = dma_sel0; - sysctl->dma_sel1 = dma_sel1; - - return 0; -} - -u32 sysctl_pll_fast_enable_pll(void) -{ - sysctl_pll0_t pll0; - sysctl_pll1_t pll1; - sysctl_pll2_t pll2; - - /* Read register from bus */ - pll0 = sysctl->pll0; - pll1 = sysctl->pll1; - pll2 = sysctl->pll2; - - /* - * Begin write PLL registers' value, - * Using atomic write method. - */ - /* PLL VCO MAX freq: 1.8GHz */ - - /* PLL0: 26M reference clk get 793M output clock */ - pll0.clkr0 = 0; - pll0.clkf0 = 60; - pll0.clkod0 = 1; - pll0.bwadj0 = 60; - - /* PLL1: 26M reference clk get 390M output clock */ - pll1.clkr1 = 0; - pll1.clkf1 = 59; - pll1.clkod1 = 3; - pll1.bwadj1 = 59; - - /* PLL2: 26M reference clk get 390M output clock */ - pll2.clkr2 = 0; - pll2.clkf2 = 59; - pll2.clkod2 = 3; - pll2.bwadj2 = 59; - - /* Write register to bus */ - sysctl->pll0 = pll0; - sysctl->pll1 = pll1; - sysctl->pll2 = pll2; - - sysctl_pll_enable(SYSCTL_PLL0); - sysctl_pll_enable(SYSCTL_PLL1); - sysctl_pll_enable(SYSCTL_PLL2); - - while (sysctl_pll_is_lock(SYSCTL_PLL0) == 0) - sysctl_pll_clear_slip(SYSCTL_PLL0); - while (sysctl_pll_is_lock(SYSCTL_PLL1) == 0) - sysctl_pll_clear_slip(SYSCTL_PLL1); - while (sysctl_pll_is_lock(SYSCTL_PLL2) == 0) - sysctl_pll_clear_slip(SYSCTL_PLL2); - - sysctl_clock_enable(SYSCTL_CLOCK_PLL0); - sysctl_clock_enable(SYSCTL_CLOCK_PLL1); - sysctl_clock_enable(SYSCTL_CLOCK_PLL2); - - /* Set ACLK to PLL0 */ - sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_PLL0); - - return 0; -} - -u32 sysctl_set_spi0_dvp_data(u8 en) +u32 sysctl_get_cpu_freq(void) { - sysctl->misc.spi_dvp_data_enable = en; - return 0; -} + int clock_source; -void sysctl_set_power_mode(sysctl_power_bank_t power_bank, sysctl_io_power_mode_t io_power_mode) -{ - if(io_power_mode) - *((u32 *)(&sysctl->power_sel)) |= (1 << power_bank); - else - *((u32 *)(&sysctl->power_sel)) &= ~(1 << power_bank); -} - -#if 0 -u32 sysctl_pll_set_freq(sysctl_pll_t pll, u32 pll_freq) -{ - u32 result; - - if(pll_freq == 0) - return 0; - - volatile sysctl_general_pll_t *v_pll_t; - switch(pll) { - case SYSCTL_PLL0: - v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll0); - break; - case SYSCTL_PLL1: - v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll1); - break; - case SYSCTL_PLL2: - v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll2); - break; + clock_source = (int)sysctl->clk_sel0.aclk_sel; + switch (clock_source) { + case 0: + return SYSCTRL_CLOCK_FREQ_IN0; + case 1: + return sysctl_pll0_get_freq() / + (2ULL << (int)sysctl->clk_sel0.aclk_divider_sel); default: return 0; - break; } - - /* 1. Change CPU CLK to XTAL */ - if (pll == SYSCTL_PLL0) - sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_IN0); - - /* 2. Disable PLL output */ - v_pll_t->pll_out_en = 0; - - /* 3. Turn off PLL */ - v_pll_t->pll_pwrd = 0; - - /* 4. Set PLL new value */ - if (pll == SYSCTL_PLL2) - result = sysctl_pll_source_set_freq(pll, v_pll_t->pll_ckin_sel, pll_freq); - else - result = sysctl_pll_source_set_freq(pll, SYSCTL_SOURCE_IN0, pll_freq); - - /* 5. Power on PLL */ - v_pll_t->pll_pwrd = 1; - /* wait >100ns */ - sysctl_usleep(1); - - /* 6. Reset PLL then Release Reset*/ - v_pll_t->pll_reset = 0; - v_pll_t->pll_reset = 1; - /* wait >100ns */ - sysctl_usleep(1); - v_pll_t->pll_reset = 0; - - /* 7. Get lock status, wait PLL stable */ - while (sysctl_pll_is_lock(pll) == 0) - sysctl_pll_clear_slip(pll); - - /* 8. Enable PLL output */ - v_pll_t->pll_out_en = 1; - - /* 9. Change CPU CLK to PLL */ - if (pll == SYSCTL_PLL0) - sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_PLL0); - - return result; -} - -u32 sysctl_cpu_set_freq(u32 freq) -{ - if (freq == 0) - return 0; - - return sysctl_pll_set_freq(SYSCTL_PLL0, (sysctl->clk_sel0.aclk_divider_sel + 1) * 2 * freq); -} -#endif - -void sysctl_enable_irq(void) -{ - csr_read_set(mie, MIP_MEIP); - csr_read_set(mstatus, MSTATUS_MIE); } -void sysctl_disable_irq(void) -{ - csr_read_clear(mie, MIP_MEIP); - csr_read_clear(mstatus, MSTATUS_MIE); -} - -u64 sysctl_get_time_us(void) -{ - u64 v_cycle = read_cycle(); - - return v_cycle * 1000000 / sysctl_clock_get_freq(SYSCTL_CLOCK_CPU); -} - -void sysctl_usleep(u64 usec) -{ - u64 nop_all = usec * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 1000000UL; - u64 cycle = read_cycle(); - - while (read_cycle() - cycle < nop_all); -} diff --git a/platform/kendryte/k210/sysctl.h b/platform/kendryte/k210/sysctl.h index 09d81ae..aa95d62 100644 --- a/platform/kendryte/k210/sysctl.h +++ b/platform/kendryte/k210/sysctl.h @@ -782,164 +782,9 @@ typedef struct _sysctl_general_pll { } __attribute__((packed, aligned(4))) sysctl_general_pll_t; /** - * System controller object instanse + * Get frequency of CPU + * @return The frequency of the CPU */ -extern volatile sysctl_t *const sysctl; - -/** - * Enable clock for peripheral - * @param[in] clock The clock to be enable - * @return result - * - 0 Success - * - Other Fail - */ -int sysctl_clock_enable(sysctl_clock_t clock); - -/** - * Enable clock for peripheral - * @param[in] clock The clock to be disable - * @return result - * - 0 Success - * - Other Fail - */ -int sysctl_clock_disable(sysctl_clock_t clock); - -/** - * Sysctl clock set threshold - * @param[in] which Which threshold to set - * @param[in] threshold The threshold value - * @return result - * - 0 Success - * - Other Fail - */ -int sysctl_clock_set_threshold(sysctl_threshold_t which, int threshold); - -/** - * Sysctl clock get threshold - * @param[in] which Which threshold to get - * @return The threshold value - * - Other Value of threshold - * - -1 Fail - */ -int sysctl_clock_get_threshold(sysctl_threshold_t which); - -/** - * Sysctl clock set clock select - * @param[in] which Which clock select to set - * @param[in] select The clock select value - * @return result - * - 0 Success - * - Other Fail - */ -int sysctl_clock_set_clock_select(sysctl_clock_select_t which, int select); - -/** - * Sysctl clock get clock select - * @param[in] which Which clock select to get - * @return The clock select value - * - Other Value of clock select - * - -1 Fail - */ -int sysctl_clock_get_clock_select(sysctl_clock_select_t which); - -/** - * Get PLL frequency - * @param[in] pll The PLL id - * @return The frequency of PLL - */ -u32 sysctl_pll_get_freq(sysctl_pll_t pll); - -/** - * Get base clock frequency by clock id - * @param[in] clock The clock id - * @return The clock frequency - */ -u32 sysctl_clock_get_freq(sysctl_clock_t clock); - -/** - * Reset device by reset controller - * @param[in] reset The reset signal - */ -void sysctl_reset(sysctl_reset_t reset); - -/** - * Enable the PLL and power on with reset - * @param[in] pll The pll id - * @return Result - * - 0 Success - * - Other Fail - */ -int sysctl_pll_enable(sysctl_pll_t pll); - -/** - * Disable the PLL and power off - * @param[in] pll The pll id - * @return Result - * - 0 Success - * - Other Fail - */ -int sysctl_pll_disable(sysctl_pll_t pll); - -/** - * Select DMA channel handshake peripheral signal - * @param[in] channel The DMA channel - * @param[in] select The peripheral select - * @return Result - * - 0 Success - * - Other Fail - */ -int sysctl_dma_select(sysctl_dma_channel_t channel, sysctl_dma_select_t select); - -/** - * Set SPI0_D0-D7 DVP_D0-D7 as spi and dvp data pin - * @param[in] en Enable or not - * @return Result - * - 0 Success - * - Other Fail - */ -u32 sysctl_set_spi0_dvp_data(u8 en); - -/** - * Set io power mode - * @param[in] power_bank IO power bank - * @param[in] io_power_mode Set power mode 3.3v or 1.8 - * @return Result - * - 0 Success - * - Other Fail - */ -void sysctl_set_power_mode(sysctl_power_bank_t power_bank, sysctl_io_power_mode_t io_power_mode); - -/** - * Set frequency of CPU - * @param[in] freq The desired frequency in Hz - * @return The actual frequency of CPU after set - */ -u32 sysctl_cpu_set_freq(u32 freq); - -/** - * Init PLL freqency - * @param[in] pll The PLL id - * @param[in] pll_freq The desired frequency in Hz - - */ -u32 sysctl_pll_set_freq(sysctl_pll_t pll, u32 pll_freq); - -/** - * Enable interrupt - */ -void sysctl_enable_irq(void); - -/** - * Disable interrupt - */ -void sysctl_disable_irq(void); - -/** - * Get the time start up to now - * @return The time of microsecond - */ -u64 sysctl_get_time_us(void); - -void sysctl_usleep(u64 usec); +u32 sysctl_get_cpu_freq(void); #endif /* _K210_SYSCTL_H_ */ diff --git a/platform/kendryte/k210/uarths.c b/platform/kendryte/k210/uarths.c index 6551de7..2a189aa 100644 --- a/platform/kendryte/k210/uarths.c +++ b/platform/kendryte/k210/uarths.c @@ -21,7 +21,7 @@ static volatile struct uarths *const uarths = void uarths_init(u32 baud_rate, enum uarths_stopbit stopbit) { - u32 freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU); + u32 freq = sysctl_get_cpu_freq(); u16 div = freq / baud_rate - 1; /* Set UART registers */ |