xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/st/io/io_mmc.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <errno.h>
9*54fd6939SJiyong Park #include <string.h>
10*54fd6939SJiyong Park 
11*54fd6939SJiyong Park #include <common/debug.h>
12*54fd6939SJiyong Park #include <drivers/io/io_driver.h>
13*54fd6939SJiyong Park #include <drivers/io/io_storage.h>
14*54fd6939SJiyong Park #include <drivers/mmc.h>
15*54fd6939SJiyong Park #include <drivers/st/io_mmc.h>
16*54fd6939SJiyong Park #include <drivers/st/stm32_sdmmc2.h>
17*54fd6939SJiyong Park 
18*54fd6939SJiyong Park /* SDMMC device functions */
19*54fd6939SJiyong Park static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
20*54fd6939SJiyong Park static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
21*54fd6939SJiyong Park 			  io_entity_t *entity);
22*54fd6939SJiyong Park static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
23*54fd6939SJiyong Park static int mmc_block_seek(io_entity_t *entity, int mode,
24*54fd6939SJiyong Park 			  signed long long offset);
25*54fd6939SJiyong Park static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
26*54fd6939SJiyong Park 			  size_t *length_read);
27*54fd6939SJiyong Park static int mmc_block_close(io_entity_t *entity);
28*54fd6939SJiyong Park static int mmc_dev_close(io_dev_info_t *dev_info);
29*54fd6939SJiyong Park static io_type_t device_type_mmc(void);
30*54fd6939SJiyong Park 
31*54fd6939SJiyong Park static signed long long seek_offset;
32*54fd6939SJiyong Park static size_t (*_read_blocks)(int lba, uintptr_t buf, size_t size);
33*54fd6939SJiyong Park 
34*54fd6939SJiyong Park static const io_dev_connector_t mmc_dev_connector = {
35*54fd6939SJiyong Park 	.dev_open = mmc_dev_open
36*54fd6939SJiyong Park };
37*54fd6939SJiyong Park 
38*54fd6939SJiyong Park static const io_dev_funcs_t mmc_dev_funcs = {
39*54fd6939SJiyong Park 	.type = device_type_mmc,
40*54fd6939SJiyong Park 	.open = mmc_block_open,
41*54fd6939SJiyong Park 	.seek = mmc_block_seek,
42*54fd6939SJiyong Park 	.size = NULL,
43*54fd6939SJiyong Park 	.read = mmc_block_read,
44*54fd6939SJiyong Park 	.write = NULL,
45*54fd6939SJiyong Park 	.close = mmc_block_close,
46*54fd6939SJiyong Park 	.dev_init = mmc_dev_init,
47*54fd6939SJiyong Park 	.dev_close = mmc_dev_close,
48*54fd6939SJiyong Park };
49*54fd6939SJiyong Park 
50*54fd6939SJiyong Park static const io_dev_info_t mmc_dev_info = {
51*54fd6939SJiyong Park 	.funcs = &mmc_dev_funcs,
52*54fd6939SJiyong Park 	.info = 0,
53*54fd6939SJiyong Park };
54*54fd6939SJiyong Park 
55*54fd6939SJiyong Park /* Identify the device type as mmc device */
device_type_mmc(void)56*54fd6939SJiyong Park static io_type_t device_type_mmc(void)
57*54fd6939SJiyong Park {
58*54fd6939SJiyong Park 	return IO_TYPE_MMC;
59*54fd6939SJiyong Park }
60*54fd6939SJiyong Park 
61*54fd6939SJiyong Park /* Open a connection to the mmc device */
mmc_dev_open(const uintptr_t init_params,io_dev_info_t ** dev_info)62*54fd6939SJiyong Park static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
63*54fd6939SJiyong Park {
64*54fd6939SJiyong Park 	struct io_mmc_dev_spec *device_spec =
65*54fd6939SJiyong Park 		(struct io_mmc_dev_spec *)init_params;
66*54fd6939SJiyong Park 
67*54fd6939SJiyong Park 	assert(dev_info != NULL);
68*54fd6939SJiyong Park 	*dev_info = (io_dev_info_t *)&mmc_dev_info;
69*54fd6939SJiyong Park 
70*54fd6939SJiyong Park 	_read_blocks = !device_spec->use_boot_part ?
71*54fd6939SJiyong Park 		mmc_read_blocks : mmc_boot_part_read_blocks;
72*54fd6939SJiyong Park 
73*54fd6939SJiyong Park 	return 0;
74*54fd6939SJiyong Park }
75*54fd6939SJiyong Park 
mmc_dev_init(io_dev_info_t * dev_info,const uintptr_t init_params)76*54fd6939SJiyong Park static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
77*54fd6939SJiyong Park {
78*54fd6939SJiyong Park 	return 0;
79*54fd6939SJiyong Park }
80*54fd6939SJiyong Park 
81*54fd6939SJiyong Park /* Close a connection to the mmc device */
mmc_dev_close(io_dev_info_t * dev_info)82*54fd6939SJiyong Park static int mmc_dev_close(io_dev_info_t *dev_info)
83*54fd6939SJiyong Park {
84*54fd6939SJiyong Park 	return 0;
85*54fd6939SJiyong Park }
86*54fd6939SJiyong Park 
87*54fd6939SJiyong Park /* Open a file on the mmc device */
mmc_block_open(io_dev_info_t * dev_info,const uintptr_t spec,io_entity_t * entity)88*54fd6939SJiyong Park static int mmc_block_open(io_dev_info_t *dev_info, const  uintptr_t spec,
89*54fd6939SJiyong Park 			  io_entity_t *entity)
90*54fd6939SJiyong Park {
91*54fd6939SJiyong Park 	seek_offset = 0;
92*54fd6939SJiyong Park 	return 0;
93*54fd6939SJiyong Park }
94*54fd6939SJiyong Park 
95*54fd6939SJiyong Park /* Seek to a particular file offset on the mmc device */
mmc_block_seek(io_entity_t * entity,int mode,signed long long offset)96*54fd6939SJiyong Park static int mmc_block_seek(io_entity_t *entity, int mode,
97*54fd6939SJiyong Park 			  signed long long offset)
98*54fd6939SJiyong Park {
99*54fd6939SJiyong Park 	seek_offset = offset;
100*54fd6939SJiyong Park 	return 0;
101*54fd6939SJiyong Park }
102*54fd6939SJiyong Park 
103*54fd6939SJiyong Park /* Read data from a file on the mmc device */
mmc_block_read(io_entity_t * entity,uintptr_t buffer,size_t length,size_t * length_read)104*54fd6939SJiyong Park static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
105*54fd6939SJiyong Park 			  size_t length, size_t *length_read)
106*54fd6939SJiyong Park {
107*54fd6939SJiyong Park 	uint8_t retries;
108*54fd6939SJiyong Park 
109*54fd6939SJiyong Park 	for (retries = 0U; retries < 3U; retries++) {
110*54fd6939SJiyong Park 		*length_read = _read_blocks(seek_offset / MMC_BLOCK_SIZE,
111*54fd6939SJiyong Park 					    buffer, length);
112*54fd6939SJiyong Park 
113*54fd6939SJiyong Park 		if (*length_read == length) {
114*54fd6939SJiyong Park 			return 0;
115*54fd6939SJiyong Park 		}
116*54fd6939SJiyong Park 		WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__,
117*54fd6939SJiyong Park 		     (unsigned long)*length_read, (unsigned long)length,
118*54fd6939SJiyong Park 		     retries + 1U);
119*54fd6939SJiyong Park 	}
120*54fd6939SJiyong Park 
121*54fd6939SJiyong Park 	return -EIO;
122*54fd6939SJiyong Park }
123*54fd6939SJiyong Park 
124*54fd6939SJiyong Park /* Close a file on the mmc device */
mmc_block_close(io_entity_t * entity)125*54fd6939SJiyong Park static int mmc_block_close(io_entity_t *entity)
126*54fd6939SJiyong Park {
127*54fd6939SJiyong Park 	return 0;
128*54fd6939SJiyong Park }
129*54fd6939SJiyong Park 
130*54fd6939SJiyong Park /* Register the mmc driver with the IO abstraction */
register_io_dev_mmc(const io_dev_connector_t ** dev_con)131*54fd6939SJiyong Park int register_io_dev_mmc(const io_dev_connector_t **dev_con)
132*54fd6939SJiyong Park {
133*54fd6939SJiyong Park 	int result;
134*54fd6939SJiyong Park 
135*54fd6939SJiyong Park 	assert(dev_con != NULL);
136*54fd6939SJiyong Park 
137*54fd6939SJiyong Park 	result = io_register_device(&mmc_dev_info);
138*54fd6939SJiyong Park 	if (result == 0) {
139*54fd6939SJiyong Park 		*dev_con = &mmc_dev_connector;
140*54fd6939SJiyong Park 	}
141*54fd6939SJiyong Park 
142*54fd6939SJiyong Park 	return result;
143*54fd6939SJiyong Park }
144