mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 09:44:13 +00:00
mcc: New module to initialize the MCC memory controller.
This turns on the system level cache. The carveout unmapping also moves here, and now it handles T8103/T6000 properly. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
ecc80f4b32
commit
4b80041d6d
6 changed files with 250 additions and 36 deletions
1
Makefile
1
Makefile
|
@ -67,6 +67,7 @@ OBJECTS := \
|
|||
iodev.o \
|
||||
kboot.o \
|
||||
main.o \
|
||||
mcc.o \
|
||||
memory.o memory_asm.o \
|
||||
payload.o \
|
||||
pcie.o \
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "exception.h"
|
||||
#include "fb.h"
|
||||
#include "heapblock.h"
|
||||
#include "mcc.h"
|
||||
#include "memory.h"
|
||||
#include "payload.h"
|
||||
#include "pcie.h"
|
||||
|
@ -82,6 +83,7 @@ void m1n1_main(void)
|
|||
get_device_info();
|
||||
|
||||
heapblock_init();
|
||||
mcc_init();
|
||||
mmu_init();
|
||||
|
||||
#ifdef USE_FB
|
||||
|
|
234
src/mcc.c
Normal file
234
src/mcc.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "mcc.h"
|
||||
#include "adt.h"
|
||||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
|
||||
static bool mcc_initialized = false;
|
||||
|
||||
#define MAX_MCC_INSTANCES 16
|
||||
|
||||
#define T8103_PLANES 4
|
||||
#define T8103_PLANE_STRIDE 0x40000
|
||||
#define T8103_DCS_STRIDE 0x40000
|
||||
|
||||
#define T6000_PLANES 4
|
||||
#define T6000_PLANE_OFFSET 0
|
||||
#define T6000_PLANE_STRIDE 0x40000
|
||||
#define T6000_GLOBAL_OFFSET 0x100000
|
||||
#define T6000_DCS_OFFSET 0x200000
|
||||
#define T6000_DCS_STRIDE 0x100000
|
||||
#define T6000_DCS_COUNT 4
|
||||
|
||||
#define PLANE_TZ_START(i) (0x6a0 + i * 0x10)
|
||||
#define PLANE_TZ_END(i) (0x6a4 + i * 0x10)
|
||||
#define PLANE_TZ_REGS 4
|
||||
|
||||
#define PLANE_CACHE_ENABLE 0x1c00
|
||||
#define PLANE_CACHE_STATUS 0x1c04
|
||||
|
||||
#define T8103_CACHE_STATUS_DATA_COUNT GENMASK(14, 10)
|
||||
#define T8103_CACHE_STATUS_TAG_COUNT GENMASK(9, 5)
|
||||
|
||||
#define T6000_CACHE_STATUS_DATA_COUNT GENMASK(13, 9)
|
||||
#define T6000_CACHE_STATUS_TAG_COUNT GENMASK(8, 4)
|
||||
|
||||
#define T6000_CACHE_WAYS 12
|
||||
#define T6000_CACHE_STATUS_MASK (T6000_CACHE_STATUS_DATA_COUNT | T6000_CACHE_STATUS_TAG_COUNT)
|
||||
#define T6000_CACHE_STATUS_VAL \
|
||||
(FIELD_PREP(T6000_CACHE_STATUS_DATA_COUNT, T6000_CACHE_WAYS) | \
|
||||
FIELD_PREP(T6000_CACHE_STATUS_TAG_COUNT, T6000_CACHE_WAYS))
|
||||
|
||||
#define T8103_CACHE_WAYS 16
|
||||
#define T8103_CACHE_STATUS_MASK (T8103_CACHE_STATUS_DATA_COUNT | T8103_CACHE_STATUS_TAG_COUNT)
|
||||
#define T8103_CACHE_STATUS_VAL \
|
||||
(FIELD_PREP(T8103_CACHE_STATUS_DATA_COUNT, T8103_CACHE_WAYS) | \
|
||||
FIELD_PREP(T8103_CACHE_STATUS_TAG_COUNT, T8103_CACHE_WAYS))
|
||||
|
||||
#define CACHE_ENABLE_TIMEOUT 10000
|
||||
|
||||
#define T8103_DCC_DRAMCFG0 0xdc4
|
||||
#define T8103_DCC_DRAMCFG1 0xdbc
|
||||
#define T8103_DCC_DRAMCFG0_DEFAULT 0x813057f
|
||||
#define T8103_DCC_DRAMCFG1_DEFAULT 0x1800180
|
||||
#define T8103_DCC_DRAMCFG0_FAST 0x133
|
||||
#define T8103_DCC_DRAMCFG1_FAST 0x55555340
|
||||
|
||||
#define T6000_DCC_DRAMCFG 0x13cc
|
||||
#define T6000_DCC_DRAMCFG_DEFAULT 0x55551555
|
||||
#define T6000_DCC_DRAMCFG_FAST 0xffff0000
|
||||
|
||||
struct mcc_regs {
|
||||
u64 plane_base;
|
||||
u64 plane_stride;
|
||||
int plane_count;
|
||||
|
||||
u64 global_base;
|
||||
|
||||
u64 dcs_base;
|
||||
u64 dcs_stride;
|
||||
int dcs_count;
|
||||
|
||||
int cache_ways;
|
||||
u32 cache_status_mask;
|
||||
u32 cache_status_val;
|
||||
};
|
||||
|
||||
static int mcc_count;
|
||||
static struct mcc_regs mcc_regs[MAX_MCC_INSTANCES];
|
||||
|
||||
static u32 plane_read32(int mcc, int plane, u64 offset)
|
||||
{
|
||||
return read32(mcc_regs[mcc].plane_base + plane * mcc_regs[mcc].plane_stride + offset);
|
||||
}
|
||||
|
||||
static void plane_write32(int mcc, int plane, u64 offset, u32 value)
|
||||
{
|
||||
write32(mcc_regs[mcc].plane_base + plane * mcc_regs[mcc].plane_stride + offset, value);
|
||||
}
|
||||
|
||||
static int plane_poll32(int mcc, int plane, u64 offset, u32 mask, u32 target, u32 timeout)
|
||||
{
|
||||
return poll32(mcc_regs[mcc].plane_base + plane * mcc_regs[mcc].plane_stride + offset, mask,
|
||||
target, timeout);
|
||||
}
|
||||
|
||||
static void mcc_enable_cache(void)
|
||||
{
|
||||
for (int mcc = 0; mcc < mcc_count; mcc++) {
|
||||
for (int plane = 0; plane < mcc_regs[mcc].plane_count; plane++) {
|
||||
plane_write32(mcc, plane, PLANE_CACHE_ENABLE, mcc_regs[mcc].cache_ways);
|
||||
if (plane_poll32(mcc, plane, PLANE_CACHE_STATUS, mcc_regs[mcc].cache_status_mask,
|
||||
mcc_regs[mcc].cache_status_val, CACHE_ENABLE_TIMEOUT))
|
||||
printf("MCC: timeout while enabling cache for MCC %d plane %d: 0x%x\n", mcc, plane,
|
||||
plane_read32(mcc, plane, PLANE_CACHE_STATUS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mcc_unmap_carveouts(void)
|
||||
{
|
||||
// All MCCs and planes should have identical configs
|
||||
for (int i = 0; i < PLANE_TZ_REGS; i++) {
|
||||
uint64_t start = ((uint64_t)plane_read32(0, 0, PLANE_TZ_START(i))) << 12;
|
||||
uint64_t end = ((uint64_t)(1 + plane_read32(0, 0, PLANE_TZ_END(i)))) << 12;
|
||||
if (start && start != end) {
|
||||
start |= ram_base;
|
||||
end |= ram_base;
|
||||
printf("MMU: Unmapping TZ%d region at 0x%lx..0x%lx\n", i, start, end);
|
||||
mmu_rm_mapping(start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcc_init_t8103(int node, int *path)
|
||||
{
|
||||
printf("MCC: Initializing T8103 MCC...\n");
|
||||
|
||||
mcc_count = 1;
|
||||
mcc_regs[0].plane_stride = T8103_PLANE_STRIDE;
|
||||
mcc_regs[0].plane_count = T8103_PLANES;
|
||||
mcc_regs[0].dcs_stride = T8103_DCS_STRIDE;
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 0, &mcc_regs[0].global_base, NULL)) {
|
||||
printf("MCC: Failed to get reg property 0!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 1, &mcc_regs[0].plane_base, NULL)) {
|
||||
printf("MCC: Failed to get reg property 1!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 2, &mcc_regs[0].dcs_base, NULL)) {
|
||||
printf("MCC: Failed to get reg property 2!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 val;
|
||||
if (ADT_GETPROP(adt, node, "#ports", &val) < 0) {
|
||||
printf("MCC: Failed to get dcs_num_channels property!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcc_regs[0].dcs_count = val;
|
||||
mcc_regs[0].cache_ways = T8103_CACHE_WAYS;
|
||||
mcc_regs[0].cache_status_mask = T8103_CACHE_STATUS_MASK;
|
||||
mcc_regs[0].cache_status_val = T8103_CACHE_STATUS_VAL;
|
||||
|
||||
mcc_enable_cache();
|
||||
|
||||
printf("MCC: Initialized T8103 MCC (%d channels)\n", val);
|
||||
|
||||
mcc_initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcc_init_t6000(int node, int *path)
|
||||
{
|
||||
u32 reg_len;
|
||||
|
||||
if (!adt_getprop(adt, node, "reg", ®_len)) {
|
||||
printf("MCC: Failed to get reg property!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcc_count = reg_len / 16;
|
||||
|
||||
printf("MCC: Initializing T6000 MCCs (%d instances)...\n", mcc_count);
|
||||
|
||||
for (int i = 0; i < mcc_count; i++) {
|
||||
u64 base;
|
||||
if (adt_get_reg(adt, path, "reg", 0, &base, NULL)) {
|
||||
printf("MCC: Failed to get reg index %d!\n", i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcc_regs[i].plane_base = base + T6000_PLANE_OFFSET;
|
||||
mcc_regs[i].plane_stride = T6000_PLANE_STRIDE;
|
||||
mcc_regs[i].plane_count = T6000_PLANES;
|
||||
|
||||
mcc_regs[i].global_base = base + T6000_GLOBAL_OFFSET;
|
||||
|
||||
mcc_regs[i].dcs_base = base + T6000_DCS_OFFSET;
|
||||
mcc_regs[i].dcs_stride = T6000_DCS_STRIDE;
|
||||
mcc_regs[i].dcs_count = T6000_DCS_COUNT;
|
||||
|
||||
mcc_regs[i].cache_ways = T6000_CACHE_WAYS;
|
||||
mcc_regs[i].cache_status_mask = T6000_CACHE_STATUS_MASK;
|
||||
mcc_regs[i].cache_status_val = T6000_CACHE_STATUS_VAL;
|
||||
}
|
||||
|
||||
mcc_enable_cache();
|
||||
|
||||
printf("MCC: Initialized T6000 MCCs (%d instances, %d planes, %d channels)\n", mcc_count,
|
||||
mcc_regs[0].plane_count, mcc_regs[0].dcs_count);
|
||||
|
||||
mcc_initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcc_init(void)
|
||||
{
|
||||
int path[8];
|
||||
int node = adt_path_offset_trace(adt, "/arm-io/mcc", path);
|
||||
|
||||
if (node < 0) {
|
||||
printf("MCC: MCC node not found!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_is_compatible(adt, node, "mcc,t8103")) {
|
||||
return mcc_init_t8103(node, path);
|
||||
} else if (adt_is_compatible(adt, node, "mcc,t6000")) {
|
||||
return mcc_init_t6000(node, path);
|
||||
} else {
|
||||
printf("MCC: Unsupported version\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
9
src/mcc.h
Normal file
9
src/mcc.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef MCC_H
|
||||
#define MCC_H
|
||||
|
||||
int mcc_init(void);
|
||||
int mcc_unmap_carveouts(void);
|
||||
|
||||
#endif
|
39
src/memory.c
39
src/memory.c
|
@ -7,6 +7,7 @@
|
|||
#include "fb.h"
|
||||
#include "gxf.h"
|
||||
#include "malloc.h"
|
||||
#include "mcc.h"
|
||||
#include "smp.h"
|
||||
#include "string.h"
|
||||
#include "utils.h"
|
||||
|
@ -312,46 +313,12 @@ void mmu_add_mapping(u64 from, u64 to, size_t size, u8 attribute_index, u64 perm
|
|||
sysop("isb");
|
||||
}
|
||||
|
||||
static void mmu_rm_mapping(u64 from, size_t size)
|
||||
void mmu_rm_mapping(u64 from, size_t size)
|
||||
{
|
||||
if (mmu_map(from, 0, size) < 0)
|
||||
panic("Failed to rm MMU mapping at 0x%lx (0x%lx)\n", from, size);
|
||||
}
|
||||
|
||||
#define TZ_START(i) (0x6a0 + i * 0x10)
|
||||
#define TZ_END(i) (0x6a4 + i * 0x10)
|
||||
#define TZ_REGS 4
|
||||
|
||||
static void mmu_unmap_carveouts(void)
|
||||
{
|
||||
int path[8];
|
||||
int node = adt_path_offset_trace(adt, "/arm-io/mcc", path);
|
||||
u64 mcc_tz_base;
|
||||
|
||||
if (node < 0) {
|
||||
printf("MMU: MCC node not found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 1, &mcc_tz_base, NULL)) {
|
||||
printf("MMU: Failed to get MCC reg property!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("MMU: TZ registers @ 0x%lx\n", mcc_tz_base);
|
||||
|
||||
for (int i = 0; i < TZ_REGS; i++) {
|
||||
uint64_t start = ((uint64_t)read32(mcc_tz_base + TZ_START(i))) << 12;
|
||||
uint64_t end = ((uint64_t)(1 + read32(mcc_tz_base + TZ_END(i)))) << 12;
|
||||
if (start && start != end) {
|
||||
start |= ram_base;
|
||||
end |= ram_base;
|
||||
printf("MMU: Unmapping TZ%d region at 0x%lx..0x%lx\n", i, start, end);
|
||||
mmu_rm_mapping(start, end - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mmu_map_mmio(void)
|
||||
{
|
||||
int node = adt_path_offset(adt, "/arm-io");
|
||||
|
@ -427,7 +394,7 @@ static void mmu_add_default_mappings(void)
|
|||
mmu_add_mapping(ram_base, ram_base, cur_boot_args.mem_size_actual, MAIR_IDX_NORMAL, PERM_RWX);
|
||||
|
||||
/* Unmap carveout regions */
|
||||
mmu_unmap_carveouts();
|
||||
mcc_unmap_carveouts();
|
||||
|
||||
/*
|
||||
* Remap m1n1 executable code as RX.
|
||||
|
|
|
@ -70,6 +70,7 @@ void mmu_init(void);
|
|||
void mmu_init_secondary(int cpu);
|
||||
void mmu_shutdown(void);
|
||||
void mmu_add_mapping(u64 from, u64 to, size_t size, u8 attribute_index, u64 perms);
|
||||
void mmu_rm_mapping(u64 from, size_t size);
|
||||
|
||||
u64 mmu_disable(void);
|
||||
void mmu_restore(u64 state);
|
||||
|
|
Loading…
Reference in a new issue