mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-08 16:41:55 +00:00
Merge "Split reset cause and image copy code."
This commit is contained in:
@@ -1,32 +1,13 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* System module for Chrome EC */
|
||||
/* System module for Chrome EC : hardware specific implementation */
|
||||
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
|
||||
struct version_struct {
|
||||
uint32_t cookie1;
|
||||
char version[32];
|
||||
uint32_t cookie2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static const struct version_struct version_data = {
|
||||
0xce112233,
|
||||
CROS_EC_VERSION_STRING,
|
||||
0xce445566
|
||||
};
|
||||
|
||||
static uint32_t raw_reset_cause = 0;
|
||||
static enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN;
|
||||
|
||||
|
||||
static int wait_for_hibctl_wc(void)
|
||||
@@ -45,6 +26,8 @@ static void check_reset_cause(void)
|
||||
{
|
||||
enum system_image_copy_t copy = system_get_image_copy();
|
||||
uint32_t hib_status = LM4_HIBERNATE_HIBRIS;
|
||||
enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN;
|
||||
uint32_t raw_reset_cause;
|
||||
|
||||
/* Read the raw reset cause */
|
||||
raw_reset_cause = LM4_SYSTEM_RESC;
|
||||
@@ -80,6 +63,7 @@ static void check_reset_cause(void)
|
||||
} else {
|
||||
reset_cause = SYSTEM_RESET_UNKNOWN;
|
||||
}
|
||||
system_set_reset_cause(reset_cause);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,85 +136,6 @@ int system_init(void)
|
||||
}
|
||||
|
||||
|
||||
enum system_reset_cause_t system_get_reset_cause(void)
|
||||
{
|
||||
return reset_cause;
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_reset_cause_string(void)
|
||||
{
|
||||
static const char * const cause_descs[] = {
|
||||
"unknown", "other", "brownout", "power-on", "reset pin",
|
||||
"soft cold", "soft warm", "watchdog", "rtc alarm", "wake pin",
|
||||
"low battery"};
|
||||
|
||||
return reset_cause < ARRAY_SIZE(cause_descs) ?
|
||||
cause_descs[reset_cause] : "?";
|
||||
}
|
||||
|
||||
|
||||
enum system_image_copy_t system_get_image_copy(void)
|
||||
{
|
||||
int copy = (uint32_t)system_get_image_copy / CONFIG_FW_IMAGE_SIZE;
|
||||
switch (copy) {
|
||||
case 0:
|
||||
return SYSTEM_IMAGE_RO;
|
||||
case 1:
|
||||
return SYSTEM_IMAGE_RW_A;
|
||||
case 2:
|
||||
return SYSTEM_IMAGE_RW_B;
|
||||
default:
|
||||
return SYSTEM_IMAGE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_image_copy_string(void)
|
||||
{
|
||||
static const char * const copy_descs[] = {"unknown", "RO", "A", "B"};
|
||||
int copy = system_get_image_copy();
|
||||
return copy < ARRAY_SIZE(copy_descs) ? copy_descs[copy] : "?";
|
||||
}
|
||||
|
||||
|
||||
int system_run_image_copy(enum system_image_copy_t copy)
|
||||
{
|
||||
uint32_t init_addr;
|
||||
void (*resetvec)(void);
|
||||
|
||||
/* Fail if we're not in RO firmware */
|
||||
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Load the appropriate reset vector */
|
||||
if (copy == SYSTEM_IMAGE_RW_A)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_A_OFF + 4);
|
||||
else if (copy == SYSTEM_IMAGE_RW_B)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_B_OFF + 4);
|
||||
else
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* TODO: sanity checks (crosbug.com/p/7468)
|
||||
*
|
||||
* Fail if called outside of pre-init.
|
||||
*
|
||||
* Fail if reboot reason is not soft reboot. Power-on
|
||||
* reset cause must run RO firmware; if it wants to move to RW
|
||||
* firmware, it must go through a soft reboot first
|
||||
*
|
||||
* Sanity check reset vector; must be inside the appropriate
|
||||
* image. */
|
||||
|
||||
/* Jump to the reset vector */
|
||||
resetvec = (void(*)(void))init_addr;
|
||||
resetvec();
|
||||
|
||||
/* Should never get here */
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
int system_reset(int is_cold)
|
||||
{
|
||||
/* TODO: (crosbug.com/p/7470) support cold boot; this is a
|
||||
@@ -271,101 +176,3 @@ uint32_t system_get_scratchpad(void)
|
||||
{
|
||||
return LM4_HIBERNATE_HIBDATA;
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_version(enum system_image_copy_t copy)
|
||||
{
|
||||
int imoffset;
|
||||
const uint32_t *p, *pend;
|
||||
const struct version_struct *v;
|
||||
|
||||
/* Handle version of current image */
|
||||
if (copy == system_get_image_copy() || copy == SYSTEM_IMAGE_UNKNOWN)
|
||||
return version_data.version;
|
||||
|
||||
switch (copy) {
|
||||
case SYSTEM_IMAGE_RO:
|
||||
imoffset = CONFIG_FW_RO_OFF;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_A:
|
||||
imoffset = CONFIG_FW_A_OFF;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
imoffset = CONFIG_FW_B_OFF;
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
/* Search for version cookies in target image */
|
||||
/* TODO: (crosbug.com/p/7469) could be smarter about where to
|
||||
* search if we stuffed the version data into a predefined
|
||||
* area of the image - for example, immediately following the
|
||||
* reset vectors. */
|
||||
pend = (uint32_t *)(imoffset + CONFIG_FW_IMAGE_SIZE
|
||||
- sizeof(version_data));
|
||||
for (p = (uint32_t *)imoffset; p <= pend; p++) {
|
||||
v = (const struct version_struct *)p;
|
||||
if (v->cookie1 == version_data.cookie1 &&
|
||||
v->cookie2 == version_data.cookie2)
|
||||
return v->version;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
static int command_sysinfo(int argc, char **argv)
|
||||
{
|
||||
uart_printf("Reset cause: %d (%s)\n",
|
||||
system_get_reset_cause(),
|
||||
system_get_reset_cause_string());
|
||||
uart_printf("Raw reset cause: 0x%x\n", raw_reset_cause);
|
||||
uart_printf("Scratchpad: 0x%08x\n", system_get_scratchpad());
|
||||
uart_printf("Firmware copy: %s\n", system_get_image_copy_string());
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(sysinfo, command_sysinfo);
|
||||
|
||||
|
||||
static int command_set_scratchpad(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
char *e;
|
||||
|
||||
if (argc < 2) {
|
||||
uart_puts("Usage: scratchpad <value>\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
s = strtoi(argv[1], &e, 0);
|
||||
if (*e) {
|
||||
uart_puts("Invalid scratchpad value\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
uart_printf("Setting scratchpad to 0x%08x\n", s);
|
||||
return system_set_scratchpad(s);
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(setscratchpad, command_set_scratchpad);
|
||||
|
||||
static int command_hibernate(int argc, char **argv)
|
||||
{
|
||||
int seconds;
|
||||
int microseconds = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
uart_puts("Usage: hibernate <seconds> [<microseconds>]\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
seconds = strtoi(argv[1], NULL, 0);
|
||||
if (argc >= 3)
|
||||
microseconds = strtoi(argv[2], NULL, 0);
|
||||
|
||||
uart_printf("Hibernating for %d.%06d s ...\n", seconds, microseconds);
|
||||
uart_flush_output();
|
||||
|
||||
system_hibernate(seconds, microseconds);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
|
||||
common-y=main.o util.o console.o vboot.o uart_buffering.o
|
||||
common-y+=memory_commands.o shared_mem.o usb_charge.o
|
||||
common-y+=memory_commands.o shared_mem.o system.o usb_charge.o
|
||||
common-$(CONFIG_LPC)+=port80.o
|
||||
common-$(CONFIG_TASK_HOSTCMD)+=host_command.o
|
||||
common-$(CONFIG_TASK_I8042CMD)+=i8042.o keyboard.o
|
||||
|
||||
207
common/system.c
Normal file
207
common/system.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* System module for Chrome EC : common functions */
|
||||
|
||||
#include "console.h"
|
||||
#include "system.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
|
||||
struct version_struct {
|
||||
uint32_t cookie1;
|
||||
char version[32];
|
||||
uint32_t cookie2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static const struct version_struct version_data = {
|
||||
0xce112233,
|
||||
CROS_EC_VERSION_STRING,
|
||||
0xce445566
|
||||
};
|
||||
|
||||
static enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN;
|
||||
|
||||
enum system_reset_cause_t system_get_reset_cause(void)
|
||||
{
|
||||
return reset_cause;
|
||||
}
|
||||
|
||||
|
||||
void system_set_reset_cause(enum system_reset_cause_t cause)
|
||||
{
|
||||
reset_cause = cause;
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_reset_cause_string(void)
|
||||
{
|
||||
static const char * const cause_descs[] = {
|
||||
"unknown", "other", "brownout", "power-on", "reset pin",
|
||||
"soft cold", "soft warm", "watchdog", "rtc alarm", "wake pin",
|
||||
"low battery"};
|
||||
|
||||
return reset_cause < ARRAY_SIZE(cause_descs) ?
|
||||
cause_descs[reset_cause] : "?";
|
||||
}
|
||||
|
||||
|
||||
enum system_image_copy_t system_get_image_copy(void)
|
||||
{
|
||||
int copy = (uint32_t)system_get_image_copy / CONFIG_FW_IMAGE_SIZE;
|
||||
switch (copy) {
|
||||
case 0:
|
||||
return SYSTEM_IMAGE_RO;
|
||||
case 1:
|
||||
return SYSTEM_IMAGE_RW_A;
|
||||
case 2:
|
||||
return SYSTEM_IMAGE_RW_B;
|
||||
default:
|
||||
return SYSTEM_IMAGE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_image_copy_string(void)
|
||||
{
|
||||
static const char * const copy_descs[] = {"unknown", "RO", "A", "B"};
|
||||
int copy = system_get_image_copy();
|
||||
return copy < ARRAY_SIZE(copy_descs) ? copy_descs[copy] : "?";
|
||||
}
|
||||
|
||||
|
||||
int system_run_image_copy(enum system_image_copy_t copy)
|
||||
{
|
||||
uint32_t init_addr;
|
||||
void (*resetvec)(void);
|
||||
|
||||
/* Fail if we're not in RO firmware */
|
||||
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Load the appropriate reset vector */
|
||||
if (copy == SYSTEM_IMAGE_RW_A)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_A_OFF + 4);
|
||||
else if (copy == SYSTEM_IMAGE_RW_B)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_B_OFF + 4);
|
||||
else
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* TODO: sanity checks (crosbug.com/p/7468)
|
||||
*
|
||||
* Fail if called outside of pre-init.
|
||||
*
|
||||
* Fail if reboot reason is not soft reboot. Power-on
|
||||
* reset cause must run RO firmware; if it wants to move to RW
|
||||
* firmware, it must go through a soft reboot first
|
||||
*
|
||||
* Sanity check reset vector; must be inside the appropriate
|
||||
* image. */
|
||||
|
||||
/* Jump to the reset vector */
|
||||
resetvec = (void(*)(void))init_addr;
|
||||
resetvec();
|
||||
|
||||
/* Should never get here */
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
const char *system_get_version(enum system_image_copy_t copy)
|
||||
{
|
||||
int imoffset;
|
||||
const uint32_t *p, *pend;
|
||||
const struct version_struct *v;
|
||||
|
||||
/* Handle version of current image */
|
||||
if (copy == system_get_image_copy() || copy == SYSTEM_IMAGE_UNKNOWN)
|
||||
return version_data.version;
|
||||
|
||||
switch (copy) {
|
||||
case SYSTEM_IMAGE_RO:
|
||||
imoffset = CONFIG_FW_RO_OFF;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_A:
|
||||
imoffset = CONFIG_FW_A_OFF;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
imoffset = CONFIG_FW_B_OFF;
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
/* Search for version cookies in target image */
|
||||
/* TODO: (crosbug.com/p/7469) could be smarter about where to
|
||||
* search if we stuffed the version data into a predefined
|
||||
* area of the image - for example, immediately following the
|
||||
* reset vectors. */
|
||||
pend = (uint32_t *)(imoffset + CONFIG_FW_IMAGE_SIZE
|
||||
- sizeof(version_data));
|
||||
for (p = (uint32_t *)imoffset; p <= pend; p++) {
|
||||
v = (const struct version_struct *)p;
|
||||
if (v->cookie1 == version_data.cookie1 &&
|
||||
v->cookie2 == version_data.cookie2)
|
||||
return v->version;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
static int command_sysinfo(int argc, char **argv)
|
||||
{
|
||||
uart_printf("Reset cause: %d (%s)\n",
|
||||
system_get_reset_cause(),
|
||||
system_get_reset_cause_string());
|
||||
uart_printf("Scratchpad: 0x%08x\n", system_get_scratchpad());
|
||||
uart_printf("Firmware copy: %s\n", system_get_image_copy_string());
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(sysinfo, command_sysinfo);
|
||||
|
||||
|
||||
static int command_set_scratchpad(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
char *e;
|
||||
|
||||
if (argc < 2) {
|
||||
uart_puts("Usage: scratchpad <value>\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
s = strtoi(argv[1], &e, 0);
|
||||
if (*e) {
|
||||
uart_puts("Invalid scratchpad value\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
uart_printf("Setting scratchpad to 0x%08x\n", s);
|
||||
return system_set_scratchpad(s);
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(setscratchpad, command_set_scratchpad);
|
||||
|
||||
static int command_hibernate(int argc, char **argv)
|
||||
{
|
||||
int seconds;
|
||||
int microseconds = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
uart_puts("Usage: hibernate <seconds> [<microseconds>]\n");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
seconds = strtoi(argv[1], NULL, 0);
|
||||
if (argc >= 3)
|
||||
microseconds = strtoi(argv[2], NULL, 0);
|
||||
|
||||
uart_printf("Hibernating for %d.%06d s ...\n", seconds, microseconds);
|
||||
uart_flush_output();
|
||||
|
||||
system_hibernate(seconds, microseconds);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate);
|
||||
@@ -56,6 +56,9 @@ int system_init(void);
|
||||
* the cause is not known. */
|
||||
enum system_reset_cause_t system_get_reset_cause(void);
|
||||
|
||||
/* Record the cause of the last reset. */
|
||||
void system_set_reset_cause(enum system_reset_cause_t cause);
|
||||
|
||||
/* Returns a text description of the last reset cause. */
|
||||
const char *system_get_reset_cause_string(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user