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