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