blob: f74bd5f4ead1a39acf61d662c2b6712c464f3c68 [file] [log] [blame]
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02001/*
2 * Copyright (c) 2015-2017, 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_emmcdrv.h"
14#include "io_private.h"
15#include "emmc_config.h"
16#include "emmc_hal.h"
17#include "emmc_std.h"
18#include "emmc_def.h"
19
20static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)),
21 io_dev_info_t **dev_info);
22static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info);
23
24typedef struct {
25 uint32_t in_use;
26 uintptr_t base;
27 ssize_t file_pos;
28 EMMC_PARTITION_ID partition;
29} file_state_t;
30
31static file_state_t current_file = { 0 };
32
33static EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER;
34
35static io_type_t device_type_emmcdrv(void)
36{
37 return IO_TYPE_MEMMAP;
38}
39
40static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode,
41 ssize_t offset)
42{
43 if (mode != IO_SEEK_SET)
44 return IO_FAIL;
45
46 ((file_state_t *) entity->info)->file_pos = offset;
47
48 return IO_SUCCESS;
49}
50
51static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer,
52 size_t length, size_t *length_read)
53{
54 file_state_t *fp = (file_state_t *) entity->info;
55 uint32_t sector_add, sector_num, emmc_dma = 0;
56 int32_t result = IO_SUCCESS;
57
58 sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT;
59 sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT;
60
61 NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%lx(%d) len=0x%lx(%d)\n",
62 buffer,
63 current_file.partition, current_file.file_pos,
64 sector_add, length, sector_num);
65
66 if (buffer + length - 1 <= UINT32_MAX)
67 emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE;
68
69 if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num,
70 emmc_dma) != EMMC_SUCCESS)
71 result = IO_FAIL;
72
73 *length_read = length;
74 fp->file_pos += length;
75
76 return result;
77}
78
79static int32_t emmcdrv_block_open(io_dev_info_t *dev_info,
80 const uintptr_t spec, io_entity_t *entity)
81{
82 const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec;
83
84 if (current_file.in_use) {
85 WARN("mmc_block: Only one open spec at a time\n");
86 return IO_RESOURCES_EXHAUSTED;
87 }
88
89 current_file.file_pos = 0;
90 current_file.in_use = 1;
91
92 if (emmcdrv_bootpartition == PARTITION_ID_USER) {
93 emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en;
94 if ((PARTITION_ID_BOOT_1 == emmcdrv_bootpartition) ||
95 (PARTITION_ID_BOOT_2 == emmcdrv_bootpartition)) {
96 current_file.partition = emmcdrv_bootpartition;
97
98 NOTICE("BL2: eMMC boot from partition %d\n",
99 emmcdrv_bootpartition);
100 goto done;
101 }
102 return IO_FAIL;
103 }
104
105 if (PARTITION_ID_USER == block_spec->partition ||
106 PARTITION_ID_BOOT_1 == block_spec->partition ||
107 PARTITION_ID_BOOT_2 == block_spec->partition)
108 current_file.partition = block_spec->partition;
109 else
110 current_file.partition = emmcdrv_bootpartition;
111
112done:
113 if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS)
114 return IO_FAIL;
115
116 entity->info = (uintptr_t) &current_file;
117
118 return IO_SUCCESS;
119}
120
121static int32_t emmcdrv_block_close(io_entity_t *entity)
122{
123 memset((void *)&current_file, 0, sizeof(current_file));
124 entity->info = 0U;
125
126 return IO_SUCCESS;
127}
128
129static const io_dev_funcs_t emmcdrv_dev_funcs = {
130 .type = &device_type_emmcdrv,
131 .open = &emmcdrv_block_open,
132 .seek = &emmcdrv_block_seek,
133 .size = NULL,
134 .read = &emmcdrv_block_read,
135 .write = NULL,
136 .close = &emmcdrv_block_close,
137 .dev_init = NULL,
138 .dev_close = &emmcdrv_dev_close
139};
140
141static const io_dev_info_t emmcdrv_dev_info = {
142 .funcs = &emmcdrv_dev_funcs,
143 .info = (uintptr_t) 0
144};
145
146static const io_dev_connector_t emmcdrv_dev_connector = {
147 &emmcdrv_dev_open,
148};
149
150static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)),
151 io_dev_info_t **dev_info)
152{
153 *dev_info = (io_dev_info_t *) &emmcdrv_dev_info;
154
155 return IO_SUCCESS;
156}
157
158static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info)
159{
160 return IO_SUCCESS;
161}
162
163int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **dev_con)
164{
165 int32_t rc;
166
167 rc = io_register_device(&emmcdrv_dev_info);
168 if (rc == IO_SUCCESS)
169 *dev_con = &emmcdrv_dev_connector;
170
171 return rc;
172}