176 lines
3.6 KiB
C
176 lines
3.6 KiB
C
/* Copyright 2018 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 : hardware specific implementation */
|
|
|
|
#include "clock_chip.h"
|
|
#include "console.h"
|
|
#include "cpu.h"
|
|
#include "flash.h"
|
|
#include "hooks.h"
|
|
#include "host_command.h"
|
|
#include "memmap.h"
|
|
#include "registers.h"
|
|
#include "system.h"
|
|
#include "task.h"
|
|
#include "util.h"
|
|
#include "version.h"
|
|
#include "watchdog.h"
|
|
|
|
/*
|
|
* SCP_GPR[0] b15-b0 - scratchpad
|
|
* SCP_GPR[0] b31-b16 - saved_flags
|
|
*/
|
|
|
|
int system_set_scratchpad(uint32_t value)
|
|
{
|
|
/* Check if value fits in 16 bits */
|
|
if (value & 0xffff0000)
|
|
return EC_ERROR_INVAL;
|
|
|
|
SCP_GPR[0] = (SCP_GPR[0] & 0xffff0000) | value;
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
uint32_t system_get_scratchpad(void)
|
|
{
|
|
return SCP_GPR[0] & 0xffff;
|
|
}
|
|
|
|
const char *system_get_chip_vendor(void)
|
|
{
|
|
return "mtk";
|
|
}
|
|
|
|
const char *system_get_chip_name(void)
|
|
{
|
|
/* Support only SCP_A for now */
|
|
return "scp_a";
|
|
}
|
|
|
|
const char *system_get_chip_revision(void)
|
|
{
|
|
return "";
|
|
}
|
|
|
|
void chip_pre_init(void)
|
|
{
|
|
}
|
|
|
|
static void scp_cm4_mod(void)
|
|
{
|
|
CM4_MODIFICATION = 3;
|
|
CM4_DCM_FEATURE = 3;
|
|
}
|
|
|
|
static void scp_enable_pirq(void)
|
|
{
|
|
/* Enable all peripheral to SCP IRQ, except IPC0. */
|
|
SCP_INTC_IRQ_ENABLE = 0xFFFFFFFE;
|
|
SCP_INTC_IRQ_ENABLE_MSB = 0xFFFFFFFF;
|
|
}
|
|
|
|
void system_pre_init(void)
|
|
{
|
|
/* CM4 Modification */
|
|
scp_cm4_mod();
|
|
/* Clock */
|
|
scp_enable_clock();
|
|
/* Peripheral IRQ */
|
|
scp_enable_pirq();
|
|
/* Init dram mapping (and cache) */
|
|
scp_memmap_init();
|
|
/* Disable jump (mt_scp has only RW) and enable MPU. */
|
|
system_disable_jump();
|
|
}
|
|
|
|
void system_reset(int flags)
|
|
{
|
|
uint32_t save_flags = 0;
|
|
|
|
/* Disable interrupts to avoid task swaps during reboot */
|
|
interrupt_disable();
|
|
|
|
/* Save current reset reasons if necessary */
|
|
if (flags & SYSTEM_RESET_PRESERVE_FLAGS)
|
|
save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED;
|
|
|
|
if (flags & SYSTEM_RESET_LEAVE_AP_OFF)
|
|
save_flags |= EC_RESET_FLAG_AP_OFF;
|
|
|
|
/* Remember that the software asked us to hard reboot */
|
|
if (flags & SYSTEM_RESET_HARD)
|
|
save_flags |= EC_RESET_FLAG_HARD;
|
|
|
|
/* Reset flags are 32-bits, but save only 16 bits. */
|
|
ASSERT(!(save_flags >> 16));
|
|
SCP_GPR[0] = (save_flags << 16) | (SCP_GPR[0] & 0xffff);
|
|
|
|
/* SCP can not hard reset itself */
|
|
ASSERT(!(flags & SYSTEM_RESET_HARD));
|
|
|
|
if (flags & SYSTEM_RESET_WAIT_EXT) {
|
|
int i;
|
|
|
|
/* Wait 10 seconds for external reset */
|
|
for (i = 0; i < 1000; i++) {
|
|
watchdog_reload();
|
|
udelay(10000);
|
|
}
|
|
}
|
|
|
|
/* Set watchdog timer to small value, and spin wait for watchdog reset */
|
|
SCP_WDT_CFG = 0;
|
|
SCP_WDT_CFG = SCP_WDT_ENABLE | SCP_WDT_PERIOD(1);
|
|
watchdog_reload();
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
static void check_reset_cause(void)
|
|
{
|
|
uint32_t flags = 0;
|
|
uint32_t raw_reset_cause = SCP_GPR[1];
|
|
|
|
/* Set state to power-on */
|
|
SCP_PWRON_STATE = PWRON_DEFAULT;
|
|
|
|
if ((raw_reset_cause & 0xffff0000) == PWRON_DEFAULT) {
|
|
/* Reboot */
|
|
if (raw_reset_cause & PWRON_WATCHDOG)
|
|
flags |= EC_RESET_FLAG_WATCHDOG;
|
|
else if (raw_reset_cause & PWRON_RESET)
|
|
flags |= EC_RESET_FLAG_POWER_ON;
|
|
else
|
|
flags |= EC_RESET_FLAG_OTHER;
|
|
} else {
|
|
/* Power lost restart */
|
|
flags |= EC_RESET_FLAG_POWER_ON;
|
|
}
|
|
system_set_reset_flags(SCP_GPR[0] >> 16);
|
|
SCP_GPR[0] &= 0xffff;
|
|
}
|
|
|
|
int system_is_reboot_warm(void)
|
|
{
|
|
const uint32_t cold_flags =
|
|
EC_RESET_FLAG_RESET_PIN |
|
|
EC_RESET_FLAG_POWER_ON |
|
|
EC_RESET_FLAG_WATCHDOG |
|
|
EC_RESET_FLAG_HARD |
|
|
EC_RESET_FLAG_SOFT |
|
|
EC_RESET_FLAG_HIBERNATE;
|
|
|
|
check_reset_cause();
|
|
|
|
return !(system_get_reset_flags() & cold_flags);
|
|
}
|
|
|
|
int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
|
|
{
|
|
return EC_ERROR_INVAL;
|
|
}
|