summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDino Li <Dino.Li@ite.com.tw>2016-06-07 10:02:02 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-06-14 22:00:58 -0700
commit43552fb3f596573e0c633ad20fb313c21ddb281f (patch)
tree51e58abbf6a2b62f589b972b6c34e7fce1a6d564
parent4bb0efcc28d5c13721867f0bca1bfd3db68268b4 (diff)
downloadchrome-ec-43552fb3f596573e0c633ad20fb313c21ddb281f.tar.gz
it83xx: Support different PLL frequencies setting (24/48/96 MHz)
Default setting is at 48MHz. For PLL frequency at 24MHz: 1. USB module can't work, it requires 48MHz to work. 2. SSPI clock frequency is divide by two. Signed-off-by: Dino Li <dino.li@ite.com.tw> BRANCH=none BUG=none TEST=1. uart, i2c, timer, and pd modules are function normally at different PLL frequency settings. 2. use 'flashrom' utility to flash EC binary with different PLL settings. Change-Id: Iabce4726baff493a6136136af18732b58df45d7f Reviewed-on: https://chromium-review.googlesource.com/347551 Commit-Ready: Dino Li <Dino.Li@ite.com.tw> Tested-by: Dino Li <Dino.Li@ite.com.tw> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/it83xx/clock.c161
-rw-r--r--chip/it83xx/hwtimer.c9
-rw-r--r--chip/it83xx/registers.h2
-rw-r--r--chip/it83xx/spi.c3
-rw-r--r--chip/it83xx/uart.c7
-rw-r--r--core/nds32/cpu.c8
-rw-r--r--core/nds32/ec.lds.S5
-rw-r--r--driver/tcpm/it83xx.c2
8 files changed, 161 insertions, 36 deletions
diff --git a/chip/it83xx/clock.c b/chip/it83xx/clock.c
index 2e5bdca1d2..a63a86ec0a 100644
--- a/chip/it83xx/clock.c
+++ b/chip/it83xx/clock.c
@@ -65,16 +65,153 @@ static void clock_module_disable(void)
CGC_OFFSET_USB), 0, 0);
}
+enum pll_freq_idx {
+ PLL_24_MHZ = 1,
+ PLL_48_MHZ = 2,
+ PLL_96_MHZ = 4,
+};
+
+static const uint8_t pll_to_idx[8] = {
+ 0,
+ 0,
+ PLL_24_MHZ,
+ 0,
+ PLL_48_MHZ,
+ 0,
+ 0,
+ PLL_96_MHZ
+};
+
+struct clock_pll_t {
+ int pll_freq;
+ uint8_t pll_setting;
+ uint8_t div_fnd;
+ uint8_t div_uart;
+ uint8_t div_usb;
+ uint8_t div_smb;
+ uint8_t div_sspi;
+ uint8_t div_ec;
+ uint8_t div_jtag;
+ uint8_t div_pwm;
+ uint8_t div_usbpd;
+};
+
+const struct clock_pll_t clock_pll_ctrl[] = {
+ /*
+ * UART: 24MHz
+ * SMB: 24MHz
+ * EC: 8MHz
+ * JTAG: 24MHz
+ * USBPD: 8MHz
+ * USB: 48MHz(no support if PLL=24MHz)
+ * SSPI: 48MHz(24MHz if PLL=24MHz)
+ */
+ /* PLL:24MHz, MCU:24MHz, Fnd(e-flash):24MHz */
+ [PLL_24_MHZ] = {24000000, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0x2},
+ /* PLL:48MHz, MCU:48MHz, Fnd:24MHz */
+ [PLL_48_MHZ] = {48000000, 4, 1, 1, 0, 1, 0, 2, 1, 0, 0x5},
+ /* PLL:96MHz, MCU:96MHz, Fnd:32MHz */
+ [PLL_96_MHZ] = {96000000, 7, 2, 3, 1, 3, 1, 4, 3, 1, 0xb},
+};
+
+static uint8_t pll_div_fnd;
+static uint8_t pll_div_ec;
+static uint8_t pll_div_jtag;
+static uint8_t pll_setting;
+
+void __ram_code clock_ec_pll_ctrl(enum ec_pll_ctrl mode)
+{
+ IT83XX_ECPM_PLLCTRL = mode;
+ /* for deep doze / sleep mode */
+ IT83XX_ECPM_PLLCTRL = mode;
+ asm volatile ("dsb");
+}
+
+void __ram_code clock_pll_changed(void)
+{
+ IT83XX_GCTRL_SSCR &= ~(1 << 0);
+ /*
+ * Update PLL settings.
+ * Writing data to this register doesn't change the
+ * PLL frequency immediately until the status is changed
+ * into wakeup from the sleep mode.
+ * The following code is intended to make the system
+ * enter sleep mode, and set up a HW timer to wakeup EC to
+ * complete PLL update.
+ */
+ IT83XX_ECPM_PLLFREQR = pll_setting;
+ /* Pre-set FND clock frequency = PLL / 3 */
+ IT83XX_ECPM_SCDCR0 = (2 << 4);
+ /* JTAG and EC */
+ IT83XX_ECPM_SCDCR3 = (pll_div_jtag << 4) | pll_div_ec;
+ /* EC sleep after stanbdy instructioin */
+ clock_ec_pll_ctrl(EC_PLL_SLEEP);
+ /* Global interrupt enable */
+ asm volatile ("setgie.e");
+ /* EC sleep */
+ asm("standby wake_grant");
+ /* Global interrupt disable */
+ asm volatile ("setgie.d");
+ /* New FND clock frequency */
+ IT83XX_ECPM_SCDCR0 = (pll_div_fnd << 4);
+ /* EC doze after stanbdy instructioin */
+ clock_ec_pll_ctrl(EC_PLL_DOZE);
+}
+
+/* NOTE: Don't use this function in other place. */
+static void clock_set_pll(enum pll_freq_idx idx)
+{
+ int pll;
+
+ pll_div_fnd = clock_pll_ctrl[idx].div_fnd;
+ pll_div_ec = clock_pll_ctrl[idx].div_ec;
+ pll_div_jtag = clock_pll_ctrl[idx].div_jtag;
+ pll_setting = clock_pll_ctrl[idx].pll_setting;
+
+ /* Update PLL settings or not */
+ if (((IT83XX_ECPM_PLLFREQR & 0xf) != pll_setting) ||
+ ((IT83XX_ECPM_SCDCR0 & 0xf0) != (pll_div_fnd << 4)) ||
+ ((IT83XX_ECPM_SCDCR3 & 0xf) != pll_div_ec)) {
+ /* Enable hw timer to wakeup EC from the sleep mode */
+ ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ,
+ 1, 1, 5, 1, 0);
+ task_clear_pending_irq(et_ctrl_regs[LOW_POWER_EXT_TIMER].irq);
+ /* Update PLL settings. */
+ clock_pll_changed();
+ }
+
+ /* Get new/current setting of PLL frequency */
+ pll = pll_to_idx[IT83XX_ECPM_PLLFREQR & 0xf];
+ /* USB and UART */
+ IT83XX_ECPM_SCDCR1 = (clock_pll_ctrl[pll].div_usb << 4) |
+ clock_pll_ctrl[pll].div_uart;
+ /* SSPI and SMB */
+ IT83XX_ECPM_SCDCR2 = (clock_pll_ctrl[pll].div_sspi << 4) |
+ clock_pll_ctrl[pll].div_smb;
+ /* USBPD and PWM */
+ IT83XX_ECPM_SCDCR4 = (clock_pll_ctrl[pll].div_usbpd << 4) |
+ clock_pll_ctrl[pll].div_pwm;
+ /* Current PLL frequency */
+ freq = clock_pll_ctrl[pll].pll_freq;
+}
+
void clock_init(void)
{
-#if PLL_CLOCK == 48000000
- /* Set PLL frequency to 48MHz. */
- IT83XX_ECPM_PLLFREQR = 0x04;
- freq = PLL_CLOCK;
+ uint32_t image_type = (uint32_t)clock_init;
+
+ /* To change interrupt vector base if at RW image */
+ if (image_type > CONFIG_RW_MEM_OFF)
+ /* Interrupt Vector Table Base Address, in 64k Byte unit */
+ IT83XX_GCTRL_IVTBAR = (CONFIG_RW_MEM_OFF >> 16) & 0xFF;
+
+#if (PLL_CLOCK == 24000000) || \
+ (PLL_CLOCK == 48000000) || \
+ (PLL_CLOCK == 96000000)
+ /* Set PLL frequency */
+ clock_set_pll(PLL_CLOCK / 24000000);
#else
-#error "Support only for PLL clock speed of 48MHz."
+#error "Support only for PLL clock speed of 24/48/96MHz."
#endif
-
/*
* The VCC power status is treated as power-on.
* The VCC supply of LPC and related functions (EC2I,
@@ -89,7 +226,7 @@ void clock_init(void)
IT83XX_ECPM_AUTOCG = 0x00;
/* Default doze mode */
- IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE;
+ clock_ec_pll_ctrl(EC_PLL_DOZE);
clock_module_disable();
@@ -201,19 +338,11 @@ static int clock_allow_low_power_idle(void)
return 1;
}
-static void clock_ec_pll_ctrl(enum ec_pll_ctrl mode)
-{
- IT83XX_ECPM_PLLCTRL = mode;
- /* for deep doze / sleep mode */
- IT83XX_ECPM_PLLCTRL = mode;
- asm volatile ("dsb");
-}
-
void clock_sleep_mode_wakeup_isr(void)
{
uint32_t st_us, c;
- if (IT83XX_ECPM_PLLCTRL != EC_PLL_DOZE) {
+ if (IT83XX_ECPM_PLLCTRL == EC_PLL_DEEP_DOZE) {
clock_ec_pll_ctrl(EC_PLL_DOZE);
/* update free running timer */
diff --git a/chip/it83xx/hwtimer.c b/chip/it83xx/hwtimer.c
index 72e9fc7e81..aa21092e40 100644
--- a/chip/it83xx/hwtimer.c
+++ b/chip/it83xx/hwtimer.c
@@ -203,6 +203,15 @@ static void __hw_clock_source_irq(void)
free_run_timer_overflow();
return;
}
+
+ /*
+ * This interrupt is used to wakeup EC from sleep mode
+ * to complete PLL frequency change.
+ */
+ if (irq == et_ctrl_regs[LOW_POWER_EXT_TIMER].irq) {
+ ext_timer_stop(LOW_POWER_EXT_TIMER, 1);
+ return;
+ }
}
DECLARE_IRQ(CPU_INT_GROUP_3, __hw_clock_source_irq, 1);
diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h
index 615674a5d7..b46151cbdb 100644
--- a/chip/it83xx/registers.h
+++ b/chip/it83xx/registers.h
@@ -10,6 +10,8 @@
#include "common.h"
+#define __ram_code __attribute__((section(".ram_code")))
+
/* IRQ numbers */
/* Group 0 */
#define IT83XX_IRQ_WKO20 1
diff --git a/chip/it83xx/spi.c b/chip/it83xx/spi.c
index 6e876b3aee..8e8ebf47d6 100644
--- a/chip/it83xx/spi.c
+++ b/chip/it83xx/spi.c
@@ -37,9 +37,6 @@ enum sspi_ch_sel {
static void sspi_frequency(enum sspi_clk_sel freq)
{
- /* SSPI clock frequency select 48MHz (clk_sspi) */
- IT83XX_ECPM_SCDCR2 &= ~0xF0;
-
/*
* bit[6:5]
* Bit 6:Clock Polarity (CLPOL)
diff --git a/chip/it83xx/uart.c b/chip/it83xx/uart.c
index d6bb08fbc1..91624d4930 100644
--- a/chip/it83xx/uart.c
+++ b/chip/it83xx/uart.c
@@ -125,18 +125,11 @@ DECLARE_IRQ(CPU_INT_GROUP_9, intc_cpu_int_group_9, 1);
static void uart_config(void)
{
-#if PLL_CLOCK == 48000000
- /* Set CLK_UART_DIV_SEL to /2. Assumes PLL is 48 MHz. */
- IT83XX_ECPM_SCDCR1 |= 0x01;
-
/*
* Specify clock source of the UART is 24MHz,
* must match CLK_UART_DIV_SEL.
*/
IT83XX_UART_CSSR(UART_PORT) = 0x01;
-#else
-#error "Support only for PLL clock speed of 48MHz."
-#endif
/* 8-N-1 and DLAB set to allow access to DLL and DLM registers. */
IT83XX_UART_LCR(UART_PORT) = 0x83;
diff --git a/core/nds32/cpu.c b/core/nds32/cpu.c
index 7a8a043656..3db4be3f19 100644
--- a/core/nds32/cpu.c
+++ b/core/nds32/cpu.c
@@ -11,14 +11,6 @@
void cpu_init(void)
{
/* DLM initialization is done in init.S */
-
- uint32_t image_type = (uint32_t)cpu_init;
-
- /* To change interrupt vector base if at RW image */
- if (image_type > CONFIG_RW_MEM_OFF)
- /* Interrupt Vector Table Base Address, in 64k Byte unit */
- IT83XX_GCTRL_IVTBAR = (CONFIG_RW_MEM_OFF >> 16) & 0xFF;
-
/* Global interrupt enable */
asm volatile ("setgie.e");
}
diff --git a/core/nds32/ec.lds.S b/core/nds32/ec.lds.S
index 0d91c6d6e4..adff240325 100644
--- a/core/nds32/ec.lds.S
+++ b/core/nds32/ec.lds.S
@@ -40,6 +40,11 @@ SECTIONS
. = ALIGN(CONFIG_IT83XX_ILM_BLOCK_SIZE);
__flash_dma_start = .;
KEEP(*(.flash_direct_map))
+ . = ALIGN(16);
+ KEEP(*(.ram_code))
+ __flash_dma_size = . - __flash_dma_start;
+ ASSERT((__flash_dma_size < CONFIG_IT83XX_ILM_BLOCK_SIZE),
+ "__flash_dma_size < CONFIG_IT83XX_ILM_BLOCK_SIZE");
. = ALIGN(CONFIG_IT83XX_ILM_BLOCK_SIZE);
} > FLASH
. = ALIGN(4);
diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c
index 3bc0c0db32..ed871edd02 100644
--- a/driver/tcpm/it83xx.c
+++ b/driver/tcpm/it83xx.c
@@ -262,8 +262,6 @@ static void it83xx_set_data_role(enum usbpd_port port, int pd_role)
static void it83xx_init(enum usbpd_port port, int role)
{
- /* defalut PD Clock = PLL 48 / 6 = 8M. */
- IT83XX_ECPM_SCDCR4 = (IT83XX_ECPM_SCDCR4 & 0xf0) | 5;
/* reset */
IT83XX_USBPD_GCR(port) = 0;
USBPD_SW_RESET(port);