Merge changes I23f600b5,Icf9ffdf2,Iee7a51d1,I99afc312,I4bf8e8c0, ... into integration
* changes: plat/marvell/armada: cleanup MSS SRAM if used for copy plat/marvell: cn913x: allow CP1/CP2 mapping at BLE stage plat/marvell/armada/common/mss: use MSS SRAM in secure mode include/drivers/marvell/mochi: add detection of secure mode plat/marvell: fix SPD handling in dram port marvell: drivers: move XOR0/1 DIOB from WIN 0 to 1 drivers/marvell/mochi: add support for cn913x in PCIe EP mode drivers/marvell/mochi: add missing stream IDs configurations plat/marvell/armada/a8k: support HW RNG by SMC drivers/rambus: add TRNG-IP-76 driver
This commit is contained in:
commit
8909fa9bbf
|
@ -44,6 +44,10 @@
|
|||
#define IOB_WIN_ALR_OFFSET(win) (iob_base + 0x8 + (0x20 * win))
|
||||
#define IOB_WIN_AHR_OFFSET(win) (iob_base + 0xC + (0x20 * win))
|
||||
|
||||
#define IOB_WIN_DIOB_CR_OFFSET(win) (iob_base + 0x10 + (0x20 * win))
|
||||
#define IOB_WIN_XOR0_DIOB_EN BIT(0)
|
||||
#define IOB_WIN_XOR1_DIOB_EN BIT(1)
|
||||
|
||||
uintptr_t iob_base;
|
||||
|
||||
static void iob_win_check(struct addr_map_win *win, uint32_t win_num)
|
||||
|
@ -71,6 +75,17 @@ static void iob_enable_win(struct addr_map_win *win, uint32_t win_id)
|
|||
uint32_t iob_win_reg;
|
||||
uint32_t alr, ahr;
|
||||
uint64_t end_addr;
|
||||
uint32_t reg_en;
|
||||
|
||||
/* move XOR (DMA) to use WIN1 which is used for PCI-EP address space */
|
||||
reg_en = IOB_WIN_XOR0_DIOB_EN | IOB_WIN_XOR1_DIOB_EN;
|
||||
iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(0));
|
||||
iob_win_reg &= ~reg_en;
|
||||
mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(0), iob_win_reg);
|
||||
|
||||
iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(1));
|
||||
iob_win_reg |= reg_en;
|
||||
mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(1), iob_win_reg);
|
||||
|
||||
end_addr = (win->base_addr + win->win_size - 1);
|
||||
alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#include <drivers/marvell/mci.h>
|
||||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include <mvebu_def.h>
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10)
|
||||
#define SMMU_sACR_PG_64K (1 << 16)
|
||||
|
@ -71,6 +72,23 @@
|
|||
#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \
|
||||
0x4 * index)
|
||||
|
||||
#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000)
|
||||
#define XOR_STREAM_ID_MASK 0xFFFF
|
||||
#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600)
|
||||
#define SDIO_STREAM_ID_MASK 0xFF
|
||||
|
||||
/* Do not use the default Stream ID 0 */
|
||||
#define A807_STREAM_ID_BASE (0x1)
|
||||
|
||||
static uintptr_t stream_id_reg[] = {
|
||||
XOR_STREAM_ID_REG(0),
|
||||
XOR_STREAM_ID_REG(1),
|
||||
XOR_STREAM_ID_REG(2),
|
||||
XOR_STREAM_ID_REG(3),
|
||||
SDIO_STREAM_ID_REG,
|
||||
0
|
||||
};
|
||||
|
||||
enum axi_attr {
|
||||
AXI_SDIO_ATTR = 0,
|
||||
AXI_DFX_ATTR,
|
||||
|
@ -162,6 +180,21 @@ static void mci_remap_indirect_access_base(void)
|
|||
MCI_REMAP_OFF_SHIFT);
|
||||
}
|
||||
|
||||
/* Set a unique stream id for all DMA capable devices */
|
||||
static void ap807_stream_id_init(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0;
|
||||
stream_id_reg[i] != 0 && i < ARRAY_SIZE(stream_id_reg); i++) {
|
||||
uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ?
|
||||
SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK;
|
||||
|
||||
mmio_clrsetbits_32(stream_id_reg[i], mask,
|
||||
i + A807_STREAM_ID_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ap807_axi_attr_init(void)
|
||||
{
|
||||
uint32_t index, data;
|
||||
|
@ -265,6 +298,9 @@ void ap_init(void)
|
|||
/* configure CCU windows */
|
||||
init_ccu(MVEBU_AP0);
|
||||
|
||||
/* Set the stream IDs for DMA masters */
|
||||
ap807_stream_id_init();
|
||||
|
||||
/* configure the SMMU */
|
||||
setup_smmu();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mvebu_def.h>
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10)
|
||||
#define SMMU_sACR_PG_64K (1 << 16)
|
||||
|
@ -67,6 +67,23 @@
|
|||
#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \
|
||||
0x4 * index)
|
||||
|
||||
#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000)
|
||||
#define XOR_STREAM_ID_MASK 0xFFFF
|
||||
#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600)
|
||||
#define SDIO_STREAM_ID_MASK 0xFF
|
||||
|
||||
/* Do not use the default Stream ID 0 */
|
||||
#define A806_STREAM_ID_BASE (0x1)
|
||||
|
||||
static uintptr_t stream_id_reg[] = {
|
||||
XOR_STREAM_ID_REG(0),
|
||||
XOR_STREAM_ID_REG(1),
|
||||
XOR_STREAM_ID_REG(2),
|
||||
XOR_STREAM_ID_REG(3),
|
||||
SDIO_STREAM_ID_REG,
|
||||
0
|
||||
};
|
||||
|
||||
enum axi_attr {
|
||||
AXI_SDIO_ATTR = 0,
|
||||
AXI_DFX_ATTR,
|
||||
|
@ -158,6 +175,20 @@ static void mci_remap_indirect_access_base(void)
|
|||
MCI_REMAP_OFF_SHIFT);
|
||||
}
|
||||
|
||||
/* Set a unique stream id for all DMA capable devices */
|
||||
static void ap806_stream_id_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; stream_id_reg[i] != 0; i++) {
|
||||
uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ?
|
||||
SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK;
|
||||
|
||||
mmio_clrsetbits_32(stream_id_reg[i], mask,
|
||||
i + A806_STREAM_ID_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
static void apn806_axi_attr_init(void)
|
||||
{
|
||||
uint32_t index, data;
|
||||
|
@ -236,6 +267,9 @@ void ap_init(void)
|
|||
/* configure DSS */
|
||||
dss_setup();
|
||||
|
||||
/* Set the stream IDs for DMA masters */
|
||||
ap806_stream_id_init();
|
||||
|
||||
/* configure the SMMU */
|
||||
setup_smmu();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <drivers/marvell/amb_adec.h>
|
||||
#include <drivers/marvell/iob.h>
|
||||
#include <drivers/marvell/mochi/cp110_setup.h>
|
||||
#include <drivers/rambus/trng_ip_76.h>
|
||||
|
||||
#include <plat_marvell.h>
|
||||
|
||||
|
@ -105,6 +106,11 @@
|
|||
#define MVEBU_RTC_READ_OUTPUT_DELAY_MASK 0xFFFF
|
||||
#define MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT 0x1F
|
||||
|
||||
/*******************************************************************************
|
||||
* TRNG Configuration
|
||||
******************************************************************************/
|
||||
#define MVEBU_TRNG_BASE (0x760000)
|
||||
|
||||
enum axi_attr {
|
||||
AXI_ADUNIT_ATTR = 0,
|
||||
AXI_COMUNIT_ATTR,
|
||||
|
@ -130,7 +136,7 @@ enum axi_attr {
|
|||
#define USB3H_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x10)
|
||||
#define SATA_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x14)
|
||||
#define SATA_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x18)
|
||||
#define SDIO_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x28)
|
||||
#define SDIO_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x28)
|
||||
|
||||
#define CP_DMA_0_STREAM_ID_REG (0x6B0010)
|
||||
#define CP_DMA_1_STREAM_ID_REG (0x6D0010)
|
||||
|
@ -138,14 +144,14 @@ enum axi_attr {
|
|||
/* We allocate IDs 128-255 for PCIe */
|
||||
#define MAX_STREAM_ID (0x80)
|
||||
|
||||
uintptr_t stream_id_reg[] = {
|
||||
static uintptr_t stream_id_reg[] = {
|
||||
USB3H_0_STREAM_ID_REG,
|
||||
USB3H_1_STREAM_ID_REG,
|
||||
CP_DMA_0_STREAM_ID_REG,
|
||||
CP_DMA_1_STREAM_ID_REG,
|
||||
SATA_0_STREAM_ID_REG,
|
||||
SATA_1_STREAM_ID_REG,
|
||||
SDIO_0_STREAM_ID_REG,
|
||||
SDIO_STREAM_ID_REG,
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -180,8 +186,9 @@ static void cp110_pcie_clk_cfg(uintptr_t base)
|
|||
pcie0_clk = (reg & SAR_PCIE0_CLK_CFG_MASK) >> SAR_PCIE0_CLK_CFG_OFFSET;
|
||||
pcie1_clk = (reg & SAR_PCIE1_CLK_CFG_MASK) >> SAR_PCIE1_CLK_CFG_OFFSET;
|
||||
|
||||
/* CP110 revision A2 */
|
||||
if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2) {
|
||||
/* CP110 revision A2 or CN913x */
|
||||
if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2 ||
|
||||
cp110_device_id_get(base) == MVEBU_CN9130_DEV_ID) {
|
||||
/*
|
||||
* PCIe Reference Clock Buffer Control register must be
|
||||
* set according to the clock direction (input/output)
|
||||
|
@ -378,6 +385,20 @@ static void cp110_amb_adec_init(uintptr_t base)
|
|||
init_amb_adec(base);
|
||||
}
|
||||
|
||||
static void cp110_trng_init(uintptr_t base)
|
||||
{
|
||||
static bool done;
|
||||
int ret;
|
||||
|
||||
if (!done) {
|
||||
ret = eip76_rng_probe(base + MVEBU_TRNG_BASE);
|
||||
if (ret != 0) {
|
||||
ERROR("Failed to init TRNG @ 0x%lx\n", base);
|
||||
return;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
void cp110_init(uintptr_t cp110_base, uint32_t stream_id)
|
||||
{
|
||||
INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base);
|
||||
|
@ -405,6 +426,9 @@ void cp110_init(uintptr_t cp110_base, uint32_t stream_id)
|
|||
|
||||
/* Reset RTC if needed */
|
||||
cp110_rtc_init(cp110_base);
|
||||
|
||||
/* TRNG init - for CP0 only */
|
||||
cp110_trng_init(cp110_base);
|
||||
}
|
||||
|
||||
/* Do the minimal setup required to configure the CP in BLE */
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved.
|
||||
*
|
||||
* Based on Linux kernel omap-rng.c - RNG driver for TI OMAP CPU family
|
||||
*
|
||||
* Author: Deepak Saxena <dsaxena@plexity.net>
|
||||
*
|
||||
* Copyright 2005 (c) MontaVista Software, Inc.
|
||||
*
|
||||
* Mostly based on original driver:
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation
|
||||
* Author: Juha Yrjölä <juha.yrjola@nokia.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/rambus/trng_ip_76.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/spinlock.h>
|
||||
#include <lib/utils.h>
|
||||
|
||||
#define RNG_REG_STATUS_RDY (1 << 0)
|
||||
|
||||
#define RNG_REG_INTACK_RDY_MASK (1 << 0)
|
||||
|
||||
#define RNG_CONTROL_ENABLE_TRNG_MASK (1 << 10)
|
||||
|
||||
#define RNG_CONFIG_NOISE_BLOCKS(val) ((0xff & (val)) << 0)
|
||||
#define RNG_CONFIG_NOISE_BLK_VAL 0x5
|
||||
|
||||
#define RNG_CONFIG_SAMPLE_CYCLES(val) ((0xff & (val)) << 16)
|
||||
#define RNG_CONFIG_SAMPLE_CYCLES_VAL 0x22
|
||||
|
||||
#define RNG_REG_FRO_ENABLE_MASK 0xffffff
|
||||
#define RNG_REG_FRO_DETUNE_MASK 0x0
|
||||
|
||||
#define EIP76_RNG_OUTPUT_SIZE 0x10
|
||||
#define EIP76_RNG_WAIT_ROUNDS 10
|
||||
|
||||
#define RNG_HW_IS_EIP76(ver) ((ver) & (0xff == 0x4C))
|
||||
#define RNG_HW_VER_MAJOR(ver) (((ver) & (0xf << 24)) >> 24)
|
||||
#define RNG_HW_VER_MINOR(ver) (((ver) & (0xf << 20)) >> 20)
|
||||
#define RNG_HW_VER_PATCH(ver) (((ver) & (0xf << 16)) >> 16)
|
||||
|
||||
|
||||
enum {
|
||||
RNG_OUTPUT_0_REG = 0,
|
||||
RNG_OUTPUT_1_REG,
|
||||
RNG_OUTPUT_2_REG,
|
||||
RNG_OUTPUT_3_REG,
|
||||
RNG_STATUS_REG,
|
||||
RNG_INTMASK_REG,
|
||||
RNG_INTACK_REG,
|
||||
RNG_CONTROL_REG,
|
||||
RNG_CONFIG_REG,
|
||||
RNG_ALARMCNT_REG,
|
||||
RNG_FROENABLE_REG,
|
||||
RNG_FRODETUNE_REG,
|
||||
RNG_ALARMMASK_REG,
|
||||
RNG_ALARMSTOP_REG,
|
||||
RNG_REV_REG
|
||||
};
|
||||
|
||||
static uint16_t reg_map_eip76[] = {
|
||||
[RNG_OUTPUT_0_REG] = 0x0,
|
||||
[RNG_OUTPUT_1_REG] = 0x4,
|
||||
[RNG_OUTPUT_2_REG] = 0x8,
|
||||
[RNG_OUTPUT_3_REG] = 0xc,
|
||||
[RNG_STATUS_REG] = 0x10,
|
||||
[RNG_INTACK_REG] = 0x10,
|
||||
[RNG_CONTROL_REG] = 0x14,
|
||||
[RNG_CONFIG_REG] = 0x18,
|
||||
[RNG_ALARMCNT_REG] = 0x1c,
|
||||
[RNG_FROENABLE_REG] = 0x20,
|
||||
[RNG_FRODETUNE_REG] = 0x24,
|
||||
[RNG_ALARMMASK_REG] = 0x28,
|
||||
[RNG_ALARMSTOP_REG] = 0x2c,
|
||||
[RNG_REV_REG] = 0x7c,
|
||||
};
|
||||
|
||||
struct eip76_rng_dev {
|
||||
uintptr_t base;
|
||||
uint16_t *regs;
|
||||
};
|
||||
|
||||
/* Locals */
|
||||
static struct eip76_rng_dev eip76_dev;
|
||||
static spinlock_t rng_lock;
|
||||
|
||||
static inline uint32_t eip76_rng_read(struct eip76_rng_dev *dev, uint16_t reg)
|
||||
{
|
||||
return mmio_read_32(dev->base + dev->regs[reg]);
|
||||
}
|
||||
|
||||
static inline void eip76_rng_write(struct eip76_rng_dev *dev,
|
||||
uint16_t reg, uint32_t val)
|
||||
{
|
||||
mmio_write_32(dev->base + dev->regs[reg], val);
|
||||
}
|
||||
|
||||
static void eip76_rng_init(struct eip76_rng_dev *dev)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* Return if RNG is already running. */
|
||||
if (eip76_rng_read(dev, RNG_CONTROL_REG) &
|
||||
RNG_CONTROL_ENABLE_TRNG_MASK) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This field sets the number of 512-bit blocks of raw Noise Source
|
||||
* output data that must be processed by either the Conditioning
|
||||
* Function or the SP 800-90 DRBG ‘BC_DF’ functionality to yield
|
||||
* a ‘full entropy’ output value. As according to [SP 800-90B draft]
|
||||
* the amount of entropy input to this functionality must be twice
|
||||
* the amount that is output and the 8-bit samples output by the Noise
|
||||
* Source are supposed to have one bit of entropy each, the settings
|
||||
* for this field are as follows:
|
||||
* - SHA-1 Conditioning Function:
|
||||
* generates 160 bits output, requiring 2560 sample bits,
|
||||
* equivalent to 5 blocks of raw Noise Source input.
|
||||
* - SHA-256 Conditioning Function:
|
||||
* generates 256 bits output, requiring 4096 sample bits, equivalent
|
||||
* to 8 blocks of raw Noise Source input. Note that two blocks of 256
|
||||
* bits are needed to start or re-seed the SP 800-90 DRBG
|
||||
* (in the EIP-76d-*-SHA2 configurations)
|
||||
* - SP 800-90 DRBG ‘BC_DF’ functionality:
|
||||
* generates 384 bits output, requiring 6144 sample bits, equivalent
|
||||
* to 12 blocks of raw Noise Source input.
|
||||
* This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
|
||||
* is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
|
||||
* bits in TRNG_TEST is ‘1’. Value 0 in this field selects 256 blocks
|
||||
* of 512 bits to be processed.
|
||||
*/
|
||||
val = RNG_CONFIG_NOISE_BLOCKS(RNG_CONFIG_NOISE_BLK_VAL);
|
||||
|
||||
/* This field sets the number of FRO samples that are XOR-ed together
|
||||
* into one bit to be shifted into the main shift register.
|
||||
* This value must be such that there is at least one bit of entropy
|
||||
* (in total) in each 8 bits that are shifted.
|
||||
* This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
|
||||
* is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
|
||||
* bits in TRNG_TEST is ‘1’. Value 0 in this field selects 65536 FRO
|
||||
* samples to be XOR-ed together
|
||||
*/
|
||||
val |= RNG_CONFIG_SAMPLE_CYCLES(RNG_CONFIG_SAMPLE_CYCLES_VAL);
|
||||
eip76_rng_write(dev, RNG_CONFIG_REG, val);
|
||||
|
||||
/* Enable all available FROs */
|
||||
eip76_rng_write(dev, RNG_FRODETUNE_REG, RNG_REG_FRO_DETUNE_MASK);
|
||||
eip76_rng_write(dev, RNG_FROENABLE_REG, RNG_REG_FRO_ENABLE_MASK);
|
||||
|
||||
/* Enable TRNG */
|
||||
eip76_rng_write(dev, RNG_CONTROL_REG, RNG_CONTROL_ENABLE_TRNG_MASK);
|
||||
}
|
||||
|
||||
int32_t eip76_rng_read_rand_buf(void *data, bool wait)
|
||||
{
|
||||
uint32_t i, present;
|
||||
|
||||
if (!eip76_dev.base) /* not initialized */
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < EIP76_RNG_WAIT_ROUNDS; i++) {
|
||||
present = eip76_rng_read(&eip76_dev, RNG_STATUS_REG) &
|
||||
RNG_REG_STATUS_RDY;
|
||||
if (present || !wait) {
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (present != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data,
|
||||
(void *)(eip76_dev.base + eip76_dev.regs[RNG_OUTPUT_0_REG]),
|
||||
EIP76_RNG_OUTPUT_SIZE);
|
||||
|
||||
eip76_rng_write(&eip76_dev, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
|
||||
|
||||
return EIP76_RNG_OUTPUT_SIZE;
|
||||
}
|
||||
|
||||
int32_t eip76_rng_probe(uintptr_t base_addr)
|
||||
{
|
||||
uint32_t ver;
|
||||
|
||||
eip76_dev.base = base_addr;
|
||||
eip76_dev.regs = reg_map_eip76;
|
||||
|
||||
eip76_rng_init(&eip76_dev);
|
||||
|
||||
ver = eip76_rng_read(&eip76_dev, RNG_REV_REG);
|
||||
|
||||
INFO("%s Random Number Generator HW ver. %01x.%01x.%01x\n",
|
||||
RNG_HW_IS_EIP76(ver) ? "TRNG-IP-76" : "Unknown",
|
||||
RNG_HW_VER_MAJOR(ver), RNG_HW_VER_MINOR(ver),
|
||||
RNG_HW_VER_PATCH(ver));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t eip76_rng_get_random(uint8_t *data, uint32_t len)
|
||||
{
|
||||
static uint8_t rand[EIP76_RNG_OUTPUT_SIZE];
|
||||
static uint8_t pos;
|
||||
uint32_t i;
|
||||
int32_t ret = 0;
|
||||
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
spin_lock(&rng_lock);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (pos >= EIP76_RNG_OUTPUT_SIZE) {
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
if (pos != 0U) {
|
||||
ret = eip76_rng_read_rand_buf(rand, true);
|
||||
}
|
||||
|
||||
/* Only advance FIFO index if it is non zero or
|
||||
* the update from TRNG HW was successful
|
||||
*/
|
||||
if (pos || ret > 0) {
|
||||
data[i] = rand[pos++];
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&rng_lock);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -31,6 +31,9 @@
|
|||
#define MAX_STREAM_ID_PER_CP (0x10)
|
||||
#define STREAM_ID_BASE (0x40)
|
||||
|
||||
#define MVEBU_SECUREBOOT_CTRL_REG (MVEBU_RFU_BASE + 0x4730)
|
||||
#define MVEBU_SECUREBOOT_EN_MASK BIT(0)
|
||||
|
||||
static inline uint32_t cp110_device_id_get(uintptr_t base)
|
||||
{
|
||||
/* Returns:
|
||||
|
@ -50,6 +53,12 @@ static inline uint32_t cp110_rev_id_get(uintptr_t base)
|
|||
MVEBU_DEVICE_REV_OFFSET;
|
||||
}
|
||||
|
||||
static inline uint32_t is_secure(void)
|
||||
{
|
||||
return !!(mmio_read_32(MVEBU_SECUREBOOT_CTRL_REG) &
|
||||
MVEBU_SECUREBOOT_EN_MASK);
|
||||
}
|
||||
|
||||
void cp110_init(uintptr_t cp110_base, uint32_t stream_id);
|
||||
void cp110_ble_init(uintptr_t cp110_base);
|
||||
void cp110_amb_init(uintptr_t base);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TRNG_IP_76_H__
|
||||
#define __TRNG_IP_76_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t eip76_rng_read_rand_buf(void *data, bool wait);
|
||||
int32_t eip76_rng_probe(uintptr_t base_addr);
|
||||
int32_t eip76_rng_get_random(uint8_t *data, uint32_t len);
|
||||
|
||||
#endif /* __TRNG_IP_76_H__ */
|
|
@ -138,7 +138,7 @@ void plat_marvell_dram_update_topology(void)
|
|||
i2c_init((void *)MVEBU_CP0_I2C_BASE);
|
||||
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
|
|
|
@ -123,7 +123,7 @@ void plat_marvell_dram_update_topology(void)
|
|||
/* initialize the i2c */
|
||||
i2c_init((void *)MVEBU_CP0_I2C_BASE);
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
sizeof(tm->spd_data.all_bytes));
|
||||
|
|
|
@ -132,7 +132,7 @@ void plat_marvell_dram_update_topology(void)
|
|||
/* initialize the MVEBU_AP_I2C_BASE I2C bus */
|
||||
i2c_init((void *)MVEBU_AP_I2C_BASE);
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
sizeof(tm->spd_data.all_bytes));
|
||||
|
|
|
@ -114,7 +114,8 @@ MARVELL_DRV := $(MARVELL_DRV_BASE)/io_win.c \
|
|||
$(MARVELL_DRV_BASE)/cache_llc.c \
|
||||
$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
|
||||
$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
|
||||
$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
|
||||
$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c \
|
||||
drivers/rambus/trng_ip_76.c
|
||||
|
||||
BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ PLAT_MARVELL = plat/marvell/armada
|
|||
BLE_SOURCES += $(BLE_PATH)/ble_main.c \
|
||||
$(BLE_PATH)/ble_mem.S \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/marvell/iob.c \
|
||||
$(PLAT_MARVELL)/common/aarch64/marvell_helpers.S \
|
||||
$(PLAT_MARVELL)/common/plat_delay_timer.c \
|
||||
$(PLAT_MARVELL)/common/marvell_console.c
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
|
||||
#define MSS_INTERNAL_ACCESS_BIT 28
|
||||
|
||||
#define MSS_AP_REGS_OFFSET 0x580000
|
||||
#define MSS_CP_SRAM_OFFSET 0x220000
|
||||
#define MSS_CP_REGS_OFFSET 0x280000
|
||||
|
||||
struct addr_map_win ccu_mem_map[] = {
|
||||
{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
|
||||
};
|
||||
|
@ -121,12 +125,21 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
|||
|
||||
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
|
||||
{
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + 0x280000;
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
|
||||
{
|
||||
if (is_secure()) {
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
|
||||
}
|
||||
|
||||
return 0; /* SRAM will not be used */
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
|
||||
{
|
||||
return MVEBU_REGS_BASE + 0x580000;
|
||||
return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
uint32_t bl2_plat_get_cp_count(int ap_idx)
|
||||
|
|
|
@ -720,7 +720,7 @@ static int ble_skip_current_image(void)
|
|||
|
||||
int ble_plat_setup(int *skip)
|
||||
{
|
||||
int ret;
|
||||
int ret, cp;
|
||||
unsigned int freq_mode;
|
||||
|
||||
/* Power down unused CPUs */
|
||||
|
@ -745,6 +745,10 @@ int ble_plat_setup(int *skip)
|
|||
/* Do required CP-110 setups for BLE stage */
|
||||
cp110_ble_init(MVEBU_CP_REGS_BASE(0));
|
||||
|
||||
/* Config address for each cp other than cp0 */
|
||||
for (cp = 1; cp < CP_COUNT; cp++)
|
||||
update_cp110_default_win(cp);
|
||||
|
||||
/* Setup AVS */
|
||||
ble_plat_svc_config();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <common/runtime_svc.h>
|
||||
#include <drivers/marvell/cache_llc.h>
|
||||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <drivers/rambus/trng_ip_76.h>
|
||||
#include <lib/smccc.h>
|
||||
|
||||
#include <marvell_plat_priv.h>
|
||||
|
@ -37,6 +38,9 @@
|
|||
#define MV_SIP_PMU_IRQ_ENABLE 0x82000012
|
||||
#define MV_SIP_PMU_IRQ_DISABLE 0x82000013
|
||||
|
||||
/* TRNG */
|
||||
#define MV_SIP_RNG_64 0xC200FF11
|
||||
|
||||
#define MAX_LANE_NR 6
|
||||
#define MVEBU_COMPHY_OFFSET 0x441000
|
||||
#define MVEBU_CP_BASE_MASK (~0xffffff)
|
||||
|
@ -68,6 +72,7 @@ uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
|
|||
u_register_t flags)
|
||||
{
|
||||
u_register_t ret;
|
||||
uint32_t w2[2] = {0, 0};
|
||||
int i;
|
||||
|
||||
debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n",
|
||||
|
@ -131,7 +136,9 @@ uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
|
|||
mvebu_pmu_interrupt_disable();
|
||||
SMC_RET1(handle, 0);
|
||||
#endif
|
||||
|
||||
case MV_SIP_RNG_64:
|
||||
ret = eip76_rng_get_random((uint8_t *)&w2, 4 * (x1 % 2 + 1));
|
||||
SMC_RET3(handle, ret, w2[0], w2[1]);
|
||||
default:
|
||||
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define HEADER_VERSION 0x1
|
||||
|
||||
#define MSS_IDRAM_SIZE 0x10000 /* 64KB */
|
||||
#define MSS_SRAM_SIZE 0x8000 /* 32KB */
|
||||
|
||||
/* Types definitions */
|
||||
typedef struct file_header {
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#define MSS_DMA_TIMEOUT 1000
|
||||
#define MSS_EXTERNAL_SPACE 0x50000000
|
||||
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
|
||||
#define MSS_INTERNAL_SPACE 0x40000000
|
||||
#define MSS_INTERNAL_ADDR_MASK 0x00ffffff
|
||||
|
||||
#define DMA_SIZE 128
|
||||
|
||||
|
@ -60,60 +62,113 @@ static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
|
||||
static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
|
||||
uintptr_t mss_regs)
|
||||
{
|
||||
uint32_t i, loop_num, timeout;
|
||||
|
||||
/* load image to MSS RAM using DMA */
|
||||
loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
|
||||
for (i = 0; i < loop_num; i++) {
|
||||
/* write source address */
|
||||
mmio_write_32(MSS_DMA_SRCBR(mss_regs),
|
||||
src_addr + (i * DMA_SIZE));
|
||||
/* write destination address */
|
||||
mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
|
||||
/* make sure DMA data is ready before triggering it */
|
||||
dsb();
|
||||
/* set the DMA control register */
|
||||
mmio_write_32(MSS_DMA_CTRLR(mss_regs),
|
||||
((MSS_DMA_CTRLR_REQ_SET <<
|
||||
MSS_DMA_CTRLR_REQ_OFFSET) |
|
||||
(DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
|
||||
/* Poll DMA_ACK at MSS_DMACTLR until it is ready */
|
||||
timeout = MSS_DMA_TIMEOUT;
|
||||
while (timeout > 0U) {
|
||||
if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
|
||||
(MSS_DMA_CTRLR_ACK_OFFSET &
|
||||
MSS_DMA_CTRLR_ACK_MASK))
|
||||
== MSS_DMA_CTRLR_ACK_READY) {
|
||||
break;
|
||||
}
|
||||
udelay(50);
|
||||
timeout--;
|
||||
}
|
||||
if (timeout == 0) {
|
||||
ERROR("\nMSS DMA failed (timeout)\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mss_image_load(uint32_t src_addr, uint32_t size,
|
||||
uintptr_t mss_regs, uintptr_t sram)
|
||||
{
|
||||
uint32_t chunks = 1; /* !sram case */
|
||||
uint32_t chunk_num;
|
||||
int ret;
|
||||
|
||||
/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
|
||||
if (size > MSS_IDRAM_SIZE) {
|
||||
ERROR("image is too big to fit into MSS CM3 memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NOTICE("Loading MSS image from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
|
||||
src_addr, size, mss_regs);
|
||||
/* load image to MSS RAM using DMA */
|
||||
loop_num = (size / DMA_SIZE) + (((size & (DMA_SIZE - 1)) == 0) ? 0 : 1);
|
||||
/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
|
||||
* Copy the MSS FW image to MSS SRAM by the CPU first, then run
|
||||
* MSS DMA for SRAM to IRAM copy
|
||||
*/
|
||||
if (sram != 0) {
|
||||
chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
|
||||
}
|
||||
|
||||
for (i = 0; i < loop_num; i++) {
|
||||
/* write destination and source addresses */
|
||||
mmio_write_32(MSS_DMA_SRCBR(mss_regs),
|
||||
MSS_EXTERNAL_SPACE |
|
||||
((src_addr & MSS_EXTERNAL_ADDR_MASK) +
|
||||
(i * DMA_SIZE)));
|
||||
mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
|
||||
NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
|
||||
sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
|
||||
for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
|
||||
size_t chunk_size = size;
|
||||
uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
|
||||
(src_addr & MSS_EXTERNAL_ADDR_MASK);
|
||||
|
||||
dsb(); /* make sure DMA data is ready before triggering it */
|
||||
if (sram != 0) {
|
||||
uintptr_t chunk_source =
|
||||
src_addr + MSS_SRAM_SIZE * chunk_num;
|
||||
|
||||
/* set the DMA control register */
|
||||
mmio_write_32(MSS_DMA_CTRLR(mss_regs), ((MSS_DMA_CTRLR_REQ_SET
|
||||
<< MSS_DMA_CTRLR_REQ_OFFSET) |
|
||||
(DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
|
||||
if (chunk_num != (size / MSS_SRAM_SIZE)) {
|
||||
chunk_size = MSS_SRAM_SIZE;
|
||||
} else {
|
||||
chunk_size = size % MSS_SRAM_SIZE;
|
||||
}
|
||||
|
||||
/* Poll DMA_ACK at MSS_DMACTLR until it is ready */
|
||||
timeout = MSS_DMA_TIMEOUT;
|
||||
while (timeout) {
|
||||
if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
|
||||
MSS_DMA_CTRLR_ACK_OFFSET & MSS_DMA_CTRLR_ACK_MASK)
|
||||
== MSS_DMA_CTRLR_ACK_READY) {
|
||||
if (chunk_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(50);
|
||||
timeout--;
|
||||
VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
|
||||
chunk_num, sram, chunk_source, chunk_size);
|
||||
memcpy((void *)sram, (void *)chunk_source, chunk_size);
|
||||
dsb();
|
||||
img_src = MSS_INTERNAL_SPACE |
|
||||
(sram & MSS_INTERNAL_ADDR_MASK);
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
ERROR("\nDMA failed to load MSS image\n");
|
||||
return 1;
|
||||
ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
|
||||
if (ret != 0) {
|
||||
ERROR("MSS FW chunk %d load failed\n", chunk_num);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bl2_plat_configure_mss_windows(mss_regs);
|
||||
|
||||
/* Wipe the MSS SRAM after using it as copy buffer */
|
||||
if (sram) {
|
||||
memset((void *)sram, 0, MSS_SRAM_SIZE);
|
||||
}
|
||||
|
||||
/* Release M3 from reset */
|
||||
mmio_write_32(MSS_M3_RSTCR(mss_regs), (MSS_M3_RSTCR_RST_OFF <<
|
||||
MSS_M3_RSTCR_RST_OFFSET));
|
||||
mmio_write_32(MSS_M3_RSTCR(mss_regs),
|
||||
(MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
|
||||
|
||||
NOTICE("Done\n");
|
||||
|
||||
|
@ -162,7 +217,7 @@ static int mss_ap_load_image(uintptr_t single_img,
|
|||
VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
|
||||
|
||||
ret = mss_image_load(single_img, image_size,
|
||||
bl2_plat_get_ap_mss_regs(ap_idx));
|
||||
bl2_plat_get_ap_mss_regs(ap_idx), 0);
|
||||
if (ret != 0) {
|
||||
ERROR("SCP Image load failed\n");
|
||||
return -1;
|
||||
|
@ -218,6 +273,8 @@ static int load_img_to_cm3(enum cm3_t cm3_type,
|
|||
cp_index, ap_idx);
|
||||
ret = mss_image_load(single_img, image_size,
|
||||
bl2_plat_get_cp_mss_regs(
|
||||
ap_idx, cp_index),
|
||||
bl2_plat_get_cp_mss_sram(
|
||||
ap_idx, cp_index));
|
||||
if (ret != 0) {
|
||||
ERROR("SCP Image load failed\n");
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
int scp_bootloader_transfer(void *image, unsigned int image_size);
|
||||
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx);
|
||||
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx);
|
||||
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx);
|
||||
uint32_t bl2_plat_get_cp_count(int ap_idx);
|
||||
uint32_t bl2_plat_get_ap_count(void);
|
||||
|
|
|
@ -149,7 +149,7 @@ void plat_marvell_dram_update_topology(void)
|
|||
i2c_init((void *)MVEBU_CP0_I2C_BASE);
|
||||
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
|
|
|
@ -46,15 +46,19 @@ int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
|
|||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
#if (CP_COUNT > 1)
|
||||
/* SB (MCi0) internal regs */
|
||||
{0x00000000f4000000, 0x2000000, MCI_0_TID},
|
||||
#if (CP_COUNT > 2)
|
||||
/* SB (MCi1) internal regs */
|
||||
{0x00000000f6000000, 0x2000000, MCI_1_TID},
|
||||
#endif
|
||||
#endif
|
||||
#ifndef IMAGE_BLE
|
||||
/* SB (MCi0) PCIe0-2 on CP1 */
|
||||
{0x00000000e2000000, 0x3000000, MCI_0_TID},
|
||||
/* SB (MCi1) PCIe0-2 on CP2 */
|
||||
{0x00000000e5000000, 0x3000000, MCI_1_TID},
|
||||
/* SB (MCi0) internal regs */
|
||||
{0x00000000f4000000, 0x2000000, MCI_0_TID},
|
||||
/* SB (MCi1) internal regs */
|
||||
{0x00000000f6000000, 0x2000000, MCI_1_TID},
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
|
|
Loading…
Reference in New Issue