summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-08-09 13:11:09 -0700
committerGerrit <chrome-bot@google.com>2012-08-09 14:38:16 -0700
commit3c708cb802d395fc38350a8f856ae77e9a1315ba (patch)
tree7f62d8efa2929dd64373e130ae8e9de00dd3dbfc
parent37470f1e778157f5ca3680820ca68353f3c4ab38 (diff)
downloadchrome-ec-3c708cb802d395fc38350a8f856ae77e9a1315ba.tar.gz
Enable PLL only briefly during ADC init
It was previously only enabled for 1500us during boot, but in a way that triggered a needless round of notifications to other modules. This is cleaner. This also fixes adc_init() not initializing the task IDs to wake when interrupts come in, and removes some unneeded code from other init functions. BUG=chrome-os-partner:12472 TEST=boot system and run adc command. Should still provide reasonable data. Change-Id: I9ae5857d988c727caf5d53f551a2f12b30974c0f Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/29806 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--chip/lm4/adc.c42
-rw-r--r--chip/lm4/clock.c12
-rw-r--r--common/main.c6
-rw-r--r--include/clock.h32
4 files changed, 58 insertions, 34 deletions
diff --git a/chip/lm4/adc.c b/chip/lm4/adc.c
index 03516a5eb3..57604d1204 100644
--- a/chip/lm4/adc.c
+++ b/chip/lm4/adc.c
@@ -6,6 +6,7 @@
/* LM4-specific ADC module for Chrome EC */
#include "adc.h"
+#include "clock.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
@@ -51,11 +52,6 @@ const uint32_t ain_port[24][2] = {
static void configure_gpio(void)
{
int i;
- volatile uint32_t scratch __attribute__((unused));
-
- /* Enable GPIOE module and delay a few clocks */
- LM4_SYSTEM_RCGCGPIO |= 0x0010;
- scratch = LM4_SYSTEM_RCGCGPIO;
/* Use analog function for AIN */
for (i = 0; i < ADC_CH_COUNT; ++i) {
@@ -114,22 +110,22 @@ int lm4_adc_configure(enum lm4_adc_sequencer seq,
int ain_id,
int ssctl)
{
- volatile uint32_t scratch __attribute__((unused));
- /* TODO: set up clock using ADCCC register? */
/* Configure sample sequencer */
LM4_ADC_ADCACTSS &= ~(0x01 << seq);
+
/* Trigger sequencer by processor request */
LM4_ADC_ADCEMUX = (LM4_ADC_ADCEMUX & ~(0xf << (seq * 4))) | 0x00;
+
/* Sample internal temp sensor */
if (ain_id != LM4_AIN_NONE) {
LM4_ADC_SSMUX(seq) = ain_id & 0xf;
LM4_ADC_SSEMUX(seq) = ain_id >> 4;
- }
- else {
+ } else {
LM4_ADC_SSMUX(seq) = 0x00;
LM4_ADC_SSEMUX(seq) = 0x00;
}
LM4_ADC_SSCTL(seq) = ssctl;
+
/* Enable sample sequencer */
LM4_ADC_ADCACTSS |= 0x01 << seq;
@@ -214,20 +210,36 @@ static int adc_init(void)
int i;
const struct adc_t *adc;
- /* Enable ADC0 module and delay a few clocks */
- LM4_SYSTEM_RCGCADC |= 0x01;
- udelay(1);
-
/* Configure GPIOs */
configure_gpio();
- /* Use external voltage references (VREFA+, VREFA-) instead of
- * VDDA and GNDA. */
+ /*
+ * Temporarily enable the PLL when turning on the clock to the ADC
+ * module, to work around chip errata (10.4). No need to notify
+ * other modules; the PLL isn't enabled long enough to matter.
+ */
+ clock_enable_pll(1, 0);
+
+ /* Enable ADC0 module and delay a few clocks. */
+ LM4_SYSTEM_RCGCADC = 1;
+ clock_wait_cycles(3);
+
+ /*
+ * Use external voltage references (VREFA+, VREFA-) instead of
+ * VDDA and GNDA.
+ */
LM4_ADC_ADCCTL = 0x01;
/* Use internal oscillator */
LM4_ADC_ADCCC = 0x1;
+ /* Disable the PLL now that the ADC is using the internal oscillator */
+ clock_enable_pll(0, 0);
+
+ /* No tasks waiting yet */
+ for (i = 0; i < LM4_ADC_SEQ_COUNT; i++)
+ task_waiting_on_ss[i] = TASK_ID_INVALID;
+
/* Enable interrupt */
LM4_ADC_ADCIM = 0xF;
task_enable_irq(LM4_IRQ_ADC0_SS0);
diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c
index 6031767872..65dc62d069 100644
--- a/chip/lm4/clock.c
+++ b/chip/lm4/clock.c
@@ -64,7 +64,7 @@ static void enable_pll(void)
}
-int clock_enable_pll(int enable)
+int clock_enable_pll(int enable, int notify)
{
if (enable)
enable_pll();
@@ -72,7 +72,7 @@ int clock_enable_pll(int enable)
disable_pll();
/* Notify modules of frequency change */
- return hook_notify(HOOK_FREQ_CHANGE, 0);
+ return notify ? hook_notify(HOOK_FREQ_CHANGE, 0) : EC_SUCCESS;
}
@@ -211,9 +211,9 @@ static int command_pll(int argc, char **argv)
/* Toggle the PLL */
if (argc > 1) {
if (!strcasecmp(argv[1], "off"))
- clock_enable_pll(0);
+ clock_enable_pll(0, 1);
else if (!strcasecmp(argv[1], "on"))
- clock_enable_pll(1);
+ clock_enable_pll(1, 1);
else {
/* Disable PLL and set extra divider */
char *e;
@@ -279,8 +279,8 @@ int clock_init(void)
if (!system_jumped_to_this_image())
clock_wait_cycles(500000);
- /* Start out with PLL enabled */
- enable_pll();
+ /* Make sure PLL is disabled */
+ disable_pll();
return EC_SUCCESS;
}
diff --git a/common/main.c b/common/main.c
index 79ad7bfac2..22906cb7be 100644
--- a/common/main.c
+++ b/common/main.c
@@ -52,7 +52,7 @@ int main(void)
#ifdef CONFIG_FLASH
/*
- * Initialize flash and apply write protecte if necessary. Requires
+ * Initialize flash and apply write protect if necessary. Requires
* the reset flags calculated by system initialization.
*/
flash_pre_init();
@@ -121,10 +121,6 @@ int main(void)
*/
hook_notify(HOOK_INIT, 0);
-#ifdef BOARD_link
- /* Reduce core clock now that init is done */
- clock_enable_pll(0);
-#endif
/*
* Print the init time. Not completely accurate because it can't take
* into account the time before timer_init(), but it'll at least catch
diff --git a/include/clock.h b/include/clock.h
index c28dbb1bf2..1d2506029d 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -3,24 +3,40 @@
* found in the LICENSE file.
*/
-/* Clocks and power management settings */
+/* Clocks and power management settings */
#ifndef __CROS_EC_CLOCK_H
#define __CROS_EC_CLOCK_H
#include "common.h"
-/* Set the CPU clocks and PLLs. */
+/**
+ * Set the CPU clocks and PLLs.
+ */
int clock_init(void);
-/* Return the current clock frequency in Hz. */
+/**
+ * Return the current clock frequency in Hz.
+ */
int clock_get_freq(void);
-/* Enable or disable the PLL. */
-int clock_enable_pll(int enable);
-
-/* Wait <cycles> system clock cycles. Simple busy waiting for before
- * clocks/timers are initialized. */
+/**
+ * Enable or disable the PLL.
+ *
+ * @param enable Enable PLL if non-zero; disable if zero.
+ * @param notify Notify other modules of the PLL change. This should
+ * be 1 unless you're briefly turning on the PLL to work
+ * around a chip errata at init time.
+ */
+int clock_enable_pll(int enable, int notify);
+
+/**
+ * Wait for a number of clock cycles.
+ *
+ * Simple busy waiting for use before clocks/timers are initialized.
+ *
+ * @param cycles Number of cycles to wait.
+ */
void clock_wait_cycles(uint32_t cycles);
/* Low power modes for idle API */