soc: ite: it8xxx2: support 96MHz PLL frequency and lcvco calibration
To enhance USB clock's accuracy, this change supports 96MHz PLL frequency and LCVCO calibration. Signed-off-by: Ren Chen <Ren.Chen@ite.com.tw>
This commit is contained in:
parent
cfaaf0135a
commit
b90a507ba1
3 changed files with 111 additions and 16 deletions
|
@ -1279,6 +1279,12 @@ enum chip_pll_mode {
|
||||||
#define IT8XXX2_ECPM_SCDCR2 ECREG(IT8XXX2_ECPM_BASE + 0x0e)
|
#define IT8XXX2_ECPM_SCDCR2 ECREG(IT8XXX2_ECPM_BASE + 0x0e)
|
||||||
#define IT8XXX2_ECPM_SCDCR3 ECREG(IT8XXX2_ECPM_BASE + 0x0f)
|
#define IT8XXX2_ECPM_SCDCR3 ECREG(IT8XXX2_ECPM_BASE + 0x0f)
|
||||||
#define IT8XXX2_ECPM_SCDCR4 ECREG(IT8XXX2_ECPM_BASE + 0x10)
|
#define IT8XXX2_ECPM_SCDCR4 ECREG(IT8XXX2_ECPM_BASE + 0x10)
|
||||||
|
#define IT8XXX2_ECPM_PFACC0R ECREG(IT8XXX2_ECPM_BASE + 0x20)
|
||||||
|
#define IT8XXX2_ECPM_PFACC1R ECREG(IT8XXX2_ECPM_BASE + 0x21)
|
||||||
|
#define IT8XXX2_ECPM_PFACC2R ECREG(IT8XXX2_ECPM_BASE + 0x40)
|
||||||
|
#define IT8XXX2_ECPM_LCOTF2 ECREG(IT8XXX2_ECPM_BASE + 0x54)
|
||||||
|
#define IT8XXX2_ECPM_LCOCR ECREG(IT8XXX2_ECPM_BASE + 0x55)
|
||||||
|
#define IT8XXX2_ECPM_LCOCR1 ECREG(IT8XXX2_ECPM_BASE + 0x57)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The count number of the counter for 25 ms register.
|
* The count number of the counter for 25 ms register.
|
||||||
|
|
|
@ -154,6 +154,15 @@ config SOC_IT8XXX2_JTAG_DEBUG_INTERFACE
|
||||||
- GPIOA6 -> TRST
|
- GPIOA6 -> TRST
|
||||||
Supported I/O voltage is 3.3V.
|
Supported I/O voltage is 3.3V.
|
||||||
|
|
||||||
|
config SOC_IT8XXX2_LCVCO
|
||||||
|
bool "LCVCO calibration"
|
||||||
|
depends on SOC_IT8XXX2_INT_32K
|
||||||
|
help
|
||||||
|
The LCVCO is a highly precise clock controller used for
|
||||||
|
calibrating the frequency shift of the PLL. Enabling this
|
||||||
|
option allows for supported LCVCO calibration, improving
|
||||||
|
the accuracy of the USB clock.
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Clock source for PLL reference clock"
|
prompt "Clock source for PLL reference clock"
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,21 @@ COND_CODE_1(DT_NODE_EXISTS(DT_INST(1, ite_it8xxx2_usbpd)), (2), (1))
|
||||||
*/
|
*/
|
||||||
#define SOC_USBPD_ITE_ACTIVE_PORT_COUNT DT_NUM_INST_STATUS_OKAY(ite_it8xxx2_usbpd)
|
#define SOC_USBPD_ITE_ACTIVE_PORT_COUNT DT_NUM_INST_STATUS_OKAY(ite_it8xxx2_usbpd)
|
||||||
|
|
||||||
|
/* PLL Frequency Auto-Calibration Control 0 Register */
|
||||||
|
#define PLL_FREQ_AUTO_CAL_EN BIT(7)
|
||||||
|
#define LOCK_TUNING_FACTORS_OF_LCO BIT(3)
|
||||||
|
/* LC Oscillator Control Register */
|
||||||
|
#define LCO_Power_CTRL BIT(1)
|
||||||
|
/* LC Oscillator Control Register 1 */
|
||||||
|
#define LDO_Power_CTRL BIT(1)
|
||||||
|
/* LC Oscillator Tuning Factor 2 */
|
||||||
|
#define LCO_SC_FACTOR_MASK GENMASK(6, 4)
|
||||||
|
#define LCO_SC_FACTOR(n) FIELD_PREP(LCO_SC_FACTOR_MASK, n)
|
||||||
|
/* PLL Frequency Auto-Calibration Control 2 Register */
|
||||||
|
#define AUTO_CAL_ENABLE BIT(1)
|
||||||
|
#define PLL_FREQ_AUTO_CAL_START BIT(0)
|
||||||
|
#define AUTO_CAL_ENABLE_AND_START (AUTO_CAL_ENABLE | PLL_FREQ_AUTO_CAL_START)
|
||||||
|
|
||||||
uint32_t chip_get_pll_freq(void)
|
uint32_t chip_get_pll_freq(void)
|
||||||
{
|
{
|
||||||
uint32_t pllfreq;
|
uint32_t pllfreq;
|
||||||
|
@ -83,7 +98,9 @@ void __soc_ram_code chip_pll_ctrl(enum chip_pll_mode mode)
|
||||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||||
struct pll_config_t {
|
struct pll_config_t {
|
||||||
uint8_t pll_freq;
|
uint8_t pll_freq;
|
||||||
|
uint8_t div_mcu;
|
||||||
uint8_t div_fnd;
|
uint8_t div_fnd;
|
||||||
|
uint8_t div_usb;
|
||||||
uint8_t div_uart;
|
uint8_t div_uart;
|
||||||
uint8_t div_smb;
|
uint8_t div_smb;
|
||||||
uint8_t div_sspi;
|
uint8_t div_sspi;
|
||||||
|
@ -93,10 +110,18 @@ struct pll_config_t {
|
||||||
uint8_t div_usbpd;
|
uint8_t div_usbpd;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pll_config_t pll_configuration[] = {
|
enum pll_frequency {
|
||||||
|
PLL_FREQ_48M = 0,
|
||||||
|
PLL_FREQ_96M,
|
||||||
|
PLL_FREQ_CNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pll_config_t pll_configuration[PLL_FREQ_CNT] = {
|
||||||
/*
|
/*
|
||||||
* PLL frequency setting = 4 (48MHz)
|
* PLL frequency setting = 4 (48MHz)
|
||||||
|
* MCU div = 0 (PLL / 1 = 48 mhz)
|
||||||
* FND div = 0 (PLL / 1 = 48 mhz)
|
* FND div = 0 (PLL / 1 = 48 mhz)
|
||||||
|
* USB div = 0 (PLL / 1 = 48 mhz)
|
||||||
* UART div = 1 (PLL / 2 = 24 mhz)
|
* UART div = 1 (PLL / 2 = 24 mhz)
|
||||||
* SMB div = 1 (PLL / 2 = 24 mhz)
|
* SMB div = 1 (PLL / 2 = 24 mhz)
|
||||||
* SSPI div = 1 (PLL / 2 = 24 mhz)
|
* SSPI div = 1 (PLL / 2 = 24 mhz)
|
||||||
|
@ -105,8 +130,10 @@ static const struct pll_config_t pll_configuration[] = {
|
||||||
* PWM div = 0 (PLL / 1 = 48 mhz)
|
* PWM div = 0 (PLL / 1 = 48 mhz)
|
||||||
* USBPD div = 5 (PLL / 6 = 8 mhz)
|
* USBPD div = 5 (PLL / 6 = 8 mhz)
|
||||||
*/
|
*/
|
||||||
{.pll_freq = 4,
|
[PLL_FREQ_48M] = {.pll_freq = 4,
|
||||||
|
.div_mcu = 0,
|
||||||
.div_fnd = 0,
|
.div_fnd = 0,
|
||||||
|
.div_usb = 0,
|
||||||
.div_uart = 1,
|
.div_uart = 1,
|
||||||
.div_smb = 1,
|
.div_smb = 1,
|
||||||
.div_sspi = 1,
|
.div_sspi = 1,
|
||||||
|
@ -117,7 +144,35 @@ static const struct pll_config_t pll_configuration[] = {
|
||||||
#endif
|
#endif
|
||||||
.div_jtag = 1,
|
.div_jtag = 1,
|
||||||
.div_pwm = 0,
|
.div_pwm = 0,
|
||||||
.div_usbpd = 5}
|
.div_usbpd = 5},
|
||||||
|
/*
|
||||||
|
* PLL frequency setting = 7 (96MHz)
|
||||||
|
* MCU div = 1 (PLL / 2 = 48 mhz)
|
||||||
|
* FND div = 1 (PLL / 2 = 48 mhz)
|
||||||
|
* USB div = 1 (PLL / 2 = 48 mhz)
|
||||||
|
* UART div = 3 (PLL / 4 = 24 mhz)
|
||||||
|
* SMB div = 3 (PLL / 4 = 24 mhz)
|
||||||
|
* SSPI div = 3 (PLL / 4 = 24 mhz)
|
||||||
|
* EC div = 6 (FND / 6 = 8 mhz)
|
||||||
|
* JTAG div = 3 (PLL / 4 = 24 mhz)
|
||||||
|
* PWM div = 1 (PLL / 2 = 48 mhz)
|
||||||
|
* USBPD div = 11 (PLL / 12 = 8 mhz)
|
||||||
|
*/
|
||||||
|
[PLL_FREQ_96M] = {.pll_freq = 7,
|
||||||
|
.div_mcu = 1,
|
||||||
|
.div_fnd = 1,
|
||||||
|
.div_usb = 1,
|
||||||
|
.div_uart = 3,
|
||||||
|
.div_smb = 3,
|
||||||
|
.div_sspi = 3,
|
||||||
|
#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ
|
||||||
|
.div_ec = 1,
|
||||||
|
#else
|
||||||
|
.div_ec = 6,
|
||||||
|
#endif
|
||||||
|
.div_jtag = 3,
|
||||||
|
.div_pwm = 1,
|
||||||
|
.div_usbpd = 11},
|
||||||
};
|
};
|
||||||
|
|
||||||
void __soc_ram_code chip_run_pll_sequence(const struct pll_config_t *pll)
|
void __soc_ram_code chip_run_pll_sequence(const struct pll_config_t *pll)
|
||||||
|
@ -142,12 +197,12 @@ void __soc_ram_code chip_run_pll_sequence(const struct pll_config_t *pll)
|
||||||
chip_pll_ctrl(CHIP_PLL_SLEEP);
|
chip_pll_ctrl(CHIP_PLL_SLEEP);
|
||||||
/* Chip sleep and wait timer wake it up */
|
/* Chip sleep and wait timer wake it up */
|
||||||
__asm__ volatile ("wfi");
|
__asm__ volatile ("wfi");
|
||||||
/* New FND clock frequency */
|
/* New FND and MCU clock frequency */
|
||||||
IT8XXX2_ECPM_SCDCR0 = pll->div_fnd << 4;
|
IT8XXX2_ECPM_SCDCR0 = (pll->div_fnd << 4) | pll->div_mcu;
|
||||||
/* Chip doze after wfi instruction */
|
/* Chip doze after wfi instruction */
|
||||||
chip_pll_ctrl(CHIP_PLL_DOZE);
|
chip_pll_ctrl(CHIP_PLL_DOZE);
|
||||||
/* UART */
|
/* USB and UART */
|
||||||
IT8XXX2_ECPM_SCDCR1 = pll->div_uart;
|
IT8XXX2_ECPM_SCDCR1 = (pll->div_usb << 4) | pll->div_uart;
|
||||||
/* SSPI and SMB */
|
/* SSPI and SMB */
|
||||||
IT8XXX2_ECPM_SCDCR2 = (pll->div_sspi << 4) | pll->div_smb;
|
IT8XXX2_ECPM_SCDCR2 = (pll->div_sspi << 4) | pll->div_smb;
|
||||||
/* USBPD and PWM */
|
/* USBPD and PWM */
|
||||||
|
@ -182,8 +237,27 @@ static int chip_change_pll(void)
|
||||||
if (IS_ENABLED(CONFIG_HAS_ITE_INTC)) {
|
if (IS_ENABLED(CONFIG_HAS_ITE_INTC)) {
|
||||||
ite_intc_save_and_disable_interrupts();
|
ite_intc_save_and_disable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable auto calibration before setting PLL frequency */
|
||||||
|
if (IT8XXX2_ECPM_PFACC0R & PLL_FREQ_AUTO_CAL_EN) {
|
||||||
|
IT8XXX2_ECPM_PFACC0R &= ~PLL_FREQ_AUTO_CAL_EN;
|
||||||
|
}
|
||||||
|
|
||||||
/* configure PLL/CPU/flash clock */
|
/* configure PLL/CPU/flash clock */
|
||||||
chip_configure_pll(&pll_configuration[0]);
|
if (IS_ENABLED(CONFIG_SOC_IT8XXX2_LCVCO)) {
|
||||||
|
chip_configure_pll(&pll_configuration[PLL_FREQ_96M]);
|
||||||
|
|
||||||
|
/* Enable LCVCO calibration */
|
||||||
|
IT8XXX2_ECPM_PFACC1R = 0x01;
|
||||||
|
IT8XXX2_ECPM_PFACC0R |= (PLL_FREQ_AUTO_CAL_EN | LOCK_TUNING_FACTORS_OF_LCO);
|
||||||
|
IT8XXX2_ECPM_LCOCR |= LCO_Power_CTRL;
|
||||||
|
IT8XXX2_ECPM_LCOCR1 |= LDO_Power_CTRL;
|
||||||
|
IT8XXX2_ECPM_LCOTF2 &= ~LCO_SC_FACTOR_MASK;
|
||||||
|
IT8XXX2_ECPM_LCOTF2 |= LCO_SC_FACTOR(2);
|
||||||
|
IT8XXX2_ECPM_PFACC2R = AUTO_CAL_ENABLE_AND_START;
|
||||||
|
} else {
|
||||||
|
chip_configure_pll(&pll_configuration[PLL_FREQ_48M]);
|
||||||
|
}
|
||||||
if (IS_ENABLED(CONFIG_HAS_ITE_INTC)) {
|
if (IS_ENABLED(CONFIG_HAS_ITE_INTC)) {
|
||||||
ite_intc_restore_interrupts();
|
ite_intc_restore_interrupts();
|
||||||
}
|
}
|
||||||
|
@ -253,6 +327,12 @@ void riscv_idle(enum chip_pll_mode mode, unsigned int key)
|
||||||
*/
|
*/
|
||||||
} while (ite_intc_no_irq());
|
} while (ite_intc_no_irq());
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SOC_IT8XXX2_LCVCO)) {
|
||||||
|
if (mode != CHIP_PLL_DOZE) {
|
||||||
|
IT8XXX2_ECPM_PFACC2R |= PLL_FREQ_AUTO_CAL_START;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ESPI
|
#ifdef CONFIG_ESPI
|
||||||
/* CPU has been woken up, the interrupt is no longer needed */
|
/* CPU has been woken up, the interrupt is no longer needed */
|
||||||
espi_it8xxx2_enable_trans_irq(ESPI_IT8XXX2_SOC_DEV, false);
|
espi_it8xxx2_enable_trans_irq(ESPI_IT8XXX2_SOC_DEV, false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue