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