blob: 1f31c0fb93833a69f34502d2c60ab5970d22ae3e [file] [log] [blame]
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02001/*
Biju Das50bfdc42020-12-13 20:28:45 +00002 * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02007#include <string.h>
8
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#include <common/debug.h>
10#include <drivers/io/io_driver.h>
11#include <drivers/io/io_storage.h>
12
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020013#include "io_common.h"
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020014#include "io_memdrv.h"
Biju Das50bfdc42020-12-13 20:28:45 +000015#include "io_private.h"
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020016#include "rcar_def.h"
17
18extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len);
19
20static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)),
21 io_dev_info_t **dev_info);
22static int32_t memdrv_dev_close(io_dev_info_t *dev_info);
23
Biju Das50bfdc42020-12-13 20:28:45 +000024/*
25 * As we need to be able to keep state for seek, only one file can be open
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020026 * 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 */
29typedef struct {
30 uint32_t in_use;
31 uintptr_t base;
Yann Gautierf30cddc2019-04-16 11:35:19 +020032 signed long long file_pos;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020033} file_state_t;
34
35static file_state_t current_file = { 0 };
36
37static io_type_t device_type_memdrv(void)
38{
39 return IO_TYPE_MEMMAP;
40}
41
42static 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
Biju Das50bfdc42020-12-13 20:28:45 +000047 /*
48 * Since we need to track open state for seek() we only allow one open
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020049 * spec at a time. When we have dynamic memory we can malloc and set
50 * entity->info.
51 */
Biju Das50bfdc42020-12-13 20:28:45 +000052 if (current_file.in_use != 0U) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020053 return IO_RESOURCES_EXHAUSTED;
Biju Das50bfdc42020-12-13 20:28:45 +000054 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020055
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
66static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode,
Yann Gautierf30cddc2019-04-16 11:35:19 +020067 signed long long offset)
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020068{
Biju Das50bfdc42020-12-13 20:28:45 +000069 if (mode != IO_SEEK_SET) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020070 return IO_FAIL;
Biju Das50bfdc42020-12-13 20:28:45 +000071 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020072
73 ((file_state_t *) entity->info)->file_pos = offset;
74
75 return IO_SUCCESS;
76}
77
78static 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
Yann Gautierf30cddc2019-04-16 11:35:19 +020085 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);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020088
Yann Gautierf30cddc2019-04-16 11:35:19 +020089 if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020090 ERROR("BL2: check load image (source address)\n");
91 return IO_FAIL;
92 }
93
Yann Gautierf30cddc2019-04-16 11:35:19 +020094 rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length);
95 fp->file_pos += (signed long long)length;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020096 *cnt = length;
97
98 return IO_SUCCESS;
99}
100
101static 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
110static 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
122static const io_dev_info_t memdrv_dev_info = {
123 .funcs = &memdrv_dev_funcs,
124 .info = 0,
125};
126
127static const io_dev_connector_t memdrv_dev_connector = {
128 .dev_open = &memdrv_dev_open
129};
130
131static 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
139static int32_t memdrv_dev_close(io_dev_info_t *dev_info)
140{
141 return IO_SUCCESS;
142}
143
144int32_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);
Biju Das50bfdc42020-12-13 20:28:45 +0000149 if (result == IO_SUCCESS) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200150 *dev_con = &memdrv_dev_connector;
Biju Das50bfdc42020-12-13 20:28:45 +0000151 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200152
153 return result;
154}