1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2a5eb8bbdSOndrej Zary /* 3a5eb8bbdSOndrej Zary * Toshiba PCI Secure Digital Host Controller Interface driver 4a5eb8bbdSOndrej Zary * 5a5eb8bbdSOndrej Zary * Copyright (C) 2014 Ondrej Zary 6a5eb8bbdSOndrej Zary * Copyright (C) 2007 Richard Betts, All Rights Reserved. 7a5eb8bbdSOndrej Zary * 8a5eb8bbdSOndrej Zary * Based on asic3_mmc.c, copyright (c) 2005 SDG Systems, LLC and, 9a5eb8bbdSOndrej Zary * sdhci.c, copyright (C) 2005-2006 Pierre Ossman 10a5eb8bbdSOndrej Zary */ 11a5eb8bbdSOndrej Zary 12a5eb8bbdSOndrej Zary #include <linux/delay.h> 13a5eb8bbdSOndrej Zary #include <linux/device.h> 14a5eb8bbdSOndrej Zary #include <linux/module.h> 15a5eb8bbdSOndrej Zary #include <linux/pci.h> 16a5eb8bbdSOndrej Zary #include <linux/scatterlist.h> 17a5eb8bbdSOndrej Zary #include <linux/interrupt.h> 18a5eb8bbdSOndrej Zary #include <linux/io.h> 19a5eb8bbdSOndrej Zary #include <linux/pm.h> 20372a12edSUlf Hansson #include <linux/pm_runtime.h> 21a5eb8bbdSOndrej Zary #include <linux/mmc/host.h> 22a5eb8bbdSOndrej Zary #include <linux/mmc/mmc.h> 23a5eb8bbdSOndrej Zary 24a5eb8bbdSOndrej Zary #include "toshsd.h" 25a5eb8bbdSOndrej Zary 26a5eb8bbdSOndrej Zary #define DRIVER_NAME "toshsd" 27a5eb8bbdSOndrej Zary 28a5eb8bbdSOndrej Zary static const struct pci_device_id pci_ids[] = { 29a5eb8bbdSOndrej Zary { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA, 0x0805) }, 30a5eb8bbdSOndrej Zary { /* end: all zeroes */ }, 31a5eb8bbdSOndrej Zary }; 32a5eb8bbdSOndrej Zary 33a5eb8bbdSOndrej Zary MODULE_DEVICE_TABLE(pci, pci_ids); 34a5eb8bbdSOndrej Zary 35a5eb8bbdSOndrej Zary static void toshsd_init(struct toshsd_host *host) 36a5eb8bbdSOndrej Zary { 37a5eb8bbdSOndrej Zary /* enable clock */ 38a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, 39a5eb8bbdSOndrej Zary SD_PCICFG_CLKSTOP_ENABLE_ALL); 40a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CARDDETECT, 2); 41a5eb8bbdSOndrej Zary 42a5eb8bbdSOndrej Zary /* reset */ 43a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_SOFTWARERESET); /* assert */ 44a5eb8bbdSOndrej Zary mdelay(2); 45a5eb8bbdSOndrej Zary iowrite16(1, host->ioaddr + SD_SOFTWARERESET); /* deassert */ 46a5eb8bbdSOndrej Zary mdelay(2); 47a5eb8bbdSOndrej Zary 48a5eb8bbdSOndrej Zary /* Clear card registers */ 49a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); 50a5eb8bbdSOndrej Zary iowrite32(0, host->ioaddr + SD_CARDSTATUS); 51a5eb8bbdSOndrej Zary iowrite32(0, host->ioaddr + SD_ERRORSTATUS0); 52a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_STOPINTERNAL); 53a5eb8bbdSOndrej Zary 54a5eb8bbdSOndrej Zary /* SDIO clock? */ 55a5eb8bbdSOndrej Zary iowrite16(0x100, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL); 56a5eb8bbdSOndrej Zary 57a5eb8bbdSOndrej Zary /* enable LED */ 58a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE1, 59a5eb8bbdSOndrej Zary SD_PCICFG_LED_ENABLE1_START); 60a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE2, 61a5eb8bbdSOndrej Zary SD_PCICFG_LED_ENABLE2_START); 62a5eb8bbdSOndrej Zary 63a5eb8bbdSOndrej Zary /* set interrupt masks */ 64a5eb8bbdSOndrej Zary iowrite32(~(u32)(SD_CARD_RESP_END | SD_CARD_RW_END 65a5eb8bbdSOndrej Zary | SD_CARD_CARD_REMOVED_0 | SD_CARD_CARD_INSERTED_0 66a5eb8bbdSOndrej Zary | SD_BUF_READ_ENABLE | SD_BUF_WRITE_ENABLE 67a5eb8bbdSOndrej Zary | SD_BUF_CMD_TIMEOUT), 68a5eb8bbdSOndrej Zary host->ioaddr + SD_INTMASKCARD); 69a5eb8bbdSOndrej Zary 70a5eb8bbdSOndrej Zary iowrite16(0x1000, host->ioaddr + SD_TRANSACTIONCTRL); 71a5eb8bbdSOndrej Zary } 72a5eb8bbdSOndrej Zary 73a5eb8bbdSOndrej Zary /* Set MMC clock / power. 74a5eb8bbdSOndrej Zary * Note: This controller uses a simple divider scheme therefore it cannot run 75a5eb8bbdSOndrej Zary * SD/MMC cards at full speed (24/20MHz). HCLK (=33MHz PCI clock?) is too high 76a5eb8bbdSOndrej Zary * and the next slowest is 16MHz (div=2). 77a5eb8bbdSOndrej Zary */ 78a5eb8bbdSOndrej Zary static void __toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 79a5eb8bbdSOndrej Zary { 80a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 81a5eb8bbdSOndrej Zary 82a5eb8bbdSOndrej Zary if (ios->clock) { 83a5eb8bbdSOndrej Zary u16 clk; 84a5eb8bbdSOndrej Zary int div = 1; 85a5eb8bbdSOndrej Zary 86a5eb8bbdSOndrej Zary while (ios->clock < HCLK / div) 87a5eb8bbdSOndrej Zary div *= 2; 88a5eb8bbdSOndrej Zary 89a5eb8bbdSOndrej Zary clk = div >> 2; 90a5eb8bbdSOndrej Zary 91a5eb8bbdSOndrej Zary if (div == 1) { /* disable the divider */ 92a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE, 93a5eb8bbdSOndrej Zary SD_PCICFG_CLKMODE_DIV_DISABLE); 94a5eb8bbdSOndrej Zary clk |= SD_CARDCLK_DIV_DISABLE; 95a5eb8bbdSOndrej Zary } else 96a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE, 0); 97a5eb8bbdSOndrej Zary 98a5eb8bbdSOndrej Zary clk |= SD_CARDCLK_ENABLE_CLOCK; 99a5eb8bbdSOndrej Zary iowrite16(clk, host->ioaddr + SD_CARDCLOCKCTRL); 100a5eb8bbdSOndrej Zary 101a5eb8bbdSOndrej Zary mdelay(10); 102a5eb8bbdSOndrej Zary } else 103a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); 104a5eb8bbdSOndrej Zary 105a5eb8bbdSOndrej Zary switch (ios->power_mode) { 106a5eb8bbdSOndrej Zary case MMC_POWER_OFF: 107a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, 108a5eb8bbdSOndrej Zary SD_PCICFG_PWR1_OFF); 109a5eb8bbdSOndrej Zary mdelay(1); 110a5eb8bbdSOndrej Zary break; 111a5eb8bbdSOndrej Zary case MMC_POWER_UP: 112a5eb8bbdSOndrej Zary break; 113a5eb8bbdSOndrej Zary case MMC_POWER_ON: 114a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, 115a5eb8bbdSOndrej Zary SD_PCICFG_PWR1_33V); 116a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_POWER2, 117a5eb8bbdSOndrej Zary SD_PCICFG_PWR2_AUTO); 118a5eb8bbdSOndrej Zary mdelay(20); 119a5eb8bbdSOndrej Zary break; 120a5eb8bbdSOndrej Zary } 121a5eb8bbdSOndrej Zary 122a5eb8bbdSOndrej Zary switch (ios->bus_width) { 123a5eb8bbdSOndrej Zary case MMC_BUS_WIDTH_1: 124a5eb8bbdSOndrej Zary iowrite16(SD_CARDOPT_REQUIRED | SD_CARDOPT_DATA_RESP_TIMEOUT(14) 125a5eb8bbdSOndrej Zary | SD_CARDOPT_C2_MODULE_ABSENT 126a5eb8bbdSOndrej Zary | SD_CARDOPT_DATA_XFR_WIDTH_1, 127a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDOPTIONSETUP); 128a5eb8bbdSOndrej Zary break; 129a5eb8bbdSOndrej Zary case MMC_BUS_WIDTH_4: 130a5eb8bbdSOndrej Zary iowrite16(SD_CARDOPT_REQUIRED | SD_CARDOPT_DATA_RESP_TIMEOUT(14) 131a5eb8bbdSOndrej Zary | SD_CARDOPT_C2_MODULE_ABSENT 132a5eb8bbdSOndrej Zary | SD_CARDOPT_DATA_XFR_WIDTH_4, 133a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDOPTIONSETUP); 134a5eb8bbdSOndrej Zary break; 135a5eb8bbdSOndrej Zary } 136a5eb8bbdSOndrej Zary } 137a5eb8bbdSOndrej Zary 138a5eb8bbdSOndrej Zary static void toshsd_set_led(struct toshsd_host *host, unsigned char state) 139a5eb8bbdSOndrej Zary { 140a5eb8bbdSOndrej Zary iowrite16(state, host->ioaddr + SDIO_BASE + SDIO_LEDCTRL); 141a5eb8bbdSOndrej Zary } 142a5eb8bbdSOndrej Zary 143a5eb8bbdSOndrej Zary static void toshsd_finish_request(struct toshsd_host *host) 144a5eb8bbdSOndrej Zary { 145a5eb8bbdSOndrej Zary struct mmc_request *mrq = host->mrq; 146a5eb8bbdSOndrej Zary 147a5eb8bbdSOndrej Zary /* Write something to end the command */ 148a5eb8bbdSOndrej Zary host->mrq = NULL; 149a5eb8bbdSOndrej Zary host->cmd = NULL; 150a5eb8bbdSOndrej Zary host->data = NULL; 151a5eb8bbdSOndrej Zary 152a5eb8bbdSOndrej Zary toshsd_set_led(host, 0); 153a5eb8bbdSOndrej Zary mmc_request_done(host->mmc, mrq); 154a5eb8bbdSOndrej Zary } 155a5eb8bbdSOndrej Zary 156a5eb8bbdSOndrej Zary static irqreturn_t toshsd_thread_irq(int irq, void *dev_id) 157a5eb8bbdSOndrej Zary { 158a5eb8bbdSOndrej Zary struct toshsd_host *host = dev_id; 159a5eb8bbdSOndrej Zary struct mmc_data *data = host->data; 160a5eb8bbdSOndrej Zary struct sg_mapping_iter *sg_miter = &host->sg_miter; 161a5eb8bbdSOndrej Zary unsigned short *buf; 162a5eb8bbdSOndrej Zary int count; 163a5eb8bbdSOndrej Zary unsigned long flags; 164a5eb8bbdSOndrej Zary 165a5eb8bbdSOndrej Zary if (!data) { 166a5eb8bbdSOndrej Zary dev_warn(&host->pdev->dev, "Spurious Data IRQ\n"); 167a5eb8bbdSOndrej Zary if (host->cmd) { 168a5eb8bbdSOndrej Zary host->cmd->error = -EIO; 169a5eb8bbdSOndrej Zary toshsd_finish_request(host); 170a5eb8bbdSOndrej Zary } 171a5eb8bbdSOndrej Zary return IRQ_NONE; 172a5eb8bbdSOndrej Zary } 173a5eb8bbdSOndrej Zary spin_lock_irqsave(&host->lock, flags); 174a5eb8bbdSOndrej Zary 175a5eb8bbdSOndrej Zary if (!sg_miter_next(sg_miter)) 1768a66fdaeSAxel Lin goto done; 1778a66fdaeSAxel Lin 178a5eb8bbdSOndrej Zary buf = sg_miter->addr; 179a5eb8bbdSOndrej Zary 180a5eb8bbdSOndrej Zary /* Ensure we dont read more than one block. The chip will interrupt us 181a5eb8bbdSOndrej Zary * When the next block is available. 182a5eb8bbdSOndrej Zary */ 183a5eb8bbdSOndrej Zary count = sg_miter->length; 184a5eb8bbdSOndrej Zary if (count > data->blksz) 185a5eb8bbdSOndrej Zary count = data->blksz; 186a5eb8bbdSOndrej Zary 187a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "count: %08x, flags %08x\n", count, 188a5eb8bbdSOndrej Zary data->flags); 189a5eb8bbdSOndrej Zary 190a5eb8bbdSOndrej Zary /* Transfer the data */ 191a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 192a5eb8bbdSOndrej Zary ioread32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); 193a5eb8bbdSOndrej Zary else 194a5eb8bbdSOndrej Zary iowrite32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); 195a5eb8bbdSOndrej Zary 196a5eb8bbdSOndrej Zary sg_miter->consumed = count; 197a5eb8bbdSOndrej Zary sg_miter_stop(sg_miter); 198a5eb8bbdSOndrej Zary 1998a66fdaeSAxel Lin done: 200a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 201a5eb8bbdSOndrej Zary 202a5eb8bbdSOndrej Zary return IRQ_HANDLED; 203a5eb8bbdSOndrej Zary } 204a5eb8bbdSOndrej Zary 205a5eb8bbdSOndrej Zary static void toshsd_cmd_irq(struct toshsd_host *host) 206a5eb8bbdSOndrej Zary { 207a5eb8bbdSOndrej Zary struct mmc_command *cmd = host->cmd; 2089e2a0c96SDan Carpenter u8 *buf; 209a5eb8bbdSOndrej Zary u16 data; 210a5eb8bbdSOndrej Zary 211a5eb8bbdSOndrej Zary if (!host->cmd) { 212a5eb8bbdSOndrej Zary dev_warn(&host->pdev->dev, "Spurious CMD irq\n"); 213a5eb8bbdSOndrej Zary return; 214a5eb8bbdSOndrej Zary } 2159e2a0c96SDan Carpenter buf = (u8 *)cmd->resp; 216a5eb8bbdSOndrej Zary host->cmd = NULL; 217a5eb8bbdSOndrej Zary 218a5eb8bbdSOndrej Zary if (cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) { 219a5eb8bbdSOndrej Zary /* R2 */ 220a5eb8bbdSOndrej Zary buf[12] = 0xff; 221a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE0); 222a5eb8bbdSOndrej Zary buf[13] = data & 0xff; 223a5eb8bbdSOndrej Zary buf[14] = data >> 8; 224a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE1); 225a5eb8bbdSOndrej Zary buf[15] = data & 0xff; 226a5eb8bbdSOndrej Zary buf[8] = data >> 8; 227a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE2); 228a5eb8bbdSOndrej Zary buf[9] = data & 0xff; 229a5eb8bbdSOndrej Zary buf[10] = data >> 8; 230a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE3); 231a5eb8bbdSOndrej Zary buf[11] = data & 0xff; 232a5eb8bbdSOndrej Zary buf[4] = data >> 8; 233a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE4); 234a5eb8bbdSOndrej Zary buf[5] = data & 0xff; 235a5eb8bbdSOndrej Zary buf[6] = data >> 8; 236a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE5); 237a5eb8bbdSOndrej Zary buf[7] = data & 0xff; 238a5eb8bbdSOndrej Zary buf[0] = data >> 8; 239a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE6); 240a5eb8bbdSOndrej Zary buf[1] = data & 0xff; 241a5eb8bbdSOndrej Zary buf[2] = data >> 8; 242a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE7); 243a5eb8bbdSOndrej Zary buf[3] = data & 0xff; 244a5eb8bbdSOndrej Zary } else if (cmd->flags & MMC_RSP_PRESENT) { 245a5eb8bbdSOndrej Zary /* R1, R1B, R3, R6, R7 */ 246a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE0); 247a5eb8bbdSOndrej Zary buf[0] = data & 0xff; 248a5eb8bbdSOndrej Zary buf[1] = data >> 8; 249a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE1); 250a5eb8bbdSOndrej Zary buf[2] = data & 0xff; 251a5eb8bbdSOndrej Zary buf[3] = data >> 8; 252a5eb8bbdSOndrej Zary } 253a5eb8bbdSOndrej Zary 254a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Command IRQ complete %d %d %x\n", 255a5eb8bbdSOndrej Zary cmd->opcode, cmd->error, cmd->flags); 256a5eb8bbdSOndrej Zary 257a5eb8bbdSOndrej Zary /* If there is data to handle we will 258a5eb8bbdSOndrej Zary * finish the request in the mmc_data_end_irq handler.*/ 259a5eb8bbdSOndrej Zary if (host->data) 260a5eb8bbdSOndrej Zary return; 261a5eb8bbdSOndrej Zary 262a5eb8bbdSOndrej Zary toshsd_finish_request(host); 263a5eb8bbdSOndrej Zary } 264a5eb8bbdSOndrej Zary 265a5eb8bbdSOndrej Zary static void toshsd_data_end_irq(struct toshsd_host *host) 266a5eb8bbdSOndrej Zary { 267a5eb8bbdSOndrej Zary struct mmc_data *data = host->data; 268a5eb8bbdSOndrej Zary 269a5eb8bbdSOndrej Zary host->data = NULL; 270a5eb8bbdSOndrej Zary 271a5eb8bbdSOndrej Zary if (!data) { 272a5eb8bbdSOndrej Zary dev_warn(&host->pdev->dev, "Spurious data end IRQ\n"); 273a5eb8bbdSOndrej Zary return; 274a5eb8bbdSOndrej Zary } 275a5eb8bbdSOndrej Zary 276a5eb8bbdSOndrej Zary if (data->error == 0) 277a5eb8bbdSOndrej Zary data->bytes_xfered = data->blocks * data->blksz; 278a5eb8bbdSOndrej Zary else 279a5eb8bbdSOndrej Zary data->bytes_xfered = 0; 280a5eb8bbdSOndrej Zary 281a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Completed data request xfr=%d\n", 282a5eb8bbdSOndrej Zary data->bytes_xfered); 283a5eb8bbdSOndrej Zary 284a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_STOPINTERNAL); 285a5eb8bbdSOndrej Zary 286a5eb8bbdSOndrej Zary toshsd_finish_request(host); 287a5eb8bbdSOndrej Zary } 288a5eb8bbdSOndrej Zary 289a5eb8bbdSOndrej Zary static irqreturn_t toshsd_irq(int irq, void *dev_id) 290a5eb8bbdSOndrej Zary { 291a5eb8bbdSOndrej Zary struct toshsd_host *host = dev_id; 292a5eb8bbdSOndrej Zary u32 int_reg, int_mask, int_status, detail; 293a5eb8bbdSOndrej Zary int error = 0, ret = IRQ_HANDLED; 294a5eb8bbdSOndrej Zary 295a5eb8bbdSOndrej Zary spin_lock(&host->lock); 296a5eb8bbdSOndrej Zary int_status = ioread32(host->ioaddr + SD_CARDSTATUS); 297a5eb8bbdSOndrej Zary int_mask = ioread32(host->ioaddr + SD_INTMASKCARD); 298a5eb8bbdSOndrej Zary int_reg = int_status & ~int_mask & ~IRQ_DONT_CARE_BITS; 299a5eb8bbdSOndrej Zary 300a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "IRQ status:%x mask:%x\n", 301a5eb8bbdSOndrej Zary int_status, int_mask); 302a5eb8bbdSOndrej Zary 303a5eb8bbdSOndrej Zary /* nothing to do: it's not our IRQ */ 304a5eb8bbdSOndrej Zary if (!int_reg) { 305a5eb8bbdSOndrej Zary ret = IRQ_NONE; 306a5eb8bbdSOndrej Zary goto irq_end; 307a5eb8bbdSOndrej Zary } 308a5eb8bbdSOndrej Zary 309a5eb8bbdSOndrej Zary if (int_reg & SD_BUF_CMD_TIMEOUT) { 310a5eb8bbdSOndrej Zary error = -ETIMEDOUT; 311a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Timeout\n"); 312a5eb8bbdSOndrej Zary } else if (int_reg & SD_BUF_CRC_ERR) { 313a5eb8bbdSOndrej Zary error = -EILSEQ; 314a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "BadCRC\n"); 315a5eb8bbdSOndrej Zary } else if (int_reg & (SD_BUF_ILLEGAL_ACCESS 316a5eb8bbdSOndrej Zary | SD_BUF_CMD_INDEX_ERR 317a5eb8bbdSOndrej Zary | SD_BUF_STOP_BIT_END_ERR 318a5eb8bbdSOndrej Zary | SD_BUF_OVERFLOW 319a5eb8bbdSOndrej Zary | SD_BUF_UNDERFLOW 320a5eb8bbdSOndrej Zary | SD_BUF_DATA_TIMEOUT)) { 321a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "Buffer status error: { %s%s%s%s%s%s}\n", 322a5eb8bbdSOndrej Zary int_reg & SD_BUF_ILLEGAL_ACCESS ? "ILLEGAL_ACC " : "", 323a5eb8bbdSOndrej Zary int_reg & SD_BUF_CMD_INDEX_ERR ? "CMD_INDEX " : "", 324a5eb8bbdSOndrej Zary int_reg & SD_BUF_STOP_BIT_END_ERR ? "STOPBIT_END " : "", 325a5eb8bbdSOndrej Zary int_reg & SD_BUF_OVERFLOW ? "OVERFLOW " : "", 326a5eb8bbdSOndrej Zary int_reg & SD_BUF_UNDERFLOW ? "UNDERFLOW " : "", 327a5eb8bbdSOndrej Zary int_reg & SD_BUF_DATA_TIMEOUT ? "DATA_TIMEOUT " : ""); 328a5eb8bbdSOndrej Zary 329a5eb8bbdSOndrej Zary detail = ioread32(host->ioaddr + SD_ERRORSTATUS0); 330a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "detail error status { %s%s%s%s%s%s%s%s%s%s%s%s%s}\n", 331a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD_ERR ? "RESP_CMD " : "", 332a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_NON_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "", 333a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "", 334a5eb8bbdSOndrej Zary detail & SD_ERR0_READ_DATA_END_BIT_ERR ? "READ_DATA_END_BIT " : "", 335a5eb8bbdSOndrej Zary detail & SD_ERR0_WRITE_CRC_STATUS_END_BIT_ERR ? "WRITE_CMD_END_BIT " : "", 336a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_NON_CMD12_CRC_ERR ? "RESP_CRC " : "", 337a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD12_CRC_ERR ? "RESP_CRC " : "", 338a5eb8bbdSOndrej Zary detail & SD_ERR0_READ_DATA_CRC_ERR ? "READ_DATA_CRC " : "", 339a5eb8bbdSOndrej Zary detail & SD_ERR0_WRITE_CMD_CRC_ERR ? "WRITE_CMD_CRC " : "", 340a5eb8bbdSOndrej Zary detail & SD_ERR1_NO_CMD_RESP ? "NO_CMD_RESP " : "", 341a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_READ_DATA ? "READ_DATA_TIMEOUT " : "", 342a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_CRS_STATUS ? "CRS_STATUS_TIMEOUT " : "", 343a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_CRC_BUSY ? "CRC_BUSY_TIMEOUT " : ""); 344a5eb8bbdSOndrej Zary error = -EIO; 345a5eb8bbdSOndrej Zary } 346a5eb8bbdSOndrej Zary 347a5eb8bbdSOndrej Zary if (error) { 348a5eb8bbdSOndrej Zary if (host->cmd) 349a5eb8bbdSOndrej Zary host->cmd->error = error; 350a5eb8bbdSOndrej Zary 351a5eb8bbdSOndrej Zary if (error == -ETIMEDOUT) { 352a5eb8bbdSOndrej Zary iowrite32(int_status & 353a5eb8bbdSOndrej Zary ~(SD_BUF_CMD_TIMEOUT | SD_CARD_RESP_END), 354a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 355a5eb8bbdSOndrej Zary } else { 356a5eb8bbdSOndrej Zary toshsd_init(host); 357a5eb8bbdSOndrej Zary __toshsd_set_ios(host->mmc, &host->mmc->ios); 358a5eb8bbdSOndrej Zary goto irq_end; 359a5eb8bbdSOndrej Zary } 360a5eb8bbdSOndrej Zary } 361a5eb8bbdSOndrej Zary 362a5eb8bbdSOndrej Zary /* Card insert/remove. The mmc controlling code is stateless. */ 363a5eb8bbdSOndrej Zary if (int_reg & (SD_CARD_CARD_INSERTED_0 | SD_CARD_CARD_REMOVED_0)) { 364a5eb8bbdSOndrej Zary iowrite32(int_status & 365a5eb8bbdSOndrej Zary ~(SD_CARD_CARD_REMOVED_0 | SD_CARD_CARD_INSERTED_0), 366a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 367a5eb8bbdSOndrej Zary 368a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_CARD_INSERTED_0) 369a5eb8bbdSOndrej Zary toshsd_init(host); 370a5eb8bbdSOndrej Zary 371a5eb8bbdSOndrej Zary mmc_detect_change(host->mmc, 1); 372a5eb8bbdSOndrej Zary } 373a5eb8bbdSOndrej Zary 374a5eb8bbdSOndrej Zary /* Data transfer */ 375a5eb8bbdSOndrej Zary if (int_reg & (SD_BUF_READ_ENABLE | SD_BUF_WRITE_ENABLE)) { 376a5eb8bbdSOndrej Zary iowrite32(int_status & 377a5eb8bbdSOndrej Zary ~(SD_BUF_WRITE_ENABLE | SD_BUF_READ_ENABLE), 378a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 379a5eb8bbdSOndrej Zary 380a5eb8bbdSOndrej Zary ret = IRQ_WAKE_THREAD; 381a5eb8bbdSOndrej Zary goto irq_end; 382a5eb8bbdSOndrej Zary } 383a5eb8bbdSOndrej Zary 384a5eb8bbdSOndrej Zary /* Command completion */ 385a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_RESP_END) { 386a5eb8bbdSOndrej Zary iowrite32(int_status & ~(SD_CARD_RESP_END), 387a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 388a5eb8bbdSOndrej Zary toshsd_cmd_irq(host); 389a5eb8bbdSOndrej Zary } 390a5eb8bbdSOndrej Zary 391a5eb8bbdSOndrej Zary /* Data transfer completion */ 392a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_RW_END) { 393a5eb8bbdSOndrej Zary iowrite32(int_status & ~(SD_CARD_RW_END), 394a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 395a5eb8bbdSOndrej Zary toshsd_data_end_irq(host); 396a5eb8bbdSOndrej Zary } 397a5eb8bbdSOndrej Zary irq_end: 398a5eb8bbdSOndrej Zary spin_unlock(&host->lock); 399a5eb8bbdSOndrej Zary return ret; 400a5eb8bbdSOndrej Zary } 401a5eb8bbdSOndrej Zary 402a5eb8bbdSOndrej Zary static void toshsd_start_cmd(struct toshsd_host *host, struct mmc_command *cmd) 403a5eb8bbdSOndrej Zary { 404a5eb8bbdSOndrej Zary struct mmc_data *data = host->data; 405a5eb8bbdSOndrej Zary int c = cmd->opcode; 406a5eb8bbdSOndrej Zary 407a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Command opcode: %d\n", cmd->opcode); 408a5eb8bbdSOndrej Zary 409a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_STOP_TRANSMISSION) { 410a5eb8bbdSOndrej Zary iowrite16(SD_STOPINT_ISSUE_CMD12, 411a5eb8bbdSOndrej Zary host->ioaddr + SD_STOPINTERNAL); 412a5eb8bbdSOndrej Zary 413a5eb8bbdSOndrej Zary cmd->resp[0] = cmd->opcode; 414a5eb8bbdSOndrej Zary cmd->resp[1] = 0; 415a5eb8bbdSOndrej Zary cmd->resp[2] = 0; 416a5eb8bbdSOndrej Zary cmd->resp[3] = 0; 417a5eb8bbdSOndrej Zary 418a5eb8bbdSOndrej Zary toshsd_finish_request(host); 419a5eb8bbdSOndrej Zary return; 420a5eb8bbdSOndrej Zary } 421a5eb8bbdSOndrej Zary 422a5eb8bbdSOndrej Zary switch (mmc_resp_type(cmd)) { 423a5eb8bbdSOndrej Zary case MMC_RSP_NONE: 424a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_NONE; 425a5eb8bbdSOndrej Zary break; 426a5eb8bbdSOndrej Zary 427a5eb8bbdSOndrej Zary case MMC_RSP_R1: 428a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R1; 429a5eb8bbdSOndrej Zary break; 430a5eb8bbdSOndrej Zary case MMC_RSP_R1B: 431a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R1B; 432a5eb8bbdSOndrej Zary break; 433a5eb8bbdSOndrej Zary case MMC_RSP_R2: 434a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R2; 435a5eb8bbdSOndrej Zary break; 436a5eb8bbdSOndrej Zary case MMC_RSP_R3: 437a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R3; 438a5eb8bbdSOndrej Zary break; 439a5eb8bbdSOndrej Zary 440a5eb8bbdSOndrej Zary default: 441a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "Unknown response type %d\n", 442a5eb8bbdSOndrej Zary mmc_resp_type(cmd)); 443a5eb8bbdSOndrej Zary break; 444a5eb8bbdSOndrej Zary } 445a5eb8bbdSOndrej Zary 446a5eb8bbdSOndrej Zary host->cmd = cmd; 447a5eb8bbdSOndrej Zary 448a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_APP_CMD) 449a5eb8bbdSOndrej Zary c |= SD_CMD_TYPE_ACMD; 450a5eb8bbdSOndrej Zary 451a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_GO_IDLE_STATE) 452a5eb8bbdSOndrej Zary c |= (3 << 8); /* removed from ipaq-asic3.h for some reason */ 453a5eb8bbdSOndrej Zary 454a5eb8bbdSOndrej Zary if (data) { 455a5eb8bbdSOndrej Zary c |= SD_CMD_DATA_PRESENT; 456a5eb8bbdSOndrej Zary 457a5eb8bbdSOndrej Zary if (data->blocks > 1) { 458a5eb8bbdSOndrej Zary iowrite16(SD_STOPINT_AUTO_ISSUE_CMD12, 459a5eb8bbdSOndrej Zary host->ioaddr + SD_STOPINTERNAL); 460a5eb8bbdSOndrej Zary c |= SD_CMD_MULTI_BLOCK; 461a5eb8bbdSOndrej Zary } 462a5eb8bbdSOndrej Zary 463a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 464a5eb8bbdSOndrej Zary c |= SD_CMD_TRANSFER_READ; 465a5eb8bbdSOndrej Zary 466a5eb8bbdSOndrej Zary /* MMC_DATA_WRITE does not require a bit to be set */ 467a5eb8bbdSOndrej Zary } 468a5eb8bbdSOndrej Zary 469a5eb8bbdSOndrej Zary /* Send the command */ 470a5eb8bbdSOndrej Zary iowrite32(cmd->arg, host->ioaddr + SD_ARG0); 471a5eb8bbdSOndrej Zary iowrite16(c, host->ioaddr + SD_CMD); 472a5eb8bbdSOndrej Zary } 473a5eb8bbdSOndrej Zary 474a5eb8bbdSOndrej Zary static void toshsd_start_data(struct toshsd_host *host, struct mmc_data *data) 475a5eb8bbdSOndrej Zary { 476a5eb8bbdSOndrej Zary unsigned int flags = SG_MITER_ATOMIC; 477a5eb8bbdSOndrej Zary 478a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "setup data transfer: blocksize %08x nr_blocks %d, offset: %08x\n", 479a5eb8bbdSOndrej Zary data->blksz, data->blocks, data->sg->offset); 480a5eb8bbdSOndrej Zary 481a5eb8bbdSOndrej Zary host->data = data; 482a5eb8bbdSOndrej Zary 483a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 484a5eb8bbdSOndrej Zary flags |= SG_MITER_TO_SG; 485a5eb8bbdSOndrej Zary else 486a5eb8bbdSOndrej Zary flags |= SG_MITER_FROM_SG; 487a5eb8bbdSOndrej Zary 488a5eb8bbdSOndrej Zary sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 489a5eb8bbdSOndrej Zary 490a5eb8bbdSOndrej Zary /* Set transfer length and blocksize */ 491a5eb8bbdSOndrej Zary iowrite16(data->blocks, host->ioaddr + SD_BLOCKCOUNT); 492a5eb8bbdSOndrej Zary iowrite16(data->blksz, host->ioaddr + SD_CARDXFERDATALEN); 493a5eb8bbdSOndrej Zary } 494a5eb8bbdSOndrej Zary 495a5eb8bbdSOndrej Zary /* Process requests from the MMC layer */ 496a5eb8bbdSOndrej Zary static void toshsd_request(struct mmc_host *mmc, struct mmc_request *mrq) 497a5eb8bbdSOndrej Zary { 498a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 499a5eb8bbdSOndrej Zary unsigned long flags; 500a5eb8bbdSOndrej Zary 501a5eb8bbdSOndrej Zary /* abort if card not present */ 502a5eb8bbdSOndrej Zary if (!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0)) { 503a5eb8bbdSOndrej Zary mrq->cmd->error = -ENOMEDIUM; 504a5eb8bbdSOndrej Zary mmc_request_done(mmc, mrq); 505a5eb8bbdSOndrej Zary return; 506a5eb8bbdSOndrej Zary } 507a5eb8bbdSOndrej Zary 508a5eb8bbdSOndrej Zary spin_lock_irqsave(&host->lock, flags); 509a5eb8bbdSOndrej Zary 510a5eb8bbdSOndrej Zary WARN_ON(host->mrq != NULL); 511a5eb8bbdSOndrej Zary 512a5eb8bbdSOndrej Zary host->mrq = mrq; 513a5eb8bbdSOndrej Zary 514a5eb8bbdSOndrej Zary if (mrq->data) 515a5eb8bbdSOndrej Zary toshsd_start_data(host, mrq->data); 516a5eb8bbdSOndrej Zary 517a5eb8bbdSOndrej Zary toshsd_set_led(host, 1); 518a5eb8bbdSOndrej Zary 519a5eb8bbdSOndrej Zary toshsd_start_cmd(host, mrq->cmd); 520a5eb8bbdSOndrej Zary 521a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 522a5eb8bbdSOndrej Zary } 523a5eb8bbdSOndrej Zary 524a5eb8bbdSOndrej Zary static void toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 525a5eb8bbdSOndrej Zary { 526a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 527a5eb8bbdSOndrej Zary unsigned long flags; 528a5eb8bbdSOndrej Zary 529a5eb8bbdSOndrej Zary spin_lock_irqsave(&host->lock, flags); 530a5eb8bbdSOndrej Zary __toshsd_set_ios(mmc, ios); 531a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 532a5eb8bbdSOndrej Zary } 533a5eb8bbdSOndrej Zary 534a5eb8bbdSOndrej Zary static int toshsd_get_ro(struct mmc_host *mmc) 535a5eb8bbdSOndrej Zary { 536a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 537a5eb8bbdSOndrej Zary 538a5eb8bbdSOndrej Zary /* active low */ 539a5eb8bbdSOndrej Zary return !(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_WRITE_PROTECT); 540a5eb8bbdSOndrej Zary } 541a5eb8bbdSOndrej Zary 542a5eb8bbdSOndrej Zary static int toshsd_get_cd(struct mmc_host *mmc) 543a5eb8bbdSOndrej Zary { 544a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 545a5eb8bbdSOndrej Zary 546a5eb8bbdSOndrej Zary return !!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0); 547a5eb8bbdSOndrej Zary } 548a5eb8bbdSOndrej Zary 549251db11dSJulia Lawall static const struct mmc_host_ops toshsd_ops = { 550a5eb8bbdSOndrej Zary .request = toshsd_request, 551a5eb8bbdSOndrej Zary .set_ios = toshsd_set_ios, 552a5eb8bbdSOndrej Zary .get_ro = toshsd_get_ro, 553a5eb8bbdSOndrej Zary .get_cd = toshsd_get_cd, 554a5eb8bbdSOndrej Zary }; 555a5eb8bbdSOndrej Zary 556a5eb8bbdSOndrej Zary 557a5eb8bbdSOndrej Zary static void toshsd_powerdown(struct toshsd_host *host) 558a5eb8bbdSOndrej Zary { 559a5eb8bbdSOndrej Zary /* mask all interrupts */ 560a5eb8bbdSOndrej Zary iowrite32(0xffffffff, host->ioaddr + SD_INTMASKCARD); 561a5eb8bbdSOndrej Zary /* disable card clock */ 562a5eb8bbdSOndrej Zary iowrite16(0x000, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL); 563a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); 564a5eb8bbdSOndrej Zary /* power down card */ 565a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, SD_PCICFG_PWR1_OFF); 566a5eb8bbdSOndrej Zary /* disable clock */ 567a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, 0); 568a5eb8bbdSOndrej Zary } 569a5eb8bbdSOndrej Zary 570a5eb8bbdSOndrej Zary #ifdef CONFIG_PM_SLEEP 571a5eb8bbdSOndrej Zary static int toshsd_pm_suspend(struct device *dev) 572a5eb8bbdSOndrej Zary { 573a5eb8bbdSOndrej Zary struct pci_dev *pdev = to_pci_dev(dev); 574a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 575a5eb8bbdSOndrej Zary 576a5eb8bbdSOndrej Zary toshsd_powerdown(host); 577a5eb8bbdSOndrej Zary 578a5eb8bbdSOndrej Zary pci_save_state(pdev); 579a5eb8bbdSOndrej Zary pci_enable_wake(pdev, PCI_D3hot, 0); 580a5eb8bbdSOndrej Zary pci_disable_device(pdev); 581a5eb8bbdSOndrej Zary pci_set_power_state(pdev, PCI_D3hot); 582a5eb8bbdSOndrej Zary 583a5eb8bbdSOndrej Zary return 0; 584a5eb8bbdSOndrej Zary } 585a5eb8bbdSOndrej Zary 586a5eb8bbdSOndrej Zary static int toshsd_pm_resume(struct device *dev) 587a5eb8bbdSOndrej Zary { 588a5eb8bbdSOndrej Zary struct pci_dev *pdev = to_pci_dev(dev); 589a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 590a5eb8bbdSOndrej Zary int ret; 591a5eb8bbdSOndrej Zary 592a5eb8bbdSOndrej Zary pci_set_power_state(pdev, PCI_D0); 593a5eb8bbdSOndrej Zary pci_restore_state(pdev); 594a5eb8bbdSOndrej Zary ret = pci_enable_device(pdev); 595a5eb8bbdSOndrej Zary if (ret) 596a5eb8bbdSOndrej Zary return ret; 597a5eb8bbdSOndrej Zary 598a5eb8bbdSOndrej Zary toshsd_init(host); 599a5eb8bbdSOndrej Zary 600a5eb8bbdSOndrej Zary return 0; 601a5eb8bbdSOndrej Zary } 602a5eb8bbdSOndrej Zary #endif /* CONFIG_PM_SLEEP */ 603a5eb8bbdSOndrej Zary 604a5eb8bbdSOndrej Zary static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 605a5eb8bbdSOndrej Zary { 606a5eb8bbdSOndrej Zary int ret; 607a5eb8bbdSOndrej Zary struct toshsd_host *host; 608a5eb8bbdSOndrej Zary struct mmc_host *mmc; 609a5eb8bbdSOndrej Zary resource_size_t base; 610a5eb8bbdSOndrej Zary 611a5eb8bbdSOndrej Zary ret = pci_enable_device(pdev); 612a5eb8bbdSOndrej Zary if (ret) 613a5eb8bbdSOndrej Zary return ret; 614a5eb8bbdSOndrej Zary 615a5eb8bbdSOndrej Zary mmc = mmc_alloc_host(sizeof(struct toshsd_host), &pdev->dev); 616a5eb8bbdSOndrej Zary if (!mmc) { 617a5eb8bbdSOndrej Zary ret = -ENOMEM; 618a5eb8bbdSOndrej Zary goto err; 619a5eb8bbdSOndrej Zary } 620a5eb8bbdSOndrej Zary 621a5eb8bbdSOndrej Zary host = mmc_priv(mmc); 622a5eb8bbdSOndrej Zary host->mmc = mmc; 623a5eb8bbdSOndrej Zary 624a5eb8bbdSOndrej Zary host->pdev = pdev; 625a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, host); 626a5eb8bbdSOndrej Zary 627a5eb8bbdSOndrej Zary ret = pci_request_regions(pdev, DRIVER_NAME); 628a5eb8bbdSOndrej Zary if (ret) 629a5eb8bbdSOndrej Zary goto free; 630a5eb8bbdSOndrej Zary 631a5eb8bbdSOndrej Zary host->ioaddr = pci_iomap(pdev, 0, 0); 632a5eb8bbdSOndrej Zary if (!host->ioaddr) { 633a5eb8bbdSOndrej Zary ret = -ENOMEM; 634a5eb8bbdSOndrej Zary goto release; 635a5eb8bbdSOndrej Zary } 636a5eb8bbdSOndrej Zary 637a5eb8bbdSOndrej Zary /* Set MMC host parameters */ 638a5eb8bbdSOndrej Zary mmc->ops = &toshsd_ops; 639a5eb8bbdSOndrej Zary mmc->caps = MMC_CAP_4_BIT_DATA; 640a5eb8bbdSOndrej Zary mmc->ocr_avail = MMC_VDD_32_33; 641a5eb8bbdSOndrej Zary 642a5eb8bbdSOndrej Zary mmc->f_min = HCLK / 512; 643a5eb8bbdSOndrej Zary mmc->f_max = HCLK; 644a5eb8bbdSOndrej Zary 645a5eb8bbdSOndrej Zary spin_lock_init(&host->lock); 646a5eb8bbdSOndrej Zary 647a5eb8bbdSOndrej Zary toshsd_init(host); 648a5eb8bbdSOndrej Zary 649a5eb8bbdSOndrej Zary ret = request_threaded_irq(pdev->irq, toshsd_irq, toshsd_thread_irq, 650a5eb8bbdSOndrej Zary IRQF_SHARED, DRIVER_NAME, host); 651a5eb8bbdSOndrej Zary if (ret) 652a5eb8bbdSOndrej Zary goto unmap; 653a5eb8bbdSOndrej Zary 654a5eb8bbdSOndrej Zary mmc_add_host(mmc); 655a5eb8bbdSOndrej Zary 656a5eb8bbdSOndrej Zary base = pci_resource_start(pdev, 0); 657a5eb8bbdSOndrej Zary dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq); 658a5eb8bbdSOndrej Zary 659a5eb8bbdSOndrej Zary pm_suspend_ignore_children(&pdev->dev, 1); 660a5eb8bbdSOndrej Zary 661a5eb8bbdSOndrej Zary return 0; 662a5eb8bbdSOndrej Zary 663a5eb8bbdSOndrej Zary unmap: 664a5eb8bbdSOndrej Zary pci_iounmap(pdev, host->ioaddr); 665a5eb8bbdSOndrej Zary release: 666a5eb8bbdSOndrej Zary pci_release_regions(pdev); 667a5eb8bbdSOndrej Zary free: 668a5eb8bbdSOndrej Zary mmc_free_host(mmc); 669a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, NULL); 670a5eb8bbdSOndrej Zary err: 671a5eb8bbdSOndrej Zary pci_disable_device(pdev); 672a5eb8bbdSOndrej Zary return ret; 673a5eb8bbdSOndrej Zary } 674a5eb8bbdSOndrej Zary 675a5eb8bbdSOndrej Zary static void toshsd_remove(struct pci_dev *pdev) 676a5eb8bbdSOndrej Zary { 677a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 678a5eb8bbdSOndrej Zary 679a5eb8bbdSOndrej Zary mmc_remove_host(host->mmc); 680a5eb8bbdSOndrej Zary toshsd_powerdown(host); 681a5eb8bbdSOndrej Zary free_irq(pdev->irq, host); 682a5eb8bbdSOndrej Zary pci_iounmap(pdev, host->ioaddr); 683a5eb8bbdSOndrej Zary pci_release_regions(pdev); 684a5eb8bbdSOndrej Zary mmc_free_host(host->mmc); 685a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, NULL); 686a5eb8bbdSOndrej Zary pci_disable_device(pdev); 687a5eb8bbdSOndrej Zary } 688a5eb8bbdSOndrej Zary 689a5eb8bbdSOndrej Zary static const struct dev_pm_ops toshsd_pm_ops = { 690a5eb8bbdSOndrej Zary SET_SYSTEM_SLEEP_PM_OPS(toshsd_pm_suspend, toshsd_pm_resume) 691a5eb8bbdSOndrej Zary }; 692a5eb8bbdSOndrej Zary 693a5eb8bbdSOndrej Zary static struct pci_driver toshsd_driver = { 694a5eb8bbdSOndrej Zary .name = DRIVER_NAME, 695a5eb8bbdSOndrej Zary .id_table = pci_ids, 696a5eb8bbdSOndrej Zary .probe = toshsd_probe, 697a5eb8bbdSOndrej Zary .remove = toshsd_remove, 698a5eb8bbdSOndrej Zary .driver.pm = &toshsd_pm_ops, 699a5eb8bbdSOndrej Zary }; 700a5eb8bbdSOndrej Zary 7011818681cSWei Yongjun module_pci_driver(toshsd_driver); 702a5eb8bbdSOndrej Zary 703a5eb8bbdSOndrej Zary MODULE_AUTHOR("Ondrej Zary, Richard Betts"); 704a5eb8bbdSOndrej Zary MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver"); 705a5eb8bbdSOndrej Zary MODULE_LICENSE("GPL"); 706