1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <string.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <drivers/io/io_driver.h> 11*91f16700Schasinglulu #include <drivers/io/io_storage.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include "emmc_config.h" 14*91f16700Schasinglulu #include "emmc_def.h" 15*91f16700Schasinglulu #include "emmc_hal.h" 16*91f16700Schasinglulu #include "emmc_std.h" 17*91f16700Schasinglulu #include "io_common.h" 18*91f16700Schasinglulu #include "io_emmcdrv.h" 19*91f16700Schasinglulu #include "io_private.h" 20*91f16700Schasinglulu 21*91f16700Schasinglulu static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), 22*91f16700Schasinglulu io_dev_info_t **dev_info); 23*91f16700Schasinglulu static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info); 24*91f16700Schasinglulu 25*91f16700Schasinglulu typedef struct { 26*91f16700Schasinglulu uint32_t in_use; 27*91f16700Schasinglulu uintptr_t base; 28*91f16700Schasinglulu signed long long file_pos; 29*91f16700Schasinglulu EMMC_PARTITION_ID partition; 30*91f16700Schasinglulu } file_state_t; 31*91f16700Schasinglulu 32*91f16700Schasinglulu static file_state_t current_file = { 0 }; 33*91f16700Schasinglulu 34*91f16700Schasinglulu static EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER; 35*91f16700Schasinglulu 36*91f16700Schasinglulu static io_type_t device_type_emmcdrv(void) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu return IO_TYPE_MEMMAP; 39*91f16700Schasinglulu } 40*91f16700Schasinglulu 41*91f16700Schasinglulu static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode, 42*91f16700Schasinglulu signed long long offset) 43*91f16700Schasinglulu { 44*91f16700Schasinglulu if (mode != IO_SEEK_SET) { 45*91f16700Schasinglulu return IO_FAIL; 46*91f16700Schasinglulu } 47*91f16700Schasinglulu 48*91f16700Schasinglulu ((file_state_t *) entity->info)->file_pos = offset; 49*91f16700Schasinglulu 50*91f16700Schasinglulu return IO_SUCCESS; 51*91f16700Schasinglulu } 52*91f16700Schasinglulu 53*91f16700Schasinglulu static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, 54*91f16700Schasinglulu size_t length, size_t *length_read) 55*91f16700Schasinglulu { 56*91f16700Schasinglulu file_state_t *fp = (file_state_t *) entity->info; 57*91f16700Schasinglulu uint32_t sector_add, sector_num, emmc_dma = 0; 58*91f16700Schasinglulu int32_t result = IO_SUCCESS; 59*91f16700Schasinglulu 60*91f16700Schasinglulu sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT; 61*91f16700Schasinglulu sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT; 62*91f16700Schasinglulu 63*91f16700Schasinglulu NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", 64*91f16700Schasinglulu buffer, 65*91f16700Schasinglulu current_file.partition, current_file.file_pos, 66*91f16700Schasinglulu sector_add, length, sector_num); 67*91f16700Schasinglulu 68*91f16700Schasinglulu if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) { 69*91f16700Schasinglulu emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num, 73*91f16700Schasinglulu emmc_dma) != EMMC_SUCCESS) { 74*91f16700Schasinglulu result = IO_FAIL; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu *length_read = length; 78*91f16700Schasinglulu fp->file_pos += (signed long long)length; 79*91f16700Schasinglulu 80*91f16700Schasinglulu return result; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, 84*91f16700Schasinglulu const uintptr_t spec, io_entity_t *entity) 85*91f16700Schasinglulu { 86*91f16700Schasinglulu const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; 87*91f16700Schasinglulu 88*91f16700Schasinglulu if (current_file.in_use != 0U) { 89*91f16700Schasinglulu WARN("mmc_block: Only one open spec at a time\n"); 90*91f16700Schasinglulu return IO_RESOURCES_EXHAUSTED; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu current_file.file_pos = 0; 94*91f16700Schasinglulu current_file.in_use = 1; 95*91f16700Schasinglulu 96*91f16700Schasinglulu if (emmcdrv_bootpartition == PARTITION_ID_USER) { 97*91f16700Schasinglulu emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en; 98*91f16700Schasinglulu if ((emmcdrv_bootpartition == PARTITION_ID_BOOT_1) || 99*91f16700Schasinglulu (emmcdrv_bootpartition == PARTITION_ID_BOOT_2)) { 100*91f16700Schasinglulu current_file.partition = emmcdrv_bootpartition; 101*91f16700Schasinglulu 102*91f16700Schasinglulu NOTICE("BL2: eMMC boot from partition %d\n", 103*91f16700Schasinglulu emmcdrv_bootpartition); 104*91f16700Schasinglulu goto done; 105*91f16700Schasinglulu } 106*91f16700Schasinglulu return IO_FAIL; 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu if ((block_spec->partition == PARTITION_ID_USER) || 110*91f16700Schasinglulu (block_spec->partition == PARTITION_ID_BOOT_1) || 111*91f16700Schasinglulu (block_spec->partition == PARTITION_ID_BOOT_2)) { 112*91f16700Schasinglulu current_file.partition = block_spec->partition; 113*91f16700Schasinglulu } else { 114*91f16700Schasinglulu current_file.partition = emmcdrv_bootpartition; 115*91f16700Schasinglulu } 116*91f16700Schasinglulu 117*91f16700Schasinglulu done: 118*91f16700Schasinglulu if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS) { 119*91f16700Schasinglulu return IO_FAIL; 120*91f16700Schasinglulu } 121*91f16700Schasinglulu 122*91f16700Schasinglulu entity->info = (uintptr_t) ¤t_file; 123*91f16700Schasinglulu 124*91f16700Schasinglulu return IO_SUCCESS; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu static int32_t emmcdrv_block_close(io_entity_t *entity) 128*91f16700Schasinglulu { 129*91f16700Schasinglulu memset((void *)¤t_file, 0, sizeof(current_file)); 130*91f16700Schasinglulu entity->info = 0U; 131*91f16700Schasinglulu 132*91f16700Schasinglulu return IO_SUCCESS; 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu static const io_dev_funcs_t emmcdrv_dev_funcs = { 136*91f16700Schasinglulu .type = &device_type_emmcdrv, 137*91f16700Schasinglulu .open = &emmcdrv_block_open, 138*91f16700Schasinglulu .seek = &emmcdrv_block_seek, 139*91f16700Schasinglulu .size = NULL, 140*91f16700Schasinglulu .read = &emmcdrv_block_read, 141*91f16700Schasinglulu .write = NULL, 142*91f16700Schasinglulu .close = &emmcdrv_block_close, 143*91f16700Schasinglulu .dev_init = NULL, 144*91f16700Schasinglulu .dev_close = &emmcdrv_dev_close 145*91f16700Schasinglulu }; 146*91f16700Schasinglulu 147*91f16700Schasinglulu static const io_dev_info_t emmcdrv_dev_info = { 148*91f16700Schasinglulu .funcs = &emmcdrv_dev_funcs, 149*91f16700Schasinglulu .info = (uintptr_t) 0 150*91f16700Schasinglulu }; 151*91f16700Schasinglulu 152*91f16700Schasinglulu static const io_dev_connector_t emmcdrv_dev_connector = { 153*91f16700Schasinglulu &emmcdrv_dev_open, 154*91f16700Schasinglulu }; 155*91f16700Schasinglulu 156*91f16700Schasinglulu static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), 157*91f16700Schasinglulu io_dev_info_t **dev_info) 158*91f16700Schasinglulu { 159*91f16700Schasinglulu *dev_info = (io_dev_info_t *) &emmcdrv_dev_info; 160*91f16700Schasinglulu 161*91f16700Schasinglulu return IO_SUCCESS; 162*91f16700Schasinglulu } 163*91f16700Schasinglulu 164*91f16700Schasinglulu static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info) 165*91f16700Schasinglulu { 166*91f16700Schasinglulu return IO_SUCCESS; 167*91f16700Schasinglulu } 168*91f16700Schasinglulu 169*91f16700Schasinglulu int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **dev_con) 170*91f16700Schasinglulu { 171*91f16700Schasinglulu int32_t rc; 172*91f16700Schasinglulu 173*91f16700Schasinglulu rc = io_register_device(&emmcdrv_dev_info); 174*91f16700Schasinglulu if (rc == IO_SUCCESS) { 175*91f16700Schasinglulu *dev_con = &emmcdrv_dev_connector; 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu return rc; 179*91f16700Schasinglulu } 180