summaryrefslogtreecommitdiff
path: root/chip/mt_scp/rv32i_common/memmap.c
blob: 8ae64cf585bddc582f8aa273371856f8fa527a29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* Copyright 2020 The ChromiumOS Authors
 * 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;
}