1 /* 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 136 struct dw_idmac_desc { 137 unsigned int des0; 138 unsigned int des1; 139 unsigned int des2; 140 unsigned int des3; 141 }; 142 143 static void dw_init(void); 144 static int dw_send_cmd(emmc_cmd_t *cmd); 145 static int dw_set_ios(int clk, int width); 146 static int dw_prepare(int lba, uintptr_t buf, size_t size); 147 static int dw_read(int lba, uintptr_t buf, size_t size); 148 static int dw_write(int lba, uintptr_t buf, size_t size); 149 150 static 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 159 static dw_mmc_params_t dw_params; 160 161 static 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 177 static 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 209 static 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 246 static 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 334 static 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 353 static 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 399 static int dw_read(int lba, uintptr_t buf, size_t size) 400 { 401 return 0; 402 } 403 404 static int dw_write(int lba, uintptr_t buf, size_t size) 405 { 406 return 0; 407 } 408 409 void 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 } 425