mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-06 23:51:28 +00:00
Merge "Support dynamically changing the system clock"
This commit is contained in:
@@ -11,9 +11,6 @@
|
||||
/* Config flags */
|
||||
#define CONFIG_LIGHTBAR
|
||||
|
||||
/* 66.667 Mhz clock frequency */
|
||||
#define CPU_CLOCK 66666667
|
||||
|
||||
/* Fan PWM channels */
|
||||
#define FAN_CH_KBLIGHT 1 /* Keyboard backlight */
|
||||
#define FAN_CH_POWER_LED 3 /* Power adapter LED */
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
#define CONFIG_TMP006
|
||||
#define CONFIG_USB_CHARGE
|
||||
|
||||
/* 66.667 Mhz clock frequency */
|
||||
#define CPU_CLOCK 66666667
|
||||
|
||||
/* Fan PWM channels */
|
||||
#define FAN_CH_CPU 0 /* CPU fan */
|
||||
#define FAN_CH_KBLIGHT 1 /* Keyboard backlight */
|
||||
|
||||
176
chip/lm4/clock.c
176
chip/lm4/clock.c
@@ -5,41 +5,74 @@
|
||||
|
||||
/* Clocks and power management settings */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "config.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "registers.h"
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
* Idle task
|
||||
* executed when no task are ready to be scheduled
|
||||
*/
|
||||
void __idle(void)
|
||||
#define PLL_CLOCK 66666667 /* System clock = 200MHz PLL/3 = 66.667MHz */
|
||||
|
||||
/* Disable the PLL; run off internal oscillator. */
|
||||
static void clock_disable_pll(void)
|
||||
{
|
||||
while (1) {
|
||||
/* wait for the irq event */
|
||||
asm("wfi");
|
||||
/* TODO more power management here */
|
||||
}
|
||||
/* Switch to 16MHz internal oscillator and power down the PLL */
|
||||
LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(0) |
|
||||
LM4_SYSTEM_RCC_BYPASS |
|
||||
LM4_SYSTEM_RCC_PWRDN |
|
||||
LM4_SYSTEM_RCC_OSCSRC(1) |
|
||||
LM4_SYSTEM_RCC_MOSCDIS;
|
||||
LM4_SYSTEM_RCC2 &= ~LM4_SYSTEM_RCC2_USERCC2;
|
||||
}
|
||||
|
||||
/* simple busy waiting before clocks are initialized */
|
||||
static void wait_cycles(uint32_t cycles)
|
||||
|
||||
/* Enable the PLL to run at full clock speed */
|
||||
static void clock_enable_pll(void)
|
||||
{
|
||||
/* Disable the PLL so we can reconfigure it */
|
||||
clock_disable_pll();
|
||||
|
||||
/* Enable the PLL (PWRDN is no longer set) and set divider. PLL is
|
||||
* still bypassed, since it hasn't locked yet. */
|
||||
LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(2) |
|
||||
LM4_SYSTEM_RCC_USESYSDIV |
|
||||
LM4_SYSTEM_RCC_BYPASS |
|
||||
LM4_SYSTEM_RCC_OSCSRC(1) |
|
||||
LM4_SYSTEM_RCC_MOSCDIS;
|
||||
|
||||
/* Wait for the PLL to lock */
|
||||
clock_wait_cycles(1024);
|
||||
while (!(LM4_SYSTEM_PLLSTAT & 1))
|
||||
;
|
||||
|
||||
/* Remove bypass on PLL */
|
||||
LM4_SYSTEM_RCC &= ~LM4_SYSTEM_RCC_BYPASS;
|
||||
}
|
||||
|
||||
|
||||
void clock_wait_cycles(uint32_t cycles)
|
||||
{
|
||||
asm("1: subs %0, #1\n"
|
||||
" bne 1b\n" :: "r"(cycles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to measure baseline for power consumption.
|
||||
|
||||
int clock_get_freq(void)
|
||||
{
|
||||
return (LM4_SYSTEM_PLLSTAT & 1) ? PLL_CLOCK : INTERNAL_CLOCK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console commands */
|
||||
|
||||
/* Function to measure baseline for power consumption.
|
||||
*
|
||||
* Levels :
|
||||
* 0 : CPU running in tight loop
|
||||
@@ -47,8 +80,7 @@ static void wait_cycles(uint32_t cycles)
|
||||
* 2 : CPU in sleep mode
|
||||
* 3 : CPU in sleep mode and peripherals gated
|
||||
* 4 : CPU in deep sleep mode
|
||||
* 5 : CPU in deep sleep mode and peripherals gated
|
||||
*/
|
||||
* 5 : CPU in deep sleep mode and peripherals gated */
|
||||
static int command_sleep(int argc, char **argv)
|
||||
{
|
||||
int level = 0;
|
||||
@@ -146,53 +178,71 @@ static int command_sleep(int argc, char **argv)
|
||||
DECLARE_CONSOLE_COMMAND(sleep, command_sleep);
|
||||
|
||||
|
||||
static void clock_init_pll(uint32_t value)
|
||||
/* TODO: temporary holding place for notifying modules of clock change. Should
|
||||
* be moved to main.c after we finish measuring the power savings, so the clock
|
||||
* frequency is automatically dropped after verified boot. */
|
||||
#include "i2c.h"
|
||||
#include "hwtimer.h"
|
||||
#include "peci.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
static int command_disable_pll(int argc, char **argv)
|
||||
{
|
||||
/**
|
||||
* at startup, OSCSRC is PIOSC (precision internal oscillator)
|
||||
* PLL and PLL2 are in power-down
|
||||
*/
|
||||
int freq;
|
||||
|
||||
/* PLL already setup */
|
||||
if (LM4_SYSTEM_PLLSTAT & 1)
|
||||
return;
|
||||
clock_disable_pll();
|
||||
|
||||
/* Put a bypass on the system clock PLLs, no divider */
|
||||
LM4_SYSTEM_RCC = (LM4_SYSTEM_RCC | 0x800) & ~0x400000;
|
||||
LM4_SYSTEM_RCC2 = (LM4_SYSTEM_RCC2 | 0x800) & ~0x80000000;
|
||||
|
||||
/* Enable main and precision internal oscillators */
|
||||
LM4_SYSTEM_RCC &= ~0x3;
|
||||
|
||||
/* Perform an auto calibration of the internal oscillator, using the
|
||||
* 32.768KHz hibernate clock. */
|
||||
/* TODO: (crosbug.com/p/7693) This is only needed on early chips which
|
||||
* aren't factory trimmed. */
|
||||
LM4_SYSTEM_PIOSCCAL = 0x80000000;
|
||||
LM4_SYSTEM_PIOSCCAL = 0x80000200;
|
||||
|
||||
/* wait 1 million CPU cycles */
|
||||
wait_cycles(512 * 1024);
|
||||
|
||||
/* clear PLL lock flag (aka PLLLMIS) */
|
||||
LM4_SYSTEM_MISC = 0x40;
|
||||
/* clear powerdown / set XTAL frequency, divider, and source */
|
||||
LM4_SYSTEM_RCC = (LM4_SYSTEM_RCC & ~0x07c027f0) | (value & 0x07c007f0);
|
||||
/* wait 32 CPU cycles */
|
||||
wait_cycles(16);
|
||||
/* wait for PLL to lock */
|
||||
while (!(LM4_SYSTEM_RIS & 0x40));
|
||||
|
||||
/* Remove bypass on PLL */
|
||||
LM4_SYSTEM_RCC = LM4_SYSTEM_RCC & ~0x800;
|
||||
}
|
||||
|
||||
int clock_init(void)
|
||||
{
|
||||
/* CPU clock = PLL/3 = 66.667MHz; System clock = PLL */
|
||||
BUILD_ASSERT(CPU_CLOCK == 66666667);
|
||||
/* Osc source = internal 16MHz oscillator */
|
||||
clock_init_pll(0x01400550);
|
||||
/* Notify modules of frequency change */
|
||||
freq = clock_get_freq();
|
||||
hwtimer_clock_changed(freq);
|
||||
#ifdef CONFIG_TASK_WATCHDOG
|
||||
watchdog_clock_changed(freq);
|
||||
#endif
|
||||
#ifdef CONFIG_I2C
|
||||
i2c_clock_changed(freq);
|
||||
#endif
|
||||
#ifdef CONFIG_PECI
|
||||
peci_clock_changed(freq);
|
||||
#endif
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(nopll, command_disable_pll);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Initialization */
|
||||
|
||||
int clock_init(void)
|
||||
{
|
||||
|
||||
#ifndef BOARD_bds
|
||||
/* Only BDS has an external crystal; other boards don't have one, and
|
||||
* can disable main oscillator control to reduce power consumption. */
|
||||
LM4_SYSTEM_MOSCCTL = 0x04;
|
||||
#endif
|
||||
|
||||
/* Perform an auto calibration of the internal oscillator using the
|
||||
* 32.768KHz hibernate clock, unless we've already done so. */
|
||||
/* TODO: (crosbug.com/p/7693) This is only needed on early chips which
|
||||
* aren't factory trimmed. */
|
||||
if ((LM4_SYSTEM_PIOSCSTAT & 0x300) != 0x100) {
|
||||
/* Start calibration */
|
||||
LM4_SYSTEM_PIOSCCAL = 0x80000000;
|
||||
LM4_SYSTEM_PIOSCCAL = 0x80000200;
|
||||
/* Wait for result */
|
||||
clock_wait_cycles(16);
|
||||
while (!(LM4_SYSTEM_PIOSCSTAT & 0x300))
|
||||
;
|
||||
}
|
||||
|
||||
/* TODO: UART seems to glitch unless we wait 500k cycles before
|
||||
* enabling the PLL, but only if this is a cold boot. Why? UART
|
||||
* doesn't even use the PLL'd system clock. I've heard rumors the
|
||||
* Stellaris ROM library does this too, but why? */
|
||||
if (!system_jumped_to_this_image())
|
||||
clock_wait_cycles(500000);
|
||||
|
||||
clock_enable_pll();
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -5,18 +5,14 @@
|
||||
|
||||
/* Hardware timers driver */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "hwtimer.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
|
||||
#define US_PER_SECOND 1000000
|
||||
|
||||
/* Divider to get microsecond for the clock */
|
||||
#define CLOCKSOURCE_DIVIDER (CPU_CLOCK/US_PER_SECOND)
|
||||
|
||||
void __hw_clock_event_set(uint32_t deadline)
|
||||
{
|
||||
/* set the match on the deadline */
|
||||
@@ -57,6 +53,14 @@ static void __hw_clock_source_irq(void)
|
||||
DECLARE_IRQ(LM4_IRQ_TIMERW0A, __hw_clock_source_irq, 1);
|
||||
|
||||
|
||||
void hwtimer_clock_changed(int freq)
|
||||
{
|
||||
/* Set the prescaler to increment every microsecond. This takes
|
||||
* effect immediately, because the TAILD bit in TAMR is clear. */
|
||||
LM4_TIMER_TAPR(6) = freq / US_PER_SECOND;
|
||||
}
|
||||
|
||||
|
||||
int __hw_clock_source_init(void)
|
||||
{
|
||||
volatile uint32_t scratch __attribute__((unused));
|
||||
@@ -75,8 +79,10 @@ int __hw_clock_source_init(void)
|
||||
LM4_TIMER_IMR(6) = 0x1;
|
||||
/* 32-bit timer mode */
|
||||
LM4_TIMER_CFG(6) = 4;
|
||||
/* set the prescaler to increment every microsecond */
|
||||
LM4_TIMER_TAPR(6) = CLOCKSOURCE_DIVIDER;
|
||||
|
||||
/* Set initial clock frequency */
|
||||
hwtimer_clock_changed(clock_get_freq());
|
||||
|
||||
/* Periodic mode, counting down */
|
||||
LM4_TIMER_TAMR(6) = 0x22;
|
||||
/* use the full 32-bits of the timer */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
@@ -6,6 +6,7 @@
|
||||
/* I2C port module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
@@ -58,6 +59,7 @@ static int wait_idle(int port)
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Transmit one block of raw data, then receive one block of raw data.
|
||||
* <start> flag indicates this smbus session start from idle state.
|
||||
* <stop> flag means this session can be termicate with smbus stop bit
|
||||
@@ -142,7 +144,6 @@ static int i2c_transmit_receive(int port, int slave_addr,
|
||||
}
|
||||
|
||||
|
||||
|
||||
int i2c_read16(int port, int slave_addr, int offset, int *data)
|
||||
{
|
||||
int rv;
|
||||
@@ -192,6 +193,7 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
int i2c_read8(int port, int slave_addr, int offset, int* data)
|
||||
{
|
||||
int rv;
|
||||
@@ -210,6 +212,7 @@ int i2c_read8(int port, int slave_addr, int offset, int* data)
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
int i2c_write8(int port, int slave_addr, int offset, int data)
|
||||
{
|
||||
int rv;
|
||||
@@ -226,9 +229,7 @@ int i2c_write8(int port, int slave_addr, int offset, int data)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read ascii string using smbus read block protocol.
|
||||
* The return data <data> will be null terminated.
|
||||
*/
|
||||
|
||||
int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data,
|
||||
int len)
|
||||
{
|
||||
@@ -259,6 +260,18 @@ exit:
|
||||
}
|
||||
|
||||
|
||||
void i2c_clock_changed(int freq)
|
||||
{
|
||||
LM4_I2C_MTPR(I2C_PORT_THERMAL) =
|
||||
(freq / (I2C_SPEED_THERMAL * 10 * 2)) - 1;
|
||||
LM4_I2C_MTPR(I2C_PORT_BATTERY) =
|
||||
(freq / (I2C_SPEED_BATTERY * 10 * 2)) - 1;
|
||||
LM4_I2C_MTPR(I2C_PORT_CHARGER) =
|
||||
(freq / (I2C_SPEED_CHARGER * 10 * 2)) - 1;
|
||||
LM4_I2C_MTPR(I2C_PORT_LIGHTBAR) =
|
||||
(freq / (I2C_SPEED_LIGHTBAR * 10 * 2)) - 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Interrupt handlers */
|
||||
|
||||
@@ -439,20 +452,12 @@ int i2c_init(void)
|
||||
|
||||
/* Initialize ports as master, with interrupts enabled */
|
||||
LM4_I2C_MCR(I2C_PORT_THERMAL) = 0x10;
|
||||
LM4_I2C_MTPR(I2C_PORT_THERMAL) =
|
||||
(CPU_CLOCK / (I2C_SPEED_THERMAL * 10 * 2)) - 1;
|
||||
|
||||
LM4_I2C_MCR(I2C_PORT_BATTERY) = 0x10;
|
||||
LM4_I2C_MTPR(I2C_PORT_BATTERY) =
|
||||
(CPU_CLOCK / (I2C_SPEED_BATTERY * 10 * 2)) - 1;
|
||||
|
||||
LM4_I2C_MCR(I2C_PORT_CHARGER) = 0x10;
|
||||
LM4_I2C_MTPR(I2C_PORT_CHARGER) =
|
||||
(CPU_CLOCK / (I2C_SPEED_CHARGER * 10 * 2)) - 1;
|
||||
|
||||
LM4_I2C_MCR(I2C_PORT_LIGHTBAR) = 0x10;
|
||||
LM4_I2C_MTPR(I2C_PORT_LIGHTBAR) =
|
||||
(CPU_CLOCK / (I2C_SPEED_LIGHTBAR * 10 * 2)) - 1;
|
||||
|
||||
/* Set initial clock frequency */
|
||||
i2c_clock_changed(clock_get_freq());
|
||||
|
||||
/* Enable irqs */
|
||||
task_enable_irq(LM4_IRQ_I2C0);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/* PECI interface for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "peci.h"
|
||||
@@ -51,6 +52,7 @@ int peci_get_cpu_temp(void)
|
||||
return v >> 6;
|
||||
}
|
||||
|
||||
|
||||
int peci_temp_sensor_poll(void)
|
||||
{
|
||||
last_temp_val = peci_get_cpu_temp();
|
||||
@@ -61,11 +63,33 @@ int peci_temp_sensor_poll(void)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
int peci_temp_sensor_get_val(int idx)
|
||||
{
|
||||
return last_temp_val;
|
||||
}
|
||||
|
||||
|
||||
void peci_clock_changed(int freq)
|
||||
{
|
||||
int baud;
|
||||
|
||||
/* Disable polling while reconfiguring */
|
||||
LM4_PECI_CTL = 0;
|
||||
|
||||
/* Calculate baud setting from desired rate, compensating for internal
|
||||
* and external delays. */
|
||||
baud = freq / (4 * PECI_BAUD_RATE) - 2;
|
||||
baud -= (freq / 1000000) * (PECI_TD_FET_NS + PECI_TD_INT_NS) / 1000;
|
||||
|
||||
/* Set baud rate and polling rate */
|
||||
LM4_PECI_DIV = (baud << 16) |
|
||||
(PECI_POLL_INTERVAL_MS * (freq / 1000 / 4096));
|
||||
|
||||
/* Set up temperature monitoring to report in degrees K */
|
||||
LM4_PECI_CTL = ((PECI_TJMAX + 273) << 22) | 0x2001;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console commands */
|
||||
|
||||
@@ -88,7 +112,6 @@ DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp);
|
||||
int peci_init(void)
|
||||
{
|
||||
volatile uint32_t scratch __attribute__((unused));
|
||||
int baud;
|
||||
|
||||
/* Enable the PECI module and delay a few clocks */
|
||||
LM4_SYSTEM_RCGCPECI = 1;
|
||||
@@ -97,21 +120,8 @@ int peci_init(void)
|
||||
/* Configure GPIOs */
|
||||
configure_gpios();
|
||||
|
||||
/* Disable polling while reconfiguring */
|
||||
LM4_PECI_CTL = 0;
|
||||
|
||||
/* Calculate baud setting from desired rate, compensating for internal
|
||||
* and external delays. */
|
||||
baud = CPU_CLOCK / (4 * PECI_BAUD_RATE) - 2;
|
||||
baud -= (CPU_CLOCK / 1000000) * (PECI_TD_FET_NS + PECI_TD_INT_NS)
|
||||
/ 1000;
|
||||
|
||||
/* Set baud rate and polling rate */
|
||||
LM4_PECI_DIV = (baud << 16) |
|
||||
(PECI_POLL_INTERVAL_MS * (CPU_CLOCK / 1000 / 4096));
|
||||
|
||||
/* Set up temperature monitoring to report in degrees K */
|
||||
LM4_PECI_CTL = ((PECI_TJMAX + 273) << 22) | 0x2001;
|
||||
/* Set initial clock frequency */
|
||||
peci_clock_changed(clock_get_freq());
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,17 @@ static inline int lm4_fan_addr(int ch, int offset)
|
||||
#define LM4_SYSTEM_MISC LM4REG(0x400fe058)
|
||||
#define LM4_SYSTEM_RESC LM4REG(0x400fe05c)
|
||||
#define LM4_SYSTEM_RCC LM4REG(0x400fe060)
|
||||
#define LM4_SYSTEM_RCC_SYSDIV(x) (((x) & 0xf) << 23)
|
||||
#define LM4_SYSTEM_RCC_USESYSDIV (1 << 22)
|
||||
#define LM4_SYSTEM_RCC_PWRDN (1 << 13)
|
||||
#define LM4_SYSTEM_RCC_BYPASS (1 << 11)
|
||||
#define LM4_SYSTEM_RCC_XTAL(x) (((x) & 0x1f) << 6)
|
||||
#define LM4_SYSTEM_RCC_OSCSRC(x) (((x) & 0x3) << 4)
|
||||
#define LM4_SYSTEM_RCC_IOSCDIS (1 << 1)
|
||||
#define LM4_SYSTEM_RCC_MOSCDIS (1 << 0)
|
||||
#define LM4_SYSTEM_RCC2 LM4REG(0x400fe070)
|
||||
#define LM4_SYSTEM_RCC2_USERCC2 (1 << 31)
|
||||
#define LM4_SYSTEM_MOSCCTL LM4REG(0x400fe07c)
|
||||
#define LM4_SYSTEM_PIOSCCAL LM4REG(0x400fe150)
|
||||
#define LM4_SYSTEM_PIOSCSTAT LM4REG(0x400fe154)
|
||||
#define LM4_SYSTEM_PLLSTAT LM4REG(0x400fe168)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Watchdog driver */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "registers.h"
|
||||
@@ -25,8 +24,9 @@
|
||||
/* magic value to unlock the watchdog registers */
|
||||
#define LM4_WATCHDOG_MAGIC_WORD 0x1ACCE551
|
||||
|
||||
/* watchdog counter initial value */
|
||||
static uint32_t watchdog_period;
|
||||
#define WATCHDOG_PERIOD_MS 1100 /* Watchdog period in ms */
|
||||
|
||||
static uint32_t watchdog_period; /* Watchdog counter initial value */
|
||||
|
||||
/* console debug command prototypes */
|
||||
int command_task_info(int argc, char **argv);
|
||||
@@ -110,7 +110,15 @@ void watchdog_reload(void)
|
||||
LM4_WATCHDOG_LOCK(0) = 0xdeaddead;
|
||||
}
|
||||
|
||||
int watchdog_init(int period_ms)
|
||||
|
||||
void watchdog_clock_changed(int freq)
|
||||
{
|
||||
/* Set the timeout period */
|
||||
watchdog_period = WATCHDOG_PERIOD_MS * (freq / 1000);
|
||||
}
|
||||
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
volatile uint32_t scratch __attribute__((unused));
|
||||
|
||||
@@ -122,8 +130,8 @@ int watchdog_init(int period_ms)
|
||||
/* Unlock watchdog registers */
|
||||
LM4_WATCHDOG_LOCK(0) = LM4_WATCHDOG_MAGIC_WORD;
|
||||
|
||||
/* Set the time-out period */
|
||||
watchdog_period = period_ms * (CPU_CLOCK / 1000);
|
||||
/* Set initial timeout period */
|
||||
watchdog_clock_changed(clock_get_freq());
|
||||
LM4_WATCHDOG_LOAD(0) = watchdog_period;
|
||||
|
||||
/* de-activate the watchdog when the JTAG stops the CPU */
|
||||
|
||||
@@ -13,19 +13,6 @@
|
||||
#include "registers.h"
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
* Idle task
|
||||
* executed when no task are ready to be scheduled
|
||||
*/
|
||||
void __idle(void)
|
||||
{
|
||||
while (1) {
|
||||
/* wait for the irq event */
|
||||
asm("wfi");
|
||||
/* TODO more power management here */
|
||||
}
|
||||
}
|
||||
|
||||
int clock_init(void)
|
||||
{
|
||||
uint32_t tmp_acr;
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef union {
|
||||
/* declare task routine prototypes */
|
||||
#define TASK(n, r, d) int r(void *);
|
||||
#include TASK_LIST
|
||||
void __idle(void);
|
||||
static void __idle(void);
|
||||
CONFIG_TASK_LIST
|
||||
#undef TASK
|
||||
|
||||
@@ -51,6 +51,17 @@ static const char * const task_names[] = {
|
||||
extern void __switchto(task_ *from, task_ *to);
|
||||
|
||||
|
||||
/* Idle task. Executed when no tasks are ready to be scheduled. */
|
||||
void __idle(void)
|
||||
{
|
||||
while (1) {
|
||||
/* Wait for the irq event */
|
||||
asm("wfi");
|
||||
/* TODO: more power management here */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void task_exit_trap(void)
|
||||
{
|
||||
int i = task_get_current();
|
||||
|
||||
@@ -167,7 +167,8 @@ DECLARE_CONSOLE_COMMAND(waitms, command_wait);
|
||||
static int command_get_time(int argc, char **argv)
|
||||
{
|
||||
timestamp_t ts = get_time();
|
||||
uart_printf("Time: 0x%08x%08x us\n", ts.le.hi, ts.le.lo);
|
||||
uart_printf("Time: 0x%08x%08x us (%u %u)\n", ts.le.hi, ts.le.lo,
|
||||
ts.le.hi, ts.le.lo);
|
||||
return EC_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Clocks and power management settings */
|
||||
|
||||
#ifndef __CLOCK_H
|
||||
#define __CLOCK_H
|
||||
#ifndef __CROS_EC_CLOCK_H
|
||||
#define __CROS_EC_CLOCK_H
|
||||
|
||||
/* set the CPU clocks and PLLs */
|
||||
#include "common.h"
|
||||
|
||||
/* Set the CPU clocks and PLLs. */
|
||||
int clock_init(void);
|
||||
|
||||
#endif /* __CLOCK_H */
|
||||
/* Returns the current clock frequency in Hz. */
|
||||
int clock_get_freq(void);
|
||||
|
||||
/* Wait <cycles> system clock cycles. Simple busy waiting for before
|
||||
* clocks/timers are initialized. */
|
||||
void clock_wait_cycles(uint32_t cycles);
|
||||
|
||||
#endif /* __CROS_EC_CLOCK_H */
|
||||
|
||||
@@ -30,6 +30,9 @@ uint32_t __hw_clock_source_read(void);
|
||||
*/
|
||||
int __hw_clock_source_init(void);
|
||||
|
||||
/* Notifies the module the system clock frequency has changed to <freq>. */
|
||||
void hwtimer_clock_changed(int freq);
|
||||
|
||||
/**
|
||||
* Searches the next deadline and program it in the timer hardware.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
@@ -16,6 +16,9 @@
|
||||
/* Initializes the module. */
|
||||
int i2c_init(void);
|
||||
|
||||
/* Notifies the module the system clock frequency has changed to <freq>. */
|
||||
void i2c_clock_changed(int freq);
|
||||
|
||||
/* Reads a 16-bit register from the slave at 8-bit slave address
|
||||
* <slaveaddr>, at the specified 8-bit <offset> in the slave's address
|
||||
* space. */
|
||||
|
||||
@@ -15,6 +15,9 @@ struct temp_sensor_t;
|
||||
/* Initializes the module. */
|
||||
int peci_init(void);
|
||||
|
||||
/* Notifies the module the system clock frequency has changed to <freq>. */
|
||||
void peci_clock_changed(int freq);
|
||||
|
||||
/* Returns the current CPU temperature in degrees K, or -1 if error.
|
||||
*
|
||||
* Note that the PECI interface is currently a little flaky; if you get an
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Watchdog driver */
|
||||
|
||||
#ifndef _WATCHDOG_H
|
||||
#define _WATCHDOG_H
|
||||
#ifndef __CROS_EC_WATCHDOG_H
|
||||
#define __CROS_EC_WATCHDOG_H
|
||||
|
||||
/* Initialize the watchdog. This will cause the CPU to reboot if it has been
|
||||
* more than 2 watchdog periods since watchdog_reload() has been called. */
|
||||
int watchdog_init(int period_ms);
|
||||
|
||||
/* Reload the watchdog counter */
|
||||
void watchdog_reload(void);
|
||||
|
||||
/**
|
||||
* Initialize the watchdog
|
||||
* with a reloading period of <period_ms> milliseconds.
|
||||
* It reboots the CPU if the counter has not been reloaded for twice the period.
|
||||
*/
|
||||
int watchdog_init(int period_ms);
|
||||
/* Notifies the module the system clock frequency has changed to <freq>. */
|
||||
void watchdog_clock_changed(int freq);
|
||||
|
||||
#endif /* _WATCHDOG_H */
|
||||
#endif /* __CROS_EC_WATCHDOG_H */
|
||||
|
||||
@@ -6,16 +6,14 @@
|
||||
/* Power state machine demo module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "clock.h"
|
||||
#include "powerdemo.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
#define US_PER_SECOND 1000000
|
||||
/* Divider to get microsecond for the clock */
|
||||
#define CLOCKSOURCE_DIVIDER (CPU_CLOCK/US_PER_SECOND)
|
||||
|
||||
static volatile enum {
|
||||
POWER_STATE_IDLE = 0, /* Idle */
|
||||
@@ -77,7 +75,7 @@ int power_demo_init(void)
|
||||
/* 32-bit timer mode */
|
||||
LM4_TIMER_CFG(7) = 4;
|
||||
/* Set the prescaler to increment every microsecond */
|
||||
LM4_TIMER_TAPR(7) = CLOCKSOURCE_DIVIDER;
|
||||
LM4_TIMER_TAPR(7) = clock_get_freq() / US_PER_SECOND;
|
||||
/* One-shot, counting down */
|
||||
LM4_TIMER_TAMR(7) = 0x01;
|
||||
/* Set overflow interrupt */
|
||||
|
||||
Reference in New Issue
Block a user