blob: 001747f223dd6b90e8f208e38cae10363226127c [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright 2024 - Analog Devices, Inc.
*
* Written and/or maintained by Timesys Corporation
*
* Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
* Contact: Greg Malysa <greg.malysa@timesys.com>
*/
#include <asm/io.h>
#include <asm/armv8/mmu.h>
#include <asm/arch-adi/sc5xx/sc5xx.h>
#include <asm/arch-adi/sc5xx/spl.h>
#define REG_TSGENWR0_CNTCR 0x310AE000
#define REG_PADS0_PCFG0 0x31004604
#define REG_RCU0_BCODE 0x3108C028
#define REG_SPU0_SECUREP_START 0x3108BA00
#define REG_SPU0_WP_START 0x3108B400
#define REG_SPU0_SECUREC0 0x3108B980
#define REG_SCB5_SPI2_OSPI_REMAP 0x30400000
#define BITM_SCB5_SPI2_OSPI_REMAP_REMAP 0x00000003
#define ENUM_SCB5_SPI2_OSPI_REMAP_OSPI0 0x00000001
static struct mm_region sc598_mem_map[] = {
{
/* Peripherals */
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
/* DDR */
.virt = 0x80000000UL,
.phys = 0x80000000UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
/* List terminator */
0,
}
};
struct mm_region *mem_map = sc598_mem_map;
adi_rom_boot_fn adi_rom_boot = (adi_rom_boot_fn)0x000000e4;
void sc5xx_enable_rgmii(void)
{
writel((readl(REG_PADS0_PCFG0) | 0xc), REG_PADS0_PCFG0);
// Set dw for little endian operation as well
writel(readl(REG_PADS0_PCFG0) & ~(1 << 19), REG_PADS0_PCFG0);
writel(readl(REG_PADS0_PCFG0) & ~(1 << 20), REG_PADS0_PCFG0);
}
void sc59x_remap_ospi(void)
{
clrsetbits_le32(REG_SCB5_SPI2_OSPI_REMAP,
BITM_SCB5_SPI2_OSPI_REMAP_REMAP,
ENUM_SCB5_SPI2_OSPI_REMAP_OSPI0);
}
/**
* SPU/SMPU configuration is the default for permissive access from non-secure
* EL1. If TFA and OPTEE are configured, they run *after* this code, as the
* current boot flow is SPL -> TFA -> OPTEE -> Proper -> Linux, and will
* be expected to configure peripheral security correctly. If they are not
* configured, then this permissive setting will allow Linux (which always
* runs in NS EL1) to control all access to these peripherals. Without it,
* the peripherals would simply be unavailable in a non-security build,
* which is not OK.
*/
void sc5xx_soc_init(void)
{
phys_addr_t smpus[] = {
0x31007800, //SMPU0
0x31083800, //SMPU2
0x31084800, //SMPU3
0x31085800, //SMPU4
0x31086800, //SMPU5
0x31087800, //SMPU6
0x310A0800, //SMPU9
0x310A1800, //SMPU11
0x31012800, //SMPU12
};
size_t i;
// Enable coresight timer
writel(1, REG_TSGENWR0_CNTCR);
//Do not rerun preboot routine --
// Without this, hardware resets triggered by RCU0_CTL:SYSRST
// lead to a deadlock somewhere in the boot ROM
writel(0x200, REG_RCU0_BCODE);
/* Alter outstanding transactions property of A55*/
writel(0x1, 0x30643108); /* SCB6 A55 M0 Ib.fn Mod */
isb();
/* configure DDR prefetch behavior, per ADI */
writel(0x1, 0x31076000);
/* configure smart mode, per ADI */
writel(0x1307, 0x31076004);
// Disable SPU and SPU WP registers
sc5xx_disable_spu0(REG_SPU0_SECUREP_START, REG_SPU0_SECUREP_START + 4*213);
sc5xx_disable_spu0(REG_SPU0_WP_START, REG_SPU0_WP_START + 4*213);
/* configure smpus permissively */
for (i = 0; i < ARRAY_SIZE(smpus); ++i)
writel(0x500, smpus[i]);
sc5xx_enable_ns_sharc_access(REG_SPU0_SECUREC0);
}