blob: 5b15683770de1418b2a4a7a40d7ee61be6ded25f [file] [log] [blame]
Haojian Zhuang06249dc2016-03-18 22:14:16 +08001/*
2 * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch.h>
32#include <arch_helpers.h>
33#include <assert.h>
34#include <debug.h>
35#include <delay_timer.h>
36#include <dw_mmc.h>
37#include <emmc.h>
38#include <errno.h>
39#include <mmio.h>
40#include <string.h>
41
42#define DWMMC_CTRL (0x00)
43#define CTRL_IDMAC_EN (1 << 25)
44#define CTRL_DMA_EN (1 << 5)
45#define CTRL_INT_EN (1 << 4)
46#define CTRL_DMA_RESET (1 << 2)
47#define CTRL_FIFO_RESET (1 << 1)
48#define CTRL_RESET (1 << 0)
49#define CTRL_RESET_ALL (CTRL_DMA_RESET | CTRL_FIFO_RESET | \
50 CTRL_RESET)
51
52#define DWMMC_PWREN (0x04)
53#define DWMMC_CLKDIV (0x08)
54#define DWMMC_CLKSRC (0x0c)
55#define DWMMC_CLKENA (0x10)
56#define DWMMC_TMOUT (0x14)
57#define DWMMC_CTYPE (0x18)
58#define CTYPE_8BIT (1 << 16)
59#define CTYPE_4BIT (1)
60#define CTYPE_1BIT (0)
61
62#define DWMMC_BLKSIZ (0x1c)
63#define DWMMC_BYTCNT (0x20)
64#define DWMMC_INTMASK (0x24)
65#define INT_EBE (1 << 15)
66#define INT_SBE (1 << 13)
67#define INT_HLE (1 << 12)
68#define INT_FRUN (1 << 11)
69#define INT_DRT (1 << 9)
70#define INT_RTO (1 << 8)
71#define INT_DCRC (1 << 7)
72#define INT_RCRC (1 << 6)
73#define INT_RXDR (1 << 5)
74#define INT_TXDR (1 << 4)
75#define INT_DTO (1 << 3)
76#define INT_CMD_DONE (1 << 2)
77#define INT_RE (1 << 1)
78
79#define DWMMC_CMDARG (0x28)
80#define DWMMC_CMD (0x2c)
81#define CMD_START (1 << 31)
82#define CMD_USE_HOLD_REG (1 << 29) /* 0 if SDR50/100 */
83#define CMD_UPDATE_CLK_ONLY (1 << 21)
84#define CMD_SEND_INIT (1 << 15)
85#define CMD_STOP_ABORT_CMD (1 << 14)
86#define CMD_WAIT_PRVDATA_COMPLETE (1 << 13)
87#define CMD_WRITE (1 << 10)
88#define CMD_DATA_TRANS_EXPECT (1 << 9)
89#define CMD_CHECK_RESP_CRC (1 << 8)
90#define CMD_RESP_LEN (1 << 7)
91#define CMD_RESP_EXPECT (1 << 6)
92#define CMD(x) (x & 0x3f)
93
94#define DWMMC_RESP0 (0x30)
95#define DWMMC_RESP1 (0x34)
96#define DWMMC_RESP2 (0x38)
97#define DWMMC_RESP3 (0x3c)
98#define DWMMC_RINTSTS (0x44)
99#define DWMMC_STATUS (0x48)
100#define STATUS_DATA_BUSY (1 << 9)
101
102#define DWMMC_FIFOTH (0x4c)
103#define FIFOTH_TWMARK(x) (x & 0xfff)
104#define FIFOTH_RWMARK(x) ((x & 0x1ff) << 16)
105#define FIFOTH_DMA_BURST_SIZE(x) ((x & 0x7) << 28)
106
107#define DWMMC_DEBNCE (0x64)
108#define DWMMC_BMOD (0x80)
109#define BMOD_ENABLE (1 << 7)
110#define BMOD_FB (1 << 1)
111#define BMOD_SWRESET (1 << 0)
112
113#define DWMMC_DBADDR (0x88)
114#define DWMMC_IDSTS (0x8c)
115#define DWMMC_IDINTEN (0x90)
116#define DWMMC_CARDTHRCTL (0x100)
117#define CARDTHRCTL_RD_THR(x) ((x & 0xfff) << 16)
118#define CARDTHRCTL_RD_THR_EN (1 << 0)
119
120#define IDMAC_DES0_DIC (1 << 1)
121#define IDMAC_DES0_LD (1 << 2)
122#define IDMAC_DES0_FS (1 << 3)
123#define IDMAC_DES0_CH (1 << 4)
124#define IDMAC_DES0_ER (1 << 5)
125#define IDMAC_DES0_CES (1 << 30)
126#define IDMAC_DES0_OWN (1 << 31)
127#define IDMAC_DES1_BS1(x) ((x) & 0x1fff)
128#define IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13)
129
130#define DWMMC_DMA_MAX_BUFFER_SIZE (512 * 8)
131
132#define DWMMC_8BIT_MODE (1 << 6)
133
134#define TIMEOUT 100000
135
136struct dw_idmac_desc {
137 unsigned int des0;
138 unsigned int des1;
139 unsigned int des2;
140 unsigned int des3;
141};
142
143static void dw_init(void);
144static int dw_send_cmd(emmc_cmd_t *cmd);
145static int dw_set_ios(int clk, int width);
146static int dw_prepare(int lba, uintptr_t buf, size_t size);
147static int dw_read(int lba, uintptr_t buf, size_t size);
148static int dw_write(int lba, uintptr_t buf, size_t size);
149
150static const emmc_ops_t dw_mmc_ops = {
151 .init = dw_init,
152 .send_cmd = dw_send_cmd,
153 .set_ios = dw_set_ios,
154 .prepare = dw_prepare,
155 .read = dw_read,
156 .write = dw_write,
157};
158
159static dw_mmc_params_t dw_params;
160
161static void dw_update_clk(void)
162{
163 unsigned int data;
164
165 mmio_write_32(dw_params.reg_base + DWMMC_CMD,
166 CMD_WAIT_PRVDATA_COMPLETE | CMD_UPDATE_CLK_ONLY |
167 CMD_START);
168 while (1) {
169 data = mmio_read_32(dw_params.reg_base + DWMMC_CMD);
170 if ((data & CMD_START) == 0)
171 break;
172 data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS);
173 assert(data & INT_HLE);
174 }
175}
176
177static void dw_set_clk(int clk)
178{
179 unsigned int data;
180 int div;
181
182 assert(clk > 0);
183
184 for (div = 1; div < 256; div++) {
185 if ((dw_params.clk_rate / (2 * div)) <= clk) {
186 break;
187 }
188 }
189 assert(div < 256);
190
191 /* wait until controller is idle */
192 do {
193 data = mmio_read_32(dw_params.reg_base + DWMMC_STATUS);
194 } while (data & STATUS_DATA_BUSY);
195
196 /* disable clock before change clock rate */
197 mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 0);
198 dw_update_clk();
199
200 mmio_write_32(dw_params.reg_base + DWMMC_CLKDIV, div);
201 dw_update_clk();
202
203 /* enable clock */
204 mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 1);
205 mmio_write_32(dw_params.reg_base + DWMMC_CLKSRC, 0);
206 dw_update_clk();
207}
208
209static void dw_init(void)
210{
211 unsigned int data;
212 uintptr_t base;
213
214 assert((dw_params.reg_base & EMMC_BLOCK_MASK) == 0);
215
216 base = dw_params.reg_base;
217 mmio_write_32(base + DWMMC_PWREN, 1);
218 mmio_write_32(base + DWMMC_CTRL, CTRL_RESET_ALL);
219 do {
220 data = mmio_read_32(base + DWMMC_CTRL);
221 } while (data);
222
223 /* enable DMA in CTRL */
224 data = CTRL_INT_EN | CTRL_DMA_EN | CTRL_IDMAC_EN;
225 mmio_write_32(base + DWMMC_CTRL, data);
226 mmio_write_32(base + DWMMC_RINTSTS, ~0);
227 mmio_write_32(base + DWMMC_INTMASK, 0);
228 mmio_write_32(base + DWMMC_TMOUT, ~0);
229 mmio_write_32(base + DWMMC_IDINTEN, ~0);
230 mmio_write_32(base + DWMMC_BLKSIZ, EMMC_BLOCK_SIZE);
231 mmio_write_32(base + DWMMC_BYTCNT, 256 * 1024);
232 mmio_write_32(base + DWMMC_DEBNCE, 0x00ffffff);
233 mmio_write_32(base + DWMMC_BMOD, BMOD_SWRESET);
234 do {
235 data = mmio_read_32(base + DWMMC_BMOD);
236 } while (data & BMOD_SWRESET);
237 /* enable DMA in BMOD */
238 data |= BMOD_ENABLE | BMOD_FB;
239 mmio_write_32(base + DWMMC_BMOD, data);
240
241 udelay(100);
242 dw_set_clk(EMMC_BOOT_CLK_RATE);
243 udelay(100);
244}
245
246static int dw_send_cmd(emmc_cmd_t *cmd)
247{
248 unsigned int op, data, err_mask;
249 uintptr_t base;
250 int timeout;
251
252 assert(cmd);
253
254 base = dw_params.reg_base;
255
256 switch (cmd->cmd_idx) {
257 case EMMC_CMD0:
258 op = CMD_SEND_INIT;
259 break;
260 case EMMC_CMD12:
261 op = CMD_STOP_ABORT_CMD;
262 break;
263 case EMMC_CMD13:
264 op = CMD_WAIT_PRVDATA_COMPLETE;
265 break;
266 case EMMC_CMD8:
267 case EMMC_CMD17:
268 case EMMC_CMD18:
269 op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE;
270 break;
271 case EMMC_CMD24:
272 case EMMC_CMD25:
273 op = CMD_WRITE | CMD_DATA_TRANS_EXPECT |
274 CMD_WAIT_PRVDATA_COMPLETE;
275 break;
276 default:
277 op = 0;
278 break;
279 }
280 op |= CMD_USE_HOLD_REG | CMD_START;
281 switch (cmd->resp_type) {
282 case 0:
283 break;
284 case EMMC_RESPONSE_R2:
285 op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC |
286 CMD_RESP_LEN;
287 break;
288 case EMMC_RESPONSE_R3:
289 op |= CMD_RESP_EXPECT;
290 break;
291 default:
292 op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC;
293 break;
294 }
295 timeout = TIMEOUT;
296 do {
297 data = mmio_read_32(base + DWMMC_STATUS);
298 if (--timeout <= 0)
299 panic();
300 } while (data & STATUS_DATA_BUSY);
301
302 mmio_write_32(base + DWMMC_RINTSTS, ~0);
303 mmio_write_32(base + DWMMC_CMDARG, cmd->cmd_arg);
304 mmio_write_32(base + DWMMC_CMD, op | cmd->cmd_idx);
305
306 err_mask = INT_EBE | INT_HLE | INT_RTO | INT_RCRC | INT_RE |
307 INT_DCRC | INT_DRT | INT_SBE;
308 timeout = TIMEOUT;
309 do {
310 udelay(500);
311 data = mmio_read_32(base + DWMMC_RINTSTS);
312
313 if (data & err_mask)
314 return -EIO;
315 if (data & INT_DTO)
316 break;
317 if (--timeout == 0) {
318 ERROR("%s, RINTSTS:0x%x\n", __func__, data);
319 panic();
320 }
321 } while (!(data & INT_CMD_DONE));
322
323 if (op & CMD_RESP_EXPECT) {
324 cmd->resp_data[0] = mmio_read_32(base + DWMMC_RESP0);
325 if (op & CMD_RESP_LEN) {
326 cmd->resp_data[1] = mmio_read_32(base + DWMMC_RESP1);
327 cmd->resp_data[2] = mmio_read_32(base + DWMMC_RESP2);
328 cmd->resp_data[3] = mmio_read_32(base + DWMMC_RESP3);
329 }
330 }
331 return 0;
332}
333
334static int dw_set_ios(int clk, int width)
335{
336 switch (width) {
337 case EMMC_BUS_WIDTH_1:
338 mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_1BIT);
339 break;
340 case EMMC_BUS_WIDTH_4:
341 mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_4BIT);
342 break;
343 case EMMC_BUS_WIDTH_8:
344 mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_8BIT);
345 break;
346 default:
347 assert(0);
348 }
349 dw_set_clk(clk);
350 return 0;
351}
352
353static int dw_prepare(int lba, uintptr_t buf, size_t size)
354{
355 struct dw_idmac_desc *desc;
356 int desc_cnt, i, last;
357 uintptr_t base;
358
359 assert(((buf & EMMC_BLOCK_MASK) == 0) &&
360 ((size % EMMC_BLOCK_SIZE) == 0) &&
361 (dw_params.desc_size > 0) &&
362 ((dw_params.reg_base & EMMC_BLOCK_MASK) == 0) &&
363 ((dw_params.desc_base & EMMC_BLOCK_MASK) == 0) &&
364 ((dw_params.desc_size & EMMC_BLOCK_MASK) == 0));
365
366 desc_cnt = (size + DWMMC_DMA_MAX_BUFFER_SIZE - 1) /
367 DWMMC_DMA_MAX_BUFFER_SIZE;
368 assert(desc_cnt * sizeof(struct dw_idmac_desc) < dw_params.desc_size);
369
370 base = dw_params.reg_base;
371 desc = (struct dw_idmac_desc *)dw_params.desc_base;
372 mmio_write_32(base + DWMMC_BYTCNT, size);
373 mmio_write_32(base + DWMMC_RINTSTS, ~0);
374 for (i = 0; i < desc_cnt; i++) {
375 desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC;
376 desc[i].des1 = IDMAC_DES1_BS1(DWMMC_DMA_MAX_BUFFER_SIZE);
377 desc[i].des2 = buf + DWMMC_DMA_MAX_BUFFER_SIZE * i;
378 desc[i].des3 = dw_params.desc_base +
379 (sizeof(struct dw_idmac_desc)) * (i + 1);
380 }
381 /* first descriptor */
382 desc->des0 |= IDMAC_DES0_FS;
383 /* last descriptor */
384 last = desc_cnt - 1;
385 (desc + last)->des0 |= IDMAC_DES0_LD;
386 (desc + last)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH);
387 (desc + last)->des1 = IDMAC_DES1_BS1(size - (last *
388 DWMMC_DMA_MAX_BUFFER_SIZE));
389 /* set next descriptor address as 0 */
390 (desc + last)->des3 = 0;
391
392 mmio_write_32(base + DWMMC_DBADDR, dw_params.desc_base);
393 clean_dcache_range(dw_params.desc_base,
394 desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE);
395
396 return 0;
397}
398
399static int dw_read(int lba, uintptr_t buf, size_t size)
400{
401 return 0;
402}
403
404static int dw_write(int lba, uintptr_t buf, size_t size)
405{
406 return 0;
407}
408
409void dw_mmc_init(dw_mmc_params_t *params)
410{
411 assert((params != 0) &&
412 ((params->reg_base & EMMC_BLOCK_MASK) == 0) &&
413 ((params->desc_base & EMMC_BLOCK_MASK) == 0) &&
414 ((params->desc_size & EMMC_BLOCK_MASK) == 0) &&
415 (params->desc_size > 0) &&
416 (params->clk_rate > 0) &&
417 ((params->bus_width == EMMC_BUS_WIDTH_1) ||
418 (params->bus_width == EMMC_BUS_WIDTH_4) ||
419 (params->bus_width == EMMC_BUS_WIDTH_8)));
420
421 memcpy(&dw_params, params, sizeof(dw_mmc_params_t));
422 emmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width,
423 params->flags);
424}