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:
Manish Pandey 2021-02-25 10:43:35 +00:00 committed by TrustedFirmware Code Review
commit 8909fa9bbf
20 changed files with 525 additions and 51 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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 */

249
drivers/rambus/trng_ip_76.c Normal file
View File

@ -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;
}

View File

@ -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);

View File

@ -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__ */

View File

@ -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,

View File

@ -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));

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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();

View File

@ -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);

View File

@ -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 {

View File

@ -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");

View File

@ -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);

View File

@ -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,

View File

@ -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 */