diff options
-rw-r--r-- | bl1/bl1_main.c | 4 | ||||
-rw-r--r-- | docs/plat/rpi3.rst | 8 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 714 | ||||
-rw-r--r-- | include/drivers/mmc.h | 222 | ||||
-rw-r--r-- | include/plat/arm/common/plat_arm.h | 2 | ||||
-rw-r--r-- | plat/arm/board/fvp/fvp_bl2u_setup.c | 2 | ||||
-rw-r--r-- | plat/arm/common/arm_bl1_setup.c | 2 | ||||
-rw-r--r-- | plat/arm/common/arm_bl2_setup.c | 3 | ||||
-rw-r--r-- | plat/arm/common/arm_bl2u_setup.c | 4 | ||||
-rw-r--r-- | plat/arm/common/arm_bl31_setup.c | 2 | ||||
-rw-r--r-- | plat/arm/common/arm_common.c | 2 | ||||
-rw-r--r-- | plat/arm/common/arm_image_load.c | 4 | ||||
-rw-r--r-- | plat/arm/common/arm_pm.c | 3 | ||||
-rw-r--r-- | plat/common/plat_bl1_common.c | 4 | ||||
-rw-r--r-- | plat/rpi3/include/platform_def.h | 6 | ||||
-rw-r--r-- | plat/rpi3/rpi3_common.c | 21 | ||||
-rw-r--r-- | services/spd/opteed/opteed_main.c | 2 | ||||
-rw-r--r-- | services/spd/opteed/opteed_private.h | 2 |
18 files changed, 976 insertions, 31 deletions
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index 64b363c5..047cd6fb 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -74,8 +74,8 @@ void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, * populates a new memory layout for BL2 that ensures that BL1's data sections * resident in secure RAM are not visible to BL2. ******************************************************************************/ -void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, - meminfo_t *bl2_mem_layout) +void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout, + struct meminfo *bl2_mem_layout) { bl1_calc_bl2_mem_layout(bl1_mem_layout, bl2_mem_layout); } diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst index c8e2405c..5ac90853 100644 --- a/docs/plat/rpi3.rst +++ b/docs/plat/rpi3.rst @@ -123,7 +123,7 @@ secure platform! | Secure SRAM | BL2, BL31 0x10100000 +-----------------+ | Secure DRAM | BL32 (Secure payload) - 0x10300000 +-----------------+ + 0x10C00000 +-----------------+ | Non-secure DRAM | BL33 0x11000000 +-----------------+ | | @@ -243,6 +243,12 @@ The following build options are supported: BL32_EXTRA1=tee-pager_v2.bin BL32_EXTRA2=tee-pageable_v2.bin`` to put the binaries into the FIP. + Note: If OP-TEE is used it may be needed to add the following options to the + Linux command line so that the USB driver doesn't use FIQs: + ``dwc_otg.fiq_enable=0 dwc_otg.fiq_fsm_enable=0 dwc_otg.nak_holdoff=0``. + This will unfortunately reduce the performance of the USB driver. It is needed + when using Raspbian, for example. + - ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option ``TRUSTED_BOARD_BOOT=1`` to enable it. In order to use TBB, you might want to set ``GENERATE_COT=1`` to let the contents of the FIP automatically diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c new file mode 100644 index 00000000..8fe3239e --- /dev/null +++ b/drivers/mmc/mmc.c @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Define a simple and generic interface to access eMMC and SD-card devices. */ + +#include <arch_helpers.h> +#include <assert.h> +#include <debug.h> +#include <errno.h> +#include <mmc.h> +#include <stdbool.h> +#include <string.h> +#include <utils.h> + +#define MMC_DEFAULT_MAX_RETRIES 5 +#define SEND_OP_COND_MAX_RETRIES 100 + +#define MULT_BY_512K_SHIFT 19 + +static const struct mmc_ops *ops; +static unsigned int mmc_ocr_value; +static struct mmc_csd_emmc mmc_csd; +static unsigned char mmc_ext_csd[512] __aligned(4); +static unsigned int mmc_flags; +static struct mmc_device_info *mmc_dev_info; +static unsigned int rca; + +static const unsigned char tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 +}; + +static const unsigned char sd_tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 +}; + +static bool is_cmd23_enabled(void) +{ + return ((mmc_flags & MMC_FLAG_CMD23) != 0U); +} + +static int mmc_send_cmd(unsigned int idx, unsigned int arg, + unsigned int r_type, unsigned int *r_data) +{ + struct mmc_cmd cmd; + int ret; + + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = idx; + cmd.cmd_arg = arg; + cmd.resp_type = r_type; + + ret = ops->send_cmd(&cmd); + + if ((ret == 0) && (r_data != NULL)) { + int i; + + for (i = 0; i < 4; i++) { + *r_data = cmd.resp_data[i]; + r_data++; + } + } + + if (ret != 0) { + VERBOSE("Send command %u error: %d\n", idx, ret); + } + + return ret; +} + +static int mmc_device_state(void) +{ + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int resp_data[4]; + + do { + int ret; + + if (retries == 0) { + ERROR("CMD13 failed after %d retries\n", + MMC_DEFAULT_MAX_RETRIES); + return -EIO; + } + + ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(1), &resp_data[0]); + if (ret != 0) { + return ret; + } + + if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { + return -EIO; + } + + retries--; + } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U); + + return MMC_GET_STATE(resp_data[0]); +} + +static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value) +{ + int ret; + + ret = mmc_send_cmd(MMC_CMD(6), + EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) | + EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL, + 0, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_sd_switch(unsigned int bus_width) +{ + int ret; + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int scr[2] = { 0 }; + unsigned int bus_width_arg = 0; + + ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + /* ACMD51: SEND_SCR */ + do { + ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R(1), NULL); + if ((ret != 0) && (retries == 0)) { + ERROR("ACMD51 failed after %d retries (ret=%d)\n", + MMC_DEFAULT_MAX_RETRIES, ret); + return ret; + } + + retries--; + } while (ret != 0); + + ret = ops->read(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) && + (bus_width == MMC_BUS_WIDTH_4)) { + bus_width_arg = 2; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + /* ACMD6: SET_BUS_WIDTH */ + ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_set_ios(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int width = bus_width; + + if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) { + if (width == MMC_BUS_WIDTH_8) { + WARN("Wrong bus config for SD-card, force to 4\n"); + width = MMC_BUS_WIDTH_4; + } + ret = mmc_sd_switch(width); + if (ret != 0) { + return ret; + } + } else if (mmc_csd.spec_vers == 4U) { + ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH, + (unsigned int)width); + if (ret != 0) { + return ret; + } + } else { + VERBOSE("Wrong MMC type or spec version\n"); + } + + return ops->set_ios(clk, width); +} + +static int mmc_fill_device_info(void) +{ + unsigned long long c_size; + unsigned int speed_idx; + unsigned int nb_blocks; + unsigned int freq_unit; + int ret; + struct mmc_csd_sd_v2 *csd_sd_v2; + + switch (mmc_dev_info->mmc_dev_type) { + case MMC_IS_EMMC: + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + /* MMC CMD8: SEND_EXT_CSD */ + ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + ret = ops->read(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24); + + mmc_dev_info->device_size = (unsigned long long)nb_blocks * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD: + /* + * Use the same mmc_csd struct, as required fields here + * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC. + */ + mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len); + + c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) | + (unsigned long long)mmc_csd.c_size_low; + assert(c_size != 0xFFFU); + + mmc_dev_info->device_size = (c_size + 1U) * + BIT_64(mmc_csd.c_size_mult + 2U) * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD_HC: + assert(mmc_csd.csd_structure == 1U); + + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + /* Need to use mmc_csd_sd_v2 struct */ + csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd; + c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) | + (unsigned long long)csd_sd_v2->c_size_low; + + mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT; + + break; + + default: + ret = -EINVAL; + break; + } + + if (ret != 0) { + return ret; + } + + speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >> + CSD_TRAN_SPEED_MULT_SHIFT; + + assert(speed_idx > 0U); + + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx]; + } else { + mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx]; + } + + freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK; + while (freq_unit != 0U) { + mmc_dev_info->max_bus_freq *= 10U; + --freq_unit; + } + + mmc_dev_info->max_bus_freq *= 10000U; + + return 0; +} + +static int sd_send_op_cond(void) +{ + int retries = SEND_OP_COND_MAX_RETRIES; + unsigned int resp_data[4]; + + do { + int ret; + + if (retries == 0) { + ERROR("ACMD41 failed after %d retries\n", + SEND_OP_COND_MAX_RETRIES); + return -EIO; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + /* ACMD41: SD_SEND_OP_COND */ + ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R(3), + &resp_data[0]); + if (ret != 0) { + return ret; + } + + retries--; + } while ((resp_data[0] & OCR_POWERUP) == 0U); + + mmc_ocr_value = resp_data[0]; + + if ((mmc_ocr_value & OCR_HCS) != 0U) { + mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC; + } else { + mmc_dev_info->mmc_dev_type = MMC_IS_SD; + } + + return 0; +} + +static int mmc_send_op_cond(void) +{ + int ret; + int retries = SEND_OP_COND_MAX_RETRIES; + unsigned int resp_data[4]; + + /* CMD0: reset to IDLE */ + ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); + if (ret != 0) { + return ret; + } + + do { + if (retries == 0) { + ERROR("CMD1 failed after %d retries\n", + SEND_OP_COND_MAX_RETRIES); + return -EIO; + } + + /* CMD1: get OCR register (SEND_OP_COND) */ + ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE | + OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7, + MMC_RESPONSE_R(3), &resp_data[0]); + if (ret != 0) { + return ret; + } + + retries--; + } while ((resp_data[0] & OCR_POWERUP) == 0U); + + mmc_ocr_value = resp_data[0]; + + return 0; +} + +static int mmc_enumerate(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int resp_data[4]; + + ops->init(); + + /* CMD0: reset to IDLE */ + ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); + if (ret != 0) { + return ret; + } + + /* CMD8: Send Interface Condition Command */ + ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN, + MMC_RESPONSE_R(7), &resp_data[0]); + + if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) { + ret = sd_send_op_cond(); + } else { + ret = mmc_send_op_cond(); + } + if (ret != 0) { + return ret; + } + + /* CMD2: Card Identification */ + ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R(2), NULL); + if (ret != 0) { + return ret; + } + + /* CMD3: Set Relative Address */ + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + rca = MMC_FIX_RCA; + ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + } else { + ret = mmc_send_cmd(MMC_CMD(3), 0, + MMC_RESPONSE_R(6), &resp_data[0]); + if (ret != 0) { + return ret; + } + + rca = (resp_data[0] & 0xFFFF0000U) >> 16; + } + + /* CMD9: CSD Register */ + ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(2), &resp_data[0]); + if (ret != 0) { + return ret; + } + + memcpy(&mmc_csd, &resp_data, sizeof(resp_data)); + + /* CMD7: Select Card */ + ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret != MMC_STATE_TRAN); + + ret = mmc_fill_device_info(); + if (ret != 0) { + return ret; + } + + return mmc_set_ios(clk, bus_width); +} + +size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->read != NULL) && + (size != 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(18); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(18); + } else { + cmd_idx = MMC_CMD(17); + } + } + + if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) && + (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + ret = ops->read(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->write != NULL) && + (size != 0U) && + ((buf & MMC_BLOCK_MASK) == 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(25); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(25); + } else { + cmd_idx = MMC_CMD(24); + } + } + + if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + ret = ops->write(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_erase_blocks(unsigned int lba, size_t size) +{ + int ret; + + assert(ops != NULL); + assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U)); + + ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U, + MMC_RESPONSE_R(1), NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R(0x1B), NULL); + if (ret != 0) { + return 0; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while (ret != MMC_STATE_TRAN); + + return size; +} + +static inline void mmc_rpmb_enable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE | + PART_CFG_PARTITION1_ACCESS); +} + +static inline void mmc_rpmb_disable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE); +} + +size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size) +{ + size_t size_read; + + mmc_rpmb_enable(); + size_read = mmc_read_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_read; +} + +size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf, size_t size) +{ + size_t size_written; + + mmc_rpmb_enable(); + size_written = mmc_write_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_written; +} + +size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size) +{ + size_t size_erased; + + mmc_rpmb_enable(); + size_erased = mmc_erase_blocks(lba, size); + mmc_rpmb_disable(); + + return size_erased; +} + +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info) +{ + assert((ops_ptr != NULL) && + (ops_ptr->init != NULL) && + (ops_ptr->send_cmd != NULL) && + (ops_ptr->set_ios != NULL) && + (ops_ptr->prepare != NULL) && + (ops_ptr->read != NULL) && + (ops_ptr->write != NULL) && + (device_info != NULL) && + (clk != 0) && + ((width == MMC_BUS_WIDTH_1) || + (width == MMC_BUS_WIDTH_4) || + (width == MMC_BUS_WIDTH_8) || + (width == MMC_BUS_WIDTH_DDR_4) || + (width == MMC_BUS_WIDTH_DDR_8))); + + ops = ops_ptr; + mmc_flags = flags; + mmc_dev_info = device_info; + + return mmc_enumerate(clk, width); +} diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h new file mode 100644 index 00000000..65f4bbdc --- /dev/null +++ b/include/drivers/mmc.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MMC_H__ +#define __MMC_H__ + +#include <stdint.h> +#include <utils_def.h> + +#define MMC_BLOCK_SIZE U(512) +#define MMC_BLOCK_MASK (MMC_BLOCK_SIZE - U(1)) +#define MMC_BOOT_CLK_RATE (400 * 1000) + +#define MMC_CMD(_x) U(_x) + +#define MMC_ACMD(_x) U(_x) + +#define OCR_POWERUP BIT(31) +#define OCR_HCS BIT(30) +#define OCR_BYTE_MODE (U(0) << 29) +#define OCR_SECTOR_MODE (U(2) << 29) +#define OCR_ACCESS_MODE_MASK (U(3) << 29) +#define OCR_3_5_3_6 BIT(23) +#define OCR_3_4_3_5 BIT(22) +#define OCR_3_3_3_4 BIT(21) +#define OCR_3_2_3_3 BIT(20) +#define OCR_3_1_3_2 BIT(19) +#define OCR_3_0_3_1 BIT(18) +#define OCR_2_9_3_0 BIT(17) +#define OCR_2_8_2_9 BIT(16) +#define OCR_2_7_2_8 BIT(15) +#define OCR_VDD_MIN_2V7 GENMASK(23, 15) +#define OCR_VDD_MIN_2V0 GENMASK(14, 8) +#define OCR_VDD_MIN_1V7 BIT(7) + +#define MMC_RESPONSE_R(_x) U(_x) + +/* Value randomly chosen for eMMC RCA, it should be > 1 */ +#define MMC_FIX_RCA 6 +#define RCA_SHIFT_OFFSET 16 + +#define CMD_EXTCSD_PARTITION_CONFIG 179 +#define CMD_EXTCSD_BUS_WIDTH 183 +#define CMD_EXTCSD_HS_TIMING 185 +#define CMD_EXTCSD_SEC_CNT 212 + +#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3) +#define PART_CFG_PARTITION1_ACCESS (U(1) << 0) + +/* Values in EXT CSD register */ +#define MMC_BUS_WIDTH_1 U(0) +#define MMC_BUS_WIDTH_4 U(1) +#define MMC_BUS_WIDTH_8 U(2) +#define MMC_BUS_WIDTH_DDR_4 U(5) +#define MMC_BUS_WIDTH_DDR_8 U(6) +#define MMC_BOOT_MODE_BACKWARD (U(0) << 3) +#define MMC_BOOT_MODE_HS_TIMING (U(1) << 3) +#define MMC_BOOT_MODE_DDR (U(2) << 3) + +#define EXTCSD_SET_CMD (U(0) << 24) +#define EXTCSD_SET_BITS (U(1) << 24) +#define EXTCSD_CLR_BITS (U(2) << 24) +#define EXTCSD_WRITE_BYTES (U(3) << 24) +#define EXTCSD_CMD(x) (((x) & 0xff) << 16) +#define EXTCSD_VALUE(x) (((x) & 0xff) << 8) +#define EXTCSD_CMD_SET_NORMAL U(1) + +#define CSD_TRAN_SPEED_UNIT_MASK GENMASK(2, 0) +#define CSD_TRAN_SPEED_MULT_MASK GENMASK(6, 3) +#define CSD_TRAN_SPEED_MULT_SHIFT 3 + +#define STATUS_CURRENT_STATE(x) (((x) & 0xf) << 9) +#define STATUS_READY_FOR_DATA BIT(8) +#define STATUS_SWITCH_ERROR BIT(7) +#define MMC_GET_STATE(x) (((x) >> 9) & 0xf) +#define MMC_STATE_IDLE 0 +#define MMC_STATE_READY 1 +#define MMC_STATE_IDENT 2 +#define MMC_STATE_STBY 3 +#define MMC_STATE_TRAN 4 +#define MMC_STATE_DATA 5 +#define MMC_STATE_RCV 6 +#define MMC_STATE_PRG 7 +#define MMC_STATE_DIS 8 +#define MMC_STATE_BTST 9 +#define MMC_STATE_SLP 10 + +#define MMC_FLAG_CMD23 (U(1) << 0) + +#define CMD8_CHECK_PATTERN U(0xAA) +#define VHS_2_7_3_6_V BIT(8) + +#define SD_SCR_BUS_WIDTH_1 BIT(8) +#define SD_SCR_BUS_WIDTH_4 BIT(10) + +struct mmc_cmd { + unsigned int cmd_idx; + unsigned int cmd_arg; + unsigned int resp_type; + unsigned int resp_data[4]; +}; + +struct mmc_ops { + void (*init)(void); + int (*send_cmd)(struct mmc_cmd *cmd); + int (*set_ios)(unsigned int clk, unsigned int width); + int (*prepare)(int lba, uintptr_t buf, size_t size); + int (*read)(int lba, uintptr_t buf, size_t size); + int (*write)(int lba, const uintptr_t buf, size_t size); +}; + +struct mmc_csd_emmc { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int ecc: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_1: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int default_ecc: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 5; + unsigned int erase_grp_mult: 5; + unsigned int erase_grp_size: 5; + unsigned int c_size_mult: 3; + unsigned int vdd_w_curr_max: 3; + unsigned int vdd_w_curr_min: 3; + unsigned int vdd_r_curr_max: 3; + unsigned int vdd_r_curr_min: 3; + unsigned int c_size_low: 2; + + unsigned int c_size_high: 10; + unsigned int reserved_2: 2; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_3: 2; + unsigned int spec_vers: 4; + unsigned int csd_structure: 2; +}; + +struct mmc_csd_sd_v2 { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int reserved_1: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_2: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int reserved_3: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 7; + unsigned int sector_size: 7; + unsigned int erase_block_en: 1; + unsigned int reserved_4: 1; + unsigned int c_size_low: 16; + + unsigned int c_size_high: 6; + unsigned int reserved_5: 6; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_6: 6; + unsigned int csd_structure: 2; +}; + +enum mmc_device_type { + MMC_IS_EMMC, + MMC_IS_SD, + MMC_IS_SD_HC, +}; + +struct mmc_device_info { + unsigned long long device_size; /* Size of device in bytes */ + unsigned int block_size; /* Block size in bytes */ + unsigned int max_bus_freq; /* Max bus freq in Hz */ + enum mmc_device_type mmc_dev_type; /* Type of MMC */ +}; + +size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size); +size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size); +size_t mmc_erase_blocks(unsigned int lba, size_t size); +size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size); +size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf, + size_t size); +size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size); +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info); + +#endif /* __MMC_H__ */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 473b758a..42bbf385 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -86,7 +86,7 @@ void arm_setup_page_tables(uintptr_t total_base, * Use this macro to instantiate lock before it is used in below * arm_lock_xxx() macros */ -#define ARM_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(arm_lock) +#define ARM_INSTANTIATE_LOCK static DEFINE_BAKERY_LOCK(arm_lock) #define ARM_LOCK_GET_INSTANCE (&arm_lock) /* * These are wrapper macros to the Coherent Memory Bakery Lock API. diff --git a/plat/arm/board/fvp/fvp_bl2u_setup.c b/plat/arm/board/fvp/fvp_bl2u_setup.c index 361e84de..b9ab3f36 100644 --- a/plat/arm/board/fvp/fvp_bl2u_setup.c +++ b/plat/arm/board/fvp/fvp_bl2u_setup.c @@ -9,7 +9,7 @@ #include "fvp_def.h" #include "fvp_private.h" -void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) +void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) { arm_bl2u_early_platform_setup(mem_layout, plat_info); diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 34e0a29e..c9b1a68a 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -27,7 +27,7 @@ /* Data structure which holds the extents of the trusted SRAM for BL1*/ static meminfo_t bl1_tzram_layout; -meminfo_t *bl1_plat_sec_mem_layout(void) +struct meminfo *bl1_plat_sec_mem_layout(void) { return &bl1_tzram_layout; } diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index 3aa99f80..33c2fe85 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -172,7 +172,8 @@ struct entry_point_info *bl2_plat_get_bl31_ep_info(void) * in x0. This memory layout is sitting at the base of the free trusted SRAM. * Copy it to a safe location before its reclaimed by later BL2 functionality. ******************************************************************************/ -void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout) +void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, + struct meminfo *mem_layout) { /* Initialize the console to provide early debug support */ arm_console_boot_init(); diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index cd691e5c..dce00e5b 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -32,7 +32,7 @@ void bl2u_platform_setup(void) arm_bl2u_platform_setup(); } -void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) +void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) { /* Initialize the console to provide early debug support */ arm_console_boot_init(); @@ -46,7 +46,7 @@ void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) * In case of ARM FVP platforms x1 is not used. * In both cases, x0 contains the extents of the memory available to BL2U ******************************************************************************/ -void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) +void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) { arm_bl2u_early_platform_setup(mem_layout, plat_info); } diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 6346f0ff..b1f95c95 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -44,7 +44,7 @@ CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows); * while BL32 corresponds to the secure image type. A NULL pointer is returned * if the image does not exist. ******************************************************************************/ -entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) { entry_point_info_t *next_image_info; diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 32fd9ee6..270abb2b 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -14,8 +14,6 @@ #include <platform.h> #include <secure_partition.h> -extern const mmap_region_t plat_arm_mmap[]; - /* Weak definitions may be overridden in specific ARM standard platform */ #pragma weak plat_get_ns_image_entrypoint #pragma weak plat_arm_get_mmap diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c index 916fa8dc..4f86efdf 100644 --- a/plat/arm/common/arm_image_load.c +++ b/plat/arm/common/arm_image_load.c @@ -28,7 +28,7 @@ void plat_flush_next_bl_params(void) /******************************************************************************* * This function returns the list of loadable images. ******************************************************************************/ -bl_load_info_t *plat_get_bl_image_load_info(void) +struct bl_load_info *plat_get_bl_image_load_info(void) { return get_bl_load_info_from_mem_params_desc(); } @@ -36,7 +36,7 @@ bl_load_info_t *plat_get_bl_image_load_info(void) /******************************************************************************* * This function returns the list of executable images. ******************************************************************************/ -bl_params_t *plat_get_next_bl_params(void) +struct bl_params *plat_get_next_bl_params(void) { bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc(); diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index 73d7106b..d0350d6c 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -18,9 +18,6 @@ #pragma weak plat_arm_psci_override_pm_ops #pragma weak plat_arm_program_trusted_mailbox -/* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ -extern plat_psci_ops_t plat_arm_psci_pm_ops; - #if ARM_RECOM_STATE_ID_ENC extern unsigned int arm_pm_idle_states[]; #endif /* __ARM_RECOM_STATE_ID_ENC__ */ diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c index c5bbe743..67779799 100644 --- a/plat/common/plat_bl1_common.c +++ b/plat/common/plat_bl1_common.c @@ -34,7 +34,7 @@ unsigned int bl1_plat_get_next_image_id(void) } void bl1_plat_set_ep_info(unsigned int image_id, - entry_point_info_t *ep_info) + struct entry_point_info *ep_info) { } @@ -48,7 +48,7 @@ int bl1_plat_handle_pre_image_load(unsigned int image_id) * Following is the default definition that always * returns BL2 image details. */ -image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id) { static image_desc_t bl2_img_desc = BL2_IMAGE_DESC; return &bl2_img_desc; diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h index 2cd0dff2..5b84aa61 100644 --- a/plat/rpi3/include/platform_def.h +++ b/plat/rpi3/include/platform_def.h @@ -75,10 +75,10 @@ #define SEC_SRAM_SIZE ULL(0x00100000) #define SEC_DRAM0_BASE ULL(0x10100000) -#define SEC_DRAM0_SIZE ULL(0x00200000) +#define SEC_DRAM0_SIZE ULL(0x00B00000) -#define NS_DRAM0_BASE ULL(0x10300000) -#define NS_DRAM0_SIZE ULL(0x00D00000) +#define NS_DRAM0_BASE ULL(0x10C00000) +#define NS_DRAM0_SIZE ULL(0x00400000) /* End of reserved memory */ /* diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c index 65f5e7ad..98cf534c 100644 --- a/plat/rpi3/rpi3_common.c +++ b/plat/rpi3/rpi3_common.c @@ -5,6 +5,7 @@ */ #include <arch_helpers.h> +#include <assert.h> #include <bl_common.h> #include <console.h> #include <debug.h> @@ -198,15 +199,21 @@ unsigned int plat_get_syscnt_freq2(void) uint32_t plat_ic_get_pending_interrupt_type(void) { + ERROR("rpi3: Interrupt routed to EL3.\n"); return INTR_TYPE_INVAL; } -uint32_t plat_interrupt_type_to_line(uint32_t type, - uint32_t security_state) +uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state) { - /* It is not expected to receive an interrupt route to EL3. - * Hence panic() to flag error. - */ - ERROR("Interrupt not expected to be routed to EL3"); - panic(); + assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) || + (type == INTR_TYPE_NS)); + + assert(sec_state_is_valid(security_state)); + + /* Non-secure interrupts are signalled on the IRQ line always. */ + if (type == INTR_TYPE_NS) + return __builtin_ctz(SCR_IRQ_BIT); + + /* Secure interrupts are signalled on the FIQ line always. */ + return __builtin_ctz(SCR_FIQ_BIT); } diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c index 01ec2a26..59d6ed29 100644 --- a/services/spd/opteed/opteed_main.c +++ b/services/spd/opteed/opteed_main.c @@ -34,7 +34,7 @@ * Address of the entrypoint vector table in OPTEE. It is * initialised once on the primary core after a cold boot. ******************************************************************************/ -optee_vectors_t *optee_vector_table; +struct optee_vectors *optee_vector_table; /******************************************************************************* * Array to keep track of per-cpu OPTEE state diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h index b77b6d34..a5f0a416 100644 --- a/services/spd/opteed/opteed_private.h +++ b/services/spd/opteed/opteed_private.h @@ -144,7 +144,7 @@ uint64_t opteed_enter_sp(uint64_t *c_rt_ctx); void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret); uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx); void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret); -void opteed_init_optee_ep_state(struct entry_point_info *optee_ep, +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, uint32_t rw, uint64_t pc, uint64_t pageable_part, |