blob: 92f938f6b1f10b70934bc54d8281f6b949288046 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Georgiafd4c872020-05-05 23:43:18 +02002/*
Martin Roth0443ac22019-08-30 21:29:41 -06003 * Secure Digital (SD) Host Controller interface DMA support code
Lee Leahyeef40eb2017-03-23 10:54:57 -07004 */
5
Lee Leahy48dbc662017-05-08 16:56:03 -07006#include <commonlib/sdhci.h>
7#include <commonlib/storage.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +01008#include <console/console.h>
Lee Leahyeef40eb2017-03-23 10:54:57 -07009#include <delay.h>
Lee Leahyeef40eb2017-03-23 10:54:57 -070010#include <endian.h>
Elyes HAOUAS70a03dd2019-12-02 20:47:50 +010011#include <stdlib.h>
Elyes HAOUASadd76f92019-03-21 09:55:49 +010012#include <string.h>
13
Lee Leahyeef40eb2017-03-23 10:54:57 -070014#include "sdhci.h"
15#include "sd_mmc.h"
16#include "storage.h"
Lee Leahyeef40eb2017-03-23 10:54:57 -070017
18static void sdhci_alloc_adma_descs(struct sdhci_ctrlr *sdhci_ctrlr,
19 u32 need_descriptors)
20{
21 if (sdhci_ctrlr->adma_descs) {
22 if (sdhci_ctrlr->adma_desc_count < need_descriptors) {
23 /* Previously allocated array is too small */
24 free(sdhci_ctrlr->adma_descs);
25 sdhci_ctrlr->adma_desc_count = 0;
26 sdhci_ctrlr->adma_descs = NULL;
27 }
28 }
29
30 /* use dma_malloc() to make sure we get the coherent/uncached memory */
31 if (!sdhci_ctrlr->adma_descs) {
32 sdhci_ctrlr->adma_descs = malloc(need_descriptors
33 * sizeof(*sdhci_ctrlr->adma_descs));
34 if (sdhci_ctrlr->adma_descs == NULL)
35 die("fail to malloc adma_descs\n");
36 sdhci_ctrlr->adma_desc_count = need_descriptors;
37 }
38
39 memset(sdhci_ctrlr->adma_descs, 0, sizeof(*sdhci_ctrlr->adma_descs)
40 * need_descriptors);
41}
42
43static void sdhci_alloc_adma64_descs(struct sdhci_ctrlr *sdhci_ctrlr,
44 u32 need_descriptors)
45{
46 if (sdhci_ctrlr->adma64_descs) {
47 if (sdhci_ctrlr->adma_desc_count < need_descriptors) {
48 /* Previously allocated array is too small */
49 free(sdhci_ctrlr->adma64_descs);
50 sdhci_ctrlr->adma_desc_count = 0;
51 sdhci_ctrlr->adma64_descs = NULL;
52 }
53 }
54
55 /* use dma_malloc() to make sure we get the coherent/uncached memory */
56 if (!sdhci_ctrlr->adma64_descs) {
57 sdhci_ctrlr->adma64_descs = malloc(need_descriptors
58 * sizeof(*sdhci_ctrlr->adma64_descs));
59 if (sdhci_ctrlr->adma64_descs == NULL)
60 die("fail to malloc adma64_descs\n");
61
62 sdhci_ctrlr->adma_desc_count = need_descriptors;
63 }
64
65 memset(sdhci_ctrlr->adma64_descs, 0, sizeof(*sdhci_ctrlr->adma64_descs)
66 * need_descriptors);
67}
68
69int sdhci_setup_adma(struct sdhci_ctrlr *sdhci_ctrlr, struct mmc_data *data)
70{
71 int i, togo, need_descriptors;
72 int dma64;
73 char *buffer_data;
74 u16 attributes;
75
76 togo = data->blocks * data->blocksize;
77 if (!togo) {
78 sdhc_error("%s: MmcData corrupted: %d blocks of %d bytes\n",
79 __func__, data->blocks, data->blocksize);
80 return -1;
81 }
82
83 need_descriptors = 1 + togo / SDHCI_MAX_PER_DESCRIPTOR;
84 dma64 = sdhci_ctrlr->sd_mmc_ctrlr.caps & DRVR_CAP_DMA_64BIT;
85 if (dma64)
86 sdhci_alloc_adma64_descs(sdhci_ctrlr, need_descriptors);
87 else
88 sdhci_alloc_adma_descs(sdhci_ctrlr, need_descriptors);
89 buffer_data = data->dest;
90
91 /* Now set up the descriptor chain. */
92 for (i = 0; togo; i++) {
93 unsigned int desc_length;
94
95 if (togo < SDHCI_MAX_PER_DESCRIPTOR)
96 desc_length = togo;
97 else
98 desc_length = SDHCI_MAX_PER_DESCRIPTOR;
99 togo -= desc_length;
100
101 attributes = SDHCI_ADMA_VALID | SDHCI_ACT_TRAN;
102 if (togo == 0)
103 attributes |= SDHCI_ADMA_END;
104
105 if (dma64) {
106 sdhci_ctrlr->adma64_descs[i].addr =
107 (uintptr_t)buffer_data;
108 sdhci_ctrlr->adma64_descs[i].addr_hi = 0;
109 sdhci_ctrlr->adma64_descs[i].length = desc_length;
110 sdhci_ctrlr->adma64_descs[i].attributes = attributes;
111
112 } else {
113 sdhci_ctrlr->adma_descs[i].addr =
114 (uintptr_t)buffer_data;
115 sdhci_ctrlr->adma_descs[i].length = desc_length;
116 sdhci_ctrlr->adma_descs[i].attributes = attributes;
117 }
118
119 buffer_data += desc_length;
120 }
121
122 if (dma64)
123 sdhci_writel(sdhci_ctrlr, (uintptr_t) sdhci_ctrlr->adma64_descs,
124 SDHCI_ADMA_ADDRESS);
125 else
126 sdhci_writel(sdhci_ctrlr, (uintptr_t) sdhci_ctrlr->adma_descs,
127 SDHCI_ADMA_ADDRESS);
128
129 return 0;
130}
131
132int sdhci_complete_adma(struct sdhci_ctrlr *sdhci_ctrlr,
133 struct mmc_command *cmd)
134{
135 int retry;
136 u32 stat = 0, mask;
137
138 mask = SDHCI_INT_RESPONSE | SDHCI_INT_ERROR;
139
140 retry = 10000; /* Command should be done in way less than 10 ms. */
141 while (--retry) {
142 stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
143 if (stat & mask)
144 break;
145 udelay(1);
146 }
147
148 sdhci_writel(sdhci_ctrlr, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
149
150 if (retry && !(stat & SDHCI_INT_ERROR)) {
151 /* Command OK, let's wait for data transfer completion. */
152 mask = SDHCI_INT_DATA_END |
153 SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR;
154
155 /* Transfer should take 10 seconds tops. */
156 retry = 10 * 1000 * 1000;
157 while (--retry) {
158 stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
159 if (stat & mask)
160 break;
161 udelay(1);
162 }
163
164 sdhci_writel(sdhci_ctrlr, stat, SDHCI_INT_STATUS);
165 if (retry && !(stat & SDHCI_INT_ERROR)) {
166 sdhci_cmd_done(sdhci_ctrlr, cmd);
167 return 0;
168 }
169 }
170
171 sdhc_error("%s: transfer error, stat %#x, adma error %#x, retry %d\n",
172 __func__, stat, sdhci_readl(sdhci_ctrlr, SDHCI_ADMA_ERROR),
173 retry);
174
175 sdhci_reset(sdhci_ctrlr, SDHCI_RESET_CMD);
176 sdhci_reset(sdhci_ctrlr, SDHCI_RESET_DATA);
177
178 if (stat & SDHCI_INT_TIMEOUT)
179 return CARD_TIMEOUT;
180 return CARD_COMM_ERR;
181}