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