soc: it8xxx2: introduce SOC_IT8XXX2_PLL_FLASH_48M option
Enable SOC_IT8XXX2_PLL_FLASH_48M at default to reduce latency of fetching code from flash. Signed-off-by: Dino Li <Dino.Li@ite.com.tw>
This commit is contained in:
parent
445a23a167
commit
7d5411d6e0
6 changed files with 211 additions and 0 deletions
|
@ -69,6 +69,37 @@ inline void set_csr(unsigned long bit)
|
|||
}
|
||||
}
|
||||
|
||||
#define IT8XXX2_IER_COUNT ARRAY_SIZE(reg_enable)
|
||||
static uint8_t ier_setting[IT8XXX2_IER_COUNT];
|
||||
|
||||
void ite_intc_save_and_disable_interrupts(void)
|
||||
{
|
||||
/* Disable global interrupt for critical section */
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
/* Save and disable interrupts */
|
||||
for (int i = 0; i < IT8XXX2_IER_COUNT; i++) {
|
||||
ier_setting[i] = *reg_enable[i];
|
||||
*reg_enable[i] = 0;
|
||||
}
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
void ite_intc_restore_interrupts(void)
|
||||
{
|
||||
/*
|
||||
* Ensure the highest priority interrupt will be the first fired
|
||||
* interrupt when soc is ready to go.
|
||||
*/
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
/* Restore interrupt state */
|
||||
for (int i = 0; i < IT8XXX2_IER_COUNT; i++) {
|
||||
*reg_enable[i] = ier_setting[i];
|
||||
}
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
void ite_intc_isr_clear(unsigned int irq)
|
||||
{
|
||||
uint32_t g, i;
|
||||
|
|
|
@ -204,6 +204,34 @@ static void timer_isr(const void *unused)
|
|||
sys_clock_announce(dticks);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
#define TIMER_CHANGE_PLL EXT_TIMER_8
|
||||
static void timer_5ms_one_shot_isr(const void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
/*
|
||||
* We are here because we have completed changing PLL sequence.
|
||||
* Disabled the timer.
|
||||
*/
|
||||
timer_init_ms(TIMER_CHANGE_PLL, ET_PSR_32K, 0, 0, 5);
|
||||
}
|
||||
|
||||
/*
|
||||
* This timer is used to wake up chip from sleep mode to complete
|
||||
* changing PLL sequence.
|
||||
*/
|
||||
void timer_5ms_one_shot(void)
|
||||
{
|
||||
/* Initialize interrupt handler of external timer8. */
|
||||
IRQ_CONNECT(DT_IRQ_BY_IDX(DT_NODELABEL(timer), 8, irq),
|
||||
0, timer_5ms_one_shot_isr, NULL,
|
||||
DT_IRQ_BY_IDX(DT_NODELABEL(timer), 8, flags));
|
||||
/* enable 5ms timer with 32.768khz clock source */
|
||||
timer_init_ms(TIMER_CHANGE_PLL, ET_PSR_32K, 1, 1, 5);
|
||||
}
|
||||
#endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */
|
||||
|
||||
int sys_clock_driver_init(const struct device *dev)
|
||||
{
|
||||
timer_init_combine(CTIMER_HW_TIMER_INDEX, TRUE);
|
||||
|
|
|
@ -1774,6 +1774,15 @@ struct adc_it8xxx2_regs {
|
|||
#define CGC_OFFSET_SMBB ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x08)
|
||||
#define CGC_OFFSET_SMBA ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x04)
|
||||
|
||||
/* TODO: rename IT83XX_ECPM_BASE to IT8XXX2_ECPM_BASE */
|
||||
#define IT8XXX2_ECPM_PLLCTRL ECREG(IT83XX_ECPM_BASE + 0x03)
|
||||
#ifndef __ASSEMBLER__
|
||||
enum chip_pll_mode {
|
||||
CHIP_PLL_DOZE = 0,
|
||||
CHIP_PLL_SLEEP = 1,
|
||||
CHIP_PLL_DEEP_DOZE = 3,
|
||||
};
|
||||
#endif
|
||||
#define IT8XXX2_ECPM_AUTOCG ECREG(IT83XX_ECPM_BASE + 0x04)
|
||||
#define IT8XXX2_ECPM_CGCTRL3R ECREG(IT83XX_ECPM_BASE + 0x05)
|
||||
#define IT8XXX2_ECPM_PLLFREQR ECREG(IT83XX_ECPM_BASE + 0x06)
|
||||
|
|
|
@ -71,6 +71,14 @@ int riscv_plic_get_irq(void);
|
|||
#endif
|
||||
|
||||
#if CONFIG_ITE_IT8XXX2_INTC
|
||||
/*
|
||||
* Save current interrupt state of soc-level into ier_setting[] with
|
||||
* disabling interrupt.
|
||||
*/
|
||||
void ite_intc_save_and_disable_interrupts(void);
|
||||
/* Restore interrupt state of soc-level from ier_setting[], use with care. */
|
||||
void ite_intc_restore_interrupts(void);
|
||||
|
||||
extern void ite_intc_irq_enable(unsigned int irq);
|
||||
extern void ite_intc_irq_disable(unsigned int irq);
|
||||
extern uint8_t ite_intc_get_irq_num(void);
|
||||
|
@ -80,6 +88,10 @@ extern void ite_intc_irq_priority_set(unsigned int irq,
|
|||
extern void ite_intc_isr_clear(unsigned int irq);
|
||||
#endif /* CONFIG_ITE_IT8XXX2_INTC */
|
||||
|
||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
void timer_5ms_one_shot(void);
|
||||
#endif
|
||||
|
||||
#endif /* !_ASMLANGUAGE */
|
||||
|
||||
#endif /* __SOC_COMMON_H_ */
|
||||
|
|
|
@ -12,6 +12,15 @@ config SOC_IT8XXX2
|
|||
|
||||
endchoice
|
||||
|
||||
config SOC_IT8XXX2_PLL_FLASH_48M
|
||||
bool "Flash frequency is 48MHz"
|
||||
default y
|
||||
help
|
||||
Change frequency of PLL, CPU, and flash to 48MHz during initialization.
|
||||
|
||||
Set n to use the default settings.
|
||||
(PLL and CPU run at 48MHz, flash frequency is 16MHz)
|
||||
|
||||
choice
|
||||
prompt "Clock source for PLL reference clock"
|
||||
|
||||
|
|
|
@ -9,6 +9,128 @@
|
|||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <soc.h>
|
||||
#include <dt-bindings/interrupt-controller/ite-intc.h>
|
||||
|
||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
#define __intc_ram_code __attribute__((section(".__ram_code")))
|
||||
|
||||
struct pll_config_t {
|
||||
uint8_t pll_freq;
|
||||
uint8_t div_fnd;
|
||||
uint8_t div_uart;
|
||||
uint8_t div_smb;
|
||||
uint8_t div_sspi;
|
||||
uint8_t div_ec;
|
||||
uint8_t div_jtag;
|
||||
uint8_t div_pwm;
|
||||
uint8_t div_usbpd;
|
||||
};
|
||||
|
||||
static const struct pll_config_t pll_configuration[] = {
|
||||
/*
|
||||
* PLL frequency setting = 4 (48MHz)
|
||||
* FND div = 0 (PLL / 1 = 48 mhz)
|
||||
* UART div = 1 (PLL / 2 = 24 mhz)
|
||||
* SMB div = 1 (PLL / 2 = 24 mhz)
|
||||
* SSPI div = 1 (PLL / 2 = 24 mhz)
|
||||
* EC div = 6 (FND / 6 = 8 mhz)
|
||||
* JTAG div = 1 (PLL / 2 = 24 mhz)
|
||||
* PWM div = 0 (PLL / 1 = 48 mhz)
|
||||
* USBPD div = 5 (PLL / 6 = 8 mhz)
|
||||
*/
|
||||
{.pll_freq = 4,
|
||||
.div_fnd = 0,
|
||||
.div_uart = 1,
|
||||
.div_smb = 1,
|
||||
.div_sspi = 1,
|
||||
.div_ec = 6,
|
||||
.div_jtag = 1,
|
||||
.div_pwm = 0,
|
||||
.div_usbpd = 5}
|
||||
};
|
||||
|
||||
void __intc_ram_code chip_pll_ctrl(enum chip_pll_mode mode)
|
||||
{
|
||||
IT8XXX2_ECPM_PLLCTRL = mode;
|
||||
/* for deep doze / sleep mode */
|
||||
IT8XXX2_ECPM_PLLCTRL = mode;
|
||||
}
|
||||
|
||||
void __intc_ram_code chip_run_pll_sequence(const struct pll_config_t *pll)
|
||||
{
|
||||
/* Enable HW timer to wakeup chip from the sleep mode */
|
||||
timer_5ms_one_shot();
|
||||
/*
|
||||
* Configure PLL clock dividers.
|
||||
* Writing data to these registers doesn't change the
|
||||
* PLL frequency immediately until the status is changed
|
||||
* into wakeup from the sleep mode.
|
||||
* The following code is intended to make the system
|
||||
* enter sleep mode, and wait HW timer to wakeup chip to
|
||||
* complete PLL update.
|
||||
*/
|
||||
IT8XXX2_ECPM_PLLFREQR = pll->pll_freq;
|
||||
/* Pre-set FND clock frequency = PLL / 3 */
|
||||
IT8XXX2_ECPM_SCDCR0 = (2 << 4);
|
||||
/* JTAG and EC */
|
||||
IT8XXX2_ECPM_SCDCR3 = (pll->div_jtag << 4) | pll->div_ec;
|
||||
/* Chip sleep after wait for interrupt (wfi) instruction */
|
||||
chip_pll_ctrl(CHIP_PLL_SLEEP);
|
||||
/* Chip sleep and wait timer wake it up */
|
||||
__asm__ volatile ("wfi");
|
||||
/* New FND clock frequency */
|
||||
IT8XXX2_ECPM_SCDCR0 = pll->div_fnd << 4;
|
||||
/* Chip doze after wfi instruction */
|
||||
chip_pll_ctrl(CHIP_PLL_DOZE);
|
||||
/* UART */
|
||||
IT8XXX2_ECPM_SCDCR1 = pll->div_uart;
|
||||
/* SSPI and SMB */
|
||||
IT8XXX2_ECPM_SCDCR2 = (pll->div_sspi << 4) | pll->div_smb;
|
||||
/* USBPD and PWM */
|
||||
IT8XXX2_ECPM_SCDCR4 = (pll->div_usbpd << 4) | pll->div_pwm;
|
||||
}
|
||||
|
||||
static void chip_configure_pll(const struct pll_config_t *pll)
|
||||
{
|
||||
/* Re-configure PLL clock or not. */
|
||||
if (((IT8XXX2_ECPM_PLLFREQR & 0xf) != pll->pll_freq) ||
|
||||
((IT8XXX2_ECPM_SCDCR0 & 0xf0) != (pll->div_fnd << 4)) ||
|
||||
((IT8XXX2_ECPM_SCDCR3 & 0xf) != pll->div_ec)) {
|
||||
#ifdef CONFIG_ESPI
|
||||
/*
|
||||
* TODO: implement me
|
||||
* We have to disable eSPI pad before changing
|
||||
* PLL sequence or sequence will fail if CS# pin is low.
|
||||
*/
|
||||
#endif
|
||||
/* Run change PLL sequence */
|
||||
chip_run_pll_sequence(pll);
|
||||
#ifdef CONFIG_ESPI
|
||||
/*
|
||||
* TODO: implement me
|
||||
* Enable eSPI pad after changing PLL sequence
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int chip_change_pll(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) {
|
||||
ite_intc_save_and_disable_interrupts();
|
||||
}
|
||||
/* configure PLL/CPU/flash clock */
|
||||
chip_configure_pll(&pll_configuration[0]);
|
||||
if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) {
|
||||
ite_intc_restore_interrupts();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
SYS_INIT(chip_change_pll, POST_KERNEL, 0);
|
||||
#endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */
|
||||
|
||||
static int ite_it8xxx2_init(const struct device *arg)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue