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)) 179*8a66fdaeSAxel Lin goto done; 180*8a66fdaeSAxel Lin 181a5eb8bbdSOndrej Zary buf = sg_miter->addr; 182a5eb8bbdSOndrej Zary 183a5eb8bbdSOndrej Zary /* Ensure we dont read more than one block. The chip will interrupt us 184a5eb8bbdSOndrej Zary * When the next block is available. 185a5eb8bbdSOndrej Zary */ 186a5eb8bbdSOndrej Zary count = sg_miter->length; 187a5eb8bbdSOndrej Zary if (count > data->blksz) 188a5eb8bbdSOndrej Zary count = data->blksz; 189a5eb8bbdSOndrej Zary 190a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "count: %08x, flags %08x\n", count, 191a5eb8bbdSOndrej Zary data->flags); 192a5eb8bbdSOndrej Zary 193a5eb8bbdSOndrej Zary /* Transfer the data */ 194a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 195a5eb8bbdSOndrej Zary ioread32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); 196a5eb8bbdSOndrej Zary else 197a5eb8bbdSOndrej Zary iowrite32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2); 198a5eb8bbdSOndrej Zary 199a5eb8bbdSOndrej Zary sg_miter->consumed = count; 200a5eb8bbdSOndrej Zary sg_miter_stop(sg_miter); 201a5eb8bbdSOndrej Zary 202*8a66fdaeSAxel Lin done: 203a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 204a5eb8bbdSOndrej Zary 205a5eb8bbdSOndrej Zary return IRQ_HANDLED; 206a5eb8bbdSOndrej Zary } 207a5eb8bbdSOndrej Zary 208a5eb8bbdSOndrej Zary static void toshsd_cmd_irq(struct toshsd_host *host) 209a5eb8bbdSOndrej Zary { 210a5eb8bbdSOndrej Zary struct mmc_command *cmd = host->cmd; 2119e2a0c96SDan Carpenter u8 *buf; 212a5eb8bbdSOndrej Zary u16 data; 213a5eb8bbdSOndrej Zary 214a5eb8bbdSOndrej Zary if (!host->cmd) { 215a5eb8bbdSOndrej Zary dev_warn(&host->pdev->dev, "Spurious CMD irq\n"); 216a5eb8bbdSOndrej Zary return; 217a5eb8bbdSOndrej Zary } 2189e2a0c96SDan Carpenter buf = (u8 *)cmd->resp; 219a5eb8bbdSOndrej Zary host->cmd = NULL; 220a5eb8bbdSOndrej Zary 221a5eb8bbdSOndrej Zary if (cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) { 222a5eb8bbdSOndrej Zary /* R2 */ 223a5eb8bbdSOndrej Zary buf[12] = 0xff; 224a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE0); 225a5eb8bbdSOndrej Zary buf[13] = data & 0xff; 226a5eb8bbdSOndrej Zary buf[14] = data >> 8; 227a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE1); 228a5eb8bbdSOndrej Zary buf[15] = data & 0xff; 229a5eb8bbdSOndrej Zary buf[8] = data >> 8; 230a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE2); 231a5eb8bbdSOndrej Zary buf[9] = data & 0xff; 232a5eb8bbdSOndrej Zary buf[10] = data >> 8; 233a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE3); 234a5eb8bbdSOndrej Zary buf[11] = data & 0xff; 235a5eb8bbdSOndrej Zary buf[4] = data >> 8; 236a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE4); 237a5eb8bbdSOndrej Zary buf[5] = data & 0xff; 238a5eb8bbdSOndrej Zary buf[6] = data >> 8; 239a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE5); 240a5eb8bbdSOndrej Zary buf[7] = data & 0xff; 241a5eb8bbdSOndrej Zary buf[0] = data >> 8; 242a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE6); 243a5eb8bbdSOndrej Zary buf[1] = data & 0xff; 244a5eb8bbdSOndrej Zary buf[2] = data >> 8; 245a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE7); 246a5eb8bbdSOndrej Zary buf[3] = data & 0xff; 247a5eb8bbdSOndrej Zary } else if (cmd->flags & MMC_RSP_PRESENT) { 248a5eb8bbdSOndrej Zary /* R1, R1B, R3, R6, R7 */ 249a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE0); 250a5eb8bbdSOndrej Zary buf[0] = data & 0xff; 251a5eb8bbdSOndrej Zary buf[1] = data >> 8; 252a5eb8bbdSOndrej Zary data = ioread16(host->ioaddr + SD_RESPONSE1); 253a5eb8bbdSOndrej Zary buf[2] = data & 0xff; 254a5eb8bbdSOndrej Zary buf[3] = data >> 8; 255a5eb8bbdSOndrej Zary } 256a5eb8bbdSOndrej Zary 257a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Command IRQ complete %d %d %x\n", 258a5eb8bbdSOndrej Zary cmd->opcode, cmd->error, cmd->flags); 259a5eb8bbdSOndrej Zary 260a5eb8bbdSOndrej Zary /* If there is data to handle we will 261a5eb8bbdSOndrej Zary * finish the request in the mmc_data_end_irq handler.*/ 262a5eb8bbdSOndrej Zary if (host->data) 263a5eb8bbdSOndrej Zary return; 264a5eb8bbdSOndrej Zary 265a5eb8bbdSOndrej Zary toshsd_finish_request(host); 266a5eb8bbdSOndrej Zary } 267a5eb8bbdSOndrej Zary 268a5eb8bbdSOndrej Zary static void toshsd_data_end_irq(struct toshsd_host *host) 269a5eb8bbdSOndrej Zary { 270a5eb8bbdSOndrej Zary struct mmc_data *data = host->data; 271a5eb8bbdSOndrej Zary 272a5eb8bbdSOndrej Zary host->data = NULL; 273a5eb8bbdSOndrej Zary 274a5eb8bbdSOndrej Zary if (!data) { 275a5eb8bbdSOndrej Zary dev_warn(&host->pdev->dev, "Spurious data end IRQ\n"); 276a5eb8bbdSOndrej Zary return; 277a5eb8bbdSOndrej Zary } 278a5eb8bbdSOndrej Zary 279a5eb8bbdSOndrej Zary if (data->error == 0) 280a5eb8bbdSOndrej Zary data->bytes_xfered = data->blocks * data->blksz; 281a5eb8bbdSOndrej Zary else 282a5eb8bbdSOndrej Zary data->bytes_xfered = 0; 283a5eb8bbdSOndrej Zary 284a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Completed data request xfr=%d\n", 285a5eb8bbdSOndrej Zary data->bytes_xfered); 286a5eb8bbdSOndrej Zary 287a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_STOPINTERNAL); 288a5eb8bbdSOndrej Zary 289a5eb8bbdSOndrej Zary toshsd_finish_request(host); 290a5eb8bbdSOndrej Zary } 291a5eb8bbdSOndrej Zary 292a5eb8bbdSOndrej Zary static irqreturn_t toshsd_irq(int irq, void *dev_id) 293a5eb8bbdSOndrej Zary { 294a5eb8bbdSOndrej Zary struct toshsd_host *host = dev_id; 295a5eb8bbdSOndrej Zary u32 int_reg, int_mask, int_status, detail; 296a5eb8bbdSOndrej Zary int error = 0, ret = IRQ_HANDLED; 297a5eb8bbdSOndrej Zary 298a5eb8bbdSOndrej Zary spin_lock(&host->lock); 299a5eb8bbdSOndrej Zary int_status = ioread32(host->ioaddr + SD_CARDSTATUS); 300a5eb8bbdSOndrej Zary int_mask = ioread32(host->ioaddr + SD_INTMASKCARD); 301a5eb8bbdSOndrej Zary int_reg = int_status & ~int_mask & ~IRQ_DONT_CARE_BITS; 302a5eb8bbdSOndrej Zary 303a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "IRQ status:%x mask:%x\n", 304a5eb8bbdSOndrej Zary int_status, int_mask); 305a5eb8bbdSOndrej Zary 306a5eb8bbdSOndrej Zary /* nothing to do: it's not our IRQ */ 307a5eb8bbdSOndrej Zary if (!int_reg) { 308a5eb8bbdSOndrej Zary ret = IRQ_NONE; 309a5eb8bbdSOndrej Zary goto irq_end; 310a5eb8bbdSOndrej Zary } 311a5eb8bbdSOndrej Zary 312a5eb8bbdSOndrej Zary if (int_reg & SD_BUF_CMD_TIMEOUT) { 313a5eb8bbdSOndrej Zary error = -ETIMEDOUT; 314a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Timeout\n"); 315a5eb8bbdSOndrej Zary } else if (int_reg & SD_BUF_CRC_ERR) { 316a5eb8bbdSOndrej Zary error = -EILSEQ; 317a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "BadCRC\n"); 318a5eb8bbdSOndrej Zary } else if (int_reg & (SD_BUF_ILLEGAL_ACCESS 319a5eb8bbdSOndrej Zary | SD_BUF_CMD_INDEX_ERR 320a5eb8bbdSOndrej Zary | SD_BUF_STOP_BIT_END_ERR 321a5eb8bbdSOndrej Zary | SD_BUF_OVERFLOW 322a5eb8bbdSOndrej Zary | SD_BUF_UNDERFLOW 323a5eb8bbdSOndrej Zary | SD_BUF_DATA_TIMEOUT)) { 324a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "Buffer status error: { %s%s%s%s%s%s}\n", 325a5eb8bbdSOndrej Zary int_reg & SD_BUF_ILLEGAL_ACCESS ? "ILLEGAL_ACC " : "", 326a5eb8bbdSOndrej Zary int_reg & SD_BUF_CMD_INDEX_ERR ? "CMD_INDEX " : "", 327a5eb8bbdSOndrej Zary int_reg & SD_BUF_STOP_BIT_END_ERR ? "STOPBIT_END " : "", 328a5eb8bbdSOndrej Zary int_reg & SD_BUF_OVERFLOW ? "OVERFLOW " : "", 329a5eb8bbdSOndrej Zary int_reg & SD_BUF_UNDERFLOW ? "UNDERFLOW " : "", 330a5eb8bbdSOndrej Zary int_reg & SD_BUF_DATA_TIMEOUT ? "DATA_TIMEOUT " : ""); 331a5eb8bbdSOndrej Zary 332a5eb8bbdSOndrej Zary detail = ioread32(host->ioaddr + SD_ERRORSTATUS0); 333a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "detail error status { %s%s%s%s%s%s%s%s%s%s%s%s%s}\n", 334a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD_ERR ? "RESP_CMD " : "", 335a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_NON_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "", 336a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "", 337a5eb8bbdSOndrej Zary detail & SD_ERR0_READ_DATA_END_BIT_ERR ? "READ_DATA_END_BIT " : "", 338a5eb8bbdSOndrej Zary detail & SD_ERR0_WRITE_CRC_STATUS_END_BIT_ERR ? "WRITE_CMD_END_BIT " : "", 339a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_NON_CMD12_CRC_ERR ? "RESP_CRC " : "", 340a5eb8bbdSOndrej Zary detail & SD_ERR0_RESP_CMD12_CRC_ERR ? "RESP_CRC " : "", 341a5eb8bbdSOndrej Zary detail & SD_ERR0_READ_DATA_CRC_ERR ? "READ_DATA_CRC " : "", 342a5eb8bbdSOndrej Zary detail & SD_ERR0_WRITE_CMD_CRC_ERR ? "WRITE_CMD_CRC " : "", 343a5eb8bbdSOndrej Zary detail & SD_ERR1_NO_CMD_RESP ? "NO_CMD_RESP " : "", 344a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_READ_DATA ? "READ_DATA_TIMEOUT " : "", 345a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_CRS_STATUS ? "CRS_STATUS_TIMEOUT " : "", 346a5eb8bbdSOndrej Zary detail & SD_ERR1_TIMEOUT_CRC_BUSY ? "CRC_BUSY_TIMEOUT " : ""); 347a5eb8bbdSOndrej Zary error = -EIO; 348a5eb8bbdSOndrej Zary } 349a5eb8bbdSOndrej Zary 350a5eb8bbdSOndrej Zary if (error) { 351a5eb8bbdSOndrej Zary if (host->cmd) 352a5eb8bbdSOndrej Zary host->cmd->error = error; 353a5eb8bbdSOndrej Zary 354a5eb8bbdSOndrej Zary if (error == -ETIMEDOUT) { 355a5eb8bbdSOndrej Zary iowrite32(int_status & 356a5eb8bbdSOndrej Zary ~(SD_BUF_CMD_TIMEOUT | SD_CARD_RESP_END), 357a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 358a5eb8bbdSOndrej Zary } else { 359a5eb8bbdSOndrej Zary toshsd_init(host); 360a5eb8bbdSOndrej Zary __toshsd_set_ios(host->mmc, &host->mmc->ios); 361a5eb8bbdSOndrej Zary goto irq_end; 362a5eb8bbdSOndrej Zary } 363a5eb8bbdSOndrej Zary } 364a5eb8bbdSOndrej Zary 365a5eb8bbdSOndrej Zary /* Card insert/remove. The mmc controlling code is stateless. */ 366a5eb8bbdSOndrej Zary if (int_reg & (SD_CARD_CARD_INSERTED_0 | SD_CARD_CARD_REMOVED_0)) { 367a5eb8bbdSOndrej Zary iowrite32(int_status & 368a5eb8bbdSOndrej Zary ~(SD_CARD_CARD_REMOVED_0 | SD_CARD_CARD_INSERTED_0), 369a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 370a5eb8bbdSOndrej Zary 371a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_CARD_INSERTED_0) 372a5eb8bbdSOndrej Zary toshsd_init(host); 373a5eb8bbdSOndrej Zary 374a5eb8bbdSOndrej Zary mmc_detect_change(host->mmc, 1); 375a5eb8bbdSOndrej Zary } 376a5eb8bbdSOndrej Zary 377a5eb8bbdSOndrej Zary /* Data transfer */ 378a5eb8bbdSOndrej Zary if (int_reg & (SD_BUF_READ_ENABLE | SD_BUF_WRITE_ENABLE)) { 379a5eb8bbdSOndrej Zary iowrite32(int_status & 380a5eb8bbdSOndrej Zary ~(SD_BUF_WRITE_ENABLE | SD_BUF_READ_ENABLE), 381a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 382a5eb8bbdSOndrej Zary 383a5eb8bbdSOndrej Zary ret = IRQ_WAKE_THREAD; 384a5eb8bbdSOndrej Zary goto irq_end; 385a5eb8bbdSOndrej Zary } 386a5eb8bbdSOndrej Zary 387a5eb8bbdSOndrej Zary /* Command completion */ 388a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_RESP_END) { 389a5eb8bbdSOndrej Zary iowrite32(int_status & ~(SD_CARD_RESP_END), 390a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 391a5eb8bbdSOndrej Zary toshsd_cmd_irq(host); 392a5eb8bbdSOndrej Zary } 393a5eb8bbdSOndrej Zary 394a5eb8bbdSOndrej Zary /* Data transfer completion */ 395a5eb8bbdSOndrej Zary if (int_reg & SD_CARD_RW_END) { 396a5eb8bbdSOndrej Zary iowrite32(int_status & ~(SD_CARD_RW_END), 397a5eb8bbdSOndrej Zary host->ioaddr + SD_CARDSTATUS); 398a5eb8bbdSOndrej Zary toshsd_data_end_irq(host); 399a5eb8bbdSOndrej Zary } 400a5eb8bbdSOndrej Zary irq_end: 401a5eb8bbdSOndrej Zary spin_unlock(&host->lock); 402a5eb8bbdSOndrej Zary return ret; 403a5eb8bbdSOndrej Zary } 404a5eb8bbdSOndrej Zary 405a5eb8bbdSOndrej Zary static void toshsd_start_cmd(struct toshsd_host *host, struct mmc_command *cmd) 406a5eb8bbdSOndrej Zary { 407a5eb8bbdSOndrej Zary struct mmc_data *data = host->data; 408a5eb8bbdSOndrej Zary int c = cmd->opcode; 409a5eb8bbdSOndrej Zary 410a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "Command opcode: %d\n", cmd->opcode); 411a5eb8bbdSOndrej Zary 412a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_STOP_TRANSMISSION) { 413a5eb8bbdSOndrej Zary iowrite16(SD_STOPINT_ISSUE_CMD12, 414a5eb8bbdSOndrej Zary host->ioaddr + SD_STOPINTERNAL); 415a5eb8bbdSOndrej Zary 416a5eb8bbdSOndrej Zary cmd->resp[0] = cmd->opcode; 417a5eb8bbdSOndrej Zary cmd->resp[1] = 0; 418a5eb8bbdSOndrej Zary cmd->resp[2] = 0; 419a5eb8bbdSOndrej Zary cmd->resp[3] = 0; 420a5eb8bbdSOndrej Zary 421a5eb8bbdSOndrej Zary toshsd_finish_request(host); 422a5eb8bbdSOndrej Zary return; 423a5eb8bbdSOndrej Zary } 424a5eb8bbdSOndrej Zary 425a5eb8bbdSOndrej Zary switch (mmc_resp_type(cmd)) { 426a5eb8bbdSOndrej Zary case MMC_RSP_NONE: 427a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_NONE; 428a5eb8bbdSOndrej Zary break; 429a5eb8bbdSOndrej Zary 430a5eb8bbdSOndrej Zary case MMC_RSP_R1: 431a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R1; 432a5eb8bbdSOndrej Zary break; 433a5eb8bbdSOndrej Zary case MMC_RSP_R1B: 434a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R1B; 435a5eb8bbdSOndrej Zary break; 436a5eb8bbdSOndrej Zary case MMC_RSP_R2: 437a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R2; 438a5eb8bbdSOndrej Zary break; 439a5eb8bbdSOndrej Zary case MMC_RSP_R3: 440a5eb8bbdSOndrej Zary c |= SD_CMD_RESP_TYPE_EXT_R3; 441a5eb8bbdSOndrej Zary break; 442a5eb8bbdSOndrej Zary 443a5eb8bbdSOndrej Zary default: 444a5eb8bbdSOndrej Zary dev_err(&host->pdev->dev, "Unknown response type %d\n", 445a5eb8bbdSOndrej Zary mmc_resp_type(cmd)); 446a5eb8bbdSOndrej Zary break; 447a5eb8bbdSOndrej Zary } 448a5eb8bbdSOndrej Zary 449a5eb8bbdSOndrej Zary host->cmd = cmd; 450a5eb8bbdSOndrej Zary 451a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_APP_CMD) 452a5eb8bbdSOndrej Zary c |= SD_CMD_TYPE_ACMD; 453a5eb8bbdSOndrej Zary 454a5eb8bbdSOndrej Zary if (cmd->opcode == MMC_GO_IDLE_STATE) 455a5eb8bbdSOndrej Zary c |= (3 << 8); /* removed from ipaq-asic3.h for some reason */ 456a5eb8bbdSOndrej Zary 457a5eb8bbdSOndrej Zary if (data) { 458a5eb8bbdSOndrej Zary c |= SD_CMD_DATA_PRESENT; 459a5eb8bbdSOndrej Zary 460a5eb8bbdSOndrej Zary if (data->blocks > 1) { 461a5eb8bbdSOndrej Zary iowrite16(SD_STOPINT_AUTO_ISSUE_CMD12, 462a5eb8bbdSOndrej Zary host->ioaddr + SD_STOPINTERNAL); 463a5eb8bbdSOndrej Zary c |= SD_CMD_MULTI_BLOCK; 464a5eb8bbdSOndrej Zary } 465a5eb8bbdSOndrej Zary 466a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 467a5eb8bbdSOndrej Zary c |= SD_CMD_TRANSFER_READ; 468a5eb8bbdSOndrej Zary 469a5eb8bbdSOndrej Zary /* MMC_DATA_WRITE does not require a bit to be set */ 470a5eb8bbdSOndrej Zary } 471a5eb8bbdSOndrej Zary 472a5eb8bbdSOndrej Zary /* Send the command */ 473a5eb8bbdSOndrej Zary iowrite32(cmd->arg, host->ioaddr + SD_ARG0); 474a5eb8bbdSOndrej Zary iowrite16(c, host->ioaddr + SD_CMD); 475a5eb8bbdSOndrej Zary } 476a5eb8bbdSOndrej Zary 477a5eb8bbdSOndrej Zary static void toshsd_start_data(struct toshsd_host *host, struct mmc_data *data) 478a5eb8bbdSOndrej Zary { 479a5eb8bbdSOndrej Zary unsigned int flags = SG_MITER_ATOMIC; 480a5eb8bbdSOndrej Zary 481a5eb8bbdSOndrej Zary dev_dbg(&host->pdev->dev, "setup data transfer: blocksize %08x nr_blocks %d, offset: %08x\n", 482a5eb8bbdSOndrej Zary data->blksz, data->blocks, data->sg->offset); 483a5eb8bbdSOndrej Zary 484a5eb8bbdSOndrej Zary host->data = data; 485a5eb8bbdSOndrej Zary 486a5eb8bbdSOndrej Zary if (data->flags & MMC_DATA_READ) 487a5eb8bbdSOndrej Zary flags |= SG_MITER_TO_SG; 488a5eb8bbdSOndrej Zary else 489a5eb8bbdSOndrej Zary flags |= SG_MITER_FROM_SG; 490a5eb8bbdSOndrej Zary 491a5eb8bbdSOndrej Zary sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 492a5eb8bbdSOndrej Zary 493a5eb8bbdSOndrej Zary /* Set transfer length and blocksize */ 494a5eb8bbdSOndrej Zary iowrite16(data->blocks, host->ioaddr + SD_BLOCKCOUNT); 495a5eb8bbdSOndrej Zary iowrite16(data->blksz, host->ioaddr + SD_CARDXFERDATALEN); 496a5eb8bbdSOndrej Zary } 497a5eb8bbdSOndrej Zary 498a5eb8bbdSOndrej Zary /* Process requests from the MMC layer */ 499a5eb8bbdSOndrej Zary static void toshsd_request(struct mmc_host *mmc, struct mmc_request *mrq) 500a5eb8bbdSOndrej Zary { 501a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 502a5eb8bbdSOndrej Zary unsigned long flags; 503a5eb8bbdSOndrej Zary 504a5eb8bbdSOndrej Zary /* abort if card not present */ 505a5eb8bbdSOndrej Zary if (!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0)) { 506a5eb8bbdSOndrej Zary mrq->cmd->error = -ENOMEDIUM; 507a5eb8bbdSOndrej Zary mmc_request_done(mmc, mrq); 508a5eb8bbdSOndrej Zary return; 509a5eb8bbdSOndrej Zary } 510a5eb8bbdSOndrej Zary 511a5eb8bbdSOndrej Zary spin_lock_irqsave(&host->lock, flags); 512a5eb8bbdSOndrej Zary 513a5eb8bbdSOndrej Zary WARN_ON(host->mrq != NULL); 514a5eb8bbdSOndrej Zary 515a5eb8bbdSOndrej Zary host->mrq = mrq; 516a5eb8bbdSOndrej Zary 517a5eb8bbdSOndrej Zary if (mrq->data) 518a5eb8bbdSOndrej Zary toshsd_start_data(host, mrq->data); 519a5eb8bbdSOndrej Zary 520a5eb8bbdSOndrej Zary toshsd_set_led(host, 1); 521a5eb8bbdSOndrej Zary 522a5eb8bbdSOndrej Zary toshsd_start_cmd(host, mrq->cmd); 523a5eb8bbdSOndrej Zary 524a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 525a5eb8bbdSOndrej Zary } 526a5eb8bbdSOndrej Zary 527a5eb8bbdSOndrej Zary static void toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 528a5eb8bbdSOndrej Zary { 529a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 530a5eb8bbdSOndrej Zary unsigned long flags; 531a5eb8bbdSOndrej Zary 532a5eb8bbdSOndrej Zary spin_lock_irqsave(&host->lock, flags); 533a5eb8bbdSOndrej Zary __toshsd_set_ios(mmc, ios); 534a5eb8bbdSOndrej Zary spin_unlock_irqrestore(&host->lock, flags); 535a5eb8bbdSOndrej Zary } 536a5eb8bbdSOndrej Zary 537a5eb8bbdSOndrej Zary static int toshsd_get_ro(struct mmc_host *mmc) 538a5eb8bbdSOndrej Zary { 539a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 540a5eb8bbdSOndrej Zary 541a5eb8bbdSOndrej Zary /* active low */ 542a5eb8bbdSOndrej Zary return !(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_WRITE_PROTECT); 543a5eb8bbdSOndrej Zary } 544a5eb8bbdSOndrej Zary 545a5eb8bbdSOndrej Zary static int toshsd_get_cd(struct mmc_host *mmc) 546a5eb8bbdSOndrej Zary { 547a5eb8bbdSOndrej Zary struct toshsd_host *host = mmc_priv(mmc); 548a5eb8bbdSOndrej Zary 549a5eb8bbdSOndrej Zary return !!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0); 550a5eb8bbdSOndrej Zary } 551a5eb8bbdSOndrej Zary 552a5eb8bbdSOndrej Zary static struct mmc_host_ops toshsd_ops = { 553a5eb8bbdSOndrej Zary .request = toshsd_request, 554a5eb8bbdSOndrej Zary .set_ios = toshsd_set_ios, 555a5eb8bbdSOndrej Zary .get_ro = toshsd_get_ro, 556a5eb8bbdSOndrej Zary .get_cd = toshsd_get_cd, 557a5eb8bbdSOndrej Zary }; 558a5eb8bbdSOndrej Zary 559a5eb8bbdSOndrej Zary 560a5eb8bbdSOndrej Zary static void toshsd_powerdown(struct toshsd_host *host) 561a5eb8bbdSOndrej Zary { 562a5eb8bbdSOndrej Zary /* mask all interrupts */ 563a5eb8bbdSOndrej Zary iowrite32(0xffffffff, host->ioaddr + SD_INTMASKCARD); 564a5eb8bbdSOndrej Zary /* disable card clock */ 565a5eb8bbdSOndrej Zary iowrite16(0x000, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL); 566a5eb8bbdSOndrej Zary iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL); 567a5eb8bbdSOndrej Zary /* power down card */ 568a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, SD_PCICFG_PWR1_OFF); 569a5eb8bbdSOndrej Zary /* disable clock */ 570a5eb8bbdSOndrej Zary pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, 0); 571a5eb8bbdSOndrej Zary } 572a5eb8bbdSOndrej Zary 573a5eb8bbdSOndrej Zary #ifdef CONFIG_PM_SLEEP 574a5eb8bbdSOndrej Zary static int toshsd_pm_suspend(struct device *dev) 575a5eb8bbdSOndrej Zary { 576a5eb8bbdSOndrej Zary struct pci_dev *pdev = to_pci_dev(dev); 577a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 578a5eb8bbdSOndrej Zary 579a5eb8bbdSOndrej Zary toshsd_powerdown(host); 580a5eb8bbdSOndrej Zary 581a5eb8bbdSOndrej Zary pci_save_state(pdev); 582a5eb8bbdSOndrej Zary pci_enable_wake(pdev, PCI_D3hot, 0); 583a5eb8bbdSOndrej Zary pci_disable_device(pdev); 584a5eb8bbdSOndrej Zary pci_set_power_state(pdev, PCI_D3hot); 585a5eb8bbdSOndrej Zary 586a5eb8bbdSOndrej Zary return 0; 587a5eb8bbdSOndrej Zary } 588a5eb8bbdSOndrej Zary 589a5eb8bbdSOndrej Zary static int toshsd_pm_resume(struct device *dev) 590a5eb8bbdSOndrej Zary { 591a5eb8bbdSOndrej Zary struct pci_dev *pdev = to_pci_dev(dev); 592a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 593a5eb8bbdSOndrej Zary int ret; 594a5eb8bbdSOndrej Zary 595a5eb8bbdSOndrej Zary pci_set_power_state(pdev, PCI_D0); 596a5eb8bbdSOndrej Zary pci_restore_state(pdev); 597a5eb8bbdSOndrej Zary ret = pci_enable_device(pdev); 598a5eb8bbdSOndrej Zary if (ret) 599a5eb8bbdSOndrej Zary return ret; 600a5eb8bbdSOndrej Zary 601a5eb8bbdSOndrej Zary toshsd_init(host); 602a5eb8bbdSOndrej Zary 603a5eb8bbdSOndrej Zary return 0; 604a5eb8bbdSOndrej Zary } 605a5eb8bbdSOndrej Zary #endif /* CONFIG_PM_SLEEP */ 606a5eb8bbdSOndrej Zary 607a5eb8bbdSOndrej Zary static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 608a5eb8bbdSOndrej Zary { 609a5eb8bbdSOndrej Zary int ret; 610a5eb8bbdSOndrej Zary struct toshsd_host *host; 611a5eb8bbdSOndrej Zary struct mmc_host *mmc; 612a5eb8bbdSOndrej Zary resource_size_t base; 613a5eb8bbdSOndrej Zary 614a5eb8bbdSOndrej Zary ret = pci_enable_device(pdev); 615a5eb8bbdSOndrej Zary if (ret) 616a5eb8bbdSOndrej Zary return ret; 617a5eb8bbdSOndrej Zary 618a5eb8bbdSOndrej Zary mmc = mmc_alloc_host(sizeof(struct toshsd_host), &pdev->dev); 619a5eb8bbdSOndrej Zary if (!mmc) { 620a5eb8bbdSOndrej Zary ret = -ENOMEM; 621a5eb8bbdSOndrej Zary goto err; 622a5eb8bbdSOndrej Zary } 623a5eb8bbdSOndrej Zary 624a5eb8bbdSOndrej Zary host = mmc_priv(mmc); 625a5eb8bbdSOndrej Zary host->mmc = mmc; 626a5eb8bbdSOndrej Zary 627a5eb8bbdSOndrej Zary host->pdev = pdev; 628a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, host); 629a5eb8bbdSOndrej Zary 630a5eb8bbdSOndrej Zary ret = pci_request_regions(pdev, DRIVER_NAME); 631a5eb8bbdSOndrej Zary if (ret) 632a5eb8bbdSOndrej Zary goto free; 633a5eb8bbdSOndrej Zary 634a5eb8bbdSOndrej Zary host->ioaddr = pci_iomap(pdev, 0, 0); 635a5eb8bbdSOndrej Zary if (!host->ioaddr) { 636a5eb8bbdSOndrej Zary ret = -ENOMEM; 637a5eb8bbdSOndrej Zary goto release; 638a5eb8bbdSOndrej Zary } 639a5eb8bbdSOndrej Zary 640a5eb8bbdSOndrej Zary /* Set MMC host parameters */ 641a5eb8bbdSOndrej Zary mmc->ops = &toshsd_ops; 642a5eb8bbdSOndrej Zary mmc->caps = MMC_CAP_4_BIT_DATA; 643a5eb8bbdSOndrej Zary mmc->ocr_avail = MMC_VDD_32_33; 644a5eb8bbdSOndrej Zary 645a5eb8bbdSOndrej Zary mmc->f_min = HCLK / 512; 646a5eb8bbdSOndrej Zary mmc->f_max = HCLK; 647a5eb8bbdSOndrej Zary 648a5eb8bbdSOndrej Zary spin_lock_init(&host->lock); 649a5eb8bbdSOndrej Zary 650a5eb8bbdSOndrej Zary toshsd_init(host); 651a5eb8bbdSOndrej Zary 652a5eb8bbdSOndrej Zary ret = request_threaded_irq(pdev->irq, toshsd_irq, toshsd_thread_irq, 653a5eb8bbdSOndrej Zary IRQF_SHARED, DRIVER_NAME, host); 654a5eb8bbdSOndrej Zary if (ret) 655a5eb8bbdSOndrej Zary goto unmap; 656a5eb8bbdSOndrej Zary 657a5eb8bbdSOndrej Zary mmc_add_host(mmc); 658a5eb8bbdSOndrej Zary 659a5eb8bbdSOndrej Zary base = pci_resource_start(pdev, 0); 660a5eb8bbdSOndrej Zary dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq); 661a5eb8bbdSOndrej Zary 662a5eb8bbdSOndrej Zary pm_suspend_ignore_children(&pdev->dev, 1); 663a5eb8bbdSOndrej Zary 664a5eb8bbdSOndrej Zary return 0; 665a5eb8bbdSOndrej Zary 666a5eb8bbdSOndrej Zary unmap: 667a5eb8bbdSOndrej Zary pci_iounmap(pdev, host->ioaddr); 668a5eb8bbdSOndrej Zary release: 669a5eb8bbdSOndrej Zary pci_release_regions(pdev); 670a5eb8bbdSOndrej Zary free: 671a5eb8bbdSOndrej Zary mmc_free_host(mmc); 672a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, NULL); 673a5eb8bbdSOndrej Zary err: 674a5eb8bbdSOndrej Zary pci_disable_device(pdev); 675a5eb8bbdSOndrej Zary return ret; 676a5eb8bbdSOndrej Zary } 677a5eb8bbdSOndrej Zary 678a5eb8bbdSOndrej Zary static void toshsd_remove(struct pci_dev *pdev) 679a5eb8bbdSOndrej Zary { 680a5eb8bbdSOndrej Zary struct toshsd_host *host = pci_get_drvdata(pdev); 681a5eb8bbdSOndrej Zary 682a5eb8bbdSOndrej Zary mmc_remove_host(host->mmc); 683a5eb8bbdSOndrej Zary toshsd_powerdown(host); 684a5eb8bbdSOndrej Zary free_irq(pdev->irq, host); 685a5eb8bbdSOndrej Zary pci_iounmap(pdev, host->ioaddr); 686a5eb8bbdSOndrej Zary pci_release_regions(pdev); 687a5eb8bbdSOndrej Zary mmc_free_host(host->mmc); 688a5eb8bbdSOndrej Zary pci_set_drvdata(pdev, NULL); 689a5eb8bbdSOndrej Zary pci_disable_device(pdev); 690a5eb8bbdSOndrej Zary } 691a5eb8bbdSOndrej Zary 692a5eb8bbdSOndrej Zary static const struct dev_pm_ops toshsd_pm_ops = { 693a5eb8bbdSOndrej Zary SET_SYSTEM_SLEEP_PM_OPS(toshsd_pm_suspend, toshsd_pm_resume) 694a5eb8bbdSOndrej Zary }; 695a5eb8bbdSOndrej Zary 696a5eb8bbdSOndrej Zary static struct pci_driver toshsd_driver = { 697a5eb8bbdSOndrej Zary .name = DRIVER_NAME, 698a5eb8bbdSOndrej Zary .id_table = pci_ids, 699a5eb8bbdSOndrej Zary .probe = toshsd_probe, 700a5eb8bbdSOndrej Zary .remove = toshsd_remove, 701a5eb8bbdSOndrej Zary .driver.pm = &toshsd_pm_ops, 702a5eb8bbdSOndrej Zary }; 703a5eb8bbdSOndrej Zary 7041818681cSWei Yongjun module_pci_driver(toshsd_driver); 705a5eb8bbdSOndrej Zary 706a5eb8bbdSOndrej Zary MODULE_AUTHOR("Ondrej Zary, Richard Betts"); 707a5eb8bbdSOndrej Zary MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver"); 708a5eb8bbdSOndrej Zary MODULE_LICENSE("GPL"); 709