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