Lines Matching +full:mmc +full:- +full:host

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Toshiba PCI Secure Digital Host Controller Interface driver
9 * sdhci.c, copyright (C) 2005-2006 Pierre Ossman
21 #include <linux/mmc/host.h>
22 #include <linux/mmc/mmc.h>
35 static void toshsd_init(struct toshsd_host *host) in toshsd_init() argument
38 pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, in toshsd_init()
40 pci_write_config_byte(host->pdev, SD_PCICFG_CARDDETECT, 2); in toshsd_init()
43 iowrite16(0, host->ioaddr + SD_SOFTWARERESET); /* assert */ in toshsd_init()
45 iowrite16(1, host->ioaddr + SD_SOFTWARERESET); /* deassert */ in toshsd_init()
49 iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); in toshsd_init()
50 iowrite32(0, host->ioaddr + SD_CARDSTATUS); in toshsd_init()
51 iowrite32(0, host->ioaddr + SD_ERRORSTATUS0); in toshsd_init()
52 iowrite16(0, host->ioaddr + SD_STOPINTERNAL); in toshsd_init()
55 iowrite16(0x100, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL); in toshsd_init()
58 pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE1, in toshsd_init()
60 pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE2, in toshsd_init()
68 host->ioaddr + SD_INTMASKCARD); in toshsd_init()
70 iowrite16(0x1000, host->ioaddr + SD_TRANSACTIONCTRL); in toshsd_init()
73 /* Set MMC clock / power.
75 * SD/MMC cards at full speed (24/20MHz). HCLK (=33MHz PCI clock?) is too high
78 static void __toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in __toshsd_set_ios() argument
80 struct toshsd_host *host = mmc_priv(mmc); in __toshsd_set_ios() local
82 if (ios->clock) { in __toshsd_set_ios()
86 while (ios->clock < HCLK / div) in __toshsd_set_ios()
92 pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE, in __toshsd_set_ios()
96 pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE, 0); in __toshsd_set_ios()
99 iowrite16(clk, host->ioaddr + SD_CARDCLOCKCTRL); in __toshsd_set_ios()
103 iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); in __toshsd_set_ios()
105 switch (ios->power_mode) { in __toshsd_set_ios()
107 pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, in __toshsd_set_ios()
114 pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, in __toshsd_set_ios()
116 pci_write_config_byte(host->pdev, SD_PCICFG_POWER2, in __toshsd_set_ios()
122 switch (ios->bus_width) { in __toshsd_set_ios()
127 host->ioaddr + SD_CARDOPTIONSETUP); in __toshsd_set_ios()
133 host->ioaddr + SD_CARDOPTIONSETUP); in __toshsd_set_ios()
138 static void toshsd_set_led(struct toshsd_host *host, unsigned char state) in toshsd_set_led() argument
140 iowrite16(state, host->ioaddr + SDIO_BASE + SDIO_LEDCTRL); in toshsd_set_led()
143 static void toshsd_finish_request(struct toshsd_host *host) in toshsd_finish_request() argument
145 struct mmc_request *mrq = host->mrq; in toshsd_finish_request()
148 host->mrq = NULL; in toshsd_finish_request()
149 host->cmd = NULL; in toshsd_finish_request()
150 host->data = NULL; in toshsd_finish_request()
152 toshsd_set_led(host, 0); in toshsd_finish_request()
153 mmc_request_done(host->mmc, mrq); in toshsd_finish_request()
158 struct toshsd_host *host = dev_id; in toshsd_thread_irq() local
159 struct mmc_data *data = host->data; in toshsd_thread_irq()
160 struct sg_mapping_iter *sg_miter = &host->sg_miter; in toshsd_thread_irq()
166 dev_warn(&host->pdev->dev, "Spurious Data IRQ\n"); in toshsd_thread_irq()
167 if (host->cmd) { in toshsd_thread_irq()
168 host->cmd->error = -EIO; in toshsd_thread_irq()
169 toshsd_finish_request(host); in toshsd_thread_irq()
173 spin_lock_irqsave(&host->lock, flags); in toshsd_thread_irq()
178 buf = sg_miter->addr; in toshsd_thread_irq()
183 count = sg_miter->length; in toshsd_thread_irq()
184 if (count > data->blksz) in toshsd_thread_irq()
185 count = data->blksz; in toshsd_thread_irq()
187 dev_dbg(&host->pdev->dev, "count: %08x, flags %08x\n", count, in toshsd_thread_irq()
188 data->flags); in toshsd_thread_irq()
191 if (data->flags & MMC_DATA_READ) in toshsd_thread_irq()
192 ioread32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); in toshsd_thread_irq()
194 iowrite32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); in toshsd_thread_irq()
196 sg_miter->consumed = count; in toshsd_thread_irq()
200 spin_unlock_irqrestore(&host->lock, flags); in toshsd_thread_irq()
205 static void toshsd_cmd_irq(struct toshsd_host *host) in toshsd_cmd_irq() argument
207 struct mmc_command *cmd = host->cmd; in toshsd_cmd_irq()
211 if (!host->cmd) { in toshsd_cmd_irq()
212 dev_warn(&host->pdev->dev, "Spurious CMD irq\n"); in toshsd_cmd_irq()
215 buf = (u8 *)cmd->resp; in toshsd_cmd_irq()
216 host->cmd = NULL; in toshsd_cmd_irq()
218 if (cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) { in toshsd_cmd_irq()
221 data = ioread16(host->ioaddr + SD_RESPONSE0); in toshsd_cmd_irq()
224 data = ioread16(host->ioaddr + SD_RESPONSE1); in toshsd_cmd_irq()
227 data = ioread16(host->ioaddr + SD_RESPONSE2); in toshsd_cmd_irq()
230 data = ioread16(host->ioaddr + SD_RESPONSE3); in toshsd_cmd_irq()
233 data = ioread16(host->ioaddr + SD_RESPONSE4); in toshsd_cmd_irq()
236 data = ioread16(host->ioaddr + SD_RESPONSE5); in toshsd_cmd_irq()
239 data = ioread16(host->ioaddr + SD_RESPONSE6); in toshsd_cmd_irq()
242 data = ioread16(host->ioaddr + SD_RESPONSE7); in toshsd_cmd_irq()
244 } else if (cmd->flags & MMC_RSP_PRESENT) { in toshsd_cmd_irq()
246 data = ioread16(host->ioaddr + SD_RESPONSE0); in toshsd_cmd_irq()
249 data = ioread16(host->ioaddr + SD_RESPONSE1); in toshsd_cmd_irq()
254 dev_dbg(&host->pdev->dev, "Command IRQ complete %d %d %x\n", in toshsd_cmd_irq()
255 cmd->opcode, cmd->error, cmd->flags); in toshsd_cmd_irq()
259 if (host->data) in toshsd_cmd_irq()
262 toshsd_finish_request(host); in toshsd_cmd_irq()
265 static void toshsd_data_end_irq(struct toshsd_host *host) in toshsd_data_end_irq() argument
267 struct mmc_data *data = host->data; in toshsd_data_end_irq()
269 host->data = NULL; in toshsd_data_end_irq()
272 dev_warn(&host->pdev->dev, "Spurious data end IRQ\n"); in toshsd_data_end_irq()
276 if (data->error == 0) in toshsd_data_end_irq()
277 data->bytes_xfered = data->blocks * data->blksz; in toshsd_data_end_irq()
279 data->bytes_xfered = 0; in toshsd_data_end_irq()
281 dev_dbg(&host->pdev->dev, "Completed data request xfr=%d\n", in toshsd_data_end_irq()
282 data->bytes_xfered); in toshsd_data_end_irq()
284 iowrite16(0, host->ioaddr + SD_STOPINTERNAL); in toshsd_data_end_irq()
286 toshsd_finish_request(host); in toshsd_data_end_irq()
291 struct toshsd_host *host = dev_id; in toshsd_irq() local
295 spin_lock(&host->lock); in toshsd_irq()
296 int_status = ioread32(host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
297 int_mask = ioread32(host->ioaddr + SD_INTMASKCARD); in toshsd_irq()
300 dev_dbg(&host->pdev->dev, "IRQ status:%x mask:%x\n", in toshsd_irq()
310 error = -ETIMEDOUT; in toshsd_irq()
311 dev_dbg(&host->pdev->dev, "Timeout\n"); in toshsd_irq()
313 error = -EILSEQ; in toshsd_irq()
314 dev_err(&host->pdev->dev, "BadCRC\n"); in toshsd_irq()
321 dev_err(&host->pdev->dev, "Buffer status error: { %s%s%s%s%s%s}\n", in toshsd_irq()
329 detail = ioread32(host->ioaddr + SD_ERRORSTATUS0); in toshsd_irq()
330 dev_err(&host->pdev->dev, "detail error status { %s%s%s%s%s%s%s%s%s%s%s%s%s}\n", in toshsd_irq()
344 error = -EIO; in toshsd_irq()
348 if (host->cmd) in toshsd_irq()
349 host->cmd->error = error; in toshsd_irq()
351 if (error == -ETIMEDOUT) { in toshsd_irq()
354 host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
356 toshsd_init(host); in toshsd_irq()
357 __toshsd_set_ios(host->mmc, &host->mmc->ios); in toshsd_irq()
362 /* Card insert/remove. The mmc controlling code is stateless. */ in toshsd_irq()
366 host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
369 toshsd_init(host); in toshsd_irq()
371 mmc_detect_change(host->mmc, 1); in toshsd_irq()
378 host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
387 host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
388 toshsd_cmd_irq(host); in toshsd_irq()
394 host->ioaddr + SD_CARDSTATUS); in toshsd_irq()
395 toshsd_data_end_irq(host); in toshsd_irq()
398 spin_unlock(&host->lock); in toshsd_irq()
402 static void toshsd_start_cmd(struct toshsd_host *host, struct mmc_command *cmd) in toshsd_start_cmd() argument
404 struct mmc_data *data = host->data; in toshsd_start_cmd()
405 int c = cmd->opcode; in toshsd_start_cmd()
407 dev_dbg(&host->pdev->dev, "Command opcode: %d\n", cmd->opcode); in toshsd_start_cmd()
409 if (cmd->opcode == MMC_STOP_TRANSMISSION) { in toshsd_start_cmd()
411 host->ioaddr + SD_STOPINTERNAL); in toshsd_start_cmd()
413 cmd->resp[0] = cmd->opcode; in toshsd_start_cmd()
414 cmd->resp[1] = 0; in toshsd_start_cmd()
415 cmd->resp[2] = 0; in toshsd_start_cmd()
416 cmd->resp[3] = 0; in toshsd_start_cmd()
418 toshsd_finish_request(host); in toshsd_start_cmd()
441 dev_err(&host->pdev->dev, "Unknown response type %d\n", in toshsd_start_cmd()
446 host->cmd = cmd; in toshsd_start_cmd()
448 if (cmd->opcode == MMC_APP_CMD) in toshsd_start_cmd()
451 if (cmd->opcode == MMC_GO_IDLE_STATE) in toshsd_start_cmd()
452 c |= (3 << 8); /* removed from ipaq-asic3.h for some reason */ in toshsd_start_cmd()
457 if (data->blocks > 1) { in toshsd_start_cmd()
459 host->ioaddr + SD_STOPINTERNAL); in toshsd_start_cmd()
463 if (data->flags & MMC_DATA_READ) in toshsd_start_cmd()
470 iowrite32(cmd->arg, host->ioaddr + SD_ARG0); in toshsd_start_cmd()
471 iowrite16(c, host->ioaddr + SD_CMD); in toshsd_start_cmd()
474 static void toshsd_start_data(struct toshsd_host *host, struct mmc_data *data) in toshsd_start_data() argument
478 dev_dbg(&host->pdev->dev, "setup data transfer: blocksize %08x nr_blocks %d, offset: %08x\n", in toshsd_start_data()
479 data->blksz, data->blocks, data->sg->offset); in toshsd_start_data()
481 host->data = data; in toshsd_start_data()
483 if (data->flags & MMC_DATA_READ) in toshsd_start_data()
488 sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); in toshsd_start_data()
491 iowrite16(data->blocks, host->ioaddr + SD_BLOCKCOUNT); in toshsd_start_data()
492 iowrite16(data->blksz, host->ioaddr + SD_CARDXFERDATALEN); in toshsd_start_data()
495 /* Process requests from the MMC layer */
496 static void toshsd_request(struct mmc_host *mmc, struct mmc_request *mrq) in toshsd_request() argument
498 struct toshsd_host *host = mmc_priv(mmc); in toshsd_request() local
502 if (!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0)) { in toshsd_request()
503 mrq->cmd->error = -ENOMEDIUM; in toshsd_request()
504 mmc_request_done(mmc, mrq); in toshsd_request()
508 spin_lock_irqsave(&host->lock, flags); in toshsd_request()
510 WARN_ON(host->mrq != NULL); in toshsd_request()
512 host->mrq = mrq; in toshsd_request()
514 if (mrq->data) in toshsd_request()
515 toshsd_start_data(host, mrq->data); in toshsd_request()
517 toshsd_set_led(host, 1); in toshsd_request()
519 toshsd_start_cmd(host, mrq->cmd); in toshsd_request()
521 spin_unlock_irqrestore(&host->lock, flags); in toshsd_request()
524 static void toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in toshsd_set_ios() argument
526 struct toshsd_host *host = mmc_priv(mmc); in toshsd_set_ios() local
529 spin_lock_irqsave(&host->lock, flags); in toshsd_set_ios()
530 __toshsd_set_ios(mmc, ios); in toshsd_set_ios()
531 spin_unlock_irqrestore(&host->lock, flags); in toshsd_set_ios()
534 static int toshsd_get_ro(struct mmc_host *mmc) in toshsd_get_ro() argument
536 struct toshsd_host *host = mmc_priv(mmc); in toshsd_get_ro() local
539 return !(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_WRITE_PROTECT); in toshsd_get_ro()
542 static int toshsd_get_cd(struct mmc_host *mmc) in toshsd_get_cd() argument
544 struct toshsd_host *host = mmc_priv(mmc); in toshsd_get_cd() local
546 return !!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0); in toshsd_get_cd()
557 static void toshsd_powerdown(struct toshsd_host *host) in toshsd_powerdown() argument
560 iowrite32(0xffffffff, host->ioaddr + SD_INTMASKCARD); in toshsd_powerdown()
562 iowrite16(0x000, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL); in toshsd_powerdown()
563 iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); in toshsd_powerdown()
565 pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, SD_PCICFG_PWR1_OFF); in toshsd_powerdown()
567 pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, 0); in toshsd_powerdown()
574 struct toshsd_host *host = pci_get_drvdata(pdev); in toshsd_pm_suspend() local
576 toshsd_powerdown(host); in toshsd_pm_suspend()
589 struct toshsd_host *host = pci_get_drvdata(pdev); in toshsd_pm_resume() local
598 toshsd_init(host); in toshsd_pm_resume()
607 struct toshsd_host *host; in toshsd_probe() local
608 struct mmc_host *mmc; in toshsd_probe() local
615 mmc = mmc_alloc_host(sizeof(struct toshsd_host), &pdev->dev); in toshsd_probe()
616 if (!mmc) { in toshsd_probe()
617 ret = -ENOMEM; in toshsd_probe()
621 host = mmc_priv(mmc); in toshsd_probe()
622 host->mmc = mmc; in toshsd_probe()
624 host->pdev = pdev; in toshsd_probe()
625 pci_set_drvdata(pdev, host); in toshsd_probe()
631 host->ioaddr = pci_iomap(pdev, 0, 0); in toshsd_probe()
632 if (!host->ioaddr) { in toshsd_probe()
633 ret = -ENOMEM; in toshsd_probe()
637 /* Set MMC host parameters */ in toshsd_probe()
638 mmc->ops = &toshsd_ops; in toshsd_probe()
639 mmc->caps = MMC_CAP_4_BIT_DATA; in toshsd_probe()
640 mmc->ocr_avail = MMC_VDD_32_33; in toshsd_probe()
642 mmc->f_min = HCLK / 512; in toshsd_probe()
643 mmc->f_max = HCLK; in toshsd_probe()
645 spin_lock_init(&host->lock); in toshsd_probe()
647 toshsd_init(host); in toshsd_probe()
649 ret = request_threaded_irq(pdev->irq, toshsd_irq, toshsd_thread_irq, in toshsd_probe()
650 IRQF_SHARED, DRIVER_NAME, host); in toshsd_probe()
654 ret = mmc_add_host(mmc); in toshsd_probe()
659 dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq); in toshsd_probe()
661 pm_suspend_ignore_children(&pdev->dev, 1); in toshsd_probe()
666 free_irq(pdev->irq, host); in toshsd_probe()
668 pci_iounmap(pdev, host->ioaddr); in toshsd_probe()
672 mmc_free_host(mmc); in toshsd_probe()
681 struct toshsd_host *host = pci_get_drvdata(pdev); in toshsd_remove() local
683 mmc_remove_host(host->mmc); in toshsd_remove()
684 toshsd_powerdown(host); in toshsd_remove()
685 free_irq(pdev->irq, host); in toshsd_remove()
686 pci_iounmap(pdev, host->ioaddr); in toshsd_remove()
688 mmc_free_host(host->mmc); in toshsd_remove()
708 MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver");