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 <Dino.Li@ite.com.tw>
This commit is contained in:
Dino Li 2023-11-08 14:11:23 +08:00 committed by Fabio Baltieri
commit a059da947c
7 changed files with 66 additions and 9 deletions

View file

@ -43,6 +43,12 @@ LOG_MODULE_REGISTER(adc_ite_it8xxx2);
#define ADC_13_16_FULL_SCALE_MASK GENMASK(3, 0) #define ADC_13_16_FULL_SCALE_MASK GENMASK(3, 0)
#endif #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. */ /* List of ADC channels. */
enum chip_adc_channel { enum chip_adc_channel {
CHIP_ADC_CH0 = 0, 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; * SCLKDIV has to be equal to or greater than 1h;
*/ */
adc_regs->ADCCTL = 1; 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 * Enable this bit, and data of VCHxDATL/VCHxDATM will be
* kept until data valid is cleared. * kept until data valid is cleared.

View file

@ -210,6 +210,15 @@ static void i2c_standard_port_timing_regs_400khz(uint8_t port)
/* Port clock frequency depends on setting of timing registers. */ /* Port clock frequency depends on setting of timing registers. */
IT8XXX2_SMB_SCLKTS(port) = 0; IT8XXX2_SMB_SCLKTS(port) = 0;
/* Suggested setting of timing registers of 400kHz. */ /* 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_4P7USL = 0x3;
IT8XXX2_SMB_4P0USL = 0; IT8XXX2_SMB_4P0USL = 0;
IT8XXX2_SMB_300NS = 0x1; 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_45P3USL = 0x6a;
IT8XXX2_SMB_45P3USH = 0x1; IT8XXX2_SMB_45P3USH = 0x1;
IT8XXX2_SMB_4P7A4P0H = 0; IT8XXX2_SMB_4P7A4P0H = 0;
#endif
} }
/* Set clock frequency for i2c port A, B , or C */ /* 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."); "Channel C cannot use FIFO mode.");
#endif #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) \ #define I2C_ITE_IT8XXX2_INIT(inst) \
PINCTRL_DT_INST_DEFINE(inst); \ PINCTRL_DT_INST_DEFINE(inst); \
BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \ BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \

View file

@ -16,6 +16,8 @@
#include <zephyr/irq.h> #include <zephyr/irq.h>
LOG_MODULE_REGISTER(timer, LOG_LEVEL_ERR); 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, BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768,
"ITE RTOS timer HW frequency is fixed at 32768Hz"); "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); hw_cnt = MS_TO_COUNT(1024, ms);
else if (clock_source_sel == EXT_PSR_32) else if (clock_source_sel == EXT_PSR_32)
hw_cnt = MS_TO_COUNT(32, ms); hw_cnt = MS_TO_COUNT(32, ms);
else if (clock_source_sel == EXT_PSR_8M) else if (clock_source_sel == EXT_PSR_EC_CLK)
hw_cnt = 8000 * ms; hw_cnt = MS_TO_COUNT(EC_FREQ, ms);
else { else {
LOG_ERR("Timer %d clock source error !", ext_timer); LOG_ERR("Timer %d clock source error !", ext_timer);
return -1; return -1;
@ -424,7 +426,7 @@ static int sys_clock_driver_init(void)
IT8XXX2_EXT_CTRLX(BUSY_WAIT_L_TIMER) |= IT8XXX2_EXT_ETXCOMB; IT8XXX2_EXT_CTRLX(BUSY_WAIT_L_TIMER) |= IT8XXX2_EXT_ETXCOMB;
/* Set 32-bit timer6 to count-- every 1us */ /* 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_TIMER_H_MAX_CNT, EXT_FIRST_TIME_ENABLE,
BUSY_WAIT_H_TIMER_IRQ, BUSY_WAIT_H_TIMER_FLAG, BUSY_WAIT_H_TIMER_IRQ, BUSY_WAIT_H_TIMER_FLAG,
EXT_WITHOUT_TIMER_INT, EXT_START_TIMER); 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 * NOTE: When the timer5 count down to overflow in combinational
* mode, timer6 counter will automatically decrease one count * mode, timer6 counter will automatically decrease one count
* and timer5 will automatically re-start counting down * and timer5 will automatically re-start counting down
* from 0x7. Timer5 clock source is 8MHz (=0.125ns), so the * from COUNT_1US. Timer5 clock source is EC_FREQ, so the
* time period from 0x7 to overflow is 0.125ns * 8 = 1us. * 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, ret = timer_init(BUSY_WAIT_L_TIMER, EXT_PSR_EC_CLK, EXT_RAW_CNT,
0x7, EXT_FIRST_TIME_ENABLE, COUNT_1US, EXT_FIRST_TIME_ENABLE,
BUSY_WAIT_L_TIMER_IRQ, BUSY_WAIT_L_TIMER_FLAG, BUSY_WAIT_L_TIMER_IRQ, BUSY_WAIT_L_TIMER_FLAG,
EXT_WITHOUT_TIMER_INT, EXT_START_TIMER); EXT_WITHOUT_TIMER_INT, EXT_START_TIMER);
if (ret < 0) { if (ret < 0) {

View file

@ -198,7 +198,7 @@ IT8XXX2_REG_OFFSET_CHECK(kscan_it8xxx2_regs, KBS_KSIGDAT, 0x08);
IT8XXX2_REG_OFFSET_CHECK(kscan_it8xxx2_regs, KBS_KSOLGOEN, 0x0e); IT8XXX2_REG_OFFSET_CHECK(kscan_it8xxx2_regs, KBS_KSOLGOEN, 0x0e);
/* ADC register structure check */ /* 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, ADCGCR, 0x03);
IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, VCH0DATM, 0x19); IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, VCH0DATM, 0x19);
IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCIVMFSCS1, 0x55); 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[0].VCHCTL, 0x60);
IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, adc_vchs_ctrl[2].VCHDATM, 0x67); 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, ADCDVSTS2, 0x6c);
IT8XXX2_REG_OFFSET_CHECK(adc_it8xxx2_regs, ADCCTL1, 0xf0);
/* Watchdog register structure check */ /* Watchdog register structure check */
IT8XXX2_REG_SIZE_CHECK(wdt_it8xxx2_regs, 0x0f); IT8XXX2_REG_SIZE_CHECK(wdt_it8xxx2_regs, 0x0f);

View file

@ -38,8 +38,12 @@
* EC clock frequency (PWM and tachometer driver need it to reply * EC clock frequency (PWM and tachometer driver need it to reply
* to api or calculate RPM) * to api or calculate RPM)
*/ */
#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ
#define EC_FREQ MHZ(24)
#else
#define EC_FREQ MHZ(8) #define EC_FREQ MHZ(8)
#endif
/* --- General Control (GCTRL) --- */ /* --- General Control (GCTRL) --- */
#define IT8XXX2_GCTRL_BASE 0x00F02000 #define IT8XXX2_GCTRL_BASE 0x00F02000
@ -403,7 +407,7 @@ enum ext_clk_src_sel {
EXT_PSR_32P768K = 0, EXT_PSR_32P768K = 0,
EXT_PSR_1P024K, EXT_PSR_1P024K,
EXT_PSR_32, EXT_PSR_32,
EXT_PSR_8M, EXT_PSR_EC_CLK,
}; };
/* /*
* 24-bit timers: external timer 3, 5, and 7 * 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]; struct adc_vchs_ctrl_t adc_vchs_ctrl[4];
/* 0x6c: ADC Data Valid Status 2 */ /* 0x6c: ADC Data Valid Status 2 */
volatile uint8_t ADCDVSTS2; volatile uint8_t ADCDVSTS2;
/* 0x6d-0xef: Reserved4 */
volatile uint8_t reserved4[131];
/* 0xf0: ADC Clock Control Register 1 */
volatile uint8_t ADCCTL1;
}; };
#endif /* !__ASSEMBLER__ */ #endif /* !__ASSEMBLER__ */

