blob: 0ed71540c3ca564bd0bceb7bce78d763c3d63f0e [file] [log] [blame]
Yann Gautier9abbd6a2018-10-15 09:36:44 +02001/*
Yann Gautierdbb9f572020-06-12 12:17:17 +02002 * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
Yann Gautier9abbd6a2018-10-15 09:36:44 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Yann Gautier9abbd6a2018-10-15 09:36:44 +02008#include <errno.h>
Yann Gautier9abbd6a2018-10-15 09:36:44 +02009#include <string.h>
10
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#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
Yann Gautier9abbd6a2018-10-15 09:36:44 +020018/* SDMMC device functions */
19static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
20static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
21 io_entity_t *entity);
22static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
Yann Gautierf30cddc2019-04-16 11:35:19 +020023static int mmc_block_seek(io_entity_t *entity, int mode,
24 signed long long offset);
Yann Gautier9abbd6a2018-10-15 09:36:44 +020025static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
26 size_t *length_read);
27static int mmc_block_close(io_entity_t *entity);
28static int mmc_dev_close(io_dev_info_t *dev_info);
29static io_type_t device_type_mmc(void);
30
Yann Gautierf30cddc2019-04-16 11:35:19 +020031static signed long long seek_offset;
Yann Gautier9abbd6a2018-10-15 09:36:44 +020032
33static const io_dev_connector_t mmc_dev_connector = {
34 .dev_open = mmc_dev_open
35};
36
37static 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
49static 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 */
55static io_type_t device_type_mmc(void)
56{
57 return IO_TYPE_MMC;
58}
59
60/* Open a connection to the mmc device */
61static 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
69static 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 */
75static int mmc_dev_close(io_dev_info_t *dev_info)
76{
77 return 0;
78}
79
80/* Open a file on the mmc device */
81static 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 */
Yann Gautierf30cddc2019-04-16 11:35:19 +020089static int mmc_block_seek(io_entity_t *entity, int mode,
90 signed long long offset)
Yann Gautier9abbd6a2018-10-15 09:36:44 +020091{
92 seek_offset = offset;
93 return 0;
94}
95
96/* Read data from a file on the mmc device */
97static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
98 size_t length, size_t *length_read)
99{
Yann Gautierdbb9f572020-06-12 12:17:17 +0200100 uint8_t retries;
Yann Gautier9abbd6a2018-10-15 09:36:44 +0200101
Yann Gautierdbb9f572020-06-12 12:17:17 +0200102 for (retries = 0U; retries < 3U; retries++) {
103 *length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
104 buffer, length);
105
106 if (*length_read == length) {
107 return 0;
108 }
109 WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__,
110 (unsigned long)*length_read, (unsigned long)length,
111 retries + 1U);
Yann Gautier9abbd6a2018-10-15 09:36:44 +0200112 }
113
Yann Gautierdbb9f572020-06-12 12:17:17 +0200114 return -EIO;
Yann Gautier9abbd6a2018-10-15 09:36:44 +0200115}
116
117/* Close a file on the mmc device */
118static int mmc_block_close(io_entity_t *entity)
119{
120 return 0;
121}
122
123/* Register the mmc driver with the IO abstraction */
124int register_io_dev_mmc(const io_dev_connector_t **dev_con)
125{
126 int result;
127
128 assert(dev_con != NULL);
129
130 result = io_register_device(&mmc_dev_info);
131 if (result == 0) {
132 *dev_con = &mmc_dev_connector;
133 }
134
135 return result;
136}