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