blob: 11cc7c906582999ceb5d86462d81254c21979b18 [file] [log] [blame] [edit]
/* Copyright 2016 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "init_chip.h"
#include "registers.h"
/* Drop run level to at least medium. */
void init_runlevel(const enum permission_level desired_level)
{
volatile uint32_t *const reg_addrs[] = {
/* CPU's use of the system peripheral bus */
GREG32_ADDR(GLOBALSEC, CPU0_S_PERMISSION),
/* CPU's use of the system bus via the debug access port */
GREG32_ADDR(GLOBALSEC, CPU0_S_DAP_PERMISSION),
/* DMA's use of the system peripheral bus */
GREG32_ADDR(GLOBALSEC, DDMA0_PERMISSION),
/*
* Current software level affects which (if any) scratch
* registers can be used for a warm boot hardware-verified
* jump.
*/
GREG32_ADDR(GLOBALSEC, SOFTWARE_LVL),
};
int i;
/* Permission registers drop by 1 level (e.g. HIGHEST -> HIGH)
* each time a write is encountered (the value written does
* not matter). So we repeat writes and reads, until the
* desired level is reached.
*/
for (i = 0; i < ARRAY_SIZE(reg_addrs); i++) {
uint32_t current_level;
while (1) {
current_level = *reg_addrs[i];
if (current_level <= desired_level)
break;
*reg_addrs[i] = desired_level;
}
}
}
int runlevel_is_high(void)
{
return ((GREAD(GLOBALSEC, CPU0_S_PERMISSION) == PERMISSION_HIGH) ||
(GREAD(GLOBALSEC, CPU0_S_PERMISSION) == PERMISSION_HIGHEST));
}