/* 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)); }