Commit d8e919c7 authored by Masahiro Yamada's avatar Masahiro Yamada
Browse files

uniphier: support Socionext UniPhier platform



Initial commit for Socionext UniPhier SoC support.  BL1, Bl2, and
BL31 are supported.  Refer to docs/plat/socionext-uniphier.md for
more detais.
Signed-off-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent c396b736
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <utils_def.h>
#include "uniphier.h"
#define UNIPHIER_ROM_RSV3 0x5980120c
#define UNIPHIER_STMBE2COM 0x5f800030
#define UNIPHIER_BETOSTMIRQ0PT 0x5f800070
#define UNIPHIER_SCP_READY_MAGIC 0x0000b6a5
#define UNIPHIER_SCP_PACKET_START 0xA0
#define UNIPHIER_SCP_PACKET_END 0xA5
#define UNIPHIER_SCP_PACKET_ESC 0xA6
#define UNIPHIER_SCP_IS_CTRL_CODE(c) (0xA0 <= (c) && (c) <= 0xA6)
int uniphier_scp_is_running(void)
{
return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
}
void uniphier_scp_start(void)
{
uint32_t tmp;
mmio_write_32(UNIPHIER_STMBE2COM + 4, UNIPHIER_SCP_BASE);
mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC);
do {
tmp = mmio_read_32(UNIPHIER_ROM_RSV3);
} while (!(tmp & BIT(8)));
mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9));
}
static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len)
{
uintptr_t reg = UNIPHIER_STMBE2COM;
uint32_t word;
int len, i;
while (packet_len) {
len = MIN(packet_len, 4);
word = 0;
for (i = 0; i < len; i++)
word |= *packet++ << (8 * i);
mmio_write_32(reg, word);
reg += 4;
packet_len -= len;
}
mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55);
}
static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len)
{
uint8_t packet[32]; /* long enough */
uint8_t *p = packet;
uint8_t c;
int i;
*p++ = UNIPHIER_SCP_PACKET_START;
*p++ = cmd_len;
for (i = 0; i < cmd_len; i++) {
c = *cmd++;
if (UNIPHIER_SCP_IS_CTRL_CODE(c)) {
*p++ = UNIPHIER_SCP_PACKET_ESC;
*p++ = c ^ BIT(7);
} else {
*p++ = c;
}
}
*p++ = UNIPHIER_SCP_PACKET_END;
uniphier_scp_send_packet(packet, p - packet);
}
#define UNIPHIER_SCP_CMD(name, ...) \
static const uint8_t __uniphier_scp_##name##_cmd[] = { \
__VA_ARGS__ \
}; \
void uniphier_scp_##name(void) \
{ \
uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \
ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \
}
UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
.globl uniphier_warmboot_entrypoint
.globl uniphier_fake_pwr_down
func uniphier_warmboot_entrypoint
mrs x0, mpidr_el1
mov_imm x1, MPIDR_AFFINITY_MASK
and x0, x0, x1
b 1f
0: wfe
1: ldr x1, uniphier_holding_pen_release
cmp x1, x0
b.ne 0b
ldr x0, uniphier_sec_entrypoint
br x0
endfunc uniphier_warmboot_entrypoint
func uniphier_fake_pwr_down
bl disable_mmu_icache_el3
b uniphier_warmboot_entrypoint
endfunc uniphier_fake_pwr_down
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include "uniphier.h"
#define UNIPHIER_REVISION 0x5f800000
static unsigned int uniphier_get_revision_field(unsigned int mask,
unsigned int shift)
{
uint32_t revision = mmio_read_32(UNIPHIER_REVISION);
return (revision >> shift) & mask;
}
unsigned int uniphier_get_soc_type(void)
{
return uniphier_get_revision_field(0xff, 16);
}
unsigned int uniphier_get_soc_model(void)
{
return uniphier_get_revision_field(0x07, 8);
}
unsigned int uniphier_get_soc_revision(void)
{
return uniphier_get_revision_field(0x1f, 0);
}
unsigned int uniphier_get_soc_id(void)
{
uint32_t type = uniphier_get_soc_type();
switch (type) {
case 0x31:
return UNIPHIER_SOC_LD11;
case 0x32:
return UNIPHIER_SOC_LD20;
case 0x35:
return UNIPHIER_SOC_PXS3;
default:
return UNIPHIER_SOC_UNKNOWN;
}
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform.h>
unsigned int plat_get_syscnt_freq2(void)
{
return 50000000;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform.h>
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
unsigned int *flags)
{
*flags = ROTPK_NOT_DEPLOYED;
return 0;
}
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
{
/*
* No support for non-volatile counter. Update the ROT key to protect
* the system against rollback.
*/
*nv_ctr = 0;
return 0;
}
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
{
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <platform.h>
#include "uniphier.h"
static unsigned char uniphier_power_domain_tree_desc[UNIPHIER_CLUSTER_COUNT + 1];
const unsigned char *plat_get_power_domain_tree_desc(void)
{
int i;
uniphier_power_domain_tree_desc[0] = UNIPHIER_CLUSTER_COUNT;
for (i = 0; i < UNIPHIER_CLUSTER_COUNT; i++)
uniphier_power_domain_tree_desc[i + 1] =
UNIPHIER_MAX_CPUS_PER_CLUSTER;
return uniphier_power_domain_tree_desc;
}
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int cluster_id, cpu_id;
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
if (cluster_id >= UNIPHIER_CLUSTER_COUNT)
return -1;
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
if (cpu_id >= UNIPHIER_MAX_CPUS_PER_CLUSTER)
return -1;
return uniphier_calc_core_pos(mpidr);
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <io/io_block.h>
#include <mmio.h>
#include <platform_def.h>
#include <sys/types.h>
#include <utils_def.h>
#include "uniphier.h"
#define UNIPHIER_LD11_USB_DESC_BASE 0x30010000
#define UNIPHIER_LD20_USB_DESC_BASE 0x30014000
#define UNIPHIER_SRB_OCM_CONT 0x61200000
struct uniphier_ld11_trans_op {
uint8_t __pad[48];
};
struct uniphier_ld11_op {
uint8_t __pad[56];
struct uniphier_ld11_trans_op *trans_op;
void *__pad2;
void *dev_desc;
};
struct uniphier_ld20_trans_op {
uint8_t __pad[40];
};
struct uniphier_ld20_op {
uint8_t __pad[192];
struct uniphier_ld20_trans_op *trans_op;
void *__pad2;
void *dev_desc;
};
static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size);
static void uniphier_ld11_usb_init(void)
{
struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE;
op->trans_op = (void *)(op + 1);
op->dev_desc = op->trans_op + 1;
}
static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size)
{
static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
unsigned int size, uintptr_t buf);
uintptr_t func_addr;
func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958;
rom_usb_read = (__typeof(rom_usb_read))func_addr;
return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf);
}
static void uniphier_ld20_usb_init(void)
{
struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE;
op->trans_op = (void *)(op + 1);
op->dev_desc = op->trans_op + 1;
}
static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size)
{
static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
unsigned int size, uintptr_t buf);
int ret;
rom_usb_read = (__typeof(rom_usb_read))0x37f0;
mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff);
/* ROM-API - return 1 on success, 0 on error */
ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf);
mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0);
return ret ? 0 : -1;
}
static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size)
{
static int (*rom_usb_read)(unsigned int lba, unsigned int size,
uintptr_t buf);
rom_usb_read = (__typeof(rom_usb_read))0x100c;
return rom_usb_read(lba, size, buf);
}
struct uniphier_usb_rom_param {
void (*init)(void);
int (*read)(int lba, uintptr_t buf, size_t size);
};
static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = {
[UNIPHIER_SOC_LD11] = {
.init = uniphier_ld11_usb_init,
.read = uniphier_ld11_usb_read,
},
[UNIPHIER_SOC_LD20] = {
.init = uniphier_ld20_usb_init,
.read = uniphier_ld20_usb_read,
},
[UNIPHIER_SOC_PXS3] = {
.read = uniphier_pxs3_usb_read,
},
};
static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size)
{
int ret;
inv_dcache_range(buf, size);
ret = __uniphier_usb_read(lba, buf, size);
inv_dcache_range(buf, size);
return ret ? 0 : size;
}
static struct io_block_dev_spec uniphier_usb_dev_spec = {
.buffer = {
.offset = UNIPHIER_BLOCK_BUF_BASE,
.length = UNIPHIER_BLOCK_BUF_SIZE,
},
.ops = {
.read = uniphier_usb_read,
},
.block_size = 512,
};
int uniphier_usb_init(unsigned int soc, uintptr_t *block_dev_spec)
{
const struct uniphier_usb_rom_param *param;
assert(soc < ARRAY_SIZE(uniphier_usb_rom_params));
param = &uniphier_usb_rom_params[soc];
if (param->init)
param->init();
__uniphier_usb_read = param->read;
*block_dev_spec = (uintptr_t)&uniphier_usb_dev_spec;
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <platform_def.h>
#include <xlat_tables_v2.h>
#define UNIPHIER_OCM_REGION_BASE 0x30000000
#define UNIPHIER_OCM_REGION_SIZE 0x00040000
#define UNIPHIER_REG_REGION_BASE 0x50000000
#define UNIPHIER_REG_REGION_SIZE 0x20000000
void uniphier_mmap_setup(uintptr_t total_base, size_t total_size,
const struct mmap_region *mmap)
{
VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
(void *)total_base, (void *)(total_base + total_size));
mmap_add_region(total_base, total_base,
total_size,
MT_MEMORY | MT_RW | MT_SECURE);
/* remap the code section */
VERBOSE("Code region: %p - %p\n",
(void *)BL_CODE_BASE, (void *)BL_CODE_END);
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE,
MT_CODE | MT_SECURE);
/* remap the coherent memory region */
VERBOSE("Coherent region: %p - %p\n",
(void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END);
mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
MT_DEVICE | MT_RW | MT_SECURE);
/*
* on-chip SRAM region: should be DEVICE attribute because the USB
* load functions provided by the ROM use this memory region as a work
* area, but do not cater to cache coherency.
*/
mmap_add_region(UNIPHIER_OCM_REGION_BASE, UNIPHIER_OCM_REGION_BASE,
UNIPHIER_OCM_REGION_SIZE,
MT_DEVICE | MT_RW | MT_SECURE);
/* register region */
mmap_add_region(UNIPHIER_REG_REGION_BASE, UNIPHIER_REG_REGION_BASE,
UNIPHIER_REG_REGION_SIZE,
MT_DEVICE | MT_RW | MT_SECURE);
/* additional regions if needed */
if (mmap)
mmap_add(mmap);
init_xlat_tables();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment