Refactor HIBDATA access so we can use multiple hibernate regs

BUG=chrome-os-partner:11368
TEST=none

Change-Id: I33ba317ce1cff957add7ebe34860fa4a3c686ca0
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/27380
This commit is contained in:
Randall Spangler
2012-07-13 12:29:18 -07:00
committed by Gerrit
parent 3b0e13173d
commit c1701c4f07
2 changed files with 55 additions and 34 deletions

View File

@@ -120,7 +120,7 @@ static inline int lm4_lpc_addr(int ch, int offset)
#define LM4_LPC_ST(ch) LM4LPCREG(ch, 0x004)
#define LM4_LPC_ADR(ch) LM4LPCREG(ch, 0x008)
#define LM4_LPC_POOL_BYTES 1024 /* Size of LPCPOOL in bytes */
#define LM4_LPC_LPCPOOL ((volatile unsigned char*)0x40080400)
#define LM4_LPC_LPCPOOL ((volatile unsigned char *)0x40080400)
#define LM4_FAN_FANSTS LM4REG(0x40084000)
#define LM4_FAN_FANCTL LM4REG(0x40084004)
@@ -187,7 +187,8 @@ static inline int lm4_fan_addr(int ch, int offset)
#define LM4_HIBERNATE_HIBIC LM4REG(0x400fc020)
#define LM4_HIBERNATE_HIBRTCT LM4REG(0x400fc024)
#define LM4_HIBERNATE_HIBRTCSS LM4REG(0x400fc028)
#define LM4_HIBERNATE_HIBDATA LM4REG(0x400fc030)
#define LM4_HIBERNATE_HIBDATA_ENTRIES 16 /* Number of entries in HIBDATA[] */
#define LM4_HIBERNATE_HIBDATA ((volatile uint32_t *)0x400fc030)
#define LM4_FLASH_FMA LM4REG(0x400fd000)
#define LM4_FLASH_FMD LM4REG(0x400fd004)

View File

@@ -3,14 +3,18 @@
* found in the LICENSE file.
*/
/* System module for Chrome EC : hardware specific implementation */
/* System module for Chrome EC : LM4 hardware specific implementation */
#include "board.h"
#include "common.h"
#include "cpu.h"
#include "registers.h"
#include "system.h"
#include "task.h"
/* Indices for hibernate data registers */
enum hibdata_index {
HIBDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
};
static int wait_for_hibctl_wc(void)
{
@@ -23,6 +27,42 @@ static int wait_for_hibctl_wc(void)
return EC_ERROR_UNKNOWN;
}
/**
* Read hibernate register at specified index.
*
* @return The value of the register or 0 if invalid index.
*/
static uint32_t hibdata_read(enum hibdata_index index)
{
if (index < 0 || index >= LM4_HIBERNATE_HIBDATA_ENTRIES)
return 0;
return LM4_HIBERNATE_HIBDATA[index];
}
/**
* Write hibernate register at specified index.
*
* @return nonzero if error.
*/
static int hibdata_write(enum hibdata_index index, uint32_t value)
{
int rv;
if (index < 0 || index >= LM4_HIBERNATE_HIBDATA_ENTRIES)
return EC_ERROR_INVAL;
/* Wait for ok-to-write */
rv = wait_for_hibctl_wc();
if (rv != EC_SUCCESS)
return rv;
/* Write register */
LM4_HIBERNATE_HIBDATA[index] = value;
/* Wait for write-complete */
return wait_for_hibctl_wc();
}
static void check_reset_cause(void)
{
@@ -65,12 +105,13 @@ static void check_reset_cause(void)
system_set_reset_cause(reset_cause);
}
/* A3 and earlier chip stepping has a problem accessing flash during shutdown.
/*
* A3 and earlier chip stepping has a problem accessing flash during shutdown.
* To work around that, we jump to RAM before hibernating. This function must
* live in RAM. It must be called with interrupts disabled, cannot call other
* functions, and can't be declared static (or else the compiler optimizes it
* into the main hibernate function. */
* into the main hibernate function.
*/
void __attribute__((section(".iram.text"))) __enter_hibernate(int hibctl)
{
LM4_HIBERNATE_HIBCTL = hibctl;
@@ -78,7 +119,6 @@ void __attribute__((section(".iram.text"))) __enter_hibernate(int hibctl)
;
}
void system_hibernate(uint32_t seconds, uint32_t microseconds)
{
/* Clear pending interrupt */
@@ -100,7 +140,6 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds)
__enter_hibernate(0x5B);
}
int system_pre_init(void)
{
volatile uint32_t scratch __attribute__((unused));
@@ -110,8 +149,10 @@ int system_pre_init(void)
/* Wait 3 clock cycles before using the module */
scratch = LM4_SYSTEM_RCGCHIB;
/* Enable the hibernation oscillator, if it's not already enabled. We
* use this to hold our scratchpad value across reboots. */
/*
* Enable the hibernation oscillator, if it's not already enabled. We
* use this to hold our scratchpad value across reboots.
*/
if (!(LM4_HIBERNATE_HIBCTL & 0x40)) {
int rv, i;
rv = wait_for_hibctl_wc();
@@ -153,7 +194,6 @@ int system_pre_init(void)
return EC_SUCCESS;
}
void system_reset(int is_hard)
{
/* Disable interrupts to avoid task swaps during reboot */
@@ -172,40 +212,21 @@ void system_reset(int is_hard)
;
}
int system_set_scratchpad(uint32_t value)
{
int rv;
/* Wait for ok-to-write */
rv = wait_for_hibctl_wc();
if (rv != EC_SUCCESS)
return rv;
/* Write scratchpad */
/* TODO: (crosbug.com/p/7472) might be more elegant to have a
* write_hibernate_reg() method which takes an address and
* data and does the delays. Then we could move the hibernate
* register accesses to a separate module. */
LM4_HIBERNATE_HIBDATA = value;
/* Wait for write-complete */
return wait_for_hibctl_wc();
return hibdata_write(HIBDATA_INDEX_SCRATCHPAD, value);
}
uint32_t system_get_scratchpad(void)
{
return LM4_HIBERNATE_HIBDATA;
return hibdata_read(HIBDATA_INDEX_SCRATCHPAD);
}
const char *system_get_chip_vendor(void)
{
return "ti";
}
const char *system_get_chip_name(void)
{
if ((LM4_SYSTEM_DID1 & 0xffff0000) == 0x10e20000) {
@@ -223,7 +244,6 @@ const char *system_get_chip_name(void)
}
}
const char *system_get_chip_revision(void)
{
static char rev[3];