blob: 62698a90526edccbe1c2cb7c89b9d69ae30d07cd [file] [log] [blame]
Jit Loon Lima7f54942023-05-17 12:26:11 +08001/*
2 * Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
Sieu Mun Tangebca5152024-08-26 07:59:10 +08003 * Copyright (c) 2024, Altera Corporation. All rights reserved.
Jit Loon Lima7f54942023-05-17 12:26:11 +08004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <assert.h>
9#include <errno.h>
10#include <stdbool.h>
11#include <string.h>
12
13#include <arch_helpers.h>
14#include <common/debug.h>
15#include <drivers/cadence/cdns_combo_phy.h>
16#include <drivers/cadence/cdns_sdmmc.h>
17#include <drivers/delay_timer.h>
18#include <lib/mmio.h>
19#include <lib/utils.h>
20
Jit Loon Lima7f54942023-05-17 12:26:11 +080021#include "sdmmc.h"
Sieu Mun Tangebca5152024-08-26 07:59:10 +080022#include "socfpga_mailbox.h"
Sieu Mun Tang31464052024-10-25 09:37:42 +080023#include "wdt/watchdog.h"
Jit Loon Lima7f54942023-05-17 12:26:11 +080024
25static const struct mmc_ops *ops;
26static unsigned int mmc_ocr_value;
Jit Loon Lima7f54942023-05-17 12:26:11 +080027static unsigned int mmc_flags;
Jit Loon Lima7f54942023-05-17 12:26:11 +080028static unsigned int rca;
Jit Loon Lima7f54942023-05-17 12:26:11 +080029
30extern const struct mmc_ops cdns_sdmmc_ops;
31extern struct cdns_sdmmc_params cdns_params;
32extern struct cdns_sdmmc_combo_phy sdmmc_combo_phy_reg;
33extern struct cdns_sdmmc_sdhc sdmmc_sdhc_reg;
34
Sieu Mun Tang31464052024-10-25 09:37:42 +080035bool is_cmd23_enabled(void)
Jit Loon Lima7f54942023-05-17 12:26:11 +080036{
37 return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
38}
39
Sieu Mun Tang31464052024-10-25 09:37:42 +080040int sdmmc_send_cmd(unsigned int idx, unsigned int arg,
Jit Loon Lima7f54942023-05-17 12:26:11 +080041 unsigned int r_type, unsigned int *r_data)
42{
43 struct mmc_cmd cmd;
44 int ret;
45
46 zeromem(&cmd, sizeof(struct mmc_cmd));
47
48 cmd.cmd_idx = idx;
49 cmd.cmd_arg = arg;
50 cmd.resp_type = r_type;
51
52 ret = ops->send_cmd(&cmd);
53
54 if ((ret == 0) && (r_data != NULL)) {
55 int i;
56
57 for (i = 0; i < 4; i++) {
58 *r_data = cmd.resp_data[i];
59 r_data++;
60 }
61 }
62
63 if (ret != 0) {
64 VERBOSE("Send command %u error: %d\n", idx, ret);
65 }
66
67 return ret;
68}
69
Sieu Mun Tang31464052024-10-25 09:37:42 +080070int sdmmc_device_state(void)
Jit Loon Lima7f54942023-05-17 12:26:11 +080071{
72 int retries = DEFAULT_SDMMC_MAX_RETRIES;
73 unsigned int resp_data[4];
74
75 do {
76 int ret;
77
78 if (retries == 0) {
79 ERROR("CMD13 failed after %d retries\n",
80 DEFAULT_SDMMC_MAX_RETRIES);
81 return -EIO;
82 }
83
84 ret = sdmmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
85 MMC_RESPONSE_R1, &resp_data[0]);
86 if (ret != 0) {
87 retries--;
88 continue;
89 }
90
91 if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
92 return -EIO;
93 }
94
95 retries--;
96 } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U);
97
98 return MMC_GET_STATE(resp_data[0]);
99}
100
Jit Loon Lima7f54942023-05-17 12:26:11 +0800101size_t sdmmc_read_blocks(int lba, uintptr_t buf, size_t size)
102{
Sieu Mun Tang31464052024-10-25 09:37:42 +0800103 mmc_read_blocks(lba, buf, size);
Jit Loon Lima7f54942023-05-17 12:26:11 +0800104
Sieu Mun Tang31464052024-10-25 09:37:42 +0800105 /* Restart watchdog for reading each chunk byte */
106 watchdog_sw_rst();
Jit Loon Lima7f54942023-05-17 12:26:11 +0800107
108 return size;
109}
110
111size_t sdmmc_write_blocks(int lba, const uintptr_t buf, size_t size)
112{
113 int ret;
114 unsigned int cmd_idx, cmd_arg;
115
116 assert((ops != NULL) &&
117 (ops->write != NULL) &&
118 (size != 0U) &&
119 ((buf & MMC_BLOCK_MASK) == 0U) &&
120 ((size & MMC_BLOCK_MASK) == 0U));
121
122 ret = ops->prepare(lba, buf, size);
123 if (ret != 0) {
124 return 0;
125 }
126
127 if (is_cmd23_enabled()) {
128 /* Set block count */
129 ret = sdmmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
130 MMC_RESPONSE_R1, NULL);
131 if (ret != 0) {
132 return 0;
133 }
134
135 cmd_idx = MMC_CMD(25);
136 } else {
137 if (size > MMC_BLOCK_SIZE) {
138 cmd_idx = MMC_CMD(25);
139 } else {
140 cmd_idx = MMC_CMD(24);
141 }
142 }
143
144 if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) {
145 cmd_arg = lba * MMC_BLOCK_SIZE;
146 } else {
147 cmd_arg = lba;
148 }
149
150 ret = sdmmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL);
151 if (ret != 0) {
152 return 0;
153 }
154
155 ret = ops->write(lba, buf, size);
156 if (ret != 0) {
157 return 0;
158 }
159
160 /* Wait buffer empty */
161 do {
162 ret = sdmmc_device_state();
163 if (ret < 0) {
164 return 0;
165 }
166 } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV));
167
168 if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
169 ret = sdmmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL);
170 if (ret != 0) {
171 return 0;
172 }
173 }
174
175 return size;
176}