From a059da947c5e2ca73ed678f0fc0c3d4e40556324 Mon Sep 17 00:00:00 2001 From: Dino Li Date: Wed, 8 Nov 2023 14:11:23 +0800 Subject: [PATCH] soc/it8xxx2: add support for raising EC bus to 24MHz This change was made to reduce read/write EC registers latency. Without enabling CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ: - Read EC register 64 times takes 80us latency. - Write EC register 64 times takes 60us latency. With enabling CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ: - Read EC register 64 times takes 40us latency. - Write EC register 64 times takes 30us latency. Signed-off-by: Dino Li --- drivers/adc/adc_ite_it8xxx2.c | 11 +++++++++++ drivers/i2c/i2c_ite_it8xxx2.c | 18 ++++++++++++++++++ drivers/timer/ite_it8xxx2_timer.c | 17 ++++++++++------- soc/riscv/ite_ec/common/check_regs.c | 3 ++- soc/riscv/ite_ec/common/chip_chipregs.h | 10 +++++++++- soc/riscv/ite_ec/it8xxx2/Kconfig.soc | 12 ++++++++++++ soc/riscv/ite_ec/it8xxx2/soc.c | 4 ++++ 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/drivers/adc/adc_ite_it8xxx2.c b/drivers/adc/adc_ite_it8xxx2.c index 87c010933d4..53aec279fd2 100644 --- a/drivers/adc/adc_ite_it8xxx2.c +++ b/drivers/adc/adc_ite_it8xxx2.c @@ -43,6 +43,12 @@ LOG_MODULE_REGISTER(adc_ite_it8xxx2); #define ADC_13_16_FULL_SCALE_MASK GENMASK(3, 0) #endif +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ +/* Select analog clock division factor */ +#define ADC_SACLKDIV_MASK GENMASK(6, 4) +#define ADC_SACLKDIV(div) FIELD_PREP(ADC_SACLKDIV_MASK, div) +#endif + /* List of ADC channels. */ enum chip_adc_channel { CHIP_ADC_CH0 = 0, @@ -451,6 +457,11 @@ static int adc_it8xxx2_init(const struct device *dev) * SCLKDIV has to be equal to or greater than 1h; */ adc_regs->ADCCTL = 1; + +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ + adc_regs->ADCCTL1 = + (adc_regs->ADCCTL1 & ~ADC_SACLKDIV_MASK) | ADC_SACLKDIV(2); +#endif /* * Enable this bit, and data of VCHxDATL/VCHxDATM will be * kept until data valid is cleared. diff --git a/drivers/i2c/i2c_ite_it8xxx2.c b/drivers/i2c/i2c_ite_it8xxx2.c index b931a932030..734a38e5b25 100644 --- a/drivers/i2c/i2c_ite_it8xxx2.c +++ b/drivers/i2c/i2c_ite_it8xxx2.c @@ -210,6 +210,15 @@ static void i2c_standard_port_timing_regs_400khz(uint8_t port) /* Port clock frequency depends on setting of timing registers. */ IT8XXX2_SMB_SCLKTS(port) = 0; /* Suggested setting of timing registers of 400kHz. */ +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ + IT8XXX2_SMB_4P7USL = 0x16; + IT8XXX2_SMB_4P0USL = 0x11; + IT8XXX2_SMB_300NS = 0x8; + IT8XXX2_SMB_250NS = 0x8; + IT8XXX2_SMB_45P3USL = 0xff; + IT8XXX2_SMB_45P3USH = 0x3; + IT8XXX2_SMB_4P7A4P0H = 0; +#else IT8XXX2_SMB_4P7USL = 0x3; IT8XXX2_SMB_4P0USL = 0; IT8XXX2_SMB_300NS = 0x1; @@ -217,6 +226,7 @@ static void i2c_standard_port_timing_regs_400khz(uint8_t port) IT8XXX2_SMB_45P3USL = 0x6a; IT8XXX2_SMB_45P3USH = 0x1; IT8XXX2_SMB_4P7A4P0H = 0; +#endif } /* Set clock frequency for i2c port A, B , or C */ @@ -1259,6 +1269,14 @@ BUILD_ASSERT((DT_PROP(DT_NODELABEL(i2c2), fifo_enable) == false), "Channel C cannot use FIFO mode."); #endif +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ +#define I2C_IT8XXX2_CHECK_SUPPORTED_CLOCK(inst) \ + BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \ + I2C_BITRATE_FAST), "Only supports 400 KHz"); + +DT_INST_FOREACH_STATUS_OKAY(I2C_IT8XXX2_CHECK_SUPPORTED_CLOCK) +#endif + #define I2C_ITE_IT8XXX2_INIT(inst) \ PINCTRL_DT_INST_DEFINE(inst); \ BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \ diff --git a/drivers/timer/ite_it8xxx2_timer.c b/drivers/timer/ite_it8xxx2_timer.c index c29c978d189..69d42790ac7 100644 --- a/drivers/timer/ite_it8xxx2_timer.c +++ b/drivers/timer/ite_it8xxx2_timer.c @@ -16,6 +16,8 @@ #include LOG_MODULE_REGISTER(timer, LOG_LEVEL_ERR); +#define COUNT_1US (EC_FREQ / USEC_PER_SEC - 1) + BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768, "ITE RTOS timer HW frequency is fixed at 32768Hz"); @@ -332,8 +334,8 @@ static int timer_init(enum ext_timer_idx ext_timer, hw_cnt = MS_TO_COUNT(1024, ms); else if (clock_source_sel == EXT_PSR_32) hw_cnt = MS_TO_COUNT(32, ms); - else if (clock_source_sel == EXT_PSR_8M) - hw_cnt = 8000 * ms; + else if (clock_source_sel == EXT_PSR_EC_CLK) + hw_cnt = MS_TO_COUNT(EC_FREQ, ms); else { LOG_ERR("Timer %d clock source error !", ext_timer); return -1; @@ -424,7 +426,7 @@ static int sys_clock_driver_init(void) IT8XXX2_EXT_CTRLX(BUSY_WAIT_L_TIMER) |= IT8XXX2_EXT_ETXCOMB; /* Set 32-bit timer6 to count-- every 1us */ - ret = timer_init(BUSY_WAIT_H_TIMER, EXT_PSR_8M, EXT_RAW_CNT, + ret = timer_init(BUSY_WAIT_H_TIMER, EXT_PSR_EC_CLK, EXT_RAW_CNT, BUSY_WAIT_TIMER_H_MAX_CNT, EXT_FIRST_TIME_ENABLE, BUSY_WAIT_H_TIMER_IRQ, BUSY_WAIT_H_TIMER_FLAG, EXT_WITHOUT_TIMER_INT, EXT_START_TIMER); @@ -438,11 +440,12 @@ static int sys_clock_driver_init(void) * NOTE: When the timer5 count down to overflow in combinational * mode, timer6 counter will automatically decrease one count * and timer5 will automatically re-start counting down - * from 0x7. Timer5 clock source is 8MHz (=0.125ns), so the - * time period from 0x7 to overflow is 0.125ns * 8 = 1us. + * from COUNT_1US. Timer5 clock source is EC_FREQ, so the + * time period from COUNT_1US to overflow is + * (1 / EC_FREQ) * (EC_FREQ / USEC_PER_SEC) = 1us. */ - ret = timer_init(BUSY_WAIT_L_TIMER, EXT_PSR_8M, EXT_RAW_CNT, - 0x7, EXT_FIRST_TIME_ENABLE, + ret = timer_init(BUSY_WAIT_L_TIMER, EXT_PSR_EC_CLK, EXT_RAW_CNT, + COUNT_1US, EXT_FIRST_TIME_ENABLE, BUSY_WAIT_L_TIMER_IRQ, BUSY_WAIT_L_TIMER_FLAG, EXT_WITHOUT_TIMER_INT, EXT_START_TIMER); if (ret < 0) { diff --git a/soc/riscv/ite_ec/common/check_regs.c b/soc/riscv/ite_ec/common/check_regs.c index c655f850dac..2fb6dcb4128 100644 --- a/soc/riscv/ite_ec/common/check_regs.c +++ b/soc/riscv/ite_ec/common/check_regs.c @@ -198,7 +198,7 @@ IT8XXX2_REG_OFFSET_CHECK(kscan_it8xxx2_regs, KBS_KSIGDAT, 0x08); IT8XXX2_REG_OFFSET_CHECK(kscan_it8xxx2_regs, KBS_KSOLGOEN, 0x0e); /* ADC register structure check */ -IT8XXX2_REG_SIZE_CHECK(adc_it8xxx2_regs, 0x6d); +IT8XXX2_REG_SIZE_CHECK(adc_it8xxx2_regs, 0xf1); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCGCR, 0x03); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, VCH0DATM, 0x19); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCIVMFSCS1, 0x55); @@ -207,6 +207,7 @@ IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCIVMFSCS3, 0x57); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, adc_vchs_ctrl[0].VCHCTL, 0x60); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, adc_vchs_ctrl[2].VCHDATM, 0x67); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCDVSTS2, 0x6c); +IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCCTL1, 0xf0); /* Watchdog register structure check */ IT8XXX2_REG_SIZE_CHECK(wdt_it8xxx2_regs, 0x0f); diff --git a/soc/riscv/ite_ec/common/chip_chipregs.h b/soc/riscv/ite_ec/common/chip_chipregs.h index 240a8bb8234..c7d640fee33 100644 --- a/soc/riscv/ite_ec/common/chip_chipregs.h +++ b/soc/riscv/ite_ec/common/chip_chipregs.h @@ -38,8 +38,12 @@ * EC clock frequency (PWM and tachometer driver need it to reply * to api or calculate RPM) */ +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ +#define EC_FREQ MHZ(24) +#else #define EC_FREQ MHZ(8) +#endif /* --- General Control (GCTRL) --- */ #define IT8XXX2_GCTRL_BASE 0x00F02000 @@ -403,7 +407,7 @@ enum ext_clk_src_sel { EXT_PSR_32P768K = 0, EXT_PSR_1P024K, EXT_PSR_32, - EXT_PSR_8M, + EXT_PSR_EC_CLK, }; /* * 24-bit timers: external timer 3, 5, and 7 @@ -1181,6 +1185,10 @@ struct adc_it8xxx2_regs { struct adc_vchs_ctrl_t adc_vchs_ctrl[4]; /* 0x6c: ADC Data Valid Status 2 */ volatile uint8_t ADCDVSTS2; + /* 0x6d-0xef: Reserved4 */ + volatile uint8_t reserved4[131]; + /* 0xf0: ADC Clock Control Register 1 */ + volatile uint8_t ADCCTL1; }; #endif /* !__ASSEMBLER__ */ diff --git a/soc/riscv/ite_ec/it8xxx2/Kconfig.soc b/soc/riscv/ite_ec/it8xxx2/Kconfig.soc index 800a2a9dafd..d918318dfaa 100644 --- a/soc/riscv/ite_ec/it8xxx2/Kconfig.soc +++ b/soc/riscv/ite_ec/it8xxx2/Kconfig.soc @@ -61,14 +61,17 @@ config SOC_IT81202_CX config SOC_IT82202_AX bool "IT82202 AX version" select SOC_IT8XXX2_REG_SET_V2 + select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED config SOC_IT82302_AX bool "IT82302 AX version" select SOC_IT8XXX2_REG_SET_V2 + select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED config SOC_IT82002_AW bool "IT82002 AW version" select SOC_IT8XXX2_REG_SET_V2 + select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED endchoice @@ -106,6 +109,15 @@ config SOC_IT8XXX2_CPU_IDLE_GATING gated by individual drivers. When this option is disabled, CPU idle mode is always permitted. +config SOC_IT8XXX2_EC_BUS_24MHZ + bool "EC bus is 24MHz" + help + Raise EC bus to 24MHz (default is 8MHz). + This reduces read/write EC registers latency by 50%. + NOTE: There is limitation to enabling this config on it81xx2 series. + The clock_frequency of ite,it8xxx2-i2c node (i2c0, i2c1, and i2c2) will + be fixed at 400KHz. + choice prompt "Clock source for PLL reference clock" diff --git a/soc/riscv/ite_ec/it8xxx2/soc.c b/soc/riscv/ite_ec/it8xxx2/soc.c index 48e9360e208..c1ab2e13562 100644 --- a/soc/riscv/ite_ec/it8xxx2/soc.c +++ b/soc/riscv/ite_ec/it8xxx2/soc.c @@ -110,7 +110,11 @@ static const struct pll_config_t pll_configuration[] = { .div_uart = 1, .div_smb = 1, .div_sspi = 1, +#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ + .div_ec = 1, +#else .div_ec = 6, +#endif .div_jtag = 1, .div_pwm = 0, .div_usbpd = 5}