summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2016-02-10 22:24:20 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-02-10 15:45:52 -0800
commit3d2ad2985aa16081cd6110482173d4f8d8297059 (patch)
tree0f3df99527b8783b2ffda3570cfc0e4357074917
parent71a8c029824f62693c9afbade597a58337cb2632 (diff)
downloadchrome-ec-3d2ad2985aa16081cd6110482173d4f8d8297059.tar.gz
nuc: Modify divider of apb2 to 1 if it's freq isn't divisible by 1MHz
We found the deviation of ITIM32 is huge since apb2's clock isn't divisible by 1MHz. (The default resolution of hwtimer is 1us.) The solution is set the freq of apb2 the same as core clock. Note apb2 is twice value of original one. It will increase power consumption slightly. But we found the difference is acceptable no matter core clock is 15M or 13MHz. In this version, we also use the arrays to adjust i2c bus timing if bus' freq is 400K or 1MHz for all source clock freqs of i2c. Modified sources: 1. i2c.c: Support all source clock freqs of i2c for best bus timing. 2. clock.c: Set divider of apb2 if it's clock isn't divisible by 1MHz. 3. uart.c: Modified baud-rate for apb2 which is the same as core clock. BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: I6089caaaf9aa16186d7c6acf6f5fea0682a55655 Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/327120 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/npcx/clock.c8
-rw-r--r--chip/npcx/i2c.c101
-rw-r--r--chip/npcx/uart.c12
3 files changed, 71 insertions, 50 deletions
diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c
index ae5080b6d4..9cda94ddc6 100644
--- a/chip/npcx/clock.c
+++ b/chip/npcx/clock.c
@@ -147,6 +147,14 @@ void clock_init(void)
NPCX_HFCGP = 0x10;
#endif
+ /*
+ * Let APB2 and Core CLK are equal if default APB2 clock isn't
+ * divisible by 1MHz
+ */
+#if (OSC_CLK % 2000000)
+ NPCX_HFCBCD = NPCX_HFCBCD & 0xF3;
+#endif
+
freq = OSC_CLK;
/* Notify modules of frequency change */
diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c
index 368ae7184f..8a25b4b29b 100644
--- a/chip/npcx/i2c.c
+++ b/chip/npcx/i2c.c
@@ -95,6 +95,36 @@ struct i2c_status {
/* I2C controller state data array */
static struct i2c_status i2c_stsobjs[I2C_CONTROLLER_COUNT];
+/* I2C timing setting */
+struct i2c_timing {
+ uint8_t clock; /* I2C source clock. (Unit: MHz)*/
+ uint8_t HLDT; /* I2C hold-time. (Unit: clocks) */
+ uint8_t k1; /* k1 = SCL low-time (Unit: clocks) */
+ uint8_t k2; /* k2 = SCL high-time (Unit: clocks) */
+};
+
+/* I2C timing setting array of 400K & 1M Hz */
+static const struct i2c_timing i2c_400k_timings[] = {
+ {50, 22, 84, 56},
+ {48, 22, 80, 54},
+ {40, 19, 66, 46},
+ {33, 17, 52, 38},
+ {24, 15, 38, 28},
+ {15, 12, 24, 18},
+ {13, 11, 22, 16},
+ {12, 11, 20, 14},};
+const unsigned int i2c_400k_timing_used = ARRAY_SIZE(i2c_400k_timings);
+
+static const struct i2c_timing i2c_1m_timings[] = {
+ {50, 13, 32, 24},
+ {48, 13, 30, 24},
+ {40, 12, 26, 20},
+ {33, 11, 20, 16},
+ {24, 10, 16, 12},
+ {15, 9, 10, 8},};
+const unsigned int i2c_1m_timing_used = ARRAY_SIZE(i2c_1m_timings);
+
+
int i2c_port_to_controller(int port)
{
if (port < 0 || port >= I2C_PORT_COUNT)
@@ -664,7 +694,7 @@ int i2c_raw_get_sda(int port)
/* Hooks */
static void i2c_freq_changed(void)
{
- int freq, i;
+ int freq, i, j;
for (i = 0; i < i2c_ports_used; i++) {
int bus_freq = i2c_ports[i].kbps;
@@ -693,61 +723,44 @@ static void i2c_freq_changed(void)
SET_FIELD(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_SCLFRQ2_FIELD
, (scl_freq >> 7));
} else {
+ const struct i2c_timing *pTiming;
+ int i2c_timing_used;
+
/* 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
+ * timing condition for all source clocks. 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);
- }
+ pTiming = i2c_400k_timings;
+ i2c_timing_used = i2c_400k_timing_used;
+ } else if (bus_freq == 1000) {
+ pTiming = i2c_1m_timings;
+ i2c_timing_used = i2c_1m_timing_used;
} 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);
+ cprints(CC_I2C, "Warning: Use 400K or 1MHz",
+ "for better timing of I2c %d", ctrl);
+ continue;
}
-#endif
+
+ for (j = 0; j < i2c_timing_used; j++, pTiming++) {
+ if (pTiming->clock == (freq/SECOND)) {
+ /* Set SCLH(L)T and hold-time */
+ NPCX_SMBSCLLT(ctrl) = pTiming->k1/2;
+ NPCX_SMBSCLHT(ctrl) = pTiming->k2/2;
+ SET_FIELD(NPCX_SMBCTL4(ctrl),
+ NPCX_SMBCTL4_HLDT_FIELD, pTiming->HLDT);
+ break;
+ }
+ }
+ if (j == i2c_timing_used)
+ cprints(CC_I2C, "Error: Please make sure src ",
+ "clock of i2c %d is supported", ctrl);
}
}
}
diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c
index b9f06f42dc..512478b05a 100644
--- a/chip/npcx/uart.c
+++ b/chip/npcx/uart.c
@@ -165,18 +165,18 @@ static void uart_config(void)
#elif (OSC_CLK == 40000000)
NPCX_UPSR = 0x30;
NPCX_UBAUD = 0x02;
-#elif (OSC_CLK == 33000000)
+#elif (OSC_CLK == 33000000) /* APB2 is the same as core clock */
NPCX_UPSR = 0x08;
- NPCX_UBAUD = 0x08;
+ NPCX_UBAUD = 0x11;
#elif (OSC_CLK == 24000000)
NPCX_UPSR = 0x60;
NPCX_UBAUD = 0x00;
-#elif (OSC_CLK == 15000000)
+#elif (OSC_CLK == 15000000) /* APB2 is the same as core clock */
NPCX_UPSR = 0x38;
- NPCX_UBAUD = 0x00;
-#elif (OSC_CLK == 13000000)
+ NPCX_UBAUD = 0x01;
+#elif (OSC_CLK == 13000000) /* APB2 is the same as core clock */
NPCX_UPSR = 0x30;
- NPCX_UBAUD = 0x00;
+ NPCX_UBAUD = 0x01;
#else
#error "Unsupported Core Clock Frequency"
#endif