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