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