1 /* 2 * ARM PrimeCell MultiMedia Card Interface - PL180 3 * 4 * Copyright (C) ST-Ericsson SA 2010 5 * 6 * Author: Ulf Hansson <ulf.hansson@stericsson.com> 7 * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com> 8 * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 /* #define DEBUG */ 27 28 #include <asm/io.h> 29 #include "common.h" 30 #include <errno.h> 31 #include <mmc.h> 32 #include "arm_pl180_mmci.h" 33 #include <malloc.h> 34 35 static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd) 36 { 37 u32 hoststatus, statusmask; 38 struct pl180_mmc_host *host = dev->priv; 39 40 statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL; 41 if ((cmd->resp_type & MMC_RSP_PRESENT)) 42 statusmask |= SDI_STA_CMDREND; 43 else 44 statusmask |= SDI_STA_CMDSENT; 45 46 do 47 hoststatus = readl(&host->base->status) & statusmask; 48 while (!hoststatus); 49 50 writel(statusmask, &host->base->status_clear); 51 if (hoststatus & SDI_STA_CTIMEOUT) { 52 debug("CMD%d time out\n", cmd->cmdidx); 53 return TIMEOUT; 54 } else if ((hoststatus & SDI_STA_CCRCFAIL) && 55 (cmd->resp_type & MMC_RSP_CRC)) { 56 printf("CMD%d CRC error\n", cmd->cmdidx); 57 return -EILSEQ; 58 } 59 60 if (cmd->resp_type & MMC_RSP_PRESENT) { 61 cmd->response[0] = readl(&host->base->response0); 62 cmd->response[1] = readl(&host->base->response1); 63 cmd->response[2] = readl(&host->base->response2); 64 cmd->response[3] = readl(&host->base->response3); 65 debug("CMD%d response[0]:0x%08X, response[1]:0x%08X, " 66 "response[2]:0x%08X, response[3]:0x%08X\n", 67 cmd->cmdidx, cmd->response[0], cmd->response[1], 68 cmd->response[2], cmd->response[3]); 69 } 70 71 return 0; 72 } 73 74 /* send command to the mmc card and wait for results */ 75 static int do_command(struct mmc *dev, struct mmc_cmd *cmd) 76 { 77 int result; 78 u32 sdi_cmd = 0; 79 struct pl180_mmc_host *host = dev->priv; 80 81 sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN); 82 83 if (cmd->resp_type) { 84 sdi_cmd |= SDI_CMD_WAITRESP; 85 if (cmd->resp_type & MMC_RSP_136) 86 sdi_cmd |= SDI_CMD_LONGRESP; 87 } 88 89 writel((u32)cmd->cmdarg, &host->base->argument); 90 udelay(COMMAND_REG_DELAY); 91 writel(sdi_cmd, &host->base->command); 92 result = wait_for_command_end(dev, cmd); 93 94 /* After CMD2 set RCA to a none zero value. */ 95 if ((result == 0) && (cmd->cmdidx == MMC_CMD_ALL_SEND_CID)) 96 dev->rca = 10; 97 98 /* After CMD3 open drain is switched off and push pull is used. */ 99 if ((result == 0) && (cmd->cmdidx == MMC_CMD_SET_RELATIVE_ADDR)) { 100 u32 sdi_pwr = readl(&host->base->power) & ~SDI_PWR_OPD; 101 writel(sdi_pwr, &host->base->power); 102 } 103 104 return result; 105 } 106 107 static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) 108 { 109 u32 *tempbuff = dest; 110 u64 xfercount = blkcount * blksize; 111 struct pl180_mmc_host *host = dev->priv; 112 u32 status, status_err; 113 114 debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); 115 116 status = readl(&host->base->status); 117 status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | 118 SDI_STA_RXOVERR); 119 while ((!status_err) && (xfercount >= sizeof(u32))) { 120 if (status & SDI_STA_RXDAVL) { 121 *(tempbuff) = readl(&host->base->fifo); 122 tempbuff++; 123 xfercount -= sizeof(u32); 124 } 125 status = readl(&host->base->status); 126 status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | 127 SDI_STA_RXOVERR); 128 } 129 130 status_err = status & 131 (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND | 132 SDI_STA_RXOVERR); 133 while (!status_err) { 134 status = readl(&host->base->status); 135 status_err = status & 136 (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND | 137 SDI_STA_RXOVERR); 138 } 139 140 if (status & SDI_STA_DTIMEOUT) { 141 printf("Read data timed out, xfercount: %llu, status: 0x%08X\n", 142 xfercount, status); 143 return -ETIMEDOUT; 144 } else if (status & SDI_STA_DCRCFAIL) { 145 printf("Read data bytes CRC error: 0x%x\n", status); 146 return -EILSEQ; 147 } else if (status & SDI_STA_RXOVERR) { 148 printf("Read data RX overflow error\n"); 149 return -EIO; 150 } 151 152 writel(SDI_ICR_MASK, &host->base->status_clear); 153 154 if (xfercount) { 155 printf("Read data error, xfercount: %llu\n", xfercount); 156 return -ENOBUFS; 157 } 158 159 return 0; 160 } 161 162 static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize) 163 { 164 u32 *tempbuff = src; 165 int i; 166 u64 xfercount = blkcount * blksize; 167 struct pl180_mmc_host *host = dev->priv; 168 u32 status, status_err; 169 170 debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); 171 172 status = readl(&host->base->status); 173 status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); 174 while (!status_err && xfercount) { 175 if (status & SDI_STA_TXFIFOBW) { 176 if (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) { 177 for (i = 0; i < SDI_FIFO_BURST_SIZE; i++) 178 writel(*(tempbuff + i), 179 &host->base->fifo); 180 tempbuff += SDI_FIFO_BURST_SIZE; 181 xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32); 182 } else { 183 while (xfercount >= sizeof(u32)) { 184 writel(*(tempbuff), &host->base->fifo); 185 tempbuff++; 186 xfercount -= sizeof(u32); 187 } 188 } 189 } 190 status = readl(&host->base->status); 191 status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); 192 } 193 194 status_err = status & 195 (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); 196 while (!status_err) { 197 status = readl(&host->base->status); 198 status_err = status & 199 (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); 200 } 201 202 if (status & SDI_STA_DTIMEOUT) { 203 printf("Write data timed out, xfercount:%llu,status:0x%08X\n", 204 xfercount, status); 205 return -ETIMEDOUT; 206 } else if (status & SDI_STA_DCRCFAIL) { 207 printf("Write data CRC error\n"); 208 return -EILSEQ; 209 } 210 211 writel(SDI_ICR_MASK, &host->base->status_clear); 212 213 if (xfercount) { 214 printf("Write data error, xfercount:%llu", xfercount); 215 return -ENOBUFS; 216 } 217 218 return 0; 219 } 220 221 static int do_data_transfer(struct mmc *dev, 222 struct mmc_cmd *cmd, 223 struct mmc_data *data) 224 { 225 int error = -ETIMEDOUT; 226 struct pl180_mmc_host *host = dev->priv; 227 u32 blksz = 0; 228 u32 data_ctrl = 0; 229 u32 data_len = (u32) (data->blocks * data->blocksize); 230 231 if (!host->version2) { 232 blksz = (ffs(data->blocksize) - 1); 233 data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK); 234 } else { 235 blksz = data->blocksize; 236 data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT); 237 } 238 data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE; 239 240 writel(SDI_DTIMER_DEFAULT, &host->base->datatimer); 241 writel(data_len, &host->base->datalength); 242 udelay(DATA_REG_DELAY); 243 244 if (data->flags & MMC_DATA_READ) { 245 data_ctrl |= SDI_DCTRL_DTDIR_IN; 246 writel(data_ctrl, &host->base->datactrl); 247 248 error = do_command(dev, cmd); 249 if (error) 250 return error; 251 252 error = read_bytes(dev, (u32 *)data->dest, (u32)data->blocks, 253 (u32)data->blocksize); 254 } else if (data->flags & MMC_DATA_WRITE) { 255 error = do_command(dev, cmd); 256 if (error) 257 return error; 258 259 writel(data_ctrl, &host->base->datactrl); 260 error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks, 261 (u32)data->blocksize); 262 } 263 264 return error; 265 } 266 267 static int host_request(struct mmc *dev, 268 struct mmc_cmd *cmd, 269 struct mmc_data *data) 270 { 271 int result; 272 273 if (data) 274 result = do_data_transfer(dev, cmd, data); 275 else 276 result = do_command(dev, cmd); 277 278 return result; 279 } 280 281 /* MMC uses open drain drivers in the enumeration phase */ 282 static int mmc_host_reset(struct mmc *dev) 283 { 284 struct pl180_mmc_host *host = dev->priv; 285 286 writel(host->pwr_init, &host->base->power); 287 288 return 0; 289 } 290 291 static void host_set_ios(struct mmc *dev) 292 { 293 struct pl180_mmc_host *host = dev->priv; 294 u32 sdi_clkcr; 295 296 sdi_clkcr = readl(&host->base->clock); 297 298 /* Ramp up the clock rate */ 299 if (dev->clock) { 300 u32 clkdiv = 0; 301 u32 tmp_clock; 302 303 if (dev->clock >= dev->f_max) { 304 clkdiv = 0; 305 dev->clock = dev->f_max; 306 } else { 307 clkdiv = (host->clock_in / dev->clock) - 2; 308 } 309 310 tmp_clock = host->clock_in / (clkdiv + 2); 311 while (tmp_clock > dev->clock) { 312 clkdiv++; 313 tmp_clock = host->clock_in / (clkdiv + 2); 314 } 315 316 if (clkdiv > SDI_CLKCR_CLKDIV_MASK) 317 clkdiv = SDI_CLKCR_CLKDIV_MASK; 318 319 tmp_clock = host->clock_in / (clkdiv + 2); 320 dev->clock = tmp_clock; 321 sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK); 322 sdi_clkcr |= clkdiv; 323 } 324 325 /* Set the bus width */ 326 if (dev->bus_width) { 327 u32 buswidth = 0; 328 329 switch (dev->bus_width) { 330 case 1: 331 buswidth |= SDI_CLKCR_WIDBUS_1; 332 break; 333 case 4: 334 buswidth |= SDI_CLKCR_WIDBUS_4; 335 break; 336 case 8: 337 buswidth |= SDI_CLKCR_WIDBUS_8; 338 break; 339 default: 340 printf("Invalid bus width: %d\n", dev->bus_width); 341 break; 342 } 343 sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK); 344 sdi_clkcr |= buswidth; 345 } 346 347 writel(sdi_clkcr, &host->base->clock); 348 udelay(CLK_CHANGE_DELAY); 349 } 350 351 /* 352 * mmc_host_init - initialize the mmc controller. 353 * Set initial clock and power for mmc slot. 354 * Initialize mmc struct and register with mmc framework. 355 */ 356 int arm_pl180_mmci_init(struct pl180_mmc_host *host) 357 { 358 struct mmc *dev; 359 u32 sdi_u32; 360 361 dev = malloc(sizeof(struct mmc)); 362 if (!dev) 363 return -ENOMEM; 364 365 memset(dev, 0, sizeof(struct mmc)); 366 dev->priv = host; 367 368 writel(host->pwr_init, &host->base->power); 369 writel(host->clkdiv_init, &host->base->clock); 370 udelay(CLK_CHANGE_DELAY); 371 372 /* Disable mmc interrupts */ 373 sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; 374 writel(sdi_u32, &host->base->mask0); 375 strncpy(dev->name, host->name, sizeof(dev->name)); 376 dev->send_cmd = host_request; 377 dev->set_ios = host_set_ios; 378 dev->init = mmc_host_reset; 379 dev->getcd = NULL; 380 dev->host_caps = host->caps; 381 dev->voltages = host->voltages; 382 dev->f_min = host->clock_min; 383 dev->f_max = host->clock_max; 384 dev->b_max = host->b_max; 385 mmc_register(dev); 386 debug("registered mmc interface number is:%d\n", dev->block_dev.dev); 387 388 return 0; 389 } 390