summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2016-01-15 11:17:43 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-01-20 20:36:53 -0800
commitebd29d455793d048daadc2dcfef7e26edee9d46b (patch)
tree2a5052c13cd2c9bfe3460e75cec449ab44c2ee71
parent17ffa6b1abdec63015054623226a09c60c38a1ee (diff)
downloadchrome-ec-ebd29d455793d048daadc2dcfef7e26edee9d46b.tar.gz
nuc: Adjust core clock from 16/12 MHz to 15/13 MHz.
We found the deviation of 115200 UART baud-rate is too large when core clock is 16 or 12MHz. It causes failure during FAFT since sometime EC could not receive correct commands to proceed test. We adjusted core clock from 16/12 to 15/13 to reduce the deviation of 115200. Both of them have run FAFT and stress tests for weeks and no UART issues were found. Since the lowest source clock of i2c is 6.5MHz, we modified tSCLL, tSCLH and hold time directly for better i2c timing when freq is 400K. And if freq is 100K, we introduced normal mode to handle it. Modified sources: 1. clock.c: Adjust core clock from 16/12 MHz to 15/13 MHz. 2. clock_chip.h: Set target core clock as 15 MHz. 3. uart.c: Add baud-rate support for 15/13 MHz. 4. register.h: Add new register definitions of SMBus. 5. i2c.c: Modified tSCLL, tSCLH and hold time directly for better i2c timing. BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: Ie5d22e87875c064b49338046c99a178f8fadf32b Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/322320 Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/npcx/clock.c19
-rw-r--r--chip/npcx/clock_chip.h4
-rw-r--r--chip/npcx/i2c.c85
-rw-r--r--chip/npcx/registers.h3
-rw-r--r--chip/npcx/uart.c11
5 files changed, 97 insertions, 25 deletions
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 */
-
- /* set SCL High/Low time */
- NPCX_SMBSCLLT(ctrl) = scl_time;
- NPCX_SMBSCLHT(ctrl) = scl_time;
+ scl_freq = (freq/1000) / (bus_freq*4); /* bus_freq is KHz */
+
+ /* 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