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_SCDCR3 ECREG(IT8XXX2_ECPM_BASE + 0x0f)
|
||||
#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.
|
||||
|
|
|
@ -154,6 +154,15 @@ config SOC_IT8XXX2_JTAG_DEBUG_INTERFACE
|
|||
- GPIOA6 -> TRST
|
||||
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
|
||||
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)
|
||||
|
||||
/* 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 pllfreq;
|
||||
|
@ -83,7 +98,9 @@ void __soc_ram_code chip_pll_ctrl(enum chip_pll_mode mode)
|
|||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
struct pll_config_t {
|
||||
uint8_t pll_freq;
|
||||
uint8_t div_mcu;
|
||||
uint8_t div_fnd;
|
||||
uint8_t div_usb;
|
||||
uint8_t div_uart;
|
||||
uint8_t div_smb;
|
||||
uint8_t div_sspi;
|
||||
|
@ -93,10 +110,18 @@ struct pll_config_t {
|
|||
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)
|
||||
* MCU 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)
|
||||
* SMB div = 1 (PLL / 2 = 24 mhz)
|
||||
* SSPI div = 1 (PLL / 2 = 24 mhz)
|
||||
|
@ -105,19 +130,49 @@ static const struct pll_config_t pll_configuration[] = {
|
|||
* 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,
|
||||
[PLL_FREQ_48M] = {.pll_freq = 4,
|
||||
.div_mcu = 0,
|
||||
.div_fnd = 0,
|
||||
.div_usb = 0,
|
||||
.div_uart = 1,
|
||||
.div_smb = 1,
|
||||
.div_sspi = 1,
|
||||
#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ
|
||||
.div_ec = 1,
|
||||
.div_ec = 1,
|
||||
#else
|
||||
.div_ec = 6,
|
||||
.div_ec = 6,
|
||||
#endif
|
||||
.div_jtag = 1,
|
||||
.div_pwm = 0,
|
||||
.div_usbpd = 5}
|
||||
.div_jtag = 1,
|
||||
.div_pwm = 0,
|
||||
.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)
|
||||
|
@ -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 sleep and wait timer wake it up */
|
||||
__asm__ volatile ("wfi");
|
||||
/* New FND clock frequency */
|
||||
IT8XXX2_ECPM_SCDCR0 = pll->div_fnd << 4;
|
||||
/* New FND and MCU clock frequency */
|
||||
IT8XXX2_ECPM_SCDCR0 = (pll->div_fnd << 4) | pll->div_mcu;
|
||||
/* Chip doze after wfi instruction */
|
||||
chip_pll_ctrl(CHIP_PLL_DOZE);
|
||||
/* UART */
|
||||
IT8XXX2_ECPM_SCDCR1 = pll->div_uart;
|
||||
/* USB and UART */
|
||||
IT8XXX2_ECPM_SCDCR1 = (pll->div_usb << 4) | pll->div_uart;
|
||||
/* SSPI and SMB */
|
||||
IT8XXX2_ECPM_SCDCR2 = (pll->div_sspi << 4) | pll->div_smb;
|
||||
/* USBPD and PWM */
|
||||
|
@ -182,8 +237,27 @@ static int chip_change_pll(void)
|
|||
if (IS_ENABLED(CONFIG_HAS_ITE_INTC)) {
|
||||
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 */
|
||||
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)) {
|
||||
ite_intc_restore_interrupts();
|
||||
}
|
||||
|
@ -253,6 +327,12 @@ void riscv_idle(enum chip_pll_mode mode, unsigned int key)
|
|||
*/
|
||||
} 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
|
||||
/* CPU has been woken up, the interrupt is no longer needed */
|
||||
espi_it8xxx2_enable_trans_irq(ESPI_IT8XXX2_SOC_DEV, false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue