Commit 9719e19a authored by Joanna Farley's avatar Joanna Farley Committed by TrustedFirmware Code Review
Browse files

Merge changes I500ddbe9,I9c10dac9,I53bfff85,I06f7594d,I24bff8d4, ... into integration

* changes:
  nxp lx2160a-aqds: new plat based on soc lx2160a
  NXP lx2160a-rdb: new plat based on SoC lx2160a
  nxp lx2162aqds: new plat based on soc lx2160a
  nxp: errata handling at soc level for lx2160a
  nxp: make file for loading additional ddr image
  nxp: adding support of soc lx2160a
  nxp: deflt hdr files for soc & their platforms
  nxp: platform files for bl2 and bl31 setup
  nxp: warm reset support to retain ddr content
  nxp: nv storage api on platforms
  nxp: supports two mode of trusted board boot
  nxp: fip-handler for additional fip_fuse.bin
  nxp: fip-handler for additional ddr-fip.bin
  nxp: image loader for loading fip image
  nxp: svp & sip smc handling
  nxp: psci platform functions used by lib/psci
  nxp: helper function used by plat & common code
  nxp: add data handler used by bl31
  nxp: adding the driver.mk file
  nxp-tool: for creating pbl file from bl2
  nxp: adding the smmu driver
  nxp: cot using nxp internal and mbedtls
  nxp:driver for crypto h/w accelerator caam
  nxp:add driver support for sd and emmc
  nxp:add qspi driver
  nxp: add flexspi driver support
  nxp: adding gic apis for nxp soc
  nxp: gpio driver support
  nxp: added csu driver
  nxp: driver pmu for nxp soc
  nxp: ddr driver enablement for nxp layerscape soc
  nxp: i2c driver support.
  NXP: Driver for NXP Security Monitor
  NXP: SFP driver support for NXP SoC
  NXP: Interconnect API based on ARM CCN-CCI driver
  NXP: TZC API to configure ddr region
  NXP: Timer API added to enable ARM generic timer
  nxp: add dcfg driver
  nxp:add console driver for nxp platform
  tools: add mechanism to allow platform specific image UUID
  tbbr-cot: conditional definition for the macro
  tbbr-cot: fix the issue of compiling time define
  cert_create: updated tool for platform defined certs, keys & extensions
  tbbr-tools: enable override TRUSTED_KEY_CERT
