1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch.h> 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <common/debug.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <drivers/mmc.h> 16*91f16700Schasinglulu #include <drivers/synopsys/dw_mmc.h> 17*91f16700Schasinglulu #include <lib/utils_def.h> 18*91f16700Schasinglulu #include <lib/mmio.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu #define DWMMC_CTRL (0x00) 21*91f16700Schasinglulu #define CTRL_IDMAC_EN (1 << 25) 22*91f16700Schasinglulu #define CTRL_DMA_EN (1 << 5) 23*91f16700Schasinglulu #define CTRL_INT_EN (1 << 4) 24*91f16700Schasinglulu #define CTRL_DMA_RESET (1 << 2) 25*91f16700Schasinglulu #define CTRL_FIFO_RESET (1 << 1) 26*91f16700Schasinglulu #define CTRL_RESET (1 << 0) 27*91f16700Schasinglulu #define CTRL_RESET_ALL (CTRL_DMA_RESET | CTRL_FIFO_RESET | \ 28*91f16700Schasinglulu CTRL_RESET) 29*91f16700Schasinglulu 30*91f16700Schasinglulu #define DWMMC_PWREN (0x04) 31*91f16700Schasinglulu #define DWMMC_CLKDIV (0x08) 32*91f16700Schasinglulu #define DWMMC_CLKSRC (0x0c) 33*91f16700Schasinglulu #define DWMMC_CLKENA (0x10) 34*91f16700Schasinglulu #define DWMMC_TMOUT (0x14) 35*91f16700Schasinglulu #define DWMMC_CTYPE (0x18) 36*91f16700Schasinglulu #define CTYPE_8BIT (1 << 16) 37*91f16700Schasinglulu #define CTYPE_4BIT (1) 38*91f16700Schasinglulu #define CTYPE_1BIT (0) 39*91f16700Schasinglulu 40*91f16700Schasinglulu #define DWMMC_BLKSIZ (0x1c) 41*91f16700Schasinglulu #define DWMMC_BYTCNT (0x20) 42*91f16700Schasinglulu #define DWMMC_INTMASK (0x24) 43*91f16700Schasinglulu #define INT_EBE (1 << 15) 44*91f16700Schasinglulu #define INT_SBE (1 << 13) 45*91f16700Schasinglulu #define INT_HLE (1 << 12) 46*91f16700Schasinglulu #define INT_FRUN (1 << 11) 47*91f16700Schasinglulu #define INT_DRT (1 << 9) 48*91f16700Schasinglulu #define INT_RTO (1 << 8) 49*91f16700Schasinglulu #define INT_DCRC (1 << 7) 50*91f16700Schasinglulu #define INT_RCRC (1 << 6) 51*91f16700Schasinglulu #define INT_RXDR (1 << 5) 52*91f16700Schasinglulu #define INT_TXDR (1 << 4) 53*91f16700Schasinglulu #define INT_DTO (1 << 3) 54*91f16700Schasinglulu #define INT_CMD_DONE (1 << 2) 55*91f16700Schasinglulu #define INT_RE (1 << 1) 56*91f16700Schasinglulu 57*91f16700Schasinglulu #define DWMMC_CMDARG (0x28) 58*91f16700Schasinglulu #define DWMMC_CMD (0x2c) 59*91f16700Schasinglulu #define CMD_START (U(1) << 31) 60*91f16700Schasinglulu #define CMD_USE_HOLD_REG (1 << 29) /* 0 if SDR50/100 */ 61*91f16700Schasinglulu #define CMD_UPDATE_CLK_ONLY (1 << 21) 62*91f16700Schasinglulu #define CMD_SEND_INIT (1 << 15) 63*91f16700Schasinglulu #define CMD_STOP_ABORT_CMD (1 << 14) 64*91f16700Schasinglulu #define CMD_WAIT_PRVDATA_COMPLETE (1 << 13) 65*91f16700Schasinglulu #define CMD_WRITE (1 << 10) 66*91f16700Schasinglulu #define CMD_DATA_TRANS_EXPECT (1 << 9) 67*91f16700Schasinglulu #define CMD_CHECK_RESP_CRC (1 << 8) 68*91f16700Schasinglulu #define CMD_RESP_LEN (1 << 7) 69*91f16700Schasinglulu #define CMD_RESP_EXPECT (1 << 6) 70*91f16700Schasinglulu #define CMD(x) (x & 0x3f) 71*91f16700Schasinglulu 72*91f16700Schasinglulu #define DWMMC_RESP0 (0x30) 73*91f16700Schasinglulu #define DWMMC_RESP1 (0x34) 74*91f16700Schasinglulu #define DWMMC_RESP2 (0x38) 75*91f16700Schasinglulu #define DWMMC_RESP3 (0x3c) 76*91f16700Schasinglulu #define DWMMC_RINTSTS (0x44) 77*91f16700Schasinglulu #define DWMMC_STATUS (0x48) 78*91f16700Schasinglulu #define STATUS_DATA_BUSY (1 << 9) 79*91f16700Schasinglulu 80*91f16700Schasinglulu #define DWMMC_FIFOTH (0x4c) 81*91f16700Schasinglulu #define FIFOTH_TWMARK(x) (x & 0xfff) 82*91f16700Schasinglulu #define FIFOTH_RWMARK(x) ((x & 0x1ff) << 16) 83*91f16700Schasinglulu #define FIFOTH_DMA_BURST_SIZE(x) ((x & 0x7) << 28) 84*91f16700Schasinglulu 85*91f16700Schasinglulu #define DWMMC_DEBNCE (0x64) 86*91f16700Schasinglulu #define DWMMC_BMOD (0x80) 87*91f16700Schasinglulu #define BMOD_ENABLE (1 << 7) 88*91f16700Schasinglulu #define BMOD_FB (1 << 1) 89*91f16700Schasinglulu #define BMOD_SWRESET (1 << 0) 90*91f16700Schasinglulu 91*91f16700Schasinglulu #define DWMMC_DBADDR (0x88) 92*91f16700Schasinglulu #define DWMMC_IDSTS (0x8c) 93*91f16700Schasinglulu #define DWMMC_IDINTEN (0x90) 94*91f16700Schasinglulu #define DWMMC_CARDTHRCTL (0x100) 95*91f16700Schasinglulu #define CARDTHRCTL_RD_THR(x) ((x & 0xfff) << 16) 96*91f16700Schasinglulu #define CARDTHRCTL_RD_THR_EN (1 << 0) 97*91f16700Schasinglulu 98*91f16700Schasinglulu #define IDMAC_DES0_DIC (1 << 1) 99*91f16700Schasinglulu #define IDMAC_DES0_LD (1 << 2) 100*91f16700Schasinglulu #define IDMAC_DES0_FS (1 << 3) 101*91f16700Schasinglulu #define IDMAC_DES0_CH (1 << 4) 102*91f16700Schasinglulu #define IDMAC_DES0_ER (1 << 5) 103*91f16700Schasinglulu #define IDMAC_DES0_CES (1 << 30) 104*91f16700Schasinglulu #define IDMAC_DES0_OWN (U(1) << 31) 105*91f16700Schasinglulu #define IDMAC_DES1_BS1(x) ((x) & 0x1fff) 106*91f16700Schasinglulu #define IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13) 107*91f16700Schasinglulu 108*91f16700Schasinglulu #define DWMMC_DMA_MAX_BUFFER_SIZE (512 * 8) 109*91f16700Schasinglulu 110*91f16700Schasinglulu #define DWMMC_8BIT_MODE (1 << 6) 111*91f16700Schasinglulu 112*91f16700Schasinglulu #define DWMMC_ADDRESS_MASK U(0x0f) 113*91f16700Schasinglulu 114*91f16700Schasinglulu #define TIMEOUT 100000 115*91f16700Schasinglulu 116*91f16700Schasinglulu struct dw_idmac_desc { 117*91f16700Schasinglulu unsigned int des0; 118*91f16700Schasinglulu unsigned int des1; 119*91f16700Schasinglulu unsigned int des2; 120*91f16700Schasinglulu unsigned int des3; 121*91f16700Schasinglulu }; 122*91f16700Schasinglulu 123*91f16700Schasinglulu static void dw_init(void); 124*91f16700Schasinglulu static int dw_send_cmd(struct mmc_cmd *cmd); 125*91f16700Schasinglulu static int dw_set_ios(unsigned int clk, unsigned int width); 126*91f16700Schasinglulu static int dw_prepare(int lba, uintptr_t buf, size_t size); 127*91f16700Schasinglulu static int dw_read(int lba, uintptr_t buf, size_t size); 128*91f16700Schasinglulu static int dw_write(int lba, uintptr_t buf, size_t size); 129*91f16700Schasinglulu 130*91f16700Schasinglulu static const struct mmc_ops dw_mmc_ops = { 131*91f16700Schasinglulu .init = dw_init, 132*91f16700Schasinglulu .send_cmd = dw_send_cmd, 133*91f16700Schasinglulu .set_ios = dw_set_ios, 134*91f16700Schasinglulu .prepare = dw_prepare, 135*91f16700Schasinglulu .read = dw_read, 136*91f16700Schasinglulu .write = dw_write, 137*91f16700Schasinglulu }; 138*91f16700Schasinglulu 139*91f16700Schasinglulu static dw_mmc_params_t dw_params; 140*91f16700Schasinglulu 141*91f16700Schasinglulu static void dw_update_clk(void) 142*91f16700Schasinglulu { 143*91f16700Schasinglulu unsigned int data; 144*91f16700Schasinglulu 145*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CMD, 146*91f16700Schasinglulu CMD_WAIT_PRVDATA_COMPLETE | CMD_UPDATE_CLK_ONLY | 147*91f16700Schasinglulu CMD_START); 148*91f16700Schasinglulu while (1) { 149*91f16700Schasinglulu data = mmio_read_32(dw_params.reg_base + DWMMC_CMD); 150*91f16700Schasinglulu if ((data & CMD_START) == 0) 151*91f16700Schasinglulu break; 152*91f16700Schasinglulu data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); 153*91f16700Schasinglulu assert((data & INT_HLE) == 0); 154*91f16700Schasinglulu } 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu static void dw_set_clk(int clk) 158*91f16700Schasinglulu { 159*91f16700Schasinglulu unsigned int data; 160*91f16700Schasinglulu int div; 161*91f16700Schasinglulu 162*91f16700Schasinglulu assert(clk > 0); 163*91f16700Schasinglulu 164*91f16700Schasinglulu for (div = 1; div < 256; div++) { 165*91f16700Schasinglulu if ((dw_params.clk_rate / (2 * div)) <= clk) { 166*91f16700Schasinglulu break; 167*91f16700Schasinglulu } 168*91f16700Schasinglulu } 169*91f16700Schasinglulu assert(div < 256); 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* wait until controller is idle */ 172*91f16700Schasinglulu do { 173*91f16700Schasinglulu data = mmio_read_32(dw_params.reg_base + DWMMC_STATUS); 174*91f16700Schasinglulu } while (data & STATUS_DATA_BUSY); 175*91f16700Schasinglulu 176*91f16700Schasinglulu /* disable clock before change clock rate */ 177*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 0); 178*91f16700Schasinglulu dw_update_clk(); 179*91f16700Schasinglulu 180*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CLKDIV, div); 181*91f16700Schasinglulu dw_update_clk(); 182*91f16700Schasinglulu 183*91f16700Schasinglulu /* enable clock */ 184*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 1); 185*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CLKSRC, 0); 186*91f16700Schasinglulu dw_update_clk(); 187*91f16700Schasinglulu } 188*91f16700Schasinglulu 189*91f16700Schasinglulu static void dw_init(void) 190*91f16700Schasinglulu { 191*91f16700Schasinglulu unsigned int data; 192*91f16700Schasinglulu uintptr_t base; 193*91f16700Schasinglulu 194*91f16700Schasinglulu assert((dw_params.reg_base & MMC_BLOCK_MASK) == 0); 195*91f16700Schasinglulu 196*91f16700Schasinglulu base = dw_params.reg_base; 197*91f16700Schasinglulu mmio_write_32(base + DWMMC_PWREN, 1); 198*91f16700Schasinglulu mmio_write_32(base + DWMMC_CTRL, CTRL_RESET_ALL); 199*91f16700Schasinglulu do { 200*91f16700Schasinglulu data = mmio_read_32(base + DWMMC_CTRL); 201*91f16700Schasinglulu } while (data); 202*91f16700Schasinglulu 203*91f16700Schasinglulu /* enable DMA in CTRL */ 204*91f16700Schasinglulu data = CTRL_INT_EN | CTRL_DMA_EN | CTRL_IDMAC_EN; 205*91f16700Schasinglulu mmio_write_32(base + DWMMC_CTRL, data); 206*91f16700Schasinglulu mmio_write_32(base + DWMMC_RINTSTS, ~0); 207*91f16700Schasinglulu mmio_write_32(base + DWMMC_INTMASK, 0); 208*91f16700Schasinglulu mmio_write_32(base + DWMMC_TMOUT, ~0); 209*91f16700Schasinglulu mmio_write_32(base + DWMMC_IDINTEN, ~0); 210*91f16700Schasinglulu mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); 211*91f16700Schasinglulu mmio_write_32(base + DWMMC_BYTCNT, 256 * 1024); 212*91f16700Schasinglulu mmio_write_32(base + DWMMC_DEBNCE, 0x00ffffff); 213*91f16700Schasinglulu mmio_write_32(base + DWMMC_BMOD, BMOD_SWRESET); 214*91f16700Schasinglulu do { 215*91f16700Schasinglulu data = mmio_read_32(base + DWMMC_BMOD); 216*91f16700Schasinglulu } while (data & BMOD_SWRESET); 217*91f16700Schasinglulu /* enable DMA in BMOD */ 218*91f16700Schasinglulu data |= BMOD_ENABLE | BMOD_FB; 219*91f16700Schasinglulu mmio_write_32(base + DWMMC_BMOD, data); 220*91f16700Schasinglulu 221*91f16700Schasinglulu udelay(100); 222*91f16700Schasinglulu dw_set_clk(MMC_BOOT_CLK_RATE); 223*91f16700Schasinglulu udelay(100); 224*91f16700Schasinglulu } 225*91f16700Schasinglulu 226*91f16700Schasinglulu static int dw_send_cmd(struct mmc_cmd *cmd) 227*91f16700Schasinglulu { 228*91f16700Schasinglulu unsigned int op, data, err_mask; 229*91f16700Schasinglulu uintptr_t base; 230*91f16700Schasinglulu int timeout; 231*91f16700Schasinglulu 232*91f16700Schasinglulu assert(cmd); 233*91f16700Schasinglulu 234*91f16700Schasinglulu base = dw_params.reg_base; 235*91f16700Schasinglulu 236*91f16700Schasinglulu switch (cmd->cmd_idx) { 237*91f16700Schasinglulu case 0: 238*91f16700Schasinglulu op = CMD_SEND_INIT; 239*91f16700Schasinglulu break; 240*91f16700Schasinglulu case 12: 241*91f16700Schasinglulu op = CMD_STOP_ABORT_CMD; 242*91f16700Schasinglulu break; 243*91f16700Schasinglulu case 13: 244*91f16700Schasinglulu op = CMD_WAIT_PRVDATA_COMPLETE; 245*91f16700Schasinglulu break; 246*91f16700Schasinglulu case 8: 247*91f16700Schasinglulu if (dw_params.mmc_dev_type == MMC_IS_EMMC) 248*91f16700Schasinglulu op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; 249*91f16700Schasinglulu else 250*91f16700Schasinglulu op = CMD_WAIT_PRVDATA_COMPLETE; 251*91f16700Schasinglulu break; 252*91f16700Schasinglulu case 17: 253*91f16700Schasinglulu case 18: 254*91f16700Schasinglulu op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; 255*91f16700Schasinglulu break; 256*91f16700Schasinglulu case 24: 257*91f16700Schasinglulu case 25: 258*91f16700Schasinglulu op = CMD_WRITE | CMD_DATA_TRANS_EXPECT | 259*91f16700Schasinglulu CMD_WAIT_PRVDATA_COMPLETE; 260*91f16700Schasinglulu break; 261*91f16700Schasinglulu case 51: 262*91f16700Schasinglulu op = CMD_DATA_TRANS_EXPECT; 263*91f16700Schasinglulu break; 264*91f16700Schasinglulu default: 265*91f16700Schasinglulu op = 0; 266*91f16700Schasinglulu break; 267*91f16700Schasinglulu } 268*91f16700Schasinglulu op |= CMD_USE_HOLD_REG | CMD_START; 269*91f16700Schasinglulu switch (cmd->resp_type) { 270*91f16700Schasinglulu case 0: 271*91f16700Schasinglulu break; 272*91f16700Schasinglulu case MMC_RESPONSE_R2: 273*91f16700Schasinglulu op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC | 274*91f16700Schasinglulu CMD_RESP_LEN; 275*91f16700Schasinglulu break; 276*91f16700Schasinglulu case MMC_RESPONSE_R3: 277*91f16700Schasinglulu op |= CMD_RESP_EXPECT; 278*91f16700Schasinglulu break; 279*91f16700Schasinglulu default: 280*91f16700Schasinglulu op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC; 281*91f16700Schasinglulu break; 282*91f16700Schasinglulu } 283*91f16700Schasinglulu timeout = TIMEOUT; 284*91f16700Schasinglulu do { 285*91f16700Schasinglulu data = mmio_read_32(base + DWMMC_STATUS); 286*91f16700Schasinglulu if (--timeout <= 0) 287*91f16700Schasinglulu panic(); 288*91f16700Schasinglulu } while (data & STATUS_DATA_BUSY); 289*91f16700Schasinglulu 290*91f16700Schasinglulu mmio_write_32(base + DWMMC_RINTSTS, ~0); 291*91f16700Schasinglulu mmio_write_32(base + DWMMC_CMDARG, cmd->cmd_arg); 292*91f16700Schasinglulu mmio_write_32(base + DWMMC_CMD, op | cmd->cmd_idx); 293*91f16700Schasinglulu 294*91f16700Schasinglulu err_mask = INT_EBE | INT_HLE | INT_RTO | INT_RCRC | INT_RE | 295*91f16700Schasinglulu INT_DCRC | INT_DRT | INT_SBE; 296*91f16700Schasinglulu timeout = TIMEOUT; 297*91f16700Schasinglulu do { 298*91f16700Schasinglulu udelay(500); 299*91f16700Schasinglulu data = mmio_read_32(base + DWMMC_RINTSTS); 300*91f16700Schasinglulu 301*91f16700Schasinglulu if (data & err_mask) 302*91f16700Schasinglulu return -EIO; 303*91f16700Schasinglulu if (data & INT_DTO) 304*91f16700Schasinglulu break; 305*91f16700Schasinglulu if (--timeout == 0) { 306*91f16700Schasinglulu ERROR("%s, RINTSTS:0x%x\n", __func__, data); 307*91f16700Schasinglulu panic(); 308*91f16700Schasinglulu } 309*91f16700Schasinglulu } while (!(data & INT_CMD_DONE)); 310*91f16700Schasinglulu 311*91f16700Schasinglulu if (op & CMD_RESP_EXPECT) { 312*91f16700Schasinglulu cmd->resp_data[0] = mmio_read_32(base + DWMMC_RESP0); 313*91f16700Schasinglulu if (op & CMD_RESP_LEN) { 314*91f16700Schasinglulu cmd->resp_data[1] = mmio_read_32(base + DWMMC_RESP1); 315*91f16700Schasinglulu cmd->resp_data[2] = mmio_read_32(base + DWMMC_RESP2); 316*91f16700Schasinglulu cmd->resp_data[3] = mmio_read_32(base + DWMMC_RESP3); 317*91f16700Schasinglulu } 318*91f16700Schasinglulu } 319*91f16700Schasinglulu return 0; 320*91f16700Schasinglulu } 321*91f16700Schasinglulu 322*91f16700Schasinglulu static int dw_set_ios(unsigned int clk, unsigned int width) 323*91f16700Schasinglulu { 324*91f16700Schasinglulu switch (width) { 325*91f16700Schasinglulu case MMC_BUS_WIDTH_1: 326*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_1BIT); 327*91f16700Schasinglulu break; 328*91f16700Schasinglulu case MMC_BUS_WIDTH_4: 329*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_4BIT); 330*91f16700Schasinglulu break; 331*91f16700Schasinglulu case MMC_BUS_WIDTH_8: 332*91f16700Schasinglulu mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_8BIT); 333*91f16700Schasinglulu break; 334*91f16700Schasinglulu default: 335*91f16700Schasinglulu assert(0); 336*91f16700Schasinglulu break; 337*91f16700Schasinglulu } 338*91f16700Schasinglulu dw_set_clk(clk); 339*91f16700Schasinglulu return 0; 340*91f16700Schasinglulu } 341*91f16700Schasinglulu 342*91f16700Schasinglulu static int dw_prepare(int lba, uintptr_t buf, size_t size) 343*91f16700Schasinglulu { 344*91f16700Schasinglulu struct dw_idmac_desc *desc; 345*91f16700Schasinglulu int desc_cnt, i, last; 346*91f16700Schasinglulu uintptr_t base; 347*91f16700Schasinglulu 348*91f16700Schasinglulu assert(((buf & DWMMC_ADDRESS_MASK) == 0) && 349*91f16700Schasinglulu (dw_params.desc_size > 0) && 350*91f16700Schasinglulu ((dw_params.reg_base & MMC_BLOCK_MASK) == 0) && 351*91f16700Schasinglulu ((dw_params.desc_base & MMC_BLOCK_MASK) == 0) && 352*91f16700Schasinglulu ((dw_params.desc_size & MMC_BLOCK_MASK) == 0)); 353*91f16700Schasinglulu 354*91f16700Schasinglulu flush_dcache_range(buf, size); 355*91f16700Schasinglulu 356*91f16700Schasinglulu desc_cnt = (size + DWMMC_DMA_MAX_BUFFER_SIZE - 1) / 357*91f16700Schasinglulu DWMMC_DMA_MAX_BUFFER_SIZE; 358*91f16700Schasinglulu assert(desc_cnt * sizeof(struct dw_idmac_desc) < dw_params.desc_size); 359*91f16700Schasinglulu 360*91f16700Schasinglulu base = dw_params.reg_base; 361*91f16700Schasinglulu desc = (struct dw_idmac_desc *)dw_params.desc_base; 362*91f16700Schasinglulu mmio_write_32(base + DWMMC_BYTCNT, size); 363*91f16700Schasinglulu 364*91f16700Schasinglulu if (size < MMC_BLOCK_SIZE) 365*91f16700Schasinglulu mmio_write_32(base + DWMMC_BLKSIZ, size); 366*91f16700Schasinglulu else 367*91f16700Schasinglulu mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); 368*91f16700Schasinglulu 369*91f16700Schasinglulu mmio_write_32(base + DWMMC_RINTSTS, ~0); 370*91f16700Schasinglulu for (i = 0; i < desc_cnt; i++) { 371*91f16700Schasinglulu desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC; 372*91f16700Schasinglulu desc[i].des1 = IDMAC_DES1_BS1(DWMMC_DMA_MAX_BUFFER_SIZE); 373*91f16700Schasinglulu desc[i].des2 = buf + DWMMC_DMA_MAX_BUFFER_SIZE * i; 374*91f16700Schasinglulu desc[i].des3 = dw_params.desc_base + 375*91f16700Schasinglulu (sizeof(struct dw_idmac_desc)) * (i + 1); 376*91f16700Schasinglulu } 377*91f16700Schasinglulu /* first descriptor */ 378*91f16700Schasinglulu desc->des0 |= IDMAC_DES0_FS; 379*91f16700Schasinglulu /* last descriptor */ 380*91f16700Schasinglulu last = desc_cnt - 1; 381*91f16700Schasinglulu (desc + last)->des0 |= IDMAC_DES0_LD; 382*91f16700Schasinglulu (desc + last)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); 383*91f16700Schasinglulu (desc + last)->des1 = IDMAC_DES1_BS1(size - (last * 384*91f16700Schasinglulu DWMMC_DMA_MAX_BUFFER_SIZE)); 385*91f16700Schasinglulu /* set next descriptor address as 0 */ 386*91f16700Schasinglulu (desc + last)->des3 = 0; 387*91f16700Schasinglulu 388*91f16700Schasinglulu mmio_write_32(base + DWMMC_DBADDR, dw_params.desc_base); 389*91f16700Schasinglulu flush_dcache_range(dw_params.desc_base, 390*91f16700Schasinglulu desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE); 391*91f16700Schasinglulu 392*91f16700Schasinglulu 393*91f16700Schasinglulu return 0; 394*91f16700Schasinglulu } 395*91f16700Schasinglulu 396*91f16700Schasinglulu static int dw_read(int lba, uintptr_t buf, size_t size) 397*91f16700Schasinglulu { 398*91f16700Schasinglulu uint32_t data = 0; 399*91f16700Schasinglulu int timeout = TIMEOUT; 400*91f16700Schasinglulu 401*91f16700Schasinglulu do { 402*91f16700Schasinglulu data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); 403*91f16700Schasinglulu udelay(50); 404*91f16700Schasinglulu } while (!(data & INT_DTO) && timeout-- > 0); 405*91f16700Schasinglulu 406*91f16700Schasinglulu inv_dcache_range(buf, size); 407*91f16700Schasinglulu 408*91f16700Schasinglulu return 0; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu 411*91f16700Schasinglulu static int dw_write(int lba, uintptr_t buf, size_t size) 412*91f16700Schasinglulu { 413*91f16700Schasinglulu return 0; 414*91f16700Schasinglulu } 415*91f16700Schasinglulu 416*91f16700Schasinglulu void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info) 417*91f16700Schasinglulu { 418*91f16700Schasinglulu assert((params != 0) && 419*91f16700Schasinglulu ((params->reg_base & MMC_BLOCK_MASK) == 0) && 420*91f16700Schasinglulu ((params->desc_base & MMC_BLOCK_MASK) == 0) && 421*91f16700Schasinglulu ((params->desc_size & MMC_BLOCK_MASK) == 0) && 422*91f16700Schasinglulu (params->desc_size > 0) && 423*91f16700Schasinglulu (params->clk_rate > 0) && 424*91f16700Schasinglulu ((params->bus_width == MMC_BUS_WIDTH_1) || 425*91f16700Schasinglulu (params->bus_width == MMC_BUS_WIDTH_4) || 426*91f16700Schasinglulu (params->bus_width == MMC_BUS_WIDTH_8))); 427*91f16700Schasinglulu 428*91f16700Schasinglulu memcpy(&dw_params, params, sizeof(dw_mmc_params_t)); 429*91f16700Schasinglulu dw_params.mmc_dev_type = info->mmc_dev_type; 430*91f16700Schasinglulu mmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width, 431*91f16700Schasinglulu params->flags, info); 432*91f16700Schasinglulu } 433