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