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