| Date: | 2010-07-12 22:49:53 (13 years 5 months ago) |
|---|---|
| Author: | Lars C. |
| Commit: | ef5286907666baca5edc4f8c243db32a6691d9bb |
| Message: | MMC: jz4740: Rework state handling Instead of sleeping inside the threaded irq handler there is now a state variable which determines in which action has to be executed next after an irq. |
| Files: |
drivers/mmc/host/jz4740_mmc.c (16 diffs) |
Change Details
| drivers/mmc/host/jz4740_mmc.c | ||
|---|---|---|
| 24 | 24 | #include <linux/clk.h> |
| 25 | 25 | #include <linux/mmc/jz4740_mmc.h> |
| 26 | 26 | |
| 27 | #include <linux/completion.h> | |
| 28 | ||
| 29 | 27 | #include <linux/bitops.h> |
| 30 | 28 | #include <linux/gpio.h> |
| 31 | 29 | #include <asm/mach-jz4740/gpio.h> |
| ... | ... | |
| 105 | 103 | |
| 106 | 104 | #define JZ_MMC_CLK_RATE 24000000 |
| 107 | 105 | |
| 106 | enum jz4740_mmc_state { | |
| 107 | JZ4740_MMC_STATE_READ_RESPONSE, | |
| 108 | JZ4740_MMC_STATE_TRANSFER_DATA, | |
| 109 | JZ4740_MMC_STATE_SEND_STOP, | |
| 110 | JZ4740_MMC_STATE_DONE, | |
| 111 | }; | |
| 112 | ||
| 108 | 113 | struct jz4740_mmc_host { |
| 109 | 114 | struct mmc_host *mmc; |
| 110 | 115 | struct platform_device *pdev; |
| ... | ... | |
| 129 | 134 | spinlock_t lock; |
| 130 | 135 | |
| 131 | 136 | struct timer_list timeout_timer; |
| 132 | struct completion completion; | |
| 137 | struct sg_mapping_iter miter; | |
| 138 | enum jz4740_mmc_state state; | |
| 133 | 139 | }; |
| 134 | 140 | |
| 135 | 141 | static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host, |
| ... | ... | |
| 161 | 167 | static void jz4740_mmc_clock_disable(struct jz4740_mmc_host *host) |
| 162 | 168 | { |
| 163 | 169 | uint32_t status; |
| 170 | unsigned int timeout = 1000; | |
| 164 | 171 | |
| 165 | 172 | writew(JZ_MMC_STRPCL_CLOCK_STOP, host->base + JZ_REG_MMC_STRPCL); |
| 166 | 173 | do { |
| 167 | 174 | status = readl(host->base + JZ_REG_MMC_STATUS); |
| 168 | } while (status & JZ_MMC_STATUS_CLK_EN); | |
| 175 | } while (status & JZ_MMC_STATUS_CLK_EN && --timeout); | |
| 169 | 176 | } |
| 170 | 177 | |
| 171 | 178 | static void jz4740_mmc_reset(struct jz4740_mmc_host *host) |
| 172 | 179 | { |
| 173 | 180 | uint32_t status; |
| 181 | unsigned int timeout = 1000; | |
| 174 | 182 | |
| 175 | 183 | writew(JZ_MMC_STRPCL_RESET, host->base + JZ_REG_MMC_STRPCL); |
| 176 | 184 | udelay(10); |
| 177 | 185 | do { |
| 178 | 186 | status = readl(host->base + JZ_REG_MMC_STATUS); |
| 179 | } while (status & JZ_MMC_STATUS_IS_RESETTING); | |
| 187 | } while (status & JZ_MMC_STATUS_IS_RESETTING && --timeout); | |
| 180 | 188 | } |
| 181 | 189 | |
| 182 | 190 | static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) |
| ... | ... | |
| 188 | 196 | |
| 189 | 197 | mmc_request_done(host->mmc, req); |
| 190 | 198 | } |
| 191 | static unsigned int jz4740_mmc_wait_irq(struct jz4740_mmc_host *host, | |
| 199 | static unsigned int jz4740_mmc_poll_irq(struct jz4740_mmc_host *host, | |
| 192 | 200 | unsigned int irq) |
| 193 | 201 | { |
| 194 | 202 | unsigned int timeout = 1000; |
| ... | ... | |
| 199 | 207 | } while (!(status & irq) && --timeout); |
| 200 | 208 | |
| 201 | 209 | if (timeout == 0) { |
| 202 | INIT_COMPLETION(host->completion); | |
| 210 | set_bit(0, &host->waiting); | |
| 211 | mod_timer(&host->timeout_timer, jiffies + 5*HZ); | |
| 203 | 212 | jz4740_mmc_set_irq_enabled(host, irq, true); |
| 204 | timeout = wait_for_completion_timeout(&host->completion, HZ); | |
| 213 | return true; | |
| 205 | 214 | } |
| 206 | 215 | |
| 207 | return timeout; | |
| 216 | return false; | |
| 208 | 217 | } |
| 209 | 218 | |
| 210 | static void jz4740_mmc_write_data(struct jz4740_mmc_host *host, | |
| 219 | static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, | |
| 211 | 220 | struct mmc_data *data) |
| 212 | 221 | { |
| 213 | struct sg_mapping_iter miter; | |
| 214 | uint32_t *buf; | |
| 215 | 222 | int status; |
| 216 | unsigned int timeout; | |
| 223 | ||
| 224 | status = readl(host->base + JZ_REG_MMC_STATUS); | |
| 225 | if (status & JZ_MMC_STATUS_WRITE_ERROR_MASK) { | |
| 226 | if (status & (JZ_MMC_STATUS_TIMEOUT_WRITE)) { | |
| 227 | host->req->cmd->error = -ETIMEDOUT; | |
| 228 | data->error = -ETIMEDOUT; | |
| 229 | } else { | |
| 230 | host->req->cmd->error = -EIO; | |
| 231 | data->error = -EIO; | |
| 232 | } | |
| 233 | } | |
| 234 | } | |
| 235 | ||
| 236 | static bool jz4740_mmc_write_data(struct jz4740_mmc_host *host, | |
| 237 | struct mmc_data *data) | |
| 238 | { | |
| 239 | struct sg_mapping_iter *miter = &host->miter; | |
| 240 | uint32_t *buf; | |
| 241 | bool timeout; | |
| 217 | 242 | size_t i, j; |
| 218 | 243 | |
| 219 | sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_FROM_SG); | |
| 220 | while (sg_miter_next(&miter)) { | |
| 221 | buf = miter.addr; | |
| 222 | i = miter.length / 4; | |
| 223 | j = i >> 3; | |
| 244 | while (sg_miter_next(miter)) { | |
| 245 | buf = miter->addr; | |
| 246 | i = miter->length / 4; | |
| 247 | j = i / 8; | |
| 224 | 248 | i = i & 0x7; |
| 225 | 249 | while (j) { |
| 226 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); | |
| 227 | if (unlikely(timeout == 0)) { | |
| 228 | sg_miter_stop(&miter); | |
| 229 | goto err_timeout; | |
| 230 | } | |
| 250 | timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); | |
| 251 | if (unlikely(timeout)) | |
| 252 | goto poll_timeout; | |
| 231 | 253 | |
| 232 | 254 | writel(buf[0], host->base + JZ_REG_MMC_TXFIFO); |
| 233 | 255 | writel(buf[1], host->base + JZ_REG_MMC_TXFIFO); |
| ... | ... | |
| 241 | 263 | --j; |
| 242 | 264 | } |
| 243 | 265 | if (unlikely(i)) { |
| 244 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); | |
| 245 | if (unlikely(timeout == 0)) { | |
| 246 | sg_miter_stop(&miter); | |
| 247 | goto err_timeout; | |
| 248 | } | |
| 266 | timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); | |
| 267 | if (unlikely(timeout)) | |
| 268 | goto poll_timeout; | |
| 249 | 269 | |
| 250 | 270 | while (i) { |
| 251 | 271 | writel(*buf, host->base + JZ_REG_MMC_TXFIFO); |
| ... | ... | |
| 253 | 273 | --i; |
| 254 | 274 | } |
| 255 | 275 | } |
| 256 | data->bytes_xfered += miter.length; | |
| 276 | data->bytes_xfered += miter->length; | |
| 257 | 277 | } |
| 258 | sg_miter_stop(&miter); | |
| 278 | sg_miter_stop(miter); | |
| 259 | 279 | |
| 260 | status = readl(host->base + JZ_REG_MMC_STATUS); | |
| 261 | if (status & JZ_MMC_STATUS_WRITE_ERROR_MASK) { | |
| 262 | if (status & (JZ_MMC_STATUS_TIMEOUT_WRITE)) { | |
| 263 | host->req->cmd->error = -ETIMEDOUT; | |
| 264 | data->error = -ETIMEDOUT; | |
| 265 | } else { | |
| 266 | host->req->cmd->error = -EIO; | |
| 267 | data->error = -EIO; | |
| 268 | } | |
| 269 | return; | |
| 270 | } | |
| 271 | ||
| 272 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_DATA_TRAN_DONE); | |
| 273 | if (unlikely(timeout == 0)) | |
| 274 | goto err_timeout; | |
| 280 | return false; | |
| 275 | 281 | |
| 276 | writew(JZ_MMC_IRQ_DATA_TRAN_DONE, host->base + JZ_REG_MMC_IREG); | |
| 282 | poll_timeout: | |
| 283 | miter->consumed = (void *)buf - miter->addr; | |
| 284 | data->bytes_xfered += miter->consumed; | |
| 285 | sg_miter_stop(miter); | |
| 277 | 286 | |
| 278 | return; | |
| 279 | ||
| 280 | err_timeout: | |
| 281 | host->req->cmd->error = -ETIMEDOUT; | |
| 282 | data->error = -ETIMEDOUT; | |
| 287 | return true; | |
| 283 | 288 | } |
| 284 | 289 | |
| 285 | static void jz4740_mmc_read_data(struct jz4740_mmc_host *host, | |
| 290 | static bool jz4740_mmc_read_data(struct jz4740_mmc_host *host, | |
| 286 | 291 | struct mmc_data *data) |
| 287 | 292 | { |
| 288 | struct sg_mapping_iter miter; | |
| 293 | struct sg_mapping_iter *miter = &host->miter; | |
| 289 | 294 | uint32_t *buf; |
| 290 | 295 | uint32_t d; |
| 291 | uint16_t status = 0; | |
| 296 | uint16_t status; | |
| 292 | 297 | size_t i, j; |
| 293 | 298 | unsigned int timeout; |
| 294 | 299 | |
| 295 | sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_TO_SG); | |
| 296 | while (sg_miter_next(&miter)) { | |
| 297 | buf = miter.addr; | |
| 298 | i = miter.length; | |
| 299 | j = i >> 5; | |
| 300 | while (sg_miter_next(miter)) { | |
| 301 | buf = miter->addr; | |
| 302 | i = miter->length; | |
| 303 | j = i / 32; | |
| 300 | 304 | i = i & 0x1f; |
| 301 | 305 | while (j) { |
| 302 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); | |
| 303 | if (unlikely(timeout == 0)) { | |
| 304 | sg_miter_stop(&miter); | |
| 305 | goto err_timeout; | |
| 306 | } | |
| 306 | timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); | |
| 307 | if (unlikely(timeout)) | |
| 308 | goto poll_timeout; | |
| 307 | 309 | |
| 308 | 310 | buf[0] = readl(host->base + JZ_REG_MMC_RXFIFO); |
| 309 | 311 | buf[1] = readl(host->base + JZ_REG_MMC_RXFIFO); |
| ... | ... | |
| 318 | 320 | --j; |
| 319 | 321 | } |
| 320 | 322 | |
| 321 | while (i >= 4) { | |
| 322 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); | |
| 323 | if (unlikely(timeout == 0)) { | |
| 324 | sg_miter_stop(&miter); | |
| 325 | goto err_timeout; | |
| 326 | } | |
| 323 | if (unlikely(i)) { | |
| 324 | timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); | |
| 325 | if (unlikely(timeout)) | |
| 326 | goto poll_timeout; | |
| 327 | 327 | |
| 328 | *buf++ = readl(host->base + JZ_REG_MMC_RXFIFO); | |
| 329 | i -= 4; | |
| 330 | } | |
| 331 | if (unlikely(i > 0)) { | |
| 332 | d = readl(host->base + JZ_REG_MMC_RXFIFO); | |
| 333 | memcpy(buf, &d, i); | |
| 328 | while (i >= 4) { | |
| 329 | *buf++ = readl(host->base + JZ_REG_MMC_RXFIFO); | |
| 330 | i -= 4; | |
| 331 | } | |
| 332 | if (unlikely(i > 0)) { | |
| 333 | d = readl(host->base + JZ_REG_MMC_RXFIFO); | |
| 334 | memcpy(buf, &d, i); | |
| 335 | } | |
| 334 | 336 | } |
| 335 | data->bytes_xfered += miter.length; | |
| 336 | ||
| 337 | /* This can go away once MIPS implements flush_kernel_dcache_page */ | |
| 338 | flush_dcache_page(miter.page); | |
| 339 | } | |
| 340 | sg_miter_stop(&miter); | |
| 337 | data->bytes_xfered += miter->length; | |
| 341 | 338 | |
| 342 | status = readl(host->base + JZ_REG_MMC_STATUS); | |
| 343 | if (status & JZ_MMC_STATUS_READ_ERROR_MASK) { | |
| 344 | if (status & JZ_MMC_STATUS_TIMEOUT_READ) { | |
| 345 | host->req->cmd->error = -ETIMEDOUT; | |
| 346 | data->error = -ETIMEDOUT; | |
| 347 | } else { | |
| 348 | host->req->cmd->error = -EIO; | |
| 349 | data->error = -EIO; | |
| 350 | } | |
| 351 | return; | |
| 339 | /* This can go away once MIPS implements | |
| 340 | * flush_kernel_dcache_page */ | |
| 341 | flush_dcache_page(miter->page); | |
| 352 | 342 | } |
| 343 | sg_miter_stop(miter); | |
| 353 | 344 | |
| 354 | 345 | /* For whatever reason there is sometime one word more in the fifo then |
| 355 | 346 | * requested */ |
| 356 | while ((status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) == 0 && --timeout) { | |
| 347 | timeout = 1000; | |
| 348 | status = readl(host->base + JZ_REG_MMC_STATUS); | |
| 349 | while (!(status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) && --timeout) { | |
| 357 | 350 | d = readl(host->base + JZ_REG_MMC_RXFIFO); |
| 358 | 351 | status = readl(host->base + JZ_REG_MMC_STATUS); |
| 359 | 352 | } |
| 360 | return; | |
| 361 | 353 | |
| 362 | err_timeout: | |
| 363 | host->req->cmd->error = -ETIMEDOUT; | |
| 364 | data->error = -ETIMEDOUT; | |
| 354 | return false; | |
| 355 | ||
| 356 | poll_timeout: | |
| 357 | miter->consumed = (void *)buf - miter->addr; | |
| 358 | data->bytes_xfered += miter->consumed; | |
| 359 | sg_miter_stop(miter); | |
| 360 | ||
| 361 | return true; | |
| 365 | 362 | } |
| 366 | 363 | |
| 367 | 364 | static void jz4740_mmc_timeout(unsigned long data) |
| ... | ... | |
| 444 | 441 | jz4740_mmc_clock_enable(host, 1); |
| 445 | 442 | } |
| 446 | 443 | |
| 444 | static void jz_mmc_prepare_data_transfer(struct jz4740_mmc_host *host) | |
| 445 | { | |
| 446 | struct mmc_command *cmd = host->req->cmd; | |
| 447 | struct mmc_data *data = cmd->data; | |
| 448 | int direction; | |
| 449 | ||
| 450 | if (cmd->data->flags & MMC_DATA_READ) | |
| 451 | direction = SG_MITER_TO_SG; | |
| 452 | else | |
| 453 | direction = SG_MITER_FROM_SG; | |
| 454 | ||
| 455 | sg_miter_start(&host->miter, data->sg, data->sg_len, direction); | |
| 456 | } | |
| 457 | ||
| 447 | 458 | |
| 448 | 459 | static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) |
| 449 | 460 | { |
| 450 | 461 | struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)devid; |
| 451 | 462 | struct mmc_command *cmd = host->req->cmd; |
| 452 | 463 | struct mmc_request *req = host->req; |
| 453 | unsigned int timeout; | |
| 464 | bool timedout = false; | |
| 454 | 465 | |
| 455 | 466 | if (cmd->error) |
| 456 | goto done; | |
| 467 | host->state = JZ4740_MMC_STATE_DONE; | |
| 457 | 468 | |
| 458 | if (cmd->flags & MMC_RSP_PRESENT) | |
| 459 | jz4740_mmc_read_response(host, cmd); | |
| 469 | switch (host->state) { | |
| 470 | case JZ4740_MMC_STATE_READ_RESPONSE: | |
| 471 | if (cmd->flags & MMC_RSP_PRESENT) | |
| 472 | jz4740_mmc_read_response(host, cmd); | |
| 460 | 473 | |
| 461 | if (cmd->data) { | |
| 474 | if (!cmd->data) | |
| 475 | break; | |
| 476 | ||
| 477 | jz_mmc_prepare_data_transfer(host); | |
| 478 | ||
| 479 | case JZ4740_MMC_STATE_TRANSFER_DATA: | |
| 462 | 480 | if (cmd->data->flags & MMC_DATA_READ) |
| 463 | jz4740_mmc_read_data(host, cmd->data); | |
| 481 | timedout = jz4740_mmc_read_data(host, cmd->data); | |
| 464 | 482 | else |
| 465 | jz4740_mmc_write_data(host, cmd->data); | |
| 466 | } | |
| 483 | timedout = jz4740_mmc_write_data(host, cmd->data); | |
| 467 | 484 | |
| 468 | if (req->stop) { | |
| 469 | jz4740_mmc_send_command(host, req->stop); | |
| 485 | if (unlikely(timedout)) { | |
| 486 | host->state = JZ4740_MMC_STATE_TRANSFER_DATA; | |
| 487 | break; | |
| 488 | } | |
| 470 | 489 | |
| 471 | timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_PRG_DONE); | |
| 472 | writew(JZ_MMC_IRQ_PRG_DONE, host->base + JZ_REG_MMC_IREG); | |
| 490 | jz4740_mmc_transfer_check_state(host, cmd->data); | |
| 473 | 491 | |
| 474 | if (unlikely(timeout == 0)) | |
| 475 | req->stop->error = -ETIMEDOUT; | |
| 476 | } | |
| 492 | timedout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_DATA_TRAN_DONE); | |
| 493 | if (unlikely(timedout)) { | |
| 494 | host->state = JZ4740_MMC_STATE_SEND_STOP; | |
| 495 | break; | |
| 496 | } | |
| 497 | writew(JZ_MMC_IRQ_DATA_TRAN_DONE, host->base + JZ_REG_MMC_IREG); | |
| 477 | 498 | |
| 499 | case JZ4740_MMC_STATE_SEND_STOP: | |
| 500 | if (!req->stop) | |
| 501 | break; | |
| 478 | 502 | |
| 479 | done: | |
| 480 | jz4740_mmc_request_done(host); | |
| 503 | jz4740_mmc_send_command(host, req->stop); | |
| 504 | ||
| 505 | timedout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); | |
| 506 | if (timedout) { | |
| 507 | host->state = JZ4740_MMC_STATE_DONE; | |
| 508 | break; | |
| 509 | } | |
| 510 | case JZ4740_MMC_STATE_DONE: | |
| 511 | break; | |
| 512 | } | |
| 513 | ||
| 514 | if (!timedout) | |
| 515 | jz4740_mmc_request_done(host); | |
| 481 | 516 | |
| 482 | 517 | return IRQ_HANDLED; |
| 483 | 518 | } |
| ... | ... | |
| 486 | 521 | { |
| 487 | 522 | struct jz4740_mmc_host *host = devid; |
| 488 | 523 | uint16_t irq_reg, status, tmp; |
| 489 | irqreturn_t ret = IRQ_HANDLED; | |
| 490 | 524 | |
| 491 | 525 | irq_reg = readw(host->base + JZ_REG_MMC_IREG); |
| 492 | 526 | |
| ... | ... | |
| 502 | 536 | if (irq_reg & JZ_MMC_IRQ_SDIO) { |
| 503 | 537 | writew(JZ_MMC_IRQ_SDIO, host->base + JZ_REG_MMC_IREG); |
| 504 | 538 | mmc_signal_sdio_irq(host->mmc); |
| 539 | irq_reg &= ~JZ_MMC_IRQ_SDIO; | |
| 505 | 540 | } |
| 506 | 541 | |
| 507 | if (!host->req || !host->cmd) | |
| 508 | goto handled; | |
| 509 | ||
| 510 | if (irq_reg & JZ_MMC_IRQ_END_CMD_RES) { | |
| 511 | ||
| 542 | if (host->req && host->cmd && irq_reg) { | |
| 512 | 543 | if (test_and_clear_bit(0, &host->waiting)) { |
| 513 | 544 | del_timer(&host->timeout_timer); |
| 514 | 545 | |
| ... | ... | |
| 526 | 557 | host->cmd->data->error = -EIO; |
| 527 | 558 | } |
| 528 | 559 | |
| 529 | ret = IRQ_WAKE_THREAD; | |
| 530 | } | |
| 560 | jz4740_mmc_set_irq_enabled(host, irq_reg, false); | |
| 561 | writew(irq_reg, host->base + JZ_REG_MMC_IREG); | |
| 531 | 562 | |
| 532 | jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, false); | |
| 533 | writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG); | |
| 534 | } else { | |
| 535 | complete(&host->completion); | |
| 536 | jz4740_mmc_set_irq_enabled(host, irq_reg, false); | |
| 537 | writew(irq_reg, host->base + JZ_REG_MMC_IREG); | |
| 563 | return IRQ_WAKE_THREAD; | |
| 564 | } | |
| 538 | 565 | } |
| 539 | 566 | |
| 540 | handled: | |
| 541 | return ret; | |
| 567 | return IRQ_HANDLED; | |
| 542 | 568 | } |
| 543 | 569 | |
| 544 | 570 | static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) |
| ... | ... | |
| 571 | 597 | writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG); |
| 572 | 598 | jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, true); |
| 573 | 599 | |
| 600 | host->state = JZ4740_MMC_STATE_READ_RESPONSE; | |
| 574 | 601 | set_bit(0, &host->waiting); |
| 575 | 602 | mod_timer(&host->timeout_timer, jiffies + 5*HZ); |
| 576 | 603 | jz4740_mmc_send_command(host, req->cmd); |
| ... | ... | |
| 770 | 797 | |
| 771 | 798 | host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 772 | 799 | if (!host->mem) { |
| 773 | ret = -ENXIO; | |
| 800 | ret = -ENOENT; | |
| 774 | 801 | dev_err(&pdev->dev, "Failed to get base platform memory\n"); |
| 775 | 802 | goto err_clk_put; |
| 776 | 803 | } |
| ... | ... | |
| 848 | 875 | jz4740_mmc_clock_disable(host); |
| 849 | 876 | setup_timer(&host->timeout_timer, jz4740_mmc_timeout, |
| 850 | 877 | (unsigned long)host); |
| 851 | init_completion(&host->completion); | |
| 878 | /* It is not that important when it times out, it just needs to timeout. */ | |
| 879 | set_timer_slack(&host->timeout_timer, HZ); | |
| 852 | 880 | |
| 853 | 881 | platform_set_drvdata(pdev, host); |
| 854 | 882 | ret = mmc_add_host(mmc); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9
