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