View file

@ -61,14 +61,17 @@ config SOC_IT81202_CX
config SOC_IT82202_AX config SOC_IT82202_AX
bool "IT82202 AX version" bool "IT82202 AX version"
select SOC_IT8XXX2_REG_SET_V2 select SOC_IT8XXX2_REG_SET_V2
select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED
config SOC_IT82302_AX config SOC_IT82302_AX
bool "IT82302 AX version" bool "IT82302 AX version"
select SOC_IT8XXX2_REG_SET_V2 select SOC_IT8XXX2_REG_SET_V2
select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED
config SOC_IT82002_AW config SOC_IT82002_AW
bool "IT82002 AW version" bool "IT82002 AW version"
select SOC_IT8XXX2_REG_SET_V2 select SOC_IT8XXX2_REG_SET_V2
select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED
endchoice endchoice
@ -106,6 +109,15 @@ config SOC_IT8XXX2_CPU_IDLE_GATING
gated by individual drivers. When this option is disabled, CPU idle gated by individual drivers. When this option is disabled, CPU idle
mode is always permitted. 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 choice
prompt "Clock source for PLL reference clock" prompt "Clock source for PLL reference clock"

View file

@ -110,7 +110,11 @@ static const struct pll_config_t pll_configuration[] = {
.div_uart = 1, .div_uart = 1,
.div_smb = 1, .div_smb = 1,
.div_sspi = 1, .div_sspi = 1,
#ifdef CONFIG_SOC_IT8XXX2_EC_BUS_24MHZ
.div_ec = 1,
#else
.div_ec = 6, .div_ec = 6,
#endif
.div_jtag = 1, .div_jtag = 1,
.div_pwm = 0, .div_pwm = 0,
.div_usbpd = 5} .div_usbpd = 5}