/* Copyright 2020 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. */ #include "cache.h" #include "registers.h" #include "stdint.h" /* * Map SCP address (bits 31~28) to AP address * * SCP address AP address Note * * 0x0000_0000 SRAM * 0x1000_0000 0x5000_0000 CPU DRAM * 0x2000_0000 0x7000_0000 * 0x3000_0000 * * 0x4000_0000 * 0x5000_0000 0x0000_0000 * 0x6000_0000 0x1000_0000 * 0x7000_0000 0xa000_0000 * * 0x8000_0000 * 0x9000_0000 0x8000_0000 * 0xa000_0000 0x9000_0000 * 0xb000_0000 * * 0xc000_0000 0x8000_0000 * 0xd000_0000 0x2000_0000 * 0xe000_0000 0x3000_0000 * 0xf000_0000 0x6000_0000 */ #define REMAP_ADDR_SHIFT 28 #define REMAP_ADDR_LSB_MASK (BIT(REMAP_ADDR_SHIFT) - 1) #define REMAP_ADDR_MSB_MASK ((~0) << REMAP_ADDR_SHIFT) #define MAP_INVALID 0xff static const uint8_t addr_map[16] = { MAP_INVALID, /* SRAM */ 0x5, /* ext_addr_0x1 */ 0x7, /* ext_addr_0x2 */ MAP_INVALID, /* no ext_addr_0x3 */ MAP_INVALID, /* no ext_addr_0x4 */ 0x0, /* ext_addr_0x5 */ 0x1, /* ext_addr_0x6 */ 0xa, /* ext_addr_0x7 */ MAP_INVALID, /* no ext_addr_0x8 */ 0x8, /* ext_addr_0x9 */ 0x9, /* ext_addr_0xa */ MAP_INVALID, /* no ext_addr_0xb */ 0x8, /* ext_addr_0xc */ 0x2, /* ext_addr_0xd */ 0x3, /* ext_addr_0xe */ 0x6, /* ext_addr_0xf */ }; void memmap_init(void) { SCP_R_REMAP_0X0123 = (uint32_t)addr_map[0x1] << 8 | (uint32_t)addr_map[0x2] << 16; SCP_R_REMAP_0X4567 = (uint32_t)addr_map[0x5] << 8 | (uint32_t)addr_map[0x6] << 16 | (uint32_t)addr_map[0x7] << 24; SCP_R_REMAP_0X89AB = (uint32_t)addr_map[0x9] << 8 | (uint32_t)addr_map[0xa] << 16; SCP_R_REMAP_0XCDEF = (uint32_t)addr_map[0xc] | (uint32_t)addr_map[0xd] << 8 | (uint32_t)addr_map[0xe] << 16 | (uint32_t)addr_map[0xf] << 24; cache_init(); } int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) { int i; uint8_t msb = ap_addr >> REMAP_ADDR_SHIFT; for (i = 0; i < ARRAY_SIZE(addr_map); ++i) { if (addr_map[i] != msb) continue; *scp_addr = (ap_addr & REMAP_ADDR_LSB_MASK) | (i << REMAP_ADDR_SHIFT); return EC_SUCCESS; } return EC_ERROR_INVAL; } int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) { int i = scp_addr >> REMAP_ADDR_SHIFT; if (addr_map[i] == MAP_INVALID) return EC_ERROR_INVAL; *ap_addr = (scp_addr & REMAP_ADDR_LSB_MASK) | (addr_map[i] << REMAP_ADDR_SHIFT); return EC_SUCCESS; }