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