parents b59444ea f359a382
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*
*/
#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/io/io_block.h>
#include "nxp_timer.h"
#include "sd_mmc.h"
#include <utils.h>
#include <utils_def.h>
/* Private structure for MMC driver data */
static struct mmc mmc_drv_data;
#ifndef NXP_POLICY_OTA
/*
* For NXP_POLICY_OTA, SD needs to do R/W on OCRAM. OCRAM is secure memory at
* default. SD can only do non-secure DMA. Configuring SD to work in PIO mode
* instead of DMA mode will make SD R/W on OCRAM available.
*/
/* To debug without dma comment this MACRO */
#define NXP_SD_DMA_CAPABILITY
#endif
#define SD_TIMEOUT 1000 /* ms */
#define SD_TIMEOUT_HIGH 20000 /* ms */
#define SD_BLOCK_TIMEOUT 8 /* ms */
#define ERROR_ESDHC_CARD_DETECT_FAIL -1
#define ERROR_ESDHC_UNUSABLE_CARD -2
#define ERROR_ESDHC_COMMUNICATION_ERROR -3
#define ERROR_ESDHC_BLOCK_LENGTH -4
#define ERROR_ESDHC_DMA_ERROR -5
#define ERROR_ESDHC_BUSY -6
/***************************************************************
* Function : set_speed
* Arguments : mmc - Pointer to mmc struct
* clock - Clock Value to be set
* Return : void
* Description : Calculates the value of SDCLKFS and DVS to be set
* for getting the required clock assuming the base_clk
* as a fixed value (MAX_PLATFORM_CLOCK)
*****************************************************************/
static void set_speed(struct mmc *mmc, uint32_t clock)
{
/* sdhc_clk = (base clock) / [(SDCLKFS × 2) × (DVS +1)] */
uint32_t dvs = 1U;
uint32_t sdclkfs = 2U;
/* TBD - Change this to actual platform clock by reading via RCW */
uint32_t base_clk = MAX_PLATFORM_CLOCK;
if (base_clk / 16 > clock) {
for (sdclkfs = 2U; sdclkfs < 256U; sdclkfs *= 2U) {
if ((base_clk / sdclkfs) <= (clock * 16)) {
break;
}
}
}
for (dvs = 1U; dvs <= 16U; dvs++) {
if ((base_clk / (dvs * sdclkfs)) <= clock) {
break;
}
}
sdclkfs >>= 1U;
dvs -= 1U;
esdhc_out32(&mmc->esdhc_regs->sysctl,
(ESDHC_SYSCTL_DTOCV(TIMEOUT_COUNTER_SDCLK_2_27) |
ESDHC_SYSCTL_SDCLKFS(sdclkfs) | ESDHC_SYSCTL_DVS(dvs) |
ESDHC_SYSCTL_SDCLKEN));
}
/***************************************************************************
* Function : esdhc_init
* Arguments : mmc - Pointer to mmc struct
* card_detect - flag to indicate if card insert needs
* to be detected or not. For SDHC2 controller, Card detect
* is not present, so this field will be false
* Return : SUCCESS or Error Code
* Description : 1. Set Initial Clock Speed
* 2. Card Detect if not eMMC
* 3. Enable Controller Clock
* 4. Send 80 ticks for card to power up
* 5. Set LE mode and Bus Width as 1 bit.
***************************************************************************/
static int esdhc_init(struct mmc *mmc, bool card_detect)
{
uint32_t val;
uint64_t start_time;
/* Reset the entire host controller */
val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_RSTA;
esdhc_out32(&mmc->esdhc_regs->sysctl, val);
/* Wait until the controller is available */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_RSTA;
if (val == 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->sysctl) &
(ESDHC_SYSCTL_RSTA);
if (val != 0U) {
ERROR("SD Reset failed\n");
return ERROR_ESDHC_BUSY;
}
/* Set initial clock speed */
set_speed(mmc, CARD_IDENTIFICATION_FREQ);
if (card_detect) {
/* Check CINS in prsstat register */
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
ESDHC_PRSSTAT_CINS;
if (val == 0) {
ERROR("CINS not set in prsstat\n");
return ERROR_ESDHC_CARD_DETECT_FAIL;
}
}
/* Enable controller clock */
val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_SDCLKEN;
esdhc_out32(&mmc->esdhc_regs->sysctl, val);
/* Send 80 clock ticks for the card to power up */
val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_INITA;
esdhc_out32(&mmc->esdhc_regs->sysctl, val);
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT) {
val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA;
if (val == 0U) {
ERROR("Failed to power up the card\n");
return ERROR_ESDHC_CARD_DETECT_FAIL;
}
INFO("Card detected successfully\n");
val = esdhc_in32(&mmc->esdhc_regs->proctl);
val = val | (ESDHC_PROCTL_EMODE_LE | ESDHC_PROCTL_DTW_1BIT);
/* Set little endian mode, set bus width as 1-bit */
esdhc_out32(&mmc->esdhc_regs->proctl, val);
/* Enable cache snooping for DMA transactions */
val = esdhc_in32(&mmc->esdhc_regs->ctl) | ESDHC_DCR_SNOOP;
esdhc_out32(&mmc->esdhc_regs->ctl, val);
return 0;
}
/***************************************************************************
* Function : esdhc_send_cmd
* Arguments : mmc - Pointer to mmc struct
* cmd - Command Number
* args - Command Args
* Return : SUCCESS is 0, or Error Code ( < 0)
* Description : Updates the eSDHC registers cmdargs and xfertype
***************************************************************************/
static int esdhc_send_cmd(struct mmc *mmc, uint32_t cmd, uint32_t args)
{
uint32_t val;
uint64_t start_time;
uint32_t xfertyp = 0;
esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL);
/* Wait for the command line & data line to be free */
/* (poll the CIHB,CDIHB bit of the present state register) */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
(ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB);
if (val == 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
(ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB);
if (val != 0U) {
ERROR("SD send cmd: Command Line or Data Line Busy cmd = %x\n",
cmd);
return ERROR_ESDHC_BUSY;
}
if (cmd == CMD2 || cmd == CMD9) {
xfertyp |= ESDHC_XFERTYP_RSPTYP_136;
} else if (cmd == CMD7 || (cmd == CMD6 && mmc->card.type == MMC_CARD)) {
xfertyp |= ESDHC_XFERTYP_RSPTYP_48_BUSY;
} else if (cmd != CMD0) {
xfertyp |= ESDHC_XFERTYP_RSPTYP_48;
}
if (cmd == CMD2 || cmd == CMD9) {
xfertyp |= ESDHC_XFERTYP_CCCEN; /* Command index check enable */
} else if ((cmd != CMD0) && (cmd != ACMD41) && (cmd != CMD1)) {
xfertyp = xfertyp | ESDHC_XFERTYP_CCCEN | ESDHC_XFERTYP_CICEN;
}
if ((cmd == CMD8 || cmd == CMD14 || cmd == CMD19) &&
mmc->card.type == MMC_CARD) {
xfertyp |= ESDHC_XFERTYP_DPSEL;
if (cmd != CMD19) {
xfertyp |= ESDHC_XFERTYP_DTDSEL;
}
}
if (cmd == CMD6 || cmd == CMD17 || cmd == CMD18 || cmd == CMD24 ||
cmd == ACMD51) {
if (!(mmc->card.type == MMC_CARD && cmd == CMD6)) {
if (cmd == CMD24) {
xfertyp |= ESDHC_XFERTYP_DPSEL;
} else {
xfertyp |= (ESDHC_XFERTYP_DPSEL |
ESDHC_XFERTYP_DTDSEL);
}
}
if (cmd == CMD18) {
xfertyp |= ESDHC_XFERTYP_BCEN;
if (mmc->dma_support != 0) {
/* Set BCEN of XFERTYP */
xfertyp |= ESDHC_XFERTYP_DMAEN;
}
}
if ((cmd == CMD17 || cmd == CMD24) && (mmc->dma_support != 0)) {
xfertyp |= ESDHC_XFERTYP_DMAEN;
}
}
xfertyp |= ((cmd & 0x3F) << 24);
esdhc_out32(&mmc->esdhc_regs->cmdarg, args);
esdhc_out32(&mmc->esdhc_regs->xfertyp, xfertyp);
#ifdef NXP_SD_DEBUG
INFO("cmd = %d\n", cmd);
INFO("args = %x\n", args);
INFO("xfertyp: = %x\n", xfertyp);
#endif
return 0;
}
/***************************************************************************
* Function : esdhc_wait_response
* Arguments : mmc - Pointer to mmc struct
* response - Value updated
* Return : SUCCESS - Response Received
* COMMUNICATION_ERROR - Command not Complete
* COMMAND_ERROR - CIE, CCE or CEBE error
* RESP_TIMEOUT - CTOE error
* Description : Checks for successful command completion.
* Clears the CC bit at the end.
***************************************************************************/
static int esdhc_wait_response(struct mmc *mmc, uint32_t *response)
{
uint32_t val;
uint64_t start_time;
uint32_t status = 0U;
/* Wait for the command to complete */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC;
if (val == 0U) {
ERROR("%s:IRQSTAT Cmd not complete(CC not set)\n", __func__);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
status = esdhc_in32(&mmc->esdhc_regs->irqstat);
/* Check whether the interrupt is a CRC, CTOE or CIE error */
if ((status & (ESDHC_IRQSTAT_CIE | ESDHC_IRQSTAT_CEBE |
ESDHC_IRQSTAT_CCE)) != 0) {
ERROR("%s: IRQSTAT CRC, CEBE or CIE error = %x\n",
__func__, status);
return COMMAND_ERROR;
}
if ((status & ESDHC_IRQSTAT_CTOE) != 0) {
INFO("%s: IRQSTAT CTOE set = %x\n", __func__, status);
return RESP_TIMEOUT;
}
if ((status & ESDHC_IRQSTAT_DMAE) != 0) {
ERROR("%s: IRQSTAT DMAE set = %x\n", __func__, status);
return ERROR_ESDHC_DMA_ERROR;
}
if (response != NULL) {
/* Get response values from eSDHC CMDRSPx registers. */
response[0] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[0]);
response[1] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[1]);
response[2] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[2]);
response[3] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[3]);
#ifdef NXP_SD_DEBUG
INFO("Resp R1 R2 R3 R4\n");
INFO("Resp R1 = %x\n", response[0]);
INFO("R2 = %x\n", response[1]);
INFO("R3 = %x\n", response[2]);
INFO("R4 = %x\n", response[3]);
INFO("\n");
#endif
}
/* Clear the CC bit - w1c */
val = esdhc_in32(&mmc->esdhc_regs->irqstat) | ESDHC_IRQSTAT_CC;
esdhc_out32(&mmc->esdhc_regs->irqstat, val);
return 0;
}
/***************************************************************************
* Function : mmc_switch_to_high_frquency
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : mmc card bellow ver 4.0 does not support high speed
* freq = 20 MHz
* Send CMD6 (CMD_SWITCH_FUNC) With args 0x03B90100
* Send CMD13 (CMD_SEND_STATUS)
* if SWITCH Error, freq = 26 MHz
* if no error, freq = 52 MHz
***************************************************************************/
static int mmc_switch_to_high_frquency(struct mmc *mmc)
{
int error;
uint32_t response[4];
uint64_t start_time;
mmc->card.bus_freq = MMC_SS_20MHZ;
/* mmc card bellow ver 4.0 does not support high speed */
if (mmc->card.version < MMC_CARD_VERSION_4_X) {
return 0;
}
/* send switch cmd to change the card to High speed */
error = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SET_EXT_CSD_HS_TIMING);
if (error != 0) {
return error;
}
error = esdhc_wait_response(mmc, response);
if (error != 0) {
return error;
}
start_time = get_timer_val(0);
do {
/* check the status for which error */
error = esdhc_send_cmd(mmc,
CMD_SEND_STATUS, mmc->card.rca << 16);
if (error != 0) {
return error;
}
error = esdhc_wait_response(mmc, response);
if (error != 0) {
return error;
}
} while (((response[0] & SWITCH_ERROR) != 0) &&
(get_timer_val(start_time) < SD_TIMEOUT));
/* Check for the present state of card */
if ((response[0] & SWITCH_ERROR) != 0) {
mmc->card.bus_freq = MMC_HS_26MHZ;
} else {
mmc->card.bus_freq = MMC_HS_52MHZ;
}
return 0;
}
/***************************************************************************
* Function : esdhc_set_data_attributes
* Arguments : mmc - Pointer to mmc struct
* blkcnt
* blklen
* Return : SUCCESS or Error Code
* Description : Set block attributes and watermark level register
***************************************************************************/
static int esdhc_set_data_attributes(struct mmc *mmc, uint32_t *dest_ptr,
uint32_t blkcnt, uint32_t blklen)
{
uint32_t val;
uint64_t start_time;
uint32_t wml;
uint32_t wl;
uint32_t dst = (uint32_t)((uint64_t)(dest_ptr));
/* set blkattr when no transactions are executing */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA;
if (val == 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA;
if (val != 0U) {
ERROR("%s: Data line active.Can't set attribute\n", __func__);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
wml = esdhc_in32(&mmc->esdhc_regs->wml);
wml &= ~(ESDHC_WML_WR_BRST_MASK | ESDHC_WML_RD_BRST_MASK |
ESDHC_WML_RD_WML_MASK | ESDHC_WML_WR_WML_MASK);
if ((mmc->dma_support != 0) && (dest_ptr != NULL)) {
/* Set burst length to 128 bytes */
esdhc_out32(&mmc->esdhc_regs->wml,
wml | ESDHC_WML_WR_BRST(BURST_128_BYTES));
esdhc_out32(&mmc->esdhc_regs->wml,
wml | ESDHC_WML_RD_BRST(BURST_128_BYTES));
/* Set DMA System Destination Address */
esdhc_out32(&mmc->esdhc_regs->dsaddr, dst);
} else {
wl = (blklen >= BLOCK_LEN_512) ?
WML_512_BYTES : ((blklen + 3) / 4);
/* Set 'Read Water Mark Level' register */
esdhc_out32(&mmc->esdhc_regs->wml, wml | ESDHC_WML_RD_WML(wl));
}
/* Configure block Attributes register */
esdhc_out32(&mmc->esdhc_regs->blkattr,
ESDHC_BLKATTR_BLKCNT(blkcnt) | ESDHC_BLKATTR_BLKSZE(blklen));
mmc->block_len = blklen;
return 0;
}
/***************************************************************************
* Function : esdhc_read_data_nodma
* Arguments : mmc - Pointer to mmc struct
* dest_ptr - Bufffer where read data is to be copied
* len - Length of Data to be read
* Return : SUCCESS or Error Code
* Description : Read data from the sdhc buffer without using DMA
* and using polling mode
***************************************************************************/
static int esdhc_read_data_nodma(struct mmc *mmc, void *dest_ptr, uint32_t len)
{
uint32_t i = 0U;
uint32_t status;
uint32_t num_blocks;
uint32_t *dst = (uint32_t *)dest_ptr;
uint32_t val;
uint64_t start_time;
num_blocks = len / mmc->block_len;
while ((num_blocks--) != 0U) {
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
ESDHC_PRSSTAT_BREN;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->prsstat)
& ESDHC_PRSSTAT_BREN;
if (val == 0U) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat);
i < mmc->block_len / 4; i++, dst++) {
/* get data from data port */
val = mmio_read_32(
(uintptr_t)&mmc->esdhc_regs->datport);
esdhc_out32(dst, val);
/* Increment destination pointer */
status = esdhc_in32(&mmc->esdhc_regs->irqstat);
}
/* Check whether the interrupt is an DTOE/DCE/DEBE */
if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE |
ESDHC_IRQSTAT_DEBE)) != 0) {
ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n",
status);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
}
/* Wait for TC */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC;
if (val == 0U) {
ERROR("SD read timeout: Transfer bit not set in IRQSTAT\n");
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
return 0;
}
/***************************************************************************
* Function : esdhc_write_data_nodma
* Arguments : mmc - Pointer to mmc struct
* src_ptr - Buffer where data is copied from
* len - Length of Data to be written
* Return : SUCCESS or Error Code
* Description : Write data to the sdhc buffer without using DMA
* and using polling mode
***************************************************************************/
static int esdhc_write_data_nodma(struct mmc *mmc, void *src_ptr, uint32_t len)
{
uint32_t i = 0U;
uint32_t status;
uint32_t num_blocks;
uint32_t *src = (uint32_t *)src_ptr;
uint32_t val;
uint64_t start_time;
num_blocks = len / mmc->block_len;
while ((num_blocks--) != 0U) {
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
ESDHC_PRSSTAT_BWEN;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->prsstat) &
ESDHC_PRSSTAT_BWEN;
if (val == 0U) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat);
i < mmc->block_len / 4; i++, src++) {
val = esdhc_in32(src);
/* put data to data port */
mmio_write_32((uintptr_t)&mmc->esdhc_regs->datport,
val);
/* Increment source pointer */
status = esdhc_in32(&mmc->esdhc_regs->irqstat);
}
/* Check whether the interrupt is an DTOE/DCE/DEBE */
if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE |
ESDHC_IRQSTAT_DEBE)) != 0) {
ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n",
status);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
}
/* Wait for TC */
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC;
if (val != 0U) {
break;
}
}
val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC;
if (val == 0U) {
ERROR("SD write timeout: Transfer bit not set in IRQSTAT\n");
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
return 0;
}
/***************************************************************************
* Function : esdhc_read_data_dma
* Arguments : mmc - Pointer to mmc struct
* len - Length of Data to be read
* Return : SUCCESS or Error Code
* Description : Read data from the sd card using DMA.
***************************************************************************/
static int esdhc_read_data_dma(struct mmc *mmc, uint32_t len)
{
uint32_t status;
uint32_t tblk;
uint64_t start_time;
tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len);
start_time = get_timer_val(0);
/* poll till TC is set */
do {
status = esdhc_in32(&mmc->esdhc_regs->irqstat);
if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE
| ESDHC_IRQSTAT_DTOE)) != 0) {
ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n",
status);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if ((status & ESDHC_IRQSTAT_DMAE) != 0) {
ERROR("SD read error - DMA error = %x\n", status);
return ERROR_ESDHC_DMA_ERROR;
}
} while (((status & ESDHC_IRQSTAT_TC) == 0) &&
((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) &&
(get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk));
if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) {
ERROR("SD read DMA timeout\n");
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
return 0;
}
/***************************************************************************
* Function : esdhc_write_data_dma
* Arguments : mmc - Pointer to mmc struct
* len - Length of Data to be written
* Return : SUCCESS or Error Code
* Description : Write data to the sd card using DMA.
***************************************************************************/
static int esdhc_write_data_dma(struct mmc *mmc, uint32_t len)
{
uint32_t status;
uint32_t tblk;
uint64_t start_time;
tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len);
start_time = get_timer_val(0);
/* poll till TC is set */
do {
status = esdhc_in32(&mmc->esdhc_regs->irqstat);
if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE
| ESDHC_IRQSTAT_DTOE)) != 0) {
ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n",
status);
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if ((status & ESDHC_IRQSTAT_DMAE) != 0) {
ERROR("SD write error - DMA error = %x\n", status);
return ERROR_ESDHC_DMA_ERROR;
}
} while (((status & ESDHC_IRQSTAT_TC) == 0) &&
((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) &&
(get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk));
if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) {
ERROR("SD write DMA timeout\n");
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
return 0;
}
/***************************************************************************
* Function : esdhc_read_data
* Arguments : mmc - Pointer to mmc struct
* dest_ptr - Bufffer where read data is to be copied
* len - Length of Data to be read
* Return : SUCCESS or Error Code
* Description : Calls esdhc_read_data_nodma and clear interrupt status
***************************************************************************/
int esdhc_read_data(struct mmc *mmc, void *dest_ptr, uint32_t len)
{
int ret;
if (mmc->dma_support && len > 64) {
ret = esdhc_read_data_dma(mmc, len);
} else {
ret = esdhc_read_data_nodma(mmc, dest_ptr, len);
}
/* clear interrupt status */
esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL);
return ret;
}
/***************************************************************************
* Function : esdhc_write_data
* Arguments : mmc - Pointer to mmc struct
* src_ptr - Buffer where data is copied from
* len - Length of Data to be written
* Return : SUCCESS or Error Code
* Description : Calls esdhc_write_data_nodma and clear interrupt status
***************************************************************************/
int esdhc_write_data(struct mmc *mmc, void *src_ptr, uint32_t len)
{
int ret;
if (mmc->dma_support && len > 64) {
ret = esdhc_write_data_dma(mmc, len);
} else {
ret = esdhc_write_data_nodma(mmc, src_ptr, len);
}
/* clear interrupt status */
esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL);
return ret;
}
/***************************************************************************
* Function : sd_switch_to_high_freq
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : 1. Send ACMD51 (CMD_SEND_SCR)
* 2. Read the SCR to check if card supports higher freq
* 3. check version from SCR
* 4. If SD 1.0, return (no Switch) freq = 25 MHz.
* 5. Send CMD6 (CMD_SWITCH_FUNC) with args 0x00FFFFF1 to
* check the status of switch func
* 6. Send CMD6 (CMD_SWITCH_FUNC) With args 0x80FFFFF1 to
* switch to high frequency = 50 Mhz
***************************************************************************/
static int sd_switch_to_high_freq(struct mmc *mmc)
{
int err;
uint8_t scr[8];
uint8_t status[64];
uint32_t response[4];
uint32_t version;
uint32_t count;
uint32_t sd_versions[] = {SD_CARD_VERSION_1_0, SD_CARD_VERSION_1_10,
SD_CARD_VERSION_2_0};
mmc->card.bus_freq = SD_SS_25MHZ;
/* Send Application command */
err = esdhc_send_cmd(mmc, CMD_APP_CMD, mmc->card.rca << 16);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
esdhc_set_data_attributes(mmc, NULL, 1, 8);
/* Read the SCR to find out if this card supports higher speeds */
err = esdhc_send_cmd(mmc, CMD_SEND_SCR, mmc->card.rca << 16);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
/* read 8 bytes of scr data */
err = esdhc_read_data(mmc, scr, 8U);
if (err != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
/* check version from SCR */
version = scr[0] & U(0xF);
if (version <= 2U) {
mmc->card.version = sd_versions[version];
} else {
mmc->card.version = SD_CARD_VERSION_2_0;
}
/* does not support switch func */
if (mmc->card.version == SD_CARD_VERSION_1_0) {
return 0;
}
/* read 64 bytes of status */
esdhc_set_data_attributes(mmc, NULL, 1U, 64U);
/* check the status of switch func */
for (count = 0U; count < 4U; count++) {
err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC,
SD_SWITCH_FUNC_CHECK_MODE);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
/* read 64 bytes of scr data */
err = esdhc_read_data(mmc, status, 64U);
if (err != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if ((status[29] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) {
break;
}
}
if ((status[13] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) {
return 0;
}
/* SWITCH */
esdhc_set_data_attributes(mmc, NULL, 1, 64);
err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SD_SWITCH_FUNC_SWITCH_MODE);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
err = esdhc_read_data(mmc, status, 64U);
if (err != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if ((status[16]) == U(0x01)) {
mmc->card.bus_freq = SD_HS_50MHZ;
}
return 0;
}
/***************************************************************************
* Function : change_state_to_transfer_state
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : 1. Send CMD7 (CMD_SELECT_CARD) to toggles the card
* between stand-by and transfer state
* 2. Send CMD13 (CMD_SEND_STATUS) to check state as
* Transfer State
***************************************************************************/
static int change_state_to_transfer_state(struct mmc *mmc)
{
int error = 0;
uint32_t response[4];
uint64_t start_time;
/* Command CMD_SELECT_CARD/CMD7 toggles the card between stand-by
* and transfer states
*/
error = esdhc_send_cmd(mmc, CMD_SELECT_CARD, mmc->card.rca << 16);
if (error != 0) {
return error;
}
error = esdhc_wait_response(mmc, response);
if (error != 0) {
return error;
}
start_time = get_timer_val(0);
while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) {
/* send CMD13 to check card status */
error = esdhc_send_cmd(mmc,
CMD_SEND_STATUS, mmc->card.rca << 16);
if (error != 0) {
return error;
}
error = esdhc_wait_response(mmc, response);
if ((error != 0) || ((response[0] & R1_ERROR) != 0)) {
return error;
}
/* Check for the present state of card */
if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) {
break;
}
}
if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) {
return 0;
} else {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
}
/***************************************************************************
* Function : get_cid_rca_csd
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : 1. Send CMD2 (CMD_ALL_SEND_CID)
* 2. get RCA for SD cards, set rca for mmc cards
* Send CMD3 (CMD_SEND_RELATIVE_ADDR)
* 3. Send CMD9 (CMD_SEND_CSD)
* 4. Get MMC Version from CSD
***************************************************************************/
static int get_cid_rca_csd(struct mmc *mmc)
{
int err;
uint32_t version;
uint32_t response[4];
uint32_t mmc_version[] = {MMC_CARD_VERSION_1_2, MMC_CARD_VERSION_1_4,
MMC_CARD_VERSION_2_X, MMC_CARD_VERSION_3_X,
MMC_CARD_VERSION_4_X};
err = esdhc_send_cmd(mmc, CMD_ALL_SEND_CID, 0);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
/* get RCA for SD cards, set rca for mmc cards */
mmc->card.rca = SD_MMC_CARD_RCA;
/* send RCA cmd */
err = esdhc_send_cmd(mmc, CMD_SEND_RELATIVE_ADDR, mmc->card.rca << 16);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
/* for SD, get the the RCA */
if (mmc->card.type == SD_CARD) {
mmc->card.rca = (response[0] >> 16) & 0xFFFF;
}
/* Get the CSD (card specific data) from card. */
err = esdhc_send_cmd(mmc, CMD_SEND_CSD, mmc->card.rca << 16);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, response);
if (err != 0) {
return err;
}
version = (response[3] >> 18U) & U(0xF);
if (mmc->card.type == MMC_CARD) {
if (version <= MMC_CARD_VERSION_4_X) {
mmc->card.version = mmc_version[version];
} else {
mmc->card.version = MMC_CARD_VERSION_4_X;
}
}
mmc->card.block_len = 1 << ((response[2] >> 8) & 0xF);
if (mmc->card.block_len > BLOCK_LEN_512) {
mmc->card.block_len = BLOCK_LEN_512;
}
return 0;
}
/***************************************************************************
* Function : identify_mmc_card
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : 1. Send Reset Command
* 2. Send CMD1 with args to set voltage range and Sector
* Mode. (Voltage Args = 0xFF8)
* 3. Check the OCR Response
***************************************************************************/
static int identify_mmc_card(struct mmc *mmc)
{
uint64_t start_time;
uint32_t resp[4];
int ret;
uint32_t args;
/* card reset */
ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret != 0) {
return ret;
}
/* Send CMD1 to get the ocr value repeatedly till the card */
/* busy is clear. timeout = 20sec */
start_time = get_timer_val(0);
do {
/* set the bits for the voltage ranges supported by host */
args = mmc->voltages_caps | MMC_OCR_SECTOR_MODE;
ret = esdhc_send_cmd(mmc, CMD_MMC_SEND_OP_COND, args);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret != 0) {
return ERROR_ESDHC_UNUSABLE_CARD;
}
} while (((resp[0] & MMC_OCR_BUSY) == 0U) &&
(get_timer_val(start_time) < SD_TIMEOUT_HIGH));
if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) {
return ERROR_ESDHC_UNUSABLE_CARD;
}
if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) {
mmc->card.is_high_capacity = 1;
}
return MMC_CARD;
}
/***************************************************************************
* Function : check_for_sd_card
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : 1. Send Reset Command
* 2. Send CMD8 with pattern 0xAA (to check for SD 2.0)
* 3. Send ACMD41 with args to set voltage range and HCS
* HCS is set only for SD Card > 2.0
* Voltage Caps = 0xFF8
* 4. Check the OCR Response
***************************************************************************/
static int check_for_sd_card(struct mmc *mmc)
{
uint64_t start_time;
uint32_t args;
int ret;
uint32_t resp[4];
/* Send reset command */
ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret != 0) {
return ret;
}
/* send CMD8 with pattern 0xAA */
args = MMC_VDD_HIGH_VOLTAGE | 0xAA;
ret = esdhc_send_cmd(mmc, CMD_SEND_IF_COND, args);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret == RESP_TIMEOUT) { /* sd ver 1.x or not sd */
mmc->card.is_high_capacity = 0;
} else if ((resp[0] & U(0xFF)) == U(0xAA)) { /* ver 2.0 or later */
mmc->card.version = SD_CARD_VERSION_2_0;
} else {
return NOT_SD_CARD;
}
/* Send Application command-55 to get the ocr value repeatedly till
* the card busy is clear. timeout = 20sec
*/
start_time = get_timer_val(0);
do {
ret = esdhc_send_cmd(mmc, CMD_APP_CMD, 0U);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret == COMMAND_ERROR) {
return ERROR_ESDHC_UNUSABLE_CARD;
}
/* set the bits for the voltage ranges supported by host */
args = mmc->voltages_caps;
if (mmc->card.version == SD_CARD_VERSION_2_0) {
args |= SD_OCR_HCS;
}
/* Send ACMD41 to set voltage range */
ret = esdhc_send_cmd(mmc, CMD_SD_SEND_OP_COND, args);
if (ret != 0) {
return ret;
}
ret = esdhc_wait_response(mmc, resp);
if (ret == COMMAND_ERROR) {
return ERROR_ESDHC_UNUSABLE_CARD;
} else if (ret == RESP_TIMEOUT) {
return NOT_SD_CARD;
}
} while (((resp[0] & MMC_OCR_BUSY) == 0U) &&
(get_timer_val(start_time) < SD_TIMEOUT_HIGH));
if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) {
INFO("SD_TIMEOUT_HIGH\n");
return ERROR_ESDHC_UNUSABLE_CARD;
}
/* bit set in card capacity status */
if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) {
mmc->card.is_high_capacity = 1;
}
return SD_CARD;
}
/***************************************************************************
* Function : esdhc_emmc_init
* Arguments : mmc - Pointer to mmc struct
* src_emmc - Flag to Indicate SRC as emmc
* Return : SUCCESS or Error Code (< 0)
* Description : Base Function called from sd_mmc_init or emmc_init
***************************************************************************/
int esdhc_emmc_init(struct mmc *mmc, bool card_detect)
{
int error = 0;
int ret = 0;
error = esdhc_init(mmc, card_detect);
if (error != 0) {
return error;
}
mmc->card.bus_freq = CARD_IDENTIFICATION_FREQ;
mmc->card.rca = 0;
mmc->card.is_high_capacity = 0;
mmc->card.type = ERROR_ESDHC_UNUSABLE_CARD;
/* Set Voltage caps as FF8 i.e all supported */
/* high voltage bits 2.7 - 3.6 */
mmc->voltages_caps = MMC_OCR_VDD_FF8;
#ifdef NXP_SD_DMA_CAPABILITY
/* Getting host DMA capabilities. */
mmc->dma_support = esdhc_in32(&mmc->esdhc_regs->hostcapblt) &
ESDHC_HOSTCAPBLT_DMAS;
#else
mmc->dma_support = 0;
#endif
ret = NOT_SD_CARD;
/* If SRC is not EMMC, check for SD or MMC */
ret = check_for_sd_card(mmc);
switch (ret) {
case SD_CARD:
mmc->card.type = SD_CARD;
break;
case NOT_SD_CARD:
/* try for MMC card */
if (identify_mmc_card(mmc) == MMC_CARD) {
mmc->card.type = MMC_CARD;
} else {
return ERROR_ESDHC_UNUSABLE_CARD;
}
break;
default:
return ERROR_ESDHC_UNUSABLE_CARD;
}
/* get CID, RCA and CSD. For MMC, set the rca */
error = get_cid_rca_csd(mmc);
if (error != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
/* change state to Transfer mode */
error = change_state_to_transfer_state(mmc);
if (error != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
/* change to high frequency if supported */
if (mmc->card.type == SD_CARD) {
error = sd_switch_to_high_freq(mmc);
} else {
error = mmc_switch_to_high_frquency(mmc);
}
if (error != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
/* mmc: 20000000, 26000000, 52000000 */
/* sd: 25000000, 50000000 */
set_speed(mmc, mmc->card.bus_freq);
INFO("init done:\n");
return 0;
}
/***************************************************************************
* Function : sd_mmc_init
* Arguments : mmc - Pointer to mmc struct
* Return : SUCCESS or Error Code
* Description : Base Function called via hal_init for SD/MMC
* initialization
***************************************************************************/
int sd_mmc_init(uintptr_t nxp_esdhc_addr, bool card_detect)
{
struct mmc *mmc = NULL;
int ret;
mmc = &mmc_drv_data;
memset(mmc, 0, sizeof(struct mmc));
mmc->esdhc_regs = (struct esdhc_regs *)nxp_esdhc_addr;
INFO("esdhc_emmc_init\n");
ret = esdhc_emmc_init(mmc, card_detect);
return ret;
}
/***************************************************************************
* Function : esdhc_read_block
* Arguments : mmc - Pointer to mmc struct
* dst - Destination Pointer
* block - Block Number
* Return : SUCCESS or Error Code
* Description : Read a Single block to Destination Pointer
* 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen
* 2. Send CMD17 (CMD_READ_SINGLE_BLOCK) with args offset
***************************************************************************/
static int esdhc_read_block(struct mmc *mmc, void *dst, uint32_t block)
{
uint32_t offset;
int err;
/* send cmd16 to set the block size. */
err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, NULL);
if (err != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if (mmc->card.is_high_capacity != 0) {
offset = block;
} else {
offset = block * mmc->card.block_len;
}
esdhc_set_data_attributes(mmc, dst, 1, mmc->card.block_len);
err = esdhc_send_cmd(mmc, CMD_READ_SINGLE_BLOCK, offset);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, NULL);
if (err != 0) {
return err;
}
err = esdhc_read_data(mmc, dst, mmc->card.block_len);
return err;
}
/***************************************************************************
* Function : esdhc_write_block
* Arguments : mmc - Pointer to mmc struct
* src - Source Pointer
* block - Block Number
* Return : SUCCESS or Error Code
* Description : Write a Single block from Source Pointer
* 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen
* 2. Send CMD24 (CMD_WRITE_SINGLE_BLOCK) with args offset
***************************************************************************/
static int esdhc_write_block(struct mmc *mmc, void *src, uint32_t block)
{
uint32_t offset;
int err;
/* send cmd16 to set the block size. */
err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, NULL);
if (err != 0) {
return ERROR_ESDHC_COMMUNICATION_ERROR;
}
if (mmc->card.is_high_capacity != 0) {
offset = block;
} else {
offset = block * mmc->card.block_len;
}
esdhc_set_data_attributes(mmc, src, 1, mmc->card.block_len);
err = esdhc_send_cmd(mmc, CMD_WRITE_SINGLE_BLOCK, offset);
if (err != 0) {
return err;
}
err = esdhc_wait_response(mmc, NULL);
if (err != 0) {
return err;
}
err = esdhc_write_data(mmc, src, mmc->card.block_len);
return err;
}
/***************************************************************************
* Function : esdhc_read
* Arguments : src_offset - offset on sd/mmc to read from. Should be block
* size aligned
* dst - Destination Pointer
* size - Length of Data ( Multiple of block size)
* Return : SUCCESS or Error Code
* Description : Calls esdhc_read_block repeatedly for reading the
* data.
***************************************************************************/
int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, size_t size)
{
int error = 0;
uint32_t blk, num_blocks;
uint8_t *buff = (uint8_t *)dst;
#ifdef NXP_SD_DEBUG
INFO("sd mmc read\n");
INFO("src = %x, dst = %lxsize = %lu\n", src_offset, dst, size);
#endif
/* check for size */
if (size == 0) {
return 0;
}
if ((size % mmc->card.block_len) != 0) {
ERROR("Size is not block aligned\n");
return -1;
}
if ((src_offset % mmc->card.block_len) != 0) {
ERROR("Size is not block aligned\n");
return -1;
}
/* start block */
blk = src_offset / mmc->card.block_len;
#ifdef NXP_SD_DEBUG
INFO("blk = %x\n", blk);
#endif
/* Number of blocks to be read */
num_blocks = size / mmc->card.block_len;
while (num_blocks) {
error = esdhc_read_block(mmc, buff, blk);
if (error != 0) {
ERROR("Read error = %x\n", error);
return error;
}
buff = buff + mmc->card.block_len;
blk++;
num_blocks--;
}
INFO("sd-mmc read done.\n");
return error;
}
/***************************************************************************
* Function : esdhc_write
* Arguments : src - Source Pointer
* dst_offset - offset on sd/mmc to write to. Should be block
* size aligned
* size - Length of Data (Multiple of block size)
* Return : SUCCESS or Error Code
* Description : Calls esdhc_write_block repeatedly for writing the
* data.
***************************************************************************/
int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset,
size_t size)
{
int error = 0;
uint32_t blk, num_blocks;
uint8_t *buff = (uint8_t *)src;
#ifdef NXP_SD_DEBUG
INFO("sd mmc write\n");
INFO("src = %x, dst = %lxsize = %lu\n", src, dst_offset, size);
#endif
/* check for size */
if (size == 0) {
return 0;
}
if ((size % mmc->card.block_len) != 0) {
ERROR("Size is not block aligned\n");
return -1;
}
if ((dst_offset % mmc->card.block_len) != 0) {
ERROR("Size is not block aligned\n");
return -1;
}
/* start block */
blk = dst_offset / mmc->card.block_len;
#ifdef NXP_SD_DEBUG
INFO("blk = %x\n", blk);
#endif
/* Number of blocks to be written */
num_blocks = size / mmc->card.block_len;
while (num_blocks != 0U) {
error = esdhc_write_block(mmc, buff, blk);
if (error != 0U) {
ERROR("Write error = %x\n", error);
return error;
}
buff = buff + mmc->card.block_len;
blk++;
num_blocks--;
}
INFO("sd-mmc write done.\n");
return error;
}
static size_t ls_sd_emmc_read(int lba, uintptr_t buf, size_t size)
{
struct mmc *mmc = NULL;
int ret;
mmc = &mmc_drv_data;
lba *= BLOCK_LEN_512;
ret = esdhc_read(mmc, lba, buf, size);
return ret ? 0 : size;
}
static struct io_block_dev_spec ls_emmc_dev_spec = {
.buffer = {
.offset = 0,
.length = 0,
},
.ops = {
.read = ls_sd_emmc_read,
},
.block_size = BLOCK_LEN_512,
};
int sd_emmc_init(uintptr_t *block_dev_spec,
uintptr_t nxp_esdhc_addr,
size_t nxp_sd_block_offset,
size_t nxp_sd_block_size,
bool card_detect)
{
int ret;
ret = sd_mmc_init(nxp_esdhc_addr, card_detect);
if (ret != 0) {
return ret;
}
ls_emmc_dev_spec.buffer.offset = nxp_sd_block_offset;
ls_emmc_dev_spec.buffer.length = nxp_sd_block_size;
*block_dev_spec = (uintptr_t)&ls_emmc_dev_spec;
return 0;
}
/*
* Copyright (c) 2015, 2016 Freescale Semiconductor, Inc.
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef SD_MMC_H
#define SD_MMC_H
#include <lib/mmio.h>
/* operating freq */
#define CARD_IDENTIFICATION_FREQ 400000
#define SD_SS_25MHZ 20000000
#define SD_HS_50MHZ 40000000
#define MMC_SS_20MHZ 15000000
#define MMC_HS_26MHZ 20000000
#define MMC_HS_52MHZ 40000000
/* Need to check this value ? */
#define MAX_PLATFORM_CLOCK 800000000
/* eSDHC system control register defines */
#define ESDHC_SYSCTL_DTOCV(t) (((t) & 0xF) << 16)
#define ESDHC_SYSCTL_SDCLKFS(f) (((f) & 0xFF) << 8)
#define ESDHC_SYSCTL_DVS(d) (((d) & 0xF) << 4)
#define ESDHC_SYSCTL_SDCLKEN (0x00000008)
#define ESDHC_SYSCTL_RSTA (0x01000000)
/* Data timeout counter value. SDHC_CLK x 227 */
#define TIMEOUT_COUNTER_SDCLK_2_27 0xE
#define ESDHC_SYSCTL_INITA 0x08000000
/* eSDHC interrupt status enable register defines */
#define ESDHC_IRQSTATEN_CINS 0x00000040
#define ESDHC_IRQSTATEN_BWR 0x00000010
/* eSDHC interrupt status register defines */
#define ESDHC_IRQSTAT_DMAE (0x10000000)
#define ESDHC_IRQSTAT_AC12E (0x01000000)
#define ESDHC_IRQSTAT_DEBE (0x00400000)
#define ESDHC_IRQSTAT_DCE (0x00200000)
#define ESDHC_IRQSTAT_DTOE (0x00100000)
#define ESDHC_IRQSTAT_CIE (0x00080000)
#define ESDHC_IRQSTAT_CEBE (0x00040000)
#define ESDHC_IRQSTAT_CCE (0x00020000)
#define ESDHC_IRQSTAT_CTOE (0x00010000)
#define ESDHC_IRQSTAT_CINT (0x00000100)
#define ESDHC_IRQSTAT_CRM (0x00000080)
#define ESDHC_IRQSTAT_CINS (0x00000040)
#define ESDHC_IRQSTAT_BRR (0x00000020)
#define ESDHC_IRQSTAT_BWR (0x00000010)
#define ESDHC_IRQSTAT_DINT (0x00000008)
#define ESDHC_IRQSTAT_BGE (0x00000004)
#define ESDHC_IRQSTAT_TC (0x00000002)
#define ESDHC_IRQSTAT_CC (0x00000001)
#define ESDHC_IRQSTAT_CMD_ERR (ESDHC_IRQSTAT_CIE |\
ESDHC_IRQSTAT_CEBE |\
ESDHC_IRQSTAT_CCE)
#define ESDHC_IRQSTAT_DATA_ERR (ESDHC_IRQSTAT_DEBE |\
ESDHC_IRQSTAT_DCE |\
ESDHC_IRQSTAT_DTOE)
#define ESDHC_IRQSTAT_CLEAR_ALL (0xFFFFFFFF)
/* eSDHC present state register defines */
#define ESDHC_PRSSTAT_CLSL 0x00800000
#define ESDHC_PRSSTAT_WPSPL 0x00080000
#define ESDHC_PRSSTAT_CDPL 0x00040000
#define ESDHC_PRSSTAT_CINS 0x00010000
#define ESDHC_PRSSTAT_BREN 0x00000800
#define ESDHC_PRSSTAT_BWEN 0x00000400
#define ESDHC_PRSSTAT_RTA 0x00000200
#define ESDHC_PRSSTAT_WTA 0x00000100
#define ESDHC_PRSSTAT_SDOFF 0x00000080
#define ESDHC_PRSSTAT_PEROFF 0x00000040
#define ESDHC_PRSSTAT_HCKOFF 0x00000020
#define ESDHC_PRSSTAT_IPGOFF 0x00000010
#define ESDHC_PRSSTAT_DLA 0x00000004
#define ESDHC_PRSSTAT_CDIHB 0x00000002
#define ESDHC_PRSSTAT_CIHB 0x00000001
/* eSDHC protocol control register defines */
#define ESDHC_PROCTL_EMODE_LE 0x00000020
#define ESDHC_PROCTL_DTW_1BIT 0x00000000
#define ESDHC_PROCTL_DTW_4BIT 0x00000002
#define ESDHC_PROCTL_DTW_8BIT 0x00000004
/* Watermark Level Register (WML) */
#define ESDHC_WML_RD_WML(w) ((w) & 0x7F)
#define ESDHC_WML_WR_WML(w) (((w) & 0x7F) << 16)
#define ESDHC_WML_RD_BRST(w) (((w) & 0xF) << 8)
#define ESDHC_WML_WR_BRST(w) (((w) & 0xF) << 24)
#define ESDHC_WML_WR_BRST_MASK (0x0F000000)
#define ESDHC_WML_RD_BRST_MASK (0x00000F00)
#define ESDHC_WML_RD_WML_MASK (0x0000007F)
#define ESDHC_WML_WR_WML_MASK (0x007F0000)
#define WML_512_BYTES (0x0)
#define BURST_128_BYTES (0x0)
/* eSDHC control register define */
#define ESDHC_DCR_SNOOP 0x00000040
/* ESDHC Block attributes register */
#define ESDHC_BLKATTR_BLKCNT(c) (((c) & 0xffff) << 16)
#define ESDHC_BLKATTR_BLKSZE(s) ((s) & 0xfff)
/* Transfer Type Register */
#define ESDHC_XFERTYP_CMD(c) (((c) & 0x3F) << 24)
#define ESDHC_XFERTYP_CMDTYP_NORMAL (0x0)
#define ESDHC_XFERTYP_CMDTYP_SUSPEND (0x00400000)
#define ESDHC_XFERTYP_CMDTYP_RESUME (0x00800000)
#define ESDHC_XFERTYP_CMDTYP_ABORT (0x00C00000)
#define ESDHC_XFERTYP_DPSEL (0x00200000)
#define ESDHC_XFERTYP_CICEN (0x00100000)
#define ESDHC_XFERTYP_CCCEN (0x00080000)
#define ESDHC_XFERTYP_RSPTYP_NONE (0x0)
#define ESDHC_XFERTYP_RSPTYP_136 (0x00010000)
#define ESDHC_XFERTYP_RSPTYP_48 (0x00020000)
#define ESDHC_XFERTYP_RSPTYP_48_BUSY (0x00030000)
#define ESDHC_XFERTYP_MSBSEL (0x00000020)
#define ESDHC_XFERTYP_DTDSEL (0x00000010)
#define ESDHC_XFERTYP_AC12EN (0x00000004)
#define ESDHC_XFERTYP_BCEN (0x00000002)
#define ESDHC_XFERTYP_DMAEN (0x00000001)
#define MMC_VDD_HIGH_VOLTAGE 0x00000100
/* command index */
#define CMD0 0
#define CMD1 1
#define CMD2 2
#define CMD3 3
#define CMD5 5
#define CMD6 6
#define CMD7 7
#define CMD8 8
#define CMD9 9
#define CMD12 12
#define CMD13 13
#define CMD14 14
#define CMD16 16
#define CMD17 17
#define CMD18 18
#define CMD19 19
#define CMD24 24
#define CMD41 41
#define CMD42 42
#define CMD51 51
#define CMD55 55
#define CMD56 56
#define ACMD6 CMD6
#define ACMD13 CMD13
#define ACMD41 CMD41
#define ACMD42 CMD42
#define ACMD51 CMD51
/* commands abbreviations */
#define CMD_GO_IDLE_STATE CMD0
#define CMD_MMC_SEND_OP_COND CMD1
#define CMD_ALL_SEND_CID CMD2
#define CMD_SEND_RELATIVE_ADDR CMD3
#define CMD_SET_DSR CMD4
#define CMD_SWITCH_FUNC CMD6
#define CMD_SELECT_CARD CMD7
#define CMD_DESELECT_CARD CMD7
#define CMD_SEND_IF_COND CMD8
#define CMD_MMC_SEND_EXT_CSD CMD8
#define CMD_SEND_CSD CMD9
#define CMD_SEND_CID CMD10
#define CMD_STOP_TRANSMISSION CMD12
#define CMD_SEND_STATUS CMD13
#define CMD_BUS_TEST_R CMD14
#define CMD_GO_INACTIVE_STATE CMD15
#define CMD_SET_BLOCKLEN CMD16
#define CMD_READ_SINGLE_BLOCK CMD17
#define CMD_READ_MULTIPLE_BLOCK CMD18
#define CMD_WRITE_SINGLE_BLOCK CMD24
#define CMD_BUS_TEST_W CMD19
#define CMD_APP_CMD CMD55
#define CMD_GEN_CMD CMD56
#define CMD_SET_BUS_WIDTH ACMD6
#define CMD_SD_STATUS ACMD13
#define CMD_SD_SEND_OP_COND ACMD41
#define CMD_SET_CLR_CARD_DETECT ACMD42
#define CMD_SEND_SCR ACMD51
/* MMC card spec version */
#define MMC_CARD_VERSION_1_2 0
#define MMC_CARD_VERSION_1_4 1
#define MMC_CARD_VERSION_2_X 2
#define MMC_CARD_VERSION_3_X 3
#define MMC_CARD_VERSION_4_X 4
/* SD Card Spec Version */
/* May need to add version 3 here? */
#define SD_CARD_VERSION_1_0 0
#define SD_CARD_VERSION_1_10 1
#define SD_CARD_VERSION_2_0 2
/* card types */
#define MMC_CARD 0
#define SD_CARD 1
#define NOT_SD_CARD MMC_CARD
/* Card rca */
#define SD_MMC_CARD_RCA 0x1
#define BLOCK_LEN_512 512
/* card state */
#define STATE_IDLE 0
#define STATE_READY 1
#define STATE_IDENT 2
#define STATE_STBY 3
#define STATE_TRAN 4
#define STATE_DATA 5
#define STATE_RCV 6
#define STATE_PRG 7
#define STATE_DIS 8
/* Card OCR register */
/* VDD voltage window 1,65 to 1.95 */
#define MMC_OCR_VDD_165_195 0x00000080
/* VDD voltage window 2.7-2.8 */
#define MMC_OCR_VDD_FF8 0x00FF8000
#define MMC_OCR_CCS 0x40000000/* Card Capacity */
#define MMC_OCR_BUSY 0x80000000/* busy bit */
#define SD_OCR_HCS 0x40000000/* High capacity host */
#define MMC_OCR_SECTOR_MODE 0x40000000/* Access Mode as Sector */
/* mmc Switch function */
#define SET_EXT_CSD_HS_TIMING 0x03B90100/* set High speed */
/* check supports switching or not */
#define SD_SWITCH_FUNC_CHECK_MODE 0x00FFFFF1
#define SD_SWITCH_FUNC_SWITCH_MODE 0x80FFFFF1/* switch */
#define SD_SWITCH_FUNC_HIGH_SPEED 0x02/* HIGH SPEED FUNC */
#define SWITCH_ERROR 0x00000080
/* errors in sending commands */
#define RESP_TIMEOUT 0x1
#define COMMAND_ERROR 0x2
/* error in response */
#define R1_ERROR (1 << 19)
#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9)
/* Host Controller Capabilities */
#define ESDHC_HOSTCAPBLT_DMAS (0x00400000)
/* SD/MMC memory map */
struct esdhc_regs {
uint32_t dsaddr; /* dma system address */
uint32_t blkattr; /* Block attributes */
uint32_t cmdarg; /* Command argument */
uint32_t xfertyp; /* Command transfer type */
uint32_t cmdrsp[4]; /* Command response0,1,2,3 */
uint32_t datport; /* Data buffer access port */
uint32_t prsstat; /* Present state */
uint32_t proctl; /* Protocol control */
uint32_t sysctl; /* System control */
uint32_t irqstat; /* Interrupt status */
uint32_t irqstaten; /* Interrupt status enable */
uint32_t irqsigen; /* Interrupt signal enable */
uint32_t autoc12err; /* Auto CMD12 status */
uint32_t hostcapblt; /* Host controller capabilities */
uint32_t wml; /* Watermark level */
uint32_t res1[2];
uint32_t fevt; /* Force event */
uint32_t res2;
uint32_t adsaddrl;
uint32_t adsaddrh;
uint32_t res3[39];
uint32_t hostver; /* Host controller version */
uint32_t res4;
uint32_t dmaerr; /* DMA error address */
uint32_t dmaerrh; /* DMA error address high */
uint32_t dmaerrattr; /* DMA error atrribute */
uint32_t res5;
uint32_t hostcapblt2;/* Host controller capabilities2 */
uint32_t res6[2];
uint32_t tcr; /* Tuning control */
uint32_t res7[7];
uint32_t dirctrl; /* Direction control */
uint32_t ccr; /* Clock control */
uint32_t res8[177];
uint32_t ctl; /* Control register */
};
/* SD/MMC card attributes */
struct card_attributes {
uint32_t type; /* sd or mmc card */
uint32_t version; /* version */
uint32_t block_len; /* block length */
uint32_t bus_freq; /* sdhc bus frequency */
uint16_t rca; /* relative card address */
uint8_t is_high_capacity; /* high capacity */
};
struct mmc {
struct esdhc_regs *esdhc_regs;
struct card_attributes card;
uint32_t block_len;
uint32_t voltages_caps; /* supported voltaes */
uint32_t dma_support; /* DMA support */
};
enum cntrl_num {
SDHC1 = 0,
SDHC2
};
int sd_emmc_init(uintptr_t *block_dev_spec,
uintptr_t nxp_esdhc_addr,
size_t nxp_sd_block_offset,
size_t nxp_sd_block_size,
bool card_detect);
int esdhc_emmc_init(struct mmc *mmc, bool card_detect);
int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst,
size_t size);
int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset,
size_t size);
#ifdef NXP_ESDHC_BE
#define esdhc_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
#elif defined(NXP_ESDHC_LE)
#define esdhc_in32(a) mmio_read_32((uintptr_t)(a))
#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), (v))
#else
#error Please define CCSR ESDHC register endianness
#endif
#endif /*SD_MMC_H*/
#
# Copyright 2020 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq (${ADD_SD_MMC},)
ADD_SD_MMC := 1
SD_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/sd
SD_MMC_BOOT_SOURCES += ${SD_DRIVERS_PATH}/sd_mmc.c \
drivers/io/io_block.c
PLAT_INCLUDES += -I$(SD_DRIVERS_PATH)
ifeq (${BL_COMM_SD_MMC_NEEDED},yes)
BL_COMMON_SOURCES += ${SD_MMC_BOOT_SOURCES}
else
ifeq (${BL2_SD_MMC_NEEDED},yes)
BL2_SOURCES += ${SD_MMC_BOOT_SOURCES}
endif
ifeq (${BL3_SD_MMC_NEEDED},yes)
BL31_SOURCES += ${SD_MMC_BOOT_SOURCES}
endif
endif
endif
#
# Copyright 2021 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq (${ADD_SNVS},)
ADD_SNVS := 1
SNVS_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/sec_mon
PLAT_INCLUDES += -I$(SNVS_DRIVERS_PATH)
SNVS_SOURCES += $(SNVS_DRIVERS_PATH)/snvs.c
ifeq (${BL_COMM_SNVS_NEEDED},yes)
BL_COMMON_SOURCES += ${SNVS_SOURCES}
else
ifeq (${BL2_SNVS_NEEDED},yes)
BL2_SOURCES += ${SNVS_SOURCES}
endif
ifeq (${BL31_SNVS_NEEDED},yes)
BL31_SOURCES += ${SNVS_SOURCES}
endif
endif
endif
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <snvs.h>
static uintptr_t g_nxp_snvs_addr;
void snvs_init(uintptr_t nxp_snvs_addr)
{
g_nxp_snvs_addr = nxp_snvs_addr;
}
uint32_t get_snvs_state(void)
{
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST);
}
static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit,
uint32_t target_state)
{
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
uint32_t sts = get_snvs_state();
uint32_t fetch_cnt = 16U;
uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit;
snvs_write32(&snvs->hp_com, val);
/* polling loop till SNVS is in target state */
do {
sts = get_snvs_state();
} while ((sts != target_state) && ((--fetch_cnt) != 0));
return sts;
}
void transition_snvs_non_secure(void)
{
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
uint32_t sts = get_snvs_state();
switch (sts) {
/* If initial state is check or Non-Secure, then
* set the Software Security Violation Bit and
* transition to Non-Secure State.
*/
case HPSTS_CHECK_SSM_ST:
sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
break;
/* If initial state is Trusted, Secure or Soft-Fail, then
* first set the Software Security Violation Bit and
* transition to Soft-Fail State.
*/
case HPSTS_TRUST_SSM_ST:
case HPSTS_SECURE_SSM_ST:
case HPSTS_SOFT_FAIL_SSM_ST:
sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
/* If SSM Soft Fail to Non-Secure State Transition
* Disable is not set, then set SSM_ST bit and
* transition to Non-Secure State.
*/
if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) {
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST);
}
break;
default:
break;
}
}
void transition_snvs_soft_fail(void)
{
do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST);
}
uint32_t transition_snvs_trusted(void)
{
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
uint32_t sts = get_snvs_state();
switch (sts) {
/* If initial state is check, set the SSM_ST bit to
* change the state to trusted.
*/
case HPSTS_CHECK_SSM_ST:
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
break;
/* If SSM Secure to Trusted State Transition Disable
* is not set, then set SSM_ST bit and
* transition to Trusted State.
*/
case HPSTS_SECURE_SSM_ST:
if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) {
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
}
break;
/* If initial state is Soft-Fail or Non-Secure, then
* transition to Trusted is not Possible.
*/
default:
break;
}
return sts;
}
uint32_t transition_snvs_secure(void)
{
uint32_t sts = get_snvs_state();
if (sts == HPSTS_SECURE_SSM_ST) {
return sts;
}
if (sts != HPSTS_TRUST_SSM_ST) {
sts = transition_snvs_trusted();
if (sts != HPSTS_TRUST_SSM_ST) {
return sts;
}
}
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
return sts;
}
void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val)
{
if (flag_val) {
snvs_write32(g_nxp_snvs_addr + offset,
(snvs_read32(g_nxp_snvs_addr + offset))
| (1 << bit_pos));
} else {
snvs_write32(g_nxp_snvs_addr + offset,
(snvs_read32(g_nxp_snvs_addr + offset))
& ~(1 << bit_pos));
}
}
uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos)
{
return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos));
}
void snvs_disable_zeroize_lp_gpr(void)
{
snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET,
NXP_GPR_Z_DIS_BIT,
true);
}
#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB)
void snvs_write_app_data_bit(uint32_t bit_pos)
{
snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET,
bit_pos,
true);
}
uint32_t snvs_read_app_data(void)
{
return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET);
}
uint32_t snvs_read_app_data_bit(uint32_t bit_pos)
{
uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos);
return ((ret != 0U) ? 1U : 0U);
}
void snvs_clear_app_data(void)
{
snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0);
}
#endif
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef SNVS_H
#define SNVS_H
#ifndef __ASSEMBLER__
#include <endian.h>
#include <stdbool.h>
#include <lib/mmio.h>
struct snvs_regs {
uint32_t reserved1;
uint32_t hp_com; /* 0x04 SNVS_HP Command Register */
uint32_t reserved2[3];
uint32_t hp_stat; /* 0x14 SNVS_HP Status Register */
};
#ifdef NXP_SNVS_BE
#define snvs_read32(a) bswap32(mmio_read_32((uintptr_t)(a)))
#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32((v)))
#elif defined(NXP_SNVS_LE)
#define snvs_read32(a) mmio_read_32((uintptr_t)(a))
#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), (v))
#else
#error Please define CCSR SNVS register endianness
#endif
void snvs_init(uintptr_t nxp_snvs_addr);
uint32_t get_snvs_state(void);
void transition_snvs_non_secure(void);
void transition_snvs_soft_fail(void);
uint32_t transition_snvs_trusted(void);
uint32_t transition_snvs_secure(void);
uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos);
void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val);
void snvs_disable_zeroize_lp_gpr(void);
#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB)
uint32_t snvs_read_app_data(void);
uint32_t snvs_read_app_data_bit(uint32_t bit_pos);
void snvs_clear_app_data(void);
void snvs_write_app_data_bit(uint32_t bit_pos);
#endif
#endif /* __ASSEMBLER__ */
/* SSM_ST field in SNVS status reg */
#define HPSTS_CHECK_SSM_ST 0x900 /* SNVS is in check state */
#define HPSTS_NON_SECURE_SSM_ST 0xb00 /* SNVS is in non secure state */
#define HPSTS_TRUST_SSM_ST 0xd00 /* SNVS is in trusted state */
#define HPSTS_SECURE_SSM_ST 0xf00 /* SNVS is in secure state */
#define HPSTS_SOFT_FAIL_SSM_ST 0x300 /* SNVS is in soft fail state */
#define HPSTS_MASK_SSM_ST 0xf00 /* SSM_ST field mask in SNVS reg */
/* SNVS register bits */
#define HPCOM_SW_SV 0x100 /* Security Violation bit */
#define HPCOM_SW_FSV 0x200 /* Fatal Security Violation bit */
#define HPCOM_SSM_ST 0x1 /* SSM_ST field in SNVS command reg */
#define HPCOM_SSM_ST_DIS 0x2 /* Disable Secure to Trusted State */
#define HPCOM_SSM_SFNS_DIS 0x4 /* Disable Soft Fail to Non-Secure */
#define NXP_LP_GPR0_OFFSET 0x90
#define NXP_LPCR_OFFSET 0x38
#define NXP_GPR_Z_DIS_BIT 24
#ifdef NXP_COINED_BB
#ifndef NXP_APP_DATA_LP_GPR_OFFSET
#define NXP_APP_DATA_LP_GPR_OFFSET NXP_LP_GPR0_OFFSET
#endif
#define NXP_LPGPR_ZEROTH_BIT 0
#endif /* NXP_COINED_BB */
#endif /* SNVS_H */
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <caam.h>
#include <common/debug.h>
#include <dcfg.h>
#include <drivers/delay_timer.h>
#include <fuse_prov.h>
#include <sfp.h>
#include <sfp_error_codes.h>
static int write_a_fuse(uint32_t *fuse_addr, uint32_t *fuse_hdr_val,
uint32_t mask)
{
uint32_t last_stored_val = sfp_read32(fuse_addr);
/* Check if fuse already blown or not */
if ((last_stored_val & mask) == mask) {
return ERROR_ALREADY_BLOWN;
}
/* Write fuse in mirror registers */
sfp_write32(fuse_addr, last_stored_val | (*fuse_hdr_val & mask));
/* Read back to check if write success */
if (sfp_read32(fuse_addr) != (last_stored_val | (*fuse_hdr_val & mask))) {
return ERROR_WRITE;
}
return 0;
}
static int write_fuses(uint32_t *fuse_addr, uint32_t *fuse_hdr_val, uint8_t len)
{
int i;
/* Check if fuse already blown or not */
for (i = 0; i < len; i++) {
if (sfp_read32(&fuse_addr[i]) != 0) {
return ERROR_ALREADY_BLOWN;
}
}
/* Write fuse in mirror registers */
for (i = 0; i < len; i++) {
sfp_write32(&fuse_addr[i], fuse_hdr_val[i]);
}
/* Read back to check if write success */
for (i = 0; i < len; i++) {
if (sfp_read32(&fuse_addr[i]) != fuse_hdr_val[i]) {
return ERROR_WRITE;
}
}
return 0;
}
/*
* This function program Super Root Key Hash (SRKH) in fuse
* registers.
*/
static int prog_srkh(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int ret = 0;
ret = write_fuses(sfp_ccsr_regs->srk_hash, fuse_hdr->srkh, 8);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_SRKH_ALREADY_BLOWN : ERROR_SRKH_WRITE;
}
return ret;
}
/* This function program OEMUID[0-4] in fuse registers. */
static int prog_oemuid(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int i, ret = 0;
for (i = 0; i < 5; i++) {
/* Check OEMUIDx to be blown or not */
if (((fuse_hdr->flags >> (FLAG_OUID0_SHIFT + i)) & 0x1) != 0) {
/* Check if OEMUID[i] already blown or not */
ret = write_fuses(&sfp_ccsr_regs->oem_uid[i],
&fuse_hdr->oem_uid[i], 1);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_OEMUID_ALREADY_BLOWN
: ERROR_OEMUID_WRITE;
}
}
}
return ret;
}
/* This function program DCV[0-1], DRV[0-1] in fuse registers. */
static int prog_debug(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int ret;
/* Check DCV to be blown or not */
if (((fuse_hdr->flags >> (FLAG_DCV0_SHIFT)) & 0x3) != 0) {
/* Check if DCV[i] already blown or not */
ret = write_fuses(sfp_ccsr_regs->dcv, fuse_hdr->dcv, 2);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_DCV_ALREADY_BLOWN
: ERROR_DCV_WRITE;
}
}
/* Check DRV to be blown or not */
if ((((fuse_hdr->flags >> (FLAG_DRV0_SHIFT)) & 0x3)) != 0) {
/* Check if DRV[i] already blown or not */
ret = write_fuses(sfp_ccsr_regs->drv, fuse_hdr->drv, 2);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_DRV_ALREADY_BLOWN
: ERROR_DRV_WRITE;
} else {
/* Check for DRV hamming error */
if (sfp_read32((void *)(get_sfp_addr()
+ SFP_SVHESR_OFFSET))
& SFP_SVHESR_DRV_MASK) {
return ERROR_DRV_HAMMING_ERROR;
}
}
}
return 0;
}
/*
* Turn a 256-bit random value (32 bytes) into an OTPMK code word
* modifying the input data array in place
*/
static void otpmk_make_code_word_256(uint8_t *otpmk, bool minimal_flag)
{
int i;
uint8_t parity_bit;
uint8_t code_bit;
if (minimal_flag == true) {
/*
* Force bits 252, 253, 254 and 255 to 1
* This is because these fuses may have already been blown
* and the OTPMK cannot force them back to 0
*/
otpmk[252/8] |= (1 << (252%8));
otpmk[253/8] |= (1 << (253%8));
otpmk[254/8] |= (1 << (254%8));
otpmk[255/8] |= (1 << (255%8));
}
/* Generate the hamming code for the code word */
parity_bit = 0;
code_bit = 0;
for (i = 0; i < 256; i += 1) {
if ((otpmk[i/8] & (1 << (i%8))) != 0) {
parity_bit ^= 1;
code_bit ^= i;
}
}
/* Inverting otpmk[code_bit] will cause the otpmk
* to become a valid code word (except for overall parity)
*/
if (code_bit < 252) {
otpmk[code_bit/8] ^= (1 << (code_bit % 8));
parity_bit ^= 1; // account for flipping a bit changing parity
} else {
/* Invert two bits: (code_bit - 4) and 4
* Because we invert two bits, no need to touch the parity bit
*/
otpmk[(code_bit - 4)/8] ^= (1 << ((code_bit - 4) % 8));
otpmk[4/8] ^= (1 << (4 % 8));
}
/* Finally, adjust the overall parity of the otpmk
* otpmk bit 0
*/
otpmk[0] ^= parity_bit;
}
/* This function program One Time Programmable Master Key (OTPMK)
* in fuse registers.
*/
static int prog_otpmk(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int ret = 0;
uint32_t otpmk_flags;
uint32_t otpmk_random[8] __aligned(CACHE_WRITEBACK_GRANULE);
otpmk_flags = (fuse_hdr->flags >> (FLAG_OTPMK_SHIFT)) & FLAG_OTPMK_MASK;
switch (otpmk_flags) {
case PROG_OTPMK_MIN:
memset(fuse_hdr->otpmk, 0, sizeof(fuse_hdr->otpmk));
/* Minimal OTPMK value (252-255 bits set to 1) */
fuse_hdr->otpmk[0] |= OTPMK_MIM_BITS_MASK;
break;
case PROG_OTPMK_RANDOM:
if (is_sec_enabled() == false) {
ret = ERROR_OTPMK_SEC_DISABLED;
goto out;
}
/* Generate Random number using CAAM for OTPMK */
memset(otpmk_random, 0, sizeof(otpmk_random));
if (get_rand_bytes_hw((uint8_t *)otpmk_random,
sizeof(otpmk_random)) != 0) {
ret = ERROR_OTPMK_SEC_ERROR;
goto out;
}
/* Run hamming over random no. to make OTPMK */
otpmk_make_code_word_256((uint8_t *)otpmk_random, false);
/* Swap OTPMK */
fuse_hdr->otpmk[0] = otpmk_random[7];
fuse_hdr->otpmk[1] = otpmk_random[6];
fuse_hdr->otpmk[2] = otpmk_random[5];
fuse_hdr->otpmk[3] = otpmk_random[4];
fuse_hdr->otpmk[4] = otpmk_random[3];
fuse_hdr->otpmk[5] = otpmk_random[2];
fuse_hdr->otpmk[6] = otpmk_random[1];
fuse_hdr->otpmk[7] = otpmk_random[0];
break;
case PROG_OTPMK_USER:
break;
case PROG_OTPMK_RANDOM_MIN:
/* Here assumption is that user is aware of minimal OTPMK
* already blown.
*/
/* Generate Random number using CAAM for OTPMK */
if (is_sec_enabled() == false) {
ret = ERROR_OTPMK_SEC_DISABLED;
goto out;
}
memset(otpmk_random, 0, sizeof(otpmk_random));
if (get_rand_bytes_hw((uint8_t *)otpmk_random,
sizeof(otpmk_random)) != 0) {
ret = ERROR_OTPMK_SEC_ERROR;
goto out;
}
/* Run hamming over random no. to make OTPMK */
otpmk_make_code_word_256((uint8_t *)otpmk_random, true);
/* Swap OTPMK */
fuse_hdr->otpmk[0] = otpmk_random[7];
fuse_hdr->otpmk[1] = otpmk_random[6];
fuse_hdr->otpmk[2] = otpmk_random[5];
fuse_hdr->otpmk[3] = otpmk_random[4];
fuse_hdr->otpmk[4] = otpmk_random[3];
fuse_hdr->otpmk[5] = otpmk_random[2];
fuse_hdr->otpmk[6] = otpmk_random[1];
fuse_hdr->otpmk[7] = otpmk_random[0];
break;
case PROG_OTPMK_USER_MIN:
/*
* Here assumption is that user is aware of minimal OTPMK
* already blown. Check if minimal bits are set in user
* supplied OTPMK.
*/
if ((fuse_hdr->otpmk[0] & OTPMK_MIM_BITS_MASK) !=
OTPMK_MIM_BITS_MASK) {
ret = ERROR_OTPMK_USER_MIN;
goto out;
}
break;
default:
ret = 0;
goto out;
}
ret = write_fuses(sfp_ccsr_regs->otpmk, fuse_hdr->otpmk, 8);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_OTPMK_ALREADY_BLOWN
: ERROR_OTPMK_WRITE;
} else {
/* Check for DRV hamming error */
if ((sfp_read32((void *)(get_sfp_addr() + SFP_SVHESR_OFFSET))
& SFP_SVHESR_OTPMK_MASK) != 0) {
ret = ERROR_OTPMK_HAMMING_ERROR;
}
}
out:
return ret;
}
/* This function program OSPR1 in fuse registers.
*/
static int prog_ospr1(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int ret;
uint32_t mask;
#ifdef NXP_SFP_VER_3_4
if (((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) {
mask = OSPR1_MC_MASK;
}
#endif
if (((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0) {
mask = mask | OSPR1_DBG_LVL_MASK;
}
ret = write_a_fuse(&sfp_ccsr_regs->ospr1, &fuse_hdr->ospr1, mask);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_OSPR1_ALREADY_BLOWN
: ERROR_OSPR1_WRITE;
}
return ret;
}
/* This function program SYSCFG in fuse registers.
*/
static int prog_syscfg(struct fuse_hdr_t *fuse_hdr,
struct sfp_ccsr_regs_t *sfp_ccsr_regs)
{
int ret;
/* Check if SYSCFG already blown or not */
ret = write_a_fuse(&sfp_ccsr_regs->ospr, &fuse_hdr->sc, OSPR0_SC_MASK);
if (ret != 0) {
ret = (ret == ERROR_ALREADY_BLOWN) ?
ERROR_SC_ALREADY_BLOWN
: ERROR_SC_WRITE;
}
return ret;
}
/* This function does fuse provisioning.
*/
int provision_fuses(unsigned long long fuse_scr_addr,
bool en_povdd_status)
{
struct fuse_hdr_t *fuse_hdr = NULL;
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr()
+ SFP_FUSE_REGS_OFFSET);
int ret = 0;
fuse_hdr = (struct fuse_hdr_t *)fuse_scr_addr;
/*
* Check for Write Protect (WP) fuse. If blown then do
* no fuse provisioning.
*/
if ((sfp_read32(&sfp_ccsr_regs->ospr) & 0x1) != 0) {
goto out;
}
/* Check if SRKH to be blown or not */
if (((fuse_hdr->flags >> FLAG_SRKH_SHIFT) & 0x1) != 0) {
INFO("Fuse: Program SRKH\n");
ret = prog_srkh(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
/* Check if OEMUID to be blown or not */
if (((fuse_hdr->flags >> FLAG_OUID0_SHIFT) & FLAG_OUID_MASK) != 0) {
INFO("Fuse: Program OEMUIDs\n");
ret = prog_oemuid(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
/* Check if Debug values to be blown or not */
if (((fuse_hdr->flags >> FLAG_DCV0_SHIFT) & FLAG_DEBUG_MASK) != 0) {
INFO("Fuse: Program Debug values\n");
ret = prog_debug(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
/* Check if OTPMK values to be blown or not */
if (((fuse_hdr->flags >> FLAG_OTPMK_SHIFT) & PROG_NO_OTPMK) !=
PROG_NO_OTPMK) {
INFO("Fuse: Program OTPMK\n");
ret = prog_otpmk(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
/* Check if MC or DBG LVL to be blown or not */
if ((((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) ||
(((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0)) {
INFO("Fuse: Program OSPR1\n");
ret = prog_ospr1(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
/* Check if SYSCFG to be blown or not */
if (((fuse_hdr->flags >> FLAG_SYSCFG_SHIFT) & 0x1) != 0) {
INFO("Fuse: Program SYSCFG\n");
ret = prog_syscfg(fuse_hdr, sfp_ccsr_regs);
if (ret != 0) {
error_handler(ret);
goto out;
}
}
if (en_povdd_status) {
ret = sfp_program_fuses();
if (ret != 0) {
error_handler(ret);
goto out;
}
}
out:
return ret;
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#if !defined(FUSE_PROV_H) && defined(POLICY_FUSE_PROVISION)
#define FUSE_PROV_H
#include <endian.h>
#include <lib/mmio.h>
#define MASK_NONE U(0xFFFFFFFF)
#define ERROR_WRITE U(0xA)
#define ERROR_ALREADY_BLOWN U(0xB)
/* Flag bit shifts */
#define FLAG_POVDD_SHIFT U(0)
#define FLAG_SYSCFG_SHIFT U(1)
#define FLAG_SRKH_SHIFT U(2)
#define FLAG_MC_SHIFT U(3)
#define FLAG_DCV0_SHIFT U(4)
#define FLAG_DCV1_SHIFT U(5)
#define FLAG_DRV0_SHIFT U(6)
#define FLAG_DRV1_SHIFT U(7)
#define FLAG_OUID0_SHIFT U(8)
#define FLAG_OUID1_SHIFT U(9)
#define FLAG_OUID2_SHIFT U(10)
#define FLAG_OUID3_SHIFT U(11)
#define FLAG_OUID4_SHIFT U(12)
#define FLAG_DBG_LVL_SHIFT U(13)
#define FLAG_OTPMK_SHIFT U(16)
#define FLAG_OUID_MASK U(0x1F)
#define FLAG_DEBUG_MASK U(0xF)
#define FLAG_OTPMK_MASK U(0xF)
/* OTPMK flag values */
#define PROG_OTPMK_MIN U(0x0)
#define PROG_OTPMK_RANDOM U(0x1)
#define PROG_OTPMK_USER U(0x2)
#define PROG_OTPMK_RANDOM_MIN U(0x5)
#define PROG_OTPMK_USER_MIN U(0x6)
#define PROG_NO_OTPMK U(0x8)
#define OTPMK_MIM_BITS_MASK U(0xF0000000)
/* System configuration bit shifts */
#define SCB_WP_SHIFT U(0)
#define SCB_ITS_SHIFT U(2)
#define SCB_NSEC_SHIFT U(4)
#define SCB_ZD_SHIFT U(5)
#define SCB_K0_SHIFT U(15)
#define SCB_K1_SHIFT U(14)
#define SCB_K2_SHIFT U(13)
#define SCB_K3_SHIFT U(12)
#define SCB_K4_SHIFT U(11)
#define SCB_K5_SHIFT U(10)
#define SCB_K6_SHIFT U(9)
#define SCB_FR0_SHIFT U(30)
#define SCB_FR1_SHIFT U(31)
/* Fuse Header Structure */
struct fuse_hdr_t {
uint8_t barker[4]; /* 0x00 Barker code */
uint32_t flags; /* 0x04 Script flags */
uint32_t povdd_gpio; /* 0x08 GPIO for POVDD */
uint32_t otpmk[8]; /* 0x0C-0x2B OTPMK */
uint32_t srkh[8]; /* 0x2C-0x4B SRKH */
uint32_t oem_uid[5]; /* 0x4C-0x5F OEM unique id's */
uint32_t dcv[2]; /* 0x60-0x67 Debug Challenge */
uint32_t drv[2]; /* 0x68-0x6F Debug Response */
uint32_t ospr1; /* 0x70 OSPR1 */
uint32_t sc; /* 0x74 OSPR0 (System Configuration) */
uint32_t reserved[2]; /* 0x78-0x7F Reserved */
};
/* Function to do fuse provisioning */
int provision_fuses(unsigned long long fuse_scr_addr,
bool en_povdd_status);
#define EFUSE_POWERUP_DELAY_mSec U(25)
#endif /* FUSE_PROV_H */
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <caam.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <sfp.h>
#include <sfp_error_codes.h>
static uintptr_t g_nxp_sfp_addr;
static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)]
__aligned(CACHE_WRITEBACK_GRANULE);
void sfp_init(uintptr_t nxp_sfp_addr)
{
g_nxp_sfp_addr = nxp_sfp_addr;
}
uintptr_t get_sfp_addr(void)
{
return g_nxp_sfp_addr;
}
uint32_t *get_sfp_srk_hash(void)
{
struct sfp_ccsr_regs_t *sfp_ccsr_regs =
(void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET);
int i = 0;
/* Add comparison of hash with SFP hash here */
for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++)
srk_hash[i] =
mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]);
return srk_hash;
}
void set_sfp_wr_disable(void)
{
/*
* Mark SFP Write Disable and Write Disable Lock
* Bit to prevent write to SFP fuses like
* OUID's, Key Revocation fuse etc
*/
void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET);
uint32_t sfpcr_val;
sfpcr_val = sfp_read32(sfpcr);
sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL);
sfp_write32(sfpcr, sfpcr_val);
}
int sfp_program_fuses(void)
{
uint32_t ingr;
uint32_t sfp_cmd_status = 0U;
int ret = 0;
/* Program SFP fuses from mirror registers */
sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET),
SFP_INGR_PROGFB_CMD);
/* Wait until fuse programming is successful */
do {
ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET);
} while (ingr & SFP_INGR_PROGFB_CMD);
/* Check for SFP fuse programming error */
sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET)
& SFP_INGR_ERROR_MASK;
if (sfp_cmd_status != 0U) {
return ERROR_PROGFB_CMD;
}
return ret;
}
uint32_t sfp_read_oem_uid(uint8_t oem_uid)
{
uint32_t val = 0U;
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
+ SFP_FUSE_REGS_OFFSET);
if (oem_uid > MAX_OEM_UID) {
ERROR("Invalid OEM UID received.\n");
return ERROR_OEMUID_WRITE;
}
val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]);
return val;
}
/*
* return val: 0 - No update required.
* 1 - successful update done.
* ERROR_OEMUID_WRITE - Invalid OEM UID
*/
uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val)
{
uint32_t val = 0U;
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
+ SFP_FUSE_REGS_OFFSET);
val = sfp_read_oem_uid(oem_uid);
if (val == ERROR_OEMUID_WRITE) {
return ERROR_OEMUID_WRITE;
}
/* Counter already set. No need to do anything */
if ((val & sfp_val) != 0U) {
return 0U;
}
val |= sfp_val;
INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val);
sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val);
return 1U;
}
int sfp_check_its(void)
{
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
+ SFP_FUSE_REGS_OFFSET);
if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) {
return 1;
} else {
return 0;
}
}
int sfp_check_oem_wp(void)
{
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
+ SFP_FUSE_REGS_OFFSET);
if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) {
return 1;
} else {
return 0;
}
}
/* This function returns ospr's key_revoc values.*/
uint32_t get_key_revoc(void)
{
struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
+ SFP_FUSE_REGS_OFFSET);
return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >>
OSPR_KEY_REVOC_SHIFT;
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef SFP_H
#define SFP_H
#include <endian.h>
#include <lib/mmio.h>
/* SFP Configuration Register Offsets */
#define SFP_INGR_OFFSET U(0x20)
#define SFP_SVHESR_OFFSET U(0x24)
#define SFP_SFPCR_OFFSET U(0x28)
#define SFP_VER_OFFSET U(0x38)
/* SFP Hamming register masks for OTPMK and DRV */
#define SFP_SVHESR_DRV_MASK U(0x7F)
#define SFP_SVHESR_OTPMK_MASK U(0x7FC00)
/* SFP commands */
#define SFP_INGR_READFB_CMD U(0x1)
#define SFP_INGR_PROGFB_CMD U(0x2)
#define SFP_INGR_ERROR_MASK U(0x100)
/* SFPCR Masks */
#define SFP_SFPCR_WD U(0x80000000)
#define SFP_SFPCR_WDL U(0x40000000)
/* SFPCR Masks */
#define SFP_SFPCR_WD U(0x80000000)
#define SFP_SFPCR_WDL U(0x40000000)
#define SFP_FUSE_REGS_OFFSET U(0x200)
#ifdef NXP_SFP_VER_3_4
#define OSPR0_SC_MASK U(0xC000FE35)
#elif defined(NXP_SFP_VER_3_2)
#define OSPR0_SC_MASK U(0x0000E035)
#endif
#if defined(NXP_SFP_VER_3_4)
#define OSPR_KEY_REVOC_SHIFT U(9)
#define OSPR_KEY_REVOC_MASK U(0x0000fe00)
#elif defined(NXP_SFP_VER_3_2)
#define OSPR_KEY_REVOC_SHIFT U(13)
#define OSPR_KEY_REVOC_MASK U(0x0000e000)
#endif /* NXP_SFP_VER_3_4 */
#define OSPR1_MC_MASK U(0xFFFF0000)
#define OSPR1_DBG_LVL_MASK U(0x00000007)
#define OSPR_ITS_MASK U(0x00000004)
#define OSPR_WP_MASK U(0x00000001)
#define MAX_OEM_UID U(5)
#define SRK_HASH_SIZE U(32)
/* SFP CCSR Register Map */
struct sfp_ccsr_regs_t {
uint32_t ospr; /* 0x200 OSPR0 */
uint32_t ospr1; /* 0x204 OSPR1 */
uint32_t dcv[2]; /* 0x208 Debug Challenge Value */
uint32_t drv[2]; /* 0x210 Debug Response Value */
uint32_t fswpr; /* 0x218 FSL Section Write Protect */
uint32_t fsl_uid[2]; /* 0x21c FSL UID 0 */
uint32_t isbcr; /* 0x224 ISBC Configuration */
uint32_t fsspr[3]; /* 0x228 FSL Scratch Pad */
uint32_t otpmk[8]; /* 0x234 OTPMK */
uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)];
/* 0x254 Super Root Key Hash */
uint32_t oem_uid[MAX_OEM_UID]; /* 0x274 OEM UID 0 */
};
uintptr_t get_sfp_addr(void);
void sfp_init(uintptr_t nxp_sfp_addr);
uint32_t *get_sfp_srk_hash(void);
int sfp_check_its(void);
int sfp_check_oem_wp(void);
uint32_t get_key_revoc(void);
void set_sfp_wr_disable(void);
int sfp_program_fuses(void);
uint32_t sfp_read_oem_uid(uint8_t oem_uid);
uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val);
#ifdef NXP_SFP_BE
#define sfp_read32(a) bswap32(mmio_read_32((uintptr_t)(a)))
#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
#elif defined(NXP_SFP_LE)
#define sfp_read32(a) mmio_read_32((uintptr_t)(a))
#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), (v))
#else
#error Please define CCSR SFP register endianness
#endif
#endif/* SFP_H */
#
# Copyright 2020 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-----------------------------------------------------------------------------
ifeq (${SFP_ADDED},)
SFP_ADDED := 1
$(eval $(call add_define, NXP_SFP_ENABLED))
SFP_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/sfp
PLAT_INCLUDES += -I$(SFP_DRIVERS_PATH)
SFP_SOURCES += $(SFP_DRIVERS_PATH)/sfp.c
ifeq (${FUSE_PROG}, 1)
SFP_BL2_SOURCES += $(SFP_DRIVERS_PATH)/fuse_prov.c
endif
ifeq (${BL_COMM_SFP_NEEDED},yes)
BL_COMMON_SOURCES += ${SFP_SOURCES}
BL2_SOURCES += ${SFP_BL2_SOURCES}
else
ifeq (${BL2_SFP_NEEDED},yes)
BL2_SOURCES += ${SFP_SOURCES}\
${SFP_BL2_SOURCES}
endif
ifeq (${BL31_SFP_NEEDED},yes)
BL31_SOURCES += ${SFP_SOURCES}
endif
endif
endif
#------------------------------------------------
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef SFP_ERROR_CODES_H
#define SFP_ERROR_CODES_H
/* Error codes */
#define ERROR_FUSE_BARKER 0x1
#define ERROR_READFB_CMD 0x2
#define ERROR_PROGFB_CMD 0x3
#define ERROR_SRKH_ALREADY_BLOWN 0x4
#define ERROR_SRKH_WRITE 0x5
#define ERROR_OEMUID_ALREADY_BLOWN 0x6
#define ERROR_OEMUID_WRITE 0x7
#define ERROR_DCV_ALREADY_BLOWN 0x8
#define ERROR_DCV_WRITE 0x9
#define ERROR_DRV_ALREADY_BLOWN 0xa
#define ERROR_DRV_HAMMING_ERROR 0xb
#define ERROR_DRV_WRITE 0x18
#define ERROR_OTPMK_ALREADY_BLOWN 0xc
#define ERROR_OTPMK_HAMMING_ERROR 0xd
#define ERROR_OTPMK_USER_MIN 0xe
#define ERROR_OSPR1_ALREADY_BLOWN 0xf
#define ERROR_OSPR1_WRITE 0x10
#define ERROR_SC_ALREADY_BLOWN 0x11
#define ERROR_SC_WRITE 0x12
#define ERROR_POVDD_GPIO_FAIL 0x13
#define ERROR_GPIO_SET_FAIL 0x14
#define ERROR_GPIO_RESET_FAIL 0x15
#define ERROR_OTPMK_SEC_DISABLED 0x16
#define ERROR_OTPMK_SEC_ERROR 0x17
#define ERROR_OTPMK_WRITE 0x19
#define PLAT_ERROR_ENABLE_POVDD 0x20
#define PLAT_ERROR_DISABLE_POVDD 0x21
#endif /* SFP_ERROR_CODES_H */
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <nxp_timer.h>
#include <plat/common/platform.h>
static uintptr_t g_nxp_timer_addr;
static timer_ops_t ops;
uint64_t get_timer_val(uint64_t start)
{
uint64_t cntpct;
isb();
cntpct = read_cntpct_el0();
return (cntpct * 1000ULL / read_cntfrq_el0() - start);
}
static uint32_t timer_get_value(void)
{
uint64_t cntpct;
isb();
cntpct = read_cntpct_el0();
#ifdef ERRATA_SOC_A008585
uint8_t max_fetch_count = 10U;
/* This erratum number needs to be confirmed to match ARM document */
uint64_t temp;
isb();
temp = read_cntpct_el0();
while (temp != cntpct && max_fetch_count) {
isb();
cntpct = read_cntpct_el0();
isb();
temp = read_cntpct_el0();
max_fetch_count--;
}
#endif
/*
* Generic delay timer implementation expects the timer to be a down
* counter. We apply bitwise NOT operator to the tick values returned
* by read_cntpct_el0() to simulate the down counter. The value is
* clipped from 64 to 32 bits.
*/
return (uint32_t)(~cntpct);
}
static void delay_timer_init_args(uint32_t mult, uint32_t div)
{
ops.get_timer_value = timer_get_value,
ops.clk_mult = mult;
ops.clk_div = div;
timer_init(&ops);
VERBOSE("Generic delay timer configured with mult=%u and div=%u\n",
mult, div);
}
/*
* Initialise the nxp on-chip free rolling usec counter as the delay
* timer.
*/
void delay_timer_init(uintptr_t nxp_timer_addr)
{
/* Value in ticks */
unsigned int mult = MHZ_TICKS_PER_SEC;
unsigned int div;
unsigned int counter_base_frequency = plat_get_syscnt_freq2();
g_nxp_timer_addr = nxp_timer_addr;
/* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */
if (counter_base_frequency > MHZ_TICKS_PER_SEC) {
counter_base_frequency = (counter_base_frequency
/ MHZ_TICKS_PER_SEC)
* MHZ_TICKS_PER_SEC;
} else {
counter_base_frequency = (counter_base_frequency
/ KHZ_TICKS_PER_SEC)
* KHZ_TICKS_PER_SEC;
}
/* Value in ticks per second (Hz) */
div = counter_base_frequency;
/* Reduce multiplier and divider by dividing them repeatedly by 10 */
while ((mult % 10U == 0U) && (div % 10U == 0U)) {
mult /= 10U;
div /= 10U;
}
/* Enable and initialize the System level generic timer */
mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
CNTCR_FCREQ(0) | CNTCR_EN);
delay_timer_init_args(mult, div);
}
#ifdef IMAGE_BL31
/*******************************************************************************
* TBD: Configures access to the system counter timer module.
******************************************************************************/
void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base,
uint8_t ls_config_cntacr,
uint8_t plat_ls_ns_timer_frame_id)
{
unsigned int reg_val;
if (ls_config_cntacr == 1U) {
reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT);
reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT);
reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT);
mmio_write_32(ls_sys_timctl_base +
CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val);
mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2());
}
reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id));
mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val);
}
void enable_init_timer(void)
{
/* Enable and initialize the System level generic timer */
mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
CNTCR_FCREQ(0) | CNTCR_EN);
}
#endif
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#
#ifndef NXP_TIMER_H
#define NXP_TIMER_H
/* System Counter Offset and Bit Mask */
#define SYS_COUNTER_CNTCR_OFFSET 0x0
#define SYS_COUNTER_CNTCR_EN 0x00000001
#define CNTCR_EN_MASK 0x1
#ifndef __ASSEMBLER__
uint64_t get_timer_val(uint64_t start);
#ifdef IMAGE_BL31
void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base,
uint8_t ls_config_cntacr,
uint8_t plat_ls_ns_timer_frame_id);
void enable_init_timer(void);
#endif
/*
* Initialise the nxp on-chip free rolling usec counter as the delay
* timer.
*/
void delay_timer_init(uintptr_t nxp_timer_addr);
void ls_bl31_timer_init(uintptr_t nxp_timer_addr);
#endif /* __ASSEMBLER__ */
#endif /* NXP_TIMER_H */
#
# Copyright 2021 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq (${ADD_TIMER},)
ADD_TIMER := 1
TIMER_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/timer
PLAT_INCLUDES += -I$(TIMER_DRIVERS_PATH)
TIMER_SOURCES += drivers/delay_timer/delay_timer.c \
$(PLAT_DRIVERS_PATH)/timer/nxp_timer.c
ifeq (${BL_COMM_TIMER_NEEDED},yes)
BL_COMMON_SOURCES += ${TIMER_SOURCES}
else
ifeq (${BL2_TIMER_NEEDED},yes)
BL2_SOURCES += ${TIMER_SOURCES}
endif
ifeq (${BL31_TIMER_NEEDED},yes)
BL31_SOURCES += ${TIMER_SOURCES}
endif
endif
endif
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <common/debug.h>
#include <plat_tzc400.h>
#pragma weak populate_tzc400_reg_list
#ifdef DEFAULT_TZASC_CONFIG
/*
* Typical Memory map of DRAM0
* |-----------NXP_NS_DRAM_ADDR ( = NXP_DRAM0_ADDR)----------|
* | |
* | |
* | Non-SECURE REGION |
* | |
* | |
* | |
* |------- (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE - 1) -------|
* |-----------------NXP_SECURE_DRAM_ADDR--------------------|
* | |
* | |
* | |
* | SECURE REGION (= 64MB) |
* | |
* | |
* | |
* |--- (NXP_SECURE_DRAM_ADDR + NXP_SECURE_DRAM_SIZE - 1)----|
* |-----------------NXP_SP_SHRD_DRAM_ADDR-------------------|
* | |
* | Secure EL1 Payload SHARED REGION (= 2MB) |
* | |
* |-----------(NXP_DRAM0_ADDR + NXP_DRAM0_SIZE - 1)---------|
*
*
*
* Typical Memory map of DRAM1
* |---------------------NXP_DRAM1_ADDR----------------------|
* | |
* | |
* | Non-SECURE REGION |
* | |
* | |
* |---(NXP_DRAM1_ADDR + Dynamically calculated Size - 1) ---|
*
*
* Typical Memory map of DRAM2
* |---------------------NXP_DRAM2_ADDR----------------------|
* | |
* | |
* | Non-SECURE REGION |
* | |
* | |
* |---(NXP_DRAM2_ADDR + Dynamically calculated Size - 1) ---|
*/
/*****************************************************************************
* This function sets up access permissions on memory regions
*
* Input:
* tzc400_reg_list : TZC400 Region List
* dram_idx : DRAM index
* list_idx : TZC400 Region List Index
* dram_start_addr : Start address of DRAM at dram_idx.
* dram_size : Size of DRAM at dram_idx.
* secure_dram_sz : Secure DRAM Size
* shrd_dram_sz : Shared DRAM Size
*
* Out:
* list_idx : last populated index + 1
*
****************************************************************************/
int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list,
int dram_idx, int list_idx,
uint64_t dram_start_addr,
uint64_t dram_size,
uint32_t secure_dram_sz,
uint32_t shrd_dram_sz)
{
if (list_idx == 0) {
/* No need to configure TZC Region 0 in this list.
*/
list_idx++;
}
/* Continue with list entries for index > 0 */
if (dram_idx == 0) {
/* TZC Region 1 on DRAM0 for Secure Memory*/
tzc400_reg_list[list_idx].reg_filter_en = 1;
tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size;
tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size
+ secure_dram_sz - 1;
tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR;
tzc400_reg_list[list_idx].nsaid_permissions = TZC_REGION_NS_NONE;
list_idx++;
/* TZC Region 2 on DRAM0 for Shared Memory*/
tzc400_reg_list[list_idx].reg_filter_en = 1;
tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size
+ secure_dram_sz;
tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size
+ secure_dram_sz
+ shrd_dram_sz
- 1;
tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR;
tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID;
list_idx++;
/* TZC Region 3 on DRAM0 for Non-Secure Memory*/
tzc400_reg_list[list_idx].reg_filter_en = 1;
tzc400_reg_list[list_idx].start_addr = dram_start_addr;
tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size
- 1;
tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR;
tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID;
list_idx++;
} else {
/* TZC Region 3+i on DRAM(> 0) for Non-Secure Memory*/
tzc400_reg_list[list_idx].reg_filter_en = 1;
tzc400_reg_list[list_idx].start_addr = dram_start_addr;
tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size
- 1;
tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR;
tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID;
list_idx++;
}
return list_idx;
}
#else
int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list,
int dram_idx, int list_idx,
uint64_t dram_start_addr,
uint64_t dram_size,
uint32_t secure_dram_sz,
uint32_t shrd_dram_sz)
{
ERROR("tzc400_reg_list used is not a default list\n");
ERROR("%s needs to be over-written.\n", __func__);
return 0;
}
#endif /* DEFAULT_TZASC_CONFIG */
/*******************************************************************************
* Configure memory access permissions
* - Region 0 with no access;
* - Region 1 to 4 as per the tzc400_reg_list populated by
* function populate_tzc400_reg_list() with default for all the SoC.
******************************************************************************/
void mem_access_setup(uintptr_t base, uint32_t total_regions,
struct tzc400_reg *tzc400_reg_list)
{
uint32_t list_indx = 0U;
INFO("Configuring TrustZone Controller\n");
tzc400_init(base);
/* Disable filters. */
tzc400_disable_filters();
/* Region 0 set to no access by default */
tzc400_configure_region0(TZC_REGION_S_NONE, 0U);
for (list_indx = 1U; list_indx < total_regions; list_indx++) {
tzc400_configure_region(
tzc400_reg_list[list_indx].reg_filter_en,
list_indx,
tzc400_reg_list[list_indx].start_addr,
tzc400_reg_list[list_indx].end_addr,
tzc400_reg_list[list_indx].sec_attr,
tzc400_reg_list[list_indx].nsaid_permissions);
}
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
tzc400_set_action(TZC_ACTION_ERR);
/* Enable filters. */
tzc400_enable_filters();
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#if !defined(PLAT_TZC400_H) && defined(IMAGE_BL2)
#define PLAT_TZC400_H
#include <tzc400.h>
/* Structure to configure TZC Regions' boundaries and attributes. */
struct tzc400_reg {
uint8_t reg_filter_en;
unsigned long long start_addr;
unsigned long long end_addr;
unsigned int sec_attr;
unsigned int nsaid_permissions;
};
#define TZC_REGION_NS_NONE 0x00000000U
/* NXP Platforms do not support NS Access ID (NSAID) based non-secure access.
* Supports only non secure through generic NS ACCESS ID
*/
#define TZC_NS_ACCESS_ID 0xFFFFFFFFU
/* Number of DRAM regions to be configured
* for the platform can be over-written.
*
* Array tzc400_reg_list too, needs be over-written
* if there is any changes to default DRAM region
* configuration.
*/
#ifndef MAX_NUM_TZC_REGION
/* 3 regions:
* Region 0(default),
* Region 1 (DRAM0, Secure Memory),
* Region 2 (DRAM0, Shared memory)
*/
#define MAX_NUM_TZC_REGION NUM_DRAM_REGIONS + 3
#define DEFAULT_TZASC_CONFIG 1
#endif
void mem_access_setup(uintptr_t base, uint32_t total_regions,
struct tzc400_reg *tzc400_reg_list);
int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list,
int dram_idx, int list_idx,
uint64_t dram_start_addr,
uint64_t dram_size,
uint32_t secure_dram_sz,
uint32_t shrd_dram_sz);
#endif /* PLAT_TZC400_H */
#
# Copyright 2021 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq (${ADD_TZASC},)
ADD_TZASC := 1
TZASC_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/tzc
PLAT_INCLUDES += -I$(TZASC_DRIVERS_PATH)
ifeq ($(TZC_ID), TZC400)
TZASC_SOURCES += drivers/arm/tzc/tzc400.c\
$(TZASC_DRIVERS_PATH)/plat_tzc400.c
else ifeq ($(TZC_ID), NONE)
$(info -> No TZC present on platform)
else
$(error -> TZC type not set!)
endif
ifeq (${BL_COMM_TZASC_NEEDED},yes)
BL_COMMON_SOURCES += ${TZASC_SOURCES}
else
ifeq (${BL2_TZASC_NEEDED},yes)
BL2_SOURCES += ${TZASC_SOURCES}
endif
ifeq (${BL31_TZASC_NEEDED},yes)
BL31_SOURCES += ${TZASC_SOURCES}
endif
endif
endif
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#ifndef COT_DEF_H #ifndef COT_DEF_H
#define COT_DEF_H #define COT_DEF_H
#ifdef MBEDTLS_CONFIG_FILE
#include MBEDTLS_CONFIG_FILE
#endif
/* TBBR CoT definitions */ /* TBBR CoT definitions */
#if defined(SPD_spmd) #if defined(SPD_spmd)
#define COT_MAX_VERIFIED_PARAMS 8 #define COT_MAX_VERIFIED_PARAMS 8
......
/* /*
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -21,9 +21,17 @@ ...@@ -21,9 +21,17 @@
#define SP_PKG7_ID (MAX_IMAGE_IDS + 8) #define SP_PKG7_ID (MAX_IMAGE_IDS + 8)
#define SP_PKG8_ID (MAX_IMAGE_IDS + 9) #define SP_PKG8_ID (MAX_IMAGE_IDS + 9)
#define MAX_SP_IDS U(8) #define MAX_SP_IDS U(8)
#define MAX_NUMBER_IDS (MAX_IMAGE_IDS + MAX_SP_IDS + U(2)) #define MAX_IMG_IDS_WITH_SPMDS (MAX_IMAGE_IDS + MAX_SP_IDS + U(2))
#else #else
#define MAX_NUMBER_IDS MAX_IMAGE_IDS #define MAX_IMG_IDS_WITH_SPMDS MAX_IMAGE_IDS
#endif
#ifdef PLAT_TBBR_IMG_DEF
#include <plat_tbbr_img_def.h>
#endif
#ifndef MAX_NUMBER_IDS
#define MAX_NUMBER_IDS MAX_IMG_IDS_WITH_SPMDS
#endif #endif
#endif /* TBBR_IMG_DEF_H */ #endif /* TBBR_IMG_DEF_H */
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