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 "io_common.h" 14*2ddb5575SBiju Das #include "io_memdrv.h" 15*2ddb5575SBiju Das #include "io_private.h" 16*2ddb5575SBiju Das #include "rcar_def.h" 17*2ddb5575SBiju Das 18*2ddb5575SBiju Das extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len); 19*2ddb5575SBiju Das 20*2ddb5575SBiju Das static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), 21*2ddb5575SBiju Das io_dev_info_t **dev_info); 22*2ddb5575SBiju Das static int32_t memdrv_dev_close(io_dev_info_t *dev_info); 23*2ddb5575SBiju Das 24*2ddb5575SBiju Das /* 25*2ddb5575SBiju Das * As we need to be able to keep state for seek, only one file can be open 26*2ddb5575SBiju Das * at a time. Make this a structure and point to the entity->info. When we 27*2ddb5575SBiju Das * can malloc memory we can change this to support more open files. 28*2ddb5575SBiju Das */ 29*2ddb5575SBiju Das typedef struct { 30*2ddb5575SBiju Das uint32_t in_use; 31*2ddb5575SBiju Das uintptr_t base; 32*2ddb5575SBiju Das signed long long file_pos; 33*2ddb5575SBiju Das } file_state_t; 34*2ddb5575SBiju Das 35*2ddb5575SBiju Das static file_state_t current_file = { 0 }; 36*2ddb5575SBiju Das 37*2ddb5575SBiju Das static io_type_t device_type_memdrv(void) 38*2ddb5575SBiju Das { 39*2ddb5575SBiju Das return IO_TYPE_MEMMAP; 40*2ddb5575SBiju Das } 41*2ddb5575SBiju Das 42*2ddb5575SBiju Das static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, 43*2ddb5575SBiju Das io_entity_t *entity) 44*2ddb5575SBiju Das { 45*2ddb5575SBiju Das const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; 46*2ddb5575SBiju Das 47*2ddb5575SBiju Das /* 48*2ddb5575SBiju Das * Since we need to track open state for seek() we only allow one open 49*2ddb5575SBiju Das * spec at a time. When we have dynamic memory we can malloc and set 50*2ddb5575SBiju Das * entity->info. 51*2ddb5575SBiju Das */ 52*2ddb5575SBiju Das if (current_file.in_use != 0U) { 53*2ddb5575SBiju Das return IO_RESOURCES_EXHAUSTED; 54*2ddb5575SBiju Das } 55*2ddb5575SBiju Das 56*2ddb5575SBiju Das /* File cursor offset for seek and incremental reads etc. */ 57*2ddb5575SBiju Das current_file.base = block_spec->offset; 58*2ddb5575SBiju Das current_file.file_pos = 0; 59*2ddb5575SBiju Das current_file.in_use = 1; 60*2ddb5575SBiju Das 61*2ddb5575SBiju Das entity->info = (uintptr_t) ¤t_file; 62*2ddb5575SBiju Das 63*2ddb5575SBiju Das return IO_SUCCESS; 64*2ddb5575SBiju Das } 65*2ddb5575SBiju Das 66*2ddb5575SBiju Das static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode, 67*2ddb5575SBiju Das signed long long offset) 68*2ddb5575SBiju Das { 69*2ddb5575SBiju Das if (mode != IO_SEEK_SET) { 70*2ddb5575SBiju Das return IO_FAIL; 71*2ddb5575SBiju Das } 72*2ddb5575SBiju Das 73*2ddb5575SBiju Das ((file_state_t *) entity->info)->file_pos = offset; 74*2ddb5575SBiju Das 75*2ddb5575SBiju Das return IO_SUCCESS; 76*2ddb5575SBiju Das } 77*2ddb5575SBiju Das 78*2ddb5575SBiju Das static int32_t memdrv_block_read(io_entity_t *entity, uintptr_t buffer, 79*2ddb5575SBiju Das size_t length, size_t *cnt) 80*2ddb5575SBiju Das { 81*2ddb5575SBiju Das file_state_t *fp; 82*2ddb5575SBiju Das 83*2ddb5575SBiju Das fp = (file_state_t *) entity->info; 84*2ddb5575SBiju Das 85*2ddb5575SBiju Das NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", 86*2ddb5575SBiju Das buffer, (unsigned long long)fp->base + 87*2ddb5575SBiju Das (unsigned long long)fp->file_pos, length, length); 88*2ddb5575SBiju Das 89*2ddb5575SBiju Das if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { 90*2ddb5575SBiju Das ERROR("BL2: check load image (source address)\n"); 91*2ddb5575SBiju Das return IO_FAIL; 92*2ddb5575SBiju Das } 93*2ddb5575SBiju Das 94*2ddb5575SBiju Das rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); 95*2ddb5575SBiju Das fp->file_pos += (signed long long)length; 96*2ddb5575SBiju Das *cnt = length; 97*2ddb5575SBiju Das 98*2ddb5575SBiju Das return IO_SUCCESS; 99*2ddb5575SBiju Das } 100*2ddb5575SBiju Das 101*2ddb5575SBiju Das static int32_t memdrv_block_close(io_entity_t *entity) 102*2ddb5575SBiju Das { 103*2ddb5575SBiju Das entity->info = 0U; 104*2ddb5575SBiju Das 105*2ddb5575SBiju Das memset((void *)¤t_file, 0, sizeof(current_file)); 106*2ddb5575SBiju Das 107*2ddb5575SBiju Das return IO_SUCCESS; 108*2ddb5575SBiju Das } 109*2ddb5575SBiju Das 110*2ddb5575SBiju Das static const io_dev_funcs_t memdrv_dev_funcs = { 111*2ddb5575SBiju Das .type = &device_type_memdrv, 112*2ddb5575SBiju Das .open = &memdrv_block_open, 113*2ddb5575SBiju Das .seek = &memdrv_block_seek, 114*2ddb5575SBiju Das .size = NULL, 115*2ddb5575SBiju Das .read = &memdrv_block_read, 116*2ddb5575SBiju Das .write = NULL, 117*2ddb5575SBiju Das .close = &memdrv_block_close, 118*2ddb5575SBiju Das .dev_init = NULL, 119*2ddb5575SBiju Das .dev_close = &memdrv_dev_close, 120*2ddb5575SBiju Das }; 121*2ddb5575SBiju Das 122*2ddb5575SBiju Das static const io_dev_info_t memdrv_dev_info = { 123*2ddb5575SBiju Das .funcs = &memdrv_dev_funcs, 124*2ddb5575SBiju Das .info = 0, 125*2ddb5575SBiju Das }; 126*2ddb5575SBiju Das 127*2ddb5575SBiju Das static const io_dev_connector_t memdrv_dev_connector = { 128*2ddb5575SBiju Das .dev_open = &memdrv_dev_open 129*2ddb5575SBiju Das }; 130*2ddb5575SBiju Das 131*2ddb5575SBiju Das static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), 132*2ddb5575SBiju Das io_dev_info_t **dev_info) 133*2ddb5575SBiju Das { 134*2ddb5575SBiju Das *dev_info = (io_dev_info_t *) &memdrv_dev_info; 135*2ddb5575SBiju Das 136*2ddb5575SBiju Das return IO_SUCCESS; 137*2ddb5575SBiju Das } 138*2ddb5575SBiju Das 139*2ddb5575SBiju Das static int32_t memdrv_dev_close(io_dev_info_t *dev_info) 140*2ddb5575SBiju Das { 141*2ddb5575SBiju Das return IO_SUCCESS; 142*2ddb5575SBiju Das } 143*2ddb5575SBiju Das 144*2ddb5575SBiju Das int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **dev_con) 145*2ddb5575SBiju Das { 146*2ddb5575SBiju Das int32_t result; 147*2ddb5575SBiju Das 148*2ddb5575SBiju Das result = io_register_device(&memdrv_dev_info); 149*2ddb5575SBiju Das if (result == IO_SUCCESS) { 150*2ddb5575SBiju Das *dev_con = &memdrv_dev_connector; 151*2ddb5575SBiju Das } 152*2ddb5575SBiju Das 153*2ddb5575SBiju Das return result; 154*2ddb5575SBiju Das } 155