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)
#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.

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. */
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) == \

View file

@ -16,6 +16,8 @@
#include <zephyr/irq.h>
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) {

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);
/* 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);

View file

@ -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__ */

View file

@ -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"

View file

@ -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}