diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c index 2dcd176c54..9eeb06efc0 100644 --- a/chip/npcx/clock.c +++ b/chip/npcx/clock.c @@ -47,11 +47,14 @@ #define HFCGMH 0x07 #define HFCGML 0xDE #elif (OSC_CLK == 24000000) -#define HFCGMH 0x05 -#define HFCGML 0xB8 -#elif (OSC_CLK == 16000000) -#define HFCGMH 0x03 -#define HFCGML 0xDC +#define HFCGMH 0x0B +#define HFCGML 0x71 +#elif (OSC_CLK == 15000000) +#define HFCGMH 0x07 +#define HFCGML 0x27 +#elif (OSC_CLK == 13000000) +#define HFCGMH 0x06 +#define HFCGML 0x33 #else #error "Unsupported FMCLK Clock Frequency" #endif @@ -135,8 +138,14 @@ void clock_init(void) while (IS_BIT_SET(NPCX_HFCGCTRL, NPCX_HFCGCTRL_CLK_CHNG)) ; + /* Keep FMCLK in 33-50 MHz which is tested strictly. */ +#if (OSC_CLK >= 33000000) /* Keep Core CLK & FMCLK are the same */ NPCX_HFCGP = 0x00; +#else + /* Keep Core CLK = 0.5 * FMCLK */ + NPCX_HFCGP = 0x10; +#endif freq = OSC_CLK; diff --git a/chip/npcx/clock_chip.h b/chip/npcx/clock_chip.h index 810543afb4..09be04d007 100644 --- a/chip/npcx/clock_chip.h +++ b/chip/npcx/clock_chip.h @@ -8,8 +8,8 @@ #ifndef __CROS_EC_CLOCK_CHIP_H #define __CROS_EC_CLOCK_CHIP_H -/* Default is 40MHz (target is 16MHz) */ -#define OSC_CLK 16000000 +/* Default is 40MHz (target is 15MHz) */ +#define OSC_CLK 15000000 /** * Return the current APB1 clock frequency in Hz. diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c index d4513af7e0..ef31160a04 100644 --- a/chip/npcx/i2c.c +++ b/chip/npcx/i2c.c @@ -658,7 +658,7 @@ static void i2c_freq_changed(void) for (i = 0; i < i2c_ports_used; i++) { int bus_freq = i2c_ports[i].kbps; int ctrl = i2c_port_to_controller(i2c_ports[i].port); - int scl_time; + int scl_freq; /* SMB0/1 use core clock & SMB2/3 use apb2 clock */ if (ctrl < 2) @@ -666,21 +666,78 @@ static void i2c_freq_changed(void) else freq = clock_get_apb2_freq(); - /* use Fast Mode */ - SET_BIT(NPCX_SMBCTL3(ctrl) , NPCX_SMBCTL3_400K); - /* - * Set SCLLT/SCLHT: - * tSCLL = 2 * SCLLT7-0 * tCLK - * tSCLH = 2 * SCLHT7-0 * tCLK - * (tSCLL+tSCLH) = 4 * SCLH(L)T * tCLK if tSCLL == tSCLH - * SCLH(L)T = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) + * Set SCL frequency by formula: + * tSCL = 4 * SCLFRQ * tCLK + * fSCL = fCLK / (4*SCLFRQ) + * SCLFRQ = fSCL/(4*fSCL) */ - scl_time = (freq/1000) / (bus_freq * 4); /* bus_freq is KHz */ + scl_freq = (freq/1000) / (bus_freq*4); /* bus_freq is KHz */ - /* set SCL High/Low time */ - NPCX_SMBSCLLT(ctrl) = scl_time; - NPCX_SMBSCLHT(ctrl) = scl_time; + /* Normal mode if i2c freq is under 100kHz */ + if (bus_freq <= 100) { + /* Set divider value of SCL */ + SET_FIELD(NPCX_SMBCTL2(ctrl), NPCX_SMBCTL2_SCLFRQ7_FIELD + , (scl_freq & 0x7F)); + SET_FIELD(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_SCLFRQ2_FIELD + , (scl_freq >> 7)); + } else { + /* use Fast Mode */ + SET_BIT(NPCX_SMBCTL3(ctrl) , NPCX_SMBCTL3_400K); +#if (OSC_CLK > 15000000) + /* + * Set SCLLT/SCLHT: + * tSCLL = 2 * SCLLT7-0 * tCLK + * tSCLH = 2 * SCLHT7-0 * tCLK + * (tSCLL+tSCLH) = 4 * SCLH(L)T * tCLK if tSCLL == tSCLH + * SCLH(L)T = tSCL/(4*tCLK) = fCLK/(4*fSCL) + * The same formula as SCLFRQ + */ + NPCX_SMBSCLLT(ctrl) = scl_freq; + NPCX_SMBSCLHT(ctrl) = scl_freq; +#else + /* + * Set SCLH(L)T and hold-time directly for best i2c + * timing condition if core clock is low. Please refer + * Section 7.5.9 "SMBus Timing - Fast Mode" for detail. + */ + if (bus_freq == 400) { + if (freq == 15000000) { + NPCX_SMBSCLLT(ctrl) = 12; + NPCX_SMBSCLHT(ctrl) = 9; + SET_FIELD(NPCX_SMBCTL4(ctrl), + NPCX_SMBCTL4_HLDT_FIELD, 7); + } else if (freq == 15000000/2) { + NPCX_SMBSCLLT(ctrl) = 7; + NPCX_SMBSCLHT(ctrl) = 5; + SET_FIELD(NPCX_SMBCTL4(ctrl), + NPCX_SMBCTL4_HLDT_FIELD, 7); + } else if (freq == 13000000) { + NPCX_SMBSCLLT(ctrl) = 11; + NPCX_SMBSCLHT(ctrl) = 8; + SET_FIELD(NPCX_SMBCTL4(ctrl), + NPCX_SMBCTL4_HLDT_FIELD, 7); + } else if (freq == 13000000/2) { + NPCX_SMBSCLLT(ctrl) = 7; + NPCX_SMBSCLHT(ctrl) = 4; + SET_FIELD(NPCX_SMBCTL4(ctrl), + NPCX_SMBCTL4_HLDT_FIELD, 7); + } else { + /* Set value from formula */ + NPCX_SMBSCLLT(ctrl) = scl_freq; + NPCX_SMBSCLHT(ctrl) = scl_freq; + cprints(CC_I2C, "Warning: Not ", + "optimized timing for i2c %d", ctrl); + } + } else { + /* Set value from formula */ + NPCX_SMBSCLLT(ctrl) = scl_freq; + NPCX_SMBSCLHT(ctrl) = scl_freq; + cprints(CC_I2C, "Warning: I2c %d don't support", + " over 400kHz if src clock is low.", ctrl); + } +#endif + } } } DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index 59aac90c25..35fb568080 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -670,11 +670,14 @@ enum { #define NPCX_SMBCTL1_NMINTE 6 #define NPCX_SMBCTL1_STASTRE 7 #define NPCX_SMBCTL2_ENABLE 0 +#define NPCX_SMBCTL2_SCLFRQ7_FIELD FIELD(1, 7) #define NPCX_SMBCTL3_ARPMEN 2 +#define NPCX_SMBCTL3_SCLFRQ2_FIELD FIELD(0, 2) #define NPCX_SMBCTL3_IDL_START 3 #define NPCX_SMBCTL3_400K 4 #define NPCX_SMBCTL3_SDA_LVL 6 #define NPCX_SMBCTL3_SCL_LVL 7 +#define NPCX_SMBCTL4_HLDT_FIELD FIELD(0, 6) #define NPCX_SMBADDR1_SAEN 7 #define NPCX_SMBADDR2_SAEN 7 #define NPCX_SMBADDR3_SAEN 7 diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c index c25b2fd01e..5b47110835 100644 --- a/chip/npcx/uart.c +++ b/chip/npcx/uart.c @@ -171,11 +171,14 @@ static void uart_config(void) #elif (OSC_CLK == 24000000) NPCX_UPSR = 0x60; NPCX_UBAUD = 0x00; -#elif (OSC_CLK == 16000000) - NPCX_UPSR = 0x10; - NPCX_UBAUD = 0x02; +#elif (OSC_CLK == 15000000) + NPCX_UPSR = 0x38; + NPCX_UBAUD = 0x00; +#elif (OSC_CLK == 13000000) + NPCX_UPSR = 0x30; + NPCX_UBAUD = 0x00; #else -#error "Unsupported FMCLK Clock Frequency" +#error "Unsupported Core Clock Frequency" #endif