xref: /rk3399_ARM-atf/drivers/renesas/common/io/io_memdrv.c (revision 2ddb55752b9da7ebf6c725d2e1e2bb04c82c76b9)
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) &current_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 *)&current_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