xref: /arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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) &current_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 *)&current_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