diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mmc/core/sdio.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/host/mxcmmc.c | 114 | ||||
| -rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 125 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-mxc.c | 4 |
4 files changed, 177 insertions, 72 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 2dd4cfe7ca17..b9dee28ee7d0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -296,6 +296,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 296 | card->type = MMC_TYPE_SDIO; | 296 | card->type = MMC_TYPE_SDIO; |
| 297 | 297 | ||
| 298 | /* | 298 | /* |
| 299 | * Call the optional HC's init_card function to handle quirks. | ||
| 300 | */ | ||
| 301 | if (host->ops->init_card) | ||
| 302 | host->ops->init_card(host, card); | ||
| 303 | |||
| 304 | /* | ||
| 299 | * For native busses: set card RCA and quit open drain mode. | 305 | * For native busses: set card RCA and quit open drain mode. |
| 300 | */ | 306 | */ |
| 301 | if (!powered_resume && !mmc_host_is_spi(host)) { | 307 | if (!powered_resume && !mmc_host_is_spi(host)) { |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 2df90412abb5..ec18e3b60342 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -119,6 +119,7 @@ struct mxcmci_host { | |||
| 119 | int detect_irq; | 119 | int detect_irq; |
| 120 | int dma; | 120 | int dma; |
| 121 | int do_dma; | 121 | int do_dma; |
| 122 | int use_sdio; | ||
| 122 | unsigned int power_mode; | 123 | unsigned int power_mode; |
| 123 | struct imxmmc_platform_data *pdata; | 124 | struct imxmmc_platform_data *pdata; |
| 124 | 125 | ||
| @@ -138,6 +139,7 @@ struct mxcmci_host { | |||
| 138 | int clock; | 139 | int clock; |
| 139 | 140 | ||
| 140 | struct work_struct datawork; | 141 | struct work_struct datawork; |
| 142 | spinlock_t lock; | ||
| 141 | }; | 143 | }; |
| 142 | 144 | ||
| 143 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 145 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
| @@ -151,6 +153,8 @@ static void mxcmci_softreset(struct mxcmci_host *host) | |||
| 151 | { | 153 | { |
| 152 | int i; | 154 | int i; |
| 153 | 155 | ||
| 156 | dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); | ||
| 157 | |||
| 154 | /* reset sequence */ | 158 | /* reset sequence */ |
| 155 | writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); | 159 | writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); |
| 156 | writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, | 160 | writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, |
| @@ -224,6 +228,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
| 224 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 228 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, |
| 225 | unsigned int cmdat) | 229 | unsigned int cmdat) |
| 226 | { | 230 | { |
| 231 | u32 int_cntr; | ||
| 232 | unsigned long flags; | ||
| 233 | |||
| 227 | WARN_ON(host->cmd != NULL); | 234 | WARN_ON(host->cmd != NULL); |
| 228 | host->cmd = cmd; | 235 | host->cmd = cmd; |
| 229 | 236 | ||
| @@ -247,12 +254,16 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | |||
| 247 | return -EINVAL; | 254 | return -EINVAL; |
| 248 | } | 255 | } |
| 249 | 256 | ||
| 257 | int_cntr = INT_END_CMD_RES_EN; | ||
| 258 | |||
| 250 | if (mxcmci_use_dma(host)) | 259 | if (mxcmci_use_dma(host)) |
| 251 | writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN | | 260 | int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN; |
| 252 | INT_END_CMD_RES_EN, | 261 | |
| 253 | host->base + MMC_REG_INT_CNTR); | 262 | spin_lock_irqsave(&host->lock, flags); |
| 254 | else | 263 | if (host->use_sdio) |
| 255 | writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR); | 264 | int_cntr |= INT_SDIO_IRQ_EN; |
| 265 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | ||
| 266 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 256 | 267 | ||
| 257 | writew(cmd->opcode, host->base + MMC_REG_CMD); | 268 | writew(cmd->opcode, host->base + MMC_REG_CMD); |
| 258 | writel(cmd->arg, host->base + MMC_REG_ARG); | 269 | writel(cmd->arg, host->base + MMC_REG_ARG); |
| @@ -264,7 +275,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | |||
| 264 | static void mxcmci_finish_request(struct mxcmci_host *host, | 275 | static void mxcmci_finish_request(struct mxcmci_host *host, |
| 265 | struct mmc_request *req) | 276 | struct mmc_request *req) |
| 266 | { | 277 | { |
| 267 | writel(0, host->base + MMC_REG_INT_CNTR); | 278 | u32 int_cntr = 0; |
| 279 | unsigned long flags; | ||
| 280 | |||
| 281 | spin_lock_irqsave(&host->lock, flags); | ||
| 282 | if (host->use_sdio) | ||
| 283 | int_cntr |= INT_SDIO_IRQ_EN; | ||
| 284 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | ||
| 285 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 268 | 286 | ||
| 269 | host->req = NULL; | 287 | host->req = NULL; |
| 270 | host->cmd = NULL; | 288 | host->cmd = NULL; |
| @@ -290,16 +308,25 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) | |||
| 290 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", | 308 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", |
| 291 | stat); | 309 | stat); |
| 292 | if (stat & STATUS_CRC_READ_ERR) { | 310 | if (stat & STATUS_CRC_READ_ERR) { |
| 311 | dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__); | ||
| 293 | data->error = -EILSEQ; | 312 | data->error = -EILSEQ; |
| 294 | } else if (stat & STATUS_CRC_WRITE_ERR) { | 313 | } else if (stat & STATUS_CRC_WRITE_ERR) { |
| 295 | u32 err_code = (stat >> 9) & 0x3; | 314 | u32 err_code = (stat >> 9) & 0x3; |
| 296 | if (err_code == 2) /* No CRC response */ | 315 | if (err_code == 2) { /* No CRC response */ |
| 316 | dev_err(mmc_dev(host->mmc), | ||
| 317 | "%s: No CRC -ETIMEDOUT\n", __func__); | ||
| 297 | data->error = -ETIMEDOUT; | 318 | data->error = -ETIMEDOUT; |
| 298 | else | 319 | } else { |
| 320 | dev_err(mmc_dev(host->mmc), | ||
| 321 | "%s: -EILSEQ\n", __func__); | ||
| 299 | data->error = -EILSEQ; | 322 | data->error = -EILSEQ; |
| 323 | } | ||
| 300 | } else if (stat & STATUS_TIME_OUT_READ) { | 324 | } else if (stat & STATUS_TIME_OUT_READ) { |
| 325 | dev_err(mmc_dev(host->mmc), | ||
| 326 | "%s: read -ETIMEDOUT\n", __func__); | ||
| 301 | data->error = -ETIMEDOUT; | 327 | data->error = -ETIMEDOUT; |
| 302 | } else { | 328 | } else { |
| 329 | dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__); | ||
| 303 | data->error = -EIO; | 330 | data->error = -EIO; |
| 304 | } | 331 | } |
| 305 | } else { | 332 | } else { |
| @@ -433,8 +460,6 @@ static int mxcmci_transfer_data(struct mxcmci_host *host) | |||
| 433 | struct scatterlist *sg; | 460 | struct scatterlist *sg; |
| 434 | int stat, i; | 461 | int stat, i; |
| 435 | 462 | ||
| 436 | host->datasize = 0; | ||
| 437 | |||
| 438 | host->data = data; | 463 | host->data = data; |
| 439 | host->datasize = 0; | 464 | host->datasize = 0; |
| 440 | 465 | ||
| @@ -464,6 +489,9 @@ static void mxcmci_datawork(struct work_struct *work) | |||
| 464 | struct mxcmci_host *host = container_of(work, struct mxcmci_host, | 489 | struct mxcmci_host *host = container_of(work, struct mxcmci_host, |
| 465 | datawork); | 490 | datawork); |
| 466 | int datastat = mxcmci_transfer_data(host); | 491 | int datastat = mxcmci_transfer_data(host); |
| 492 | |||
| 493 | writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, | ||
| 494 | host->base + MMC_REG_STATUS); | ||
| 467 | mxcmci_finish_data(host, datastat); | 495 | mxcmci_finish_data(host, datastat); |
| 468 | 496 | ||
| 469 | if (host->req->stop) { | 497 | if (host->req->stop) { |
| @@ -523,15 +551,35 @@ static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) | |||
| 523 | static irqreturn_t mxcmci_irq(int irq, void *devid) | 551 | static irqreturn_t mxcmci_irq(int irq, void *devid) |
| 524 | { | 552 | { |
| 525 | struct mxcmci_host *host = devid; | 553 | struct mxcmci_host *host = devid; |
| 554 | unsigned long flags; | ||
| 555 | bool sdio_irq; | ||
| 526 | u32 stat; | 556 | u32 stat; |
| 527 | 557 | ||
| 528 | stat = readl(host->base + MMC_REG_STATUS); | 558 | stat = readl(host->base + MMC_REG_STATUS); |
| 529 | writel(stat, host->base + MMC_REG_STATUS); | 559 | writel(stat & ~(STATUS_SDIO_INT_ACTIVE | STATUS_DATA_TRANS_DONE | |
| 560 | STATUS_WRITE_OP_DONE), host->base + MMC_REG_STATUS); | ||
| 530 | 561 | ||
| 531 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); | 562 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); |
| 532 | 563 | ||
| 564 | spin_lock_irqsave(&host->lock, flags); | ||
| 565 | sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; | ||
| 566 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 567 | |||
| 568 | #ifdef HAS_DMA | ||
| 569 | if (mxcmci_use_dma(host) && | ||
| 570 | (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) | ||
| 571 | writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, | ||
| 572 | host->base + MMC_REG_STATUS); | ||
| 573 | #endif | ||
| 574 | |||
| 575 | if (sdio_irq) { | ||
| 576 | writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); | ||
| 577 | mmc_signal_sdio_irq(host->mmc); | ||
| 578 | } | ||
| 579 | |||
| 533 | if (stat & STATUS_END_CMD_RESP) | 580 | if (stat & STATUS_END_CMD_RESP) |
| 534 | mxcmci_cmd_done(host, stat); | 581 | mxcmci_cmd_done(host, stat); |
| 582 | |||
| 535 | #ifdef HAS_DMA | 583 | #ifdef HAS_DMA |
| 536 | if (mxcmci_use_dma(host) && | 584 | if (mxcmci_use_dma(host) && |
| 537 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) | 585 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) |
| @@ -668,11 +716,46 @@ static int mxcmci_get_ro(struct mmc_host *mmc) | |||
| 668 | return -ENOSYS; | 716 | return -ENOSYS; |
| 669 | } | 717 | } |
| 670 | 718 | ||
| 719 | static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
| 720 | { | ||
| 721 | struct mxcmci_host *host = mmc_priv(mmc); | ||
| 722 | unsigned long flags; | ||
| 723 | u32 int_cntr; | ||
| 724 | |||
| 725 | spin_lock_irqsave(&host->lock, flags); | ||
| 726 | host->use_sdio = enable; | ||
| 727 | int_cntr = readl(host->base + MMC_REG_INT_CNTR); | ||
| 728 | |||
| 729 | if (enable) | ||
| 730 | int_cntr |= INT_SDIO_IRQ_EN; | ||
| 731 | else | ||
| 732 | int_cntr &= ~INT_SDIO_IRQ_EN; | ||
| 733 | |||
| 734 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | ||
| 735 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 736 | } | ||
| 737 | |||
| 738 | static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) | ||
| 739 | { | ||
| 740 | /* | ||
| 741 | * MX3 SoCs have a silicon bug which corrupts CRC calculation of | ||
| 742 | * multi-block transfers when connected SDIO peripheral doesn't | ||
| 743 | * drive the BUSY line as required by the specs. | ||
| 744 | * One way to prevent this is to only allow 1-bit transfers. | ||
| 745 | */ | ||
| 746 | |||
| 747 | if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO) | ||
| 748 | host->caps &= ~MMC_CAP_4_BIT_DATA; | ||
| 749 | else | ||
| 750 | host->caps |= MMC_CAP_4_BIT_DATA; | ||
| 751 | } | ||
| 671 | 752 | ||
| 672 | static const struct mmc_host_ops mxcmci_ops = { | 753 | static const struct mmc_host_ops mxcmci_ops = { |
| 673 | .request = mxcmci_request, | 754 | .request = mxcmci_request, |
| 674 | .set_ios = mxcmci_set_ios, | 755 | .set_ios = mxcmci_set_ios, |
| 675 | .get_ro = mxcmci_get_ro, | 756 | .get_ro = mxcmci_get_ro, |
| 757 | .enable_sdio_irq = mxcmci_enable_sdio_irq, | ||
| 758 | .init_card = mxcmci_init_card, | ||
| 676 | }; | 759 | }; |
| 677 | 760 | ||
| 678 | static int mxcmci_probe(struct platform_device *pdev) | 761 | static int mxcmci_probe(struct platform_device *pdev) |
| @@ -700,7 +783,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 700 | } | 783 | } |
| 701 | 784 | ||
| 702 | mmc->ops = &mxcmci_ops; | 785 | mmc->ops = &mxcmci_ops; |
| 703 | mmc->caps = MMC_CAP_4_BIT_DATA; | 786 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
| 704 | 787 | ||
| 705 | /* MMC core transfer sizes tunable parameters */ | 788 | /* MMC core transfer sizes tunable parameters */ |
| 706 | mmc->max_hw_segs = 64; | 789 | mmc->max_hw_segs = 64; |
| @@ -719,6 +802,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 719 | 802 | ||
| 720 | host->mmc = mmc; | 803 | host->mmc = mmc; |
| 721 | host->pdata = pdev->dev.platform_data; | 804 | host->pdata = pdev->dev.platform_data; |
| 805 | spin_lock_init(&host->lock); | ||
| 722 | 806 | ||
| 723 | if (host->pdata && host->pdata->ocr_avail) | 807 | if (host->pdata && host->pdata->ocr_avail) |
| 724 | mmc->ocr_avail = host->pdata->ocr_avail; | 808 | mmc->ocr_avail = host->pdata->ocr_avail; |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2900d8406d3..fb03aff8e83a 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #define DRIVER_NAME "mxc_nand" | 38 | #define DRIVER_NAME "mxc_nand" |
| 39 | 39 | ||
| 40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) | 40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) |
| 41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27()) | 41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) |
| 42 | 42 | ||
| 43 | /* Addresses for NFC registers */ | 43 | /* Addresses for NFC registers */ |
| 44 | #define NFC_BUF_SIZE 0xE00 | 44 | #define NFC_BUF_SIZE 0xE00 |
| @@ -168,11 +168,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
| 168 | { | 168 | { |
| 169 | struct mxc_nand_host *host = dev_id; | 169 | struct mxc_nand_host *host = dev_id; |
| 170 | 170 | ||
| 171 | uint16_t tmp; | 171 | disable_irq_nosync(irq); |
| 172 | |||
| 173 | tmp = readw(host->regs + NFC_CONFIG1); | ||
| 174 | tmp |= NFC_INT_MSK; /* Disable interrupt */ | ||
| 175 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 176 | 172 | ||
| 177 | wake_up(&host->irq_waitq); | 173 | wake_up(&host->irq_waitq); |
| 178 | 174 | ||
| @@ -184,15 +180,13 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
| 184 | */ | 180 | */ |
| 185 | static void wait_op_done(struct mxc_nand_host *host, int useirq) | 181 | static void wait_op_done(struct mxc_nand_host *host, int useirq) |
| 186 | { | 182 | { |
| 187 | uint32_t tmp; | 183 | uint16_t tmp; |
| 188 | int max_retries = 2000; | 184 | int max_retries = 8000; |
| 189 | 185 | ||
| 190 | if (useirq) { | 186 | if (useirq) { |
| 191 | if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { | 187 | if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { |
| 192 | 188 | ||
| 193 | tmp = readw(host->regs + NFC_CONFIG1); | 189 | enable_irq(host->irq); |
| 194 | tmp &= ~NFC_INT_MSK; /* Enable interrupt */ | ||
| 195 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 196 | 190 | ||
| 197 | wait_event(host->irq_waitq, | 191 | wait_event(host->irq_waitq, |
| 198 | readw(host->regs + NFC_CONFIG2) & NFC_INT); | 192 | readw(host->regs + NFC_CONFIG2) & NFC_INT); |
| @@ -226,8 +220,23 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
| 226 | writew(cmd, host->regs + NFC_FLASH_CMD); | 220 | writew(cmd, host->regs + NFC_FLASH_CMD); |
| 227 | writew(NFC_CMD, host->regs + NFC_CONFIG2); | 221 | writew(NFC_CMD, host->regs + NFC_CONFIG2); |
| 228 | 222 | ||
| 229 | /* Wait for operation to complete */ | 223 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { |
| 230 | wait_op_done(host, useirq); | 224 | int max_retries = 100; |
| 225 | /* Reset completion is indicated by NFC_CONFIG2 */ | ||
| 226 | /* being set to 0 */ | ||
| 227 | while (max_retries-- > 0) { | ||
| 228 | if (readw(host->regs + NFC_CONFIG2) == 0) { | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | udelay(1); | ||
| 232 | } | ||
| 233 | if (max_retries < 0) | ||
| 234 | DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n", | ||
| 235 | __func__); | ||
| 236 | } else { | ||
| 237 | /* Wait for operation to complete */ | ||
| 238 | wait_op_done(host, useirq); | ||
| 239 | } | ||
| 231 | } | 240 | } |
| 232 | 241 | ||
| 233 | /* This function sends an address (or partial address) to the | 242 | /* This function sends an address (or partial address) to the |
| @@ -542,6 +551,41 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
| 542 | } | 551 | } |
| 543 | } | 552 | } |
| 544 | 553 | ||
| 554 | static void preset(struct mtd_info *mtd) | ||
| 555 | { | ||
| 556 | struct nand_chip *nand_chip = mtd->priv; | ||
| 557 | struct mxc_nand_host *host = nand_chip->priv; | ||
| 558 | uint16_t tmp; | ||
| 559 | |||
| 560 | /* enable interrupt, disable spare enable */ | ||
| 561 | tmp = readw(host->regs + NFC_CONFIG1); | ||
| 562 | tmp &= ~NFC_INT_MSK; | ||
| 563 | tmp &= ~NFC_SP_EN; | ||
| 564 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | ||
| 565 | tmp |= NFC_ECC_EN; | ||
| 566 | } else { | ||
| 567 | tmp &= ~NFC_ECC_EN; | ||
| 568 | } | ||
| 569 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 570 | /* preset operation */ | ||
| 571 | |||
| 572 | /* Unlock the internal RAM Buffer */ | ||
| 573 | writew(0x2, host->regs + NFC_CONFIG); | ||
| 574 | |||
| 575 | /* Blocks to be unlocked */ | ||
| 576 | if (nfc_is_v21()) { | ||
| 577 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | ||
| 578 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | ||
| 579 | } else if (nfc_is_v1()) { | ||
| 580 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | ||
| 581 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | ||
| 582 | } else | ||
| 583 | BUG(); | ||
| 584 | |||
| 585 | /* Unlock Block Command for given address range */ | ||
| 586 | writew(0x4, host->regs + NFC_WRPROT); | ||
| 587 | } | ||
| 588 | |||
| 545 | /* Used by the upper layer to write command to NAND Flash for | 589 | /* Used by the upper layer to write command to NAND Flash for |
| 546 | * different operations to be carried out on NAND Flash */ | 590 | * different operations to be carried out on NAND Flash */ |
| 547 | static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | 591 | static void mxc_nand_command(struct mtd_info *mtd, unsigned command, |
| @@ -559,6 +603,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 559 | 603 | ||
| 560 | /* Command pre-processing step */ | 604 | /* Command pre-processing step */ |
| 561 | switch (command) { | 605 | switch (command) { |
| 606 | case NAND_CMD_RESET: | ||
| 607 | send_cmd(host, command, false); | ||
| 608 | preset(mtd); | ||
| 609 | break; | ||
| 562 | 610 | ||
| 563 | case NAND_CMD_STATUS: | 611 | case NAND_CMD_STATUS: |
| 564 | host->buf_start = 0; | 612 | host->buf_start = 0; |
| @@ -679,7 +727,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 679 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | 727 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; |
| 680 | struct mxc_nand_host *host; | 728 | struct mxc_nand_host *host; |
| 681 | struct resource *res; | 729 | struct resource *res; |
| 682 | uint16_t tmp; | ||
| 683 | int err = 0, nr_parts = 0; | 730 | int err = 0, nr_parts = 0; |
| 684 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | 731 | struct nand_ecclayout *oob_smallpage, *oob_largepage; |
| 685 | 732 | ||
| @@ -743,51 +790,17 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 743 | host->spare_len = 64; | 790 | host->spare_len = 64; |
| 744 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 791 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
| 745 | oob_largepage = &nandv2_hw_eccoob_largepage; | 792 | oob_largepage = &nandv2_hw_eccoob_largepage; |
| 793 | this->ecc.bytes = 9; | ||
| 746 | } else if (nfc_is_v1()) { | 794 | } else if (nfc_is_v1()) { |
| 747 | host->regs = host->base; | 795 | host->regs = host->base; |
| 748 | host->spare0 = host->base + 0x800; | 796 | host->spare0 = host->base + 0x800; |
| 749 | host->spare_len = 16; | 797 | host->spare_len = 16; |
| 750 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 798 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
| 751 | oob_largepage = &nandv1_hw_eccoob_largepage; | 799 | oob_largepage = &nandv1_hw_eccoob_largepage; |
| 752 | } else | ||
| 753 | BUG(); | ||
| 754 | |||
| 755 | /* disable interrupt and spare enable */ | ||
| 756 | tmp = readw(host->regs + NFC_CONFIG1); | ||
| 757 | tmp |= NFC_INT_MSK; | ||
| 758 | tmp &= ~NFC_SP_EN; | ||
| 759 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 760 | |||
| 761 | init_waitqueue_head(&host->irq_waitq); | ||
| 762 | |||
| 763 | host->irq = platform_get_irq(pdev, 0); | ||
| 764 | |||
| 765 | err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); | ||
| 766 | if (err) | ||
| 767 | goto eirq; | ||
| 768 | |||
| 769 | /* Reset NAND */ | ||
| 770 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
| 771 | |||
| 772 | /* preset operation */ | ||
| 773 | /* Unlock the internal RAM Buffer */ | ||
| 774 | writew(0x2, host->regs + NFC_CONFIG); | ||
| 775 | |||
| 776 | /* Blocks to be unlocked */ | ||
| 777 | if (nfc_is_v21()) { | ||
| 778 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | ||
| 779 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | ||
| 780 | this->ecc.bytes = 9; | ||
| 781 | } else if (nfc_is_v1()) { | ||
| 782 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | ||
| 783 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | ||
| 784 | this->ecc.bytes = 3; | 800 | this->ecc.bytes = 3; |
| 785 | } else | 801 | } else |
| 786 | BUG(); | 802 | BUG(); |
| 787 | 803 | ||
| 788 | /* Unlock Block Command for given address range */ | ||
| 789 | writew(0x4, host->regs + NFC_WRPROT); | ||
| 790 | |||
| 791 | this->ecc.size = 512; | 804 | this->ecc.size = 512; |
| 792 | this->ecc.layout = oob_smallpage; | 805 | this->ecc.layout = oob_smallpage; |
| 793 | 806 | ||
| @@ -796,14 +809,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 796 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 809 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
| 797 | this->ecc.correct = mxc_nand_correct_data; | 810 | this->ecc.correct = mxc_nand_correct_data; |
| 798 | this->ecc.mode = NAND_ECC_HW; | 811 | this->ecc.mode = NAND_ECC_HW; |
| 799 | tmp = readw(host->regs + NFC_CONFIG1); | ||
| 800 | tmp |= NFC_ECC_EN; | ||
| 801 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 802 | } else { | 812 | } else { |
| 803 | this->ecc.mode = NAND_ECC_SOFT; | 813 | this->ecc.mode = NAND_ECC_SOFT; |
| 804 | tmp = readw(host->regs + NFC_CONFIG1); | ||
| 805 | tmp &= ~NFC_ECC_EN; | ||
| 806 | writew(tmp, host->regs + NFC_CONFIG1); | ||
| 807 | } | 814 | } |
| 808 | 815 | ||
| 809 | /* NAND bus width determines access funtions used by upper layer */ | 816 | /* NAND bus width determines access funtions used by upper layer */ |
| @@ -817,6 +824,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 817 | this->options |= NAND_USE_FLASH_BBT; | 824 | this->options |= NAND_USE_FLASH_BBT; |
| 818 | } | 825 | } |
| 819 | 826 | ||
| 827 | init_waitqueue_head(&host->irq_waitq); | ||
| 828 | |||
| 829 | host->irq = platform_get_irq(pdev, 0); | ||
| 830 | |||
| 831 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); | ||
| 832 | if (err) | ||
| 833 | goto eirq; | ||
| 834 | |||
| 820 | /* first scan to find the device and get the page size */ | 835 | /* first scan to find the device and get the page size */ |
| 821 | if (nand_scan_ident(mtd, 1)) { | 836 | if (nand_scan_ident(mtd, 1)) { |
| 822 | err = -ENXIO; | 837 | err = -ENXIO; |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ead59f42e69b..544ccfd7056e 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
| @@ -199,8 +199,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
| 199 | writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); | 199 | writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); |
| 200 | mdelay(10); | 200 | mdelay(10); |
| 201 | 201 | ||
| 202 | /* setup USBCONTROL. */ | 202 | /* setup specific usb hw */ |
| 203 | ret = mxc_set_usbcontrol(pdev->id, pdata->flags); | 203 | ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); |
| 204 | if (ret < 0) | 204 | if (ret < 0) |
| 205 | goto err_init; | 205 | goto err_init; |
| 206 | 206 | ||
