^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/mmc/host/wbsd.c - Winbond W83L51xD SD/MMC driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Warning!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Changes to the FIFO system should be done with extreme care since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the hardware is full of bugs related to the FIFO. Known issues are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * - FIFO size field in FSR is always zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * - FIFO interrupts tend not to work as they should. Interrupts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * triggered only for full/empty events, not for threshold values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - On APIC systems the FIFO empty interrupt is sometimes lost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/mmc/mmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/mmc/sd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "wbsd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DRIVER_NAME "wbsd"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DBG(x...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) pr_debug(DRIVER_NAME ": " x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DBGF(f, x...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Device resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct pnp_device_id pnp_dev_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { "WEC0517", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { "WEC0518", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { "", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const int config_ports[] = { 0x2E, 0x4E };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static const int unlock_codes[] = { 0x83, 0x87 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const int valid_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x7112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static unsigned int param_nopnp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static const unsigned int param_nopnp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static unsigned int param_io = 0x248;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static unsigned int param_irq = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int param_dma = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Basic functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static inline void wbsd_unlock_config(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) BUG_ON(host->config == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) outb(host->unlock_code, host->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) outb(host->unlock_code, host->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static inline void wbsd_lock_config(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) BUG_ON(host->config == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) outb(LOCK_CODE, host->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) BUG_ON(host->config == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) outb(reg, host->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) outb(value, host->config + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) BUG_ON(host->config == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) outb(reg, host->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return inb(host->config + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) outb(index, host->base + WBSD_IDXR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) outb(value, host->base + WBSD_DATAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) outb(index, host->base + WBSD_IDXR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return inb(host->base + WBSD_DATAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Common routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void wbsd_init_device(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u8 setup, ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Reset chip (SD/MMC part) and fifo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) setup = wbsd_read_index(host, WBSD_IDX_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) wbsd_write_index(host, WBSD_IDX_SETUP, setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Set DAT3 to input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) setup &= ~WBSD_DAT3_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) wbsd_write_index(host, WBSD_IDX_SETUP, setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) host->flags &= ~WBSD_FIGNORE_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Read back default clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) host->clk = wbsd_read_index(host, WBSD_IDX_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Power down port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) outb(WBSD_POWER_N, host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Set maximum timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Test for card presence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) host->flags |= WBSD_FCARD_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) host->flags &= ~WBSD_FCARD_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Enable interesting interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ier = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ier |= WBSD_EINT_CARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ier |= WBSD_EINT_FIFO_THRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ier |= WBSD_EINT_CRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ier |= WBSD_EINT_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ier |= WBSD_EINT_TC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) outb(ier, host->base + WBSD_EIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * Clear interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) inb(host->base + WBSD_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void wbsd_reset(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) pr_err("%s: Resetting chip\n", mmc_hostname(host->mmc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Soft reset of chip (SD/MMC part).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) setup = wbsd_read_index(host, WBSD_IDX_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) setup |= WBSD_SOFT_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) wbsd_write_index(host, WBSD_IDX_SETUP, setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned long dmaflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (host->dma >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Release ISA DMA controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dmaflags = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) disable_dma(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) clear_dma_ff(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) release_dma_lock(dmaflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Disable DMA on host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) wbsd_write_index(host, WBSD_IDX_DMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) host->mrq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * MMC layer might call back into the driver so first unlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mmc_request_done(host->mmc, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * Scatter/gather functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Get info. about SG list from data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) host->cur_sg = data->sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) host->num_sg = data->sg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) host->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) host->remain = host->cur_sg->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static inline int wbsd_next_sg(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Skip to next SG entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) host->cur_sg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) host->num_sg--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Any entries left?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (host->num_sg > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) host->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) host->remain = host->cur_sg->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return host->num_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static inline char *wbsd_map_sg(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return kmap_atomic(sg_page(host->cur_sg)) + host->cur_sg->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) for (i = 0; i < data->sg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) len += data->sg[i].length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sg_copy_to_buffer(data->sg, data->sg_len, host->dma_buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) for (i = 0; i < data->sg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) len += data->sg[i].length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sg_copy_from_buffer(data->sg, data->sg_len, host->dma_buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * Command handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static inline void wbsd_get_short_reply(struct wbsd_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct mmc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * Correct response type?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) cmd->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) cmd->resp[0] = wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cmd->resp[1] = wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static inline void wbsd_get_long_reply(struct wbsd_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct mmc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * Correct response type?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) cmd->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) cmd->resp[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) cmd->resp[i] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) wbsd_read_index(host, WBSD_IDX_RESP2 + i * 4) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) cmd->resp[i] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) wbsd_read_index(host, WBSD_IDX_RESP3 + i * 4) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) cmd->resp[i] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) wbsd_read_index(host, WBSD_IDX_RESP4 + i * 4) << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u8 status, isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * Clear accumulated ISR. The interrupt routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * will fill this one with events that occur during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) host->isr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Send the command (CRC calculated by host).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) outb(cmd->opcode, host->base + WBSD_CMDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) for (i = 3; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) cmd->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * Wait for the request to complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) status = wbsd_read_index(host, WBSD_IDX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) } while (status & WBSD_CARDTRAFFIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * Do we expect a reply?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (cmd->flags & MMC_RSP_PRESENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * Read back status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) isr = host->isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* Card removed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (isr & WBSD_INT_CARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) cmd->error = -ENOMEDIUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Timeout? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else if (isr & WBSD_INT_TIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) cmd->error = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* CRC? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) cmd->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* All ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (cmd->flags & MMC_RSP_136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) wbsd_get_long_reply(host, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) wbsd_get_short_reply(host, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Data functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static void wbsd_empty_fifo(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct mmc_data *data = host->mrq->cmd->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int i, idx, fsr, fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * Handle excessive data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (host->num_sg == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) buffer = wbsd_map_sg(host) + host->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * Drain the fifo. This has a tendency to loop longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * than the FIFO length (usually one block).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * The size field in the FSR is broken so we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * do some guessing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (fsr & WBSD_FIFO_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) fifo = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) else if (fsr & WBSD_FIFO_FUTHRE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) fifo = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) fifo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) for (i = 0; i < fifo; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) buffer[idx++] = inb(host->base + WBSD_DFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) host->offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) host->remain--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) data->bytes_xfered++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * End of scatter list entry?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (host->remain == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) kunmap_atomic(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * Get next entry. Check if last.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (!wbsd_next_sg(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) buffer = wbsd_map_sg(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) kunmap_atomic(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * This is a very dirty hack to solve a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * hardware problem. The chip doesn't trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * FIFO threshold interrupts properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) tasklet_schedule(&host->fifo_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static void wbsd_fill_fifo(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct mmc_data *data = host->mrq->cmd->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int i, idx, fsr, fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * Check that we aren't being called after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * entire buffer has been transferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (host->num_sg == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) buffer = wbsd_map_sg(host) + host->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * Fill the fifo. This has a tendency to loop longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * than the FIFO length (usually one block).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * The size field in the FSR is broken so we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * do some guessing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (fsr & WBSD_FIFO_EMPTY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) fifo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) else if (fsr & WBSD_FIFO_EMTHRE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) fifo = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) fifo = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) for (i = 16; i > fifo; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) outb(buffer[idx], host->base + WBSD_DFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) host->offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) host->remain--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) data->bytes_xfered++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * End of scatter list entry?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (host->remain == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) kunmap_atomic(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * Get next entry. Check if last.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!wbsd_next_sg(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) buffer = wbsd_map_sg(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) kunmap_atomic(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * The controller stops sending interrupts for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * 'FIFO empty' under certain conditions. So we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * need to be a bit more pro-active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) tasklet_schedule(&host->fifo_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u16 blksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) u8 setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) unsigned long dmaflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * Calculate size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) size = data->blocks * data->blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Check timeout values for overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * (Yes, some cards cause this value to overflow).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (data->timeout_ns > 127000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) wbsd_write_index(host, WBSD_IDX_TAAC, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) wbsd_write_index(host, WBSD_IDX_TAAC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) data->timeout_ns / 1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (data->timeout_clks > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) wbsd_write_index(host, WBSD_IDX_NSAC, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * Inform the chip of how large blocks will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * sent. It needs this to determine when to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * calculate CRC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * Space for CRC must be included in the size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * Two bytes are needed for each data line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (host->bus_width == MMC_BUS_WIDTH_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) blksize = data->blksz + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) } else if (host->bus_width == MMC_BUS_WIDTH_4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) blksize = data->blksz + 2 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) wbsd_write_index(host, WBSD_IDX_PBSMSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) data->error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * Clear the FIFO. This is needed even for DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * transfers since the chip still uses the FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * internally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) setup = wbsd_read_index(host, WBSD_IDX_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) setup |= WBSD_FIFO_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) wbsd_write_index(host, WBSD_IDX_SETUP, setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * DMA transfer?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (host->dma >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * The buffer for DMA is only 64 kB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) BUG_ON(size > 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (size > 0x10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) data->error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * Transfer data from the SG list to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * the DMA buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (data->flags & MMC_DATA_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) wbsd_sg_to_dma(host, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * Initialise the ISA DMA controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) dmaflags = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) disable_dma(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) clear_dma_ff(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (data->flags & MMC_DATA_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) set_dma_mode(host->dma, DMA_MODE_READ & ~0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) set_dma_addr(host->dma, host->dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) set_dma_count(host->dma, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) enable_dma(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) release_dma_lock(dmaflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * Enable DMA on the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * This flag is used to keep printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * output to a minimum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) host->firsterr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * Initialise the SG list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) wbsd_init_sg(host, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * Turn off DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) wbsd_write_index(host, WBSD_IDX_DMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * Set up FIFO threshold levels (and fill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * buffer if doing a write).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (data->flags & MMC_DATA_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) wbsd_write_index(host, WBSD_IDX_FIFOEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) WBSD_FIFOEN_FULL | 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) wbsd_write_index(host, WBSD_IDX_FIFOEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) WBSD_FIFOEN_EMPTY | 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) wbsd_fill_fifo(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) data->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) unsigned long dmaflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) WARN_ON(host->mrq == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * Send a stop command if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (data->stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) wbsd_send_command(host, data->stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Wait for the controller to leave data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * transfer state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) status = wbsd_read_index(host, WBSD_IDX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * DMA transfer?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (host->dma >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * Disable DMA on the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) wbsd_write_index(host, WBSD_IDX_DMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * Turn of ISA DMA controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) dmaflags = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) disable_dma(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) clear_dma_ff(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) count = get_dma_residue(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) release_dma_lock(dmaflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) data->bytes_xfered = host->mrq->data->blocks *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) host->mrq->data->blksz - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) data->bytes_xfered -= data->bytes_xfered % data->blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * Any leftover data?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) pr_err("%s: Incomplete DMA transfer. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) "%d bytes left.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mmc_hostname(host->mmc), count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!data->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) data->error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * Transfer data from DMA buffer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * SG list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (data->flags & MMC_DATA_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) wbsd_dma_to_sg(host, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (data->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (data->bytes_xfered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) data->bytes_xfered -= data->blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) wbsd_request_end(host, host->mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*****************************************************************************\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * MMC layer callbacks *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) \*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct wbsd_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct mmc_command *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * Disable tasklets to avoid a deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) spin_lock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) BUG_ON(host->mrq != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) cmd = mrq->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) host->mrq = mrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * Check that there is actually a card in the slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (!(host->flags & WBSD_FCARD_PRESENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) cmd->error = -ENOMEDIUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (cmd->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * The hardware is so delightfully stupid that it has a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * of "data" commands. If a command isn't on this list, it'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * just go back to the idle state and won't send any data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) switch (cmd->opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case SD_SWITCH_VOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case MMC_READ_SINGLE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case MMC_READ_MULTIPLE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case MMC_WRITE_DAT_UNTIL_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case MMC_WRITE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case MMC_WRITE_MULTIPLE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case MMC_PROGRAM_CID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) case MMC_PROGRAM_CSD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) case MMC_SEND_WRITE_PROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) case MMC_LOCK_UNLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) case MMC_GEN_CMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* ACMDs. We don't keep track of state, so we just treat them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * like any other command. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) case SD_APP_SEND_SCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) pr_warn("%s: Data command %d is not supported by this controller\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mmc_hostname(host->mmc), cmd->opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) cmd->error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * Does the request include data?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (cmd->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) wbsd_prepare_data(host, cmd->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (cmd->data->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) wbsd_send_command(host, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * If this is a data transfer the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * will be finished after the data has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * transferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (cmd->data && !cmd->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * Dirty fix for hardware bug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (host->dma == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) tasklet_schedule(&host->fifo_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) spin_unlock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) wbsd_request_end(host, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) spin_unlock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct wbsd_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) u8 clk, setup, pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) spin_lock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * Reset the chip on each power off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * Should clear out any weird states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ios->power_mode == MMC_POWER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) wbsd_init_device(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (ios->clock >= 24000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) clk = WBSD_CLK_24M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) else if (ios->clock >= 16000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) clk = WBSD_CLK_16M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) else if (ios->clock >= 12000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) clk = WBSD_CLK_12M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) clk = WBSD_CLK_375K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * Only write to the clock register when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * there is an actual change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (clk != host->clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) wbsd_write_index(host, WBSD_IDX_CLK, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) host->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * Power up card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ios->power_mode != MMC_POWER_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) pwr = inb(host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) pwr &= ~WBSD_POWER_N;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) outb(pwr, host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * MMC cards need to have pin 1 high during init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * It wreaks havoc with the card detection though so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * that needs to be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) setup = wbsd_read_index(host, WBSD_IDX_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ios->chip_select == MMC_CS_HIGH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) setup |= WBSD_DAT3_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) host->flags |= WBSD_FIGNORE_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (setup & WBSD_DAT3_H) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) setup &= ~WBSD_DAT3_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * We cannot resume card detection immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * because of capacitance and delays in the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) mod_timer(&host->ignore_timer, jiffies + HZ / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) wbsd_write_index(host, WBSD_IDX_SETUP, setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * Store bus width for later. Will be used when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * setting up the data transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) host->bus_width = ios->bus_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) spin_unlock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static int wbsd_get_ro(struct mmc_host *mmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct wbsd_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) u8 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) spin_lock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) csr = inb(host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) csr |= WBSD_MSLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) outb(csr, host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) csr = inb(host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) csr &= ~WBSD_MSLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) outb(csr, host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) spin_unlock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return !!(csr & WBSD_WRPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static const struct mmc_host_ops wbsd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) .request = wbsd_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) .set_ios = wbsd_set_ios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) .get_ro = wbsd_get_ro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /*****************************************************************************\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * Interrupt handling *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) \*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * Helper function to reset detection ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static void wbsd_reset_ignore(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct wbsd_host *host = from_timer(host, t, ignore_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) BUG_ON(host == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) DBG("Resetting card detection ignore\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) spin_lock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) host->flags &= ~WBSD_FIGNORE_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * Card status might have changed during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * blackout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) tasklet_schedule(&host->card_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) spin_unlock_bh(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * Tasklets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) WARN_ON(!host->mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (!host->mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) WARN_ON(!host->mrq->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (!host->mrq->cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) WARN_ON(!host->mrq->cmd->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!host->mrq->cmd->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return host->mrq->cmd->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static void wbsd_tasklet_card(unsigned long param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct wbsd_host *host = (struct wbsd_host *)param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) u8 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) int delay = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (host->flags & WBSD_FIGNORE_DETECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) csr = inb(host->base + WBSD_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) WARN_ON(csr == 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (csr & WBSD_CARDPRESENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!(host->flags & WBSD_FCARD_PRESENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) DBG("Card inserted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) host->flags |= WBSD_FCARD_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) delay = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) } else if (host->flags & WBSD_FCARD_PRESENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) DBG("Card removed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) host->flags &= ~WBSD_FCARD_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (host->mrq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) pr_err("%s: Card removed during transfer!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) mmc_hostname(host->mmc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) wbsd_reset(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) host->mrq->cmd->error = -ENOMEDIUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) tasklet_schedule(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * Unlock first since we might get a call back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (delay != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void wbsd_tasklet_fifo(unsigned long param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct wbsd_host *host = (struct wbsd_host *)param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct mmc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (!host->mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) data = wbsd_get_data(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (data->flags & MMC_DATA_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) wbsd_fill_fifo(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) wbsd_empty_fifo(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * Done?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (host->num_sg == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) tasklet_schedule(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) static void wbsd_tasklet_crc(unsigned long param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) struct wbsd_host *host = (struct wbsd_host *)param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct mmc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (!host->mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) data = wbsd_get_data(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) DBGF("CRC error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) data->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) tasklet_schedule(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) static void wbsd_tasklet_timeout(unsigned long param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct wbsd_host *host = (struct wbsd_host *)param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct mmc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (!host->mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) data = wbsd_get_data(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) DBGF("Timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) data->error = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) tasklet_schedule(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static void wbsd_tasklet_finish(unsigned long param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct wbsd_host *host = (struct wbsd_host *)param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct mmc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) WARN_ON(!host->mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (!host->mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) data = wbsd_get_data(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) wbsd_finish_data(host, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * Interrupt handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static irqreturn_t wbsd_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) struct wbsd_host *host = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) int isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) isr = inb(host->base + WBSD_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * Was it actually our hardware that caused the interrupt?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (isr == 0xff || isr == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) host->isr |= isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) * Schedule tasklets as needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (isr & WBSD_INT_CARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) tasklet_schedule(&host->card_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (isr & WBSD_INT_FIFO_THRE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) tasklet_schedule(&host->fifo_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (isr & WBSD_INT_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) tasklet_hi_schedule(&host->crc_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (isr & WBSD_INT_TIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) tasklet_hi_schedule(&host->timeout_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (isr & WBSD_INT_TC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) tasklet_schedule(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /*****************************************************************************\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * Device initialisation and shutdown *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) \*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * Allocate/free MMC structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static int wbsd_alloc_mmc(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct mmc_host *mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * Allocate MMC structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!mmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) host->mmc = mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) host->dma = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * Set host parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) mmc->ops = &wbsd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) mmc->f_min = 375000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) mmc->f_max = 24000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) mmc->caps = MMC_CAP_4_BIT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) spin_lock_init(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * Set up timers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) timer_setup(&host->ignore_timer, wbsd_reset_ignore, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * Maximum number of segments. Worst case is one sector per segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * so this will be 64kB/512.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) mmc->max_segs = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * Maximum request size. Also limited by 64KiB buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) mmc->max_req_size = 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * Maximum segment size. Could be one segment with the maximum number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * of bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) mmc->max_seg_size = mmc->max_req_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * Maximum block size. We have 12 bits (= 4095) but have to subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * space for CRC. So the maximum is 4095 - 4*2 = 4087.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) mmc->max_blk_size = 4087;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * Maximum block count. There is no real limit so the maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * request size will be the only restriction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) mmc->max_blk_count = mmc->max_req_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) dev_set_drvdata(dev, mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static void wbsd_free_mmc(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct mmc_host *mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) mmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (!mmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) BUG_ON(host == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) del_timer_sync(&host->ignore_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) mmc_free_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) dev_set_drvdata(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * Scan for known chip id:s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) static int wbsd_scan(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * Iterate through all ports, all codes to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * find hardware that is in our known list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) for (i = 0; i < ARRAY_SIZE(config_ports); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (!request_region(config_ports[i], 2, DRIVER_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) for (j = 0; j < ARRAY_SIZE(unlock_codes); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) id = 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) host->config = config_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) host->unlock_code = unlock_codes[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) wbsd_unlock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) outb(WBSD_CONF_ID_HI, config_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) id = inb(config_ports[i] + 1) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) outb(WBSD_CONF_ID_LO, config_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) id |= inb(config_ports[i] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) wbsd_lock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) for (k = 0; k < ARRAY_SIZE(valid_ids); k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (id == valid_ids[k]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) host->chip_id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (id != 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) DBG("Unknown hardware (id %x) found at %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) id, config_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) release_region(config_ports[i], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) host->config = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) host->unlock_code = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * Allocate/free io port ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) static int wbsd_request_region(struct wbsd_host *host, int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (base & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (!request_region(base, 8, DRIVER_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) host->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) static void wbsd_release_regions(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (host->base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) release_region(host->base, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) host->base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (host->config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) release_region(host->config, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) host->config = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * Allocate/free DMA port and buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static void wbsd_request_dma(struct wbsd_host *host, int dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (dma < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (request_dma(dma, DRIVER_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * We need to allocate a special buffer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * order for ISA to be able to DMA to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) host->dma_buffer = kmalloc(WBSD_DMA_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) GFP_NOIO | GFP_DMA | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (!host->dma_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * Translate the address to a physical address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (dma_mapping_error(mmc_dev(host->mmc), host->dma_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) goto kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * ISA DMA must be aligned on a 64k basis.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if ((host->dma_addr & 0xffff) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * ISA cannot access memory above 16 MB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) else if (host->dma_addr >= 0x1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) host->dma = dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) * If we've gotten here then there is some kind of alignment bug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) BUG_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) host->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) kfree(host->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) host->dma_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) free_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) pr_warn(DRIVER_NAME ": Unable to allocate DMA %d - falling back on FIFO\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) static void wbsd_release_dma(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * host->dma_addr is valid here iff host->dma_buffer is not NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (host->dma_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) kfree(host->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (host->dma >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) free_dma(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) host->dma = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) host->dma_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) host->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * Allocate/free IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) static int wbsd_request_irq(struct wbsd_host *host, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) * Set up tasklets. Must be done before requesting interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) (unsigned long)host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) (unsigned long)host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) (unsigned long)host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) (unsigned long)host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) (unsigned long)host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * Allocate interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) host->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) static void wbsd_release_irq(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!host->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) free_irq(host->irq, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) host->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) tasklet_kill(&host->card_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) tasklet_kill(&host->fifo_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) tasklet_kill(&host->crc_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) tasklet_kill(&host->timeout_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) tasklet_kill(&host->finish_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) * Allocate all resources for the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) static int wbsd_request_resources(struct wbsd_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) int base, int irq, int dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * Allocate I/O ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) ret = wbsd_request_region(host, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * Allocate interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) ret = wbsd_request_irq(host, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * Allocate DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) wbsd_request_dma(host, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * Release all resources for the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) static void wbsd_release_resources(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) wbsd_release_dma(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) wbsd_release_irq(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) wbsd_release_regions(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * Configure the resources the chip should use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) static void wbsd_chip_config(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) wbsd_unlock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) * Reset the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) wbsd_write_config(host, WBSD_CONF_SWRST, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) wbsd_write_config(host, WBSD_CONF_SWRST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * Select SD/MMC function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) * Set up card detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * Configure chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (host->dma >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) * Enable and power up chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) wbsd_lock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) * Check that configured resources are correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) static int wbsd_chip_validate(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) int base, irq, dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) wbsd_unlock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * Select SD/MMC function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) * Read configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) irq = wbsd_read_config(host, WBSD_CONF_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) dma = wbsd_read_config(host, WBSD_CONF_DRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) wbsd_lock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) * Validate against given configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (base != host->base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (irq != host->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if ((dma != host->dma) && (host->dma != -1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) * Powers down the SD function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) static void wbsd_chip_poweroff(struct wbsd_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) wbsd_unlock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) wbsd_lock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /*****************************************************************************\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) * Devices setup and shutdown *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) \*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static int wbsd_init(struct device *dev, int base, int irq, int dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) int pnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) struct wbsd_host *host = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) struct mmc_host *mmc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) ret = wbsd_alloc_mmc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) mmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) * Scan for hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) ret = wbsd_scan(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (pnp && (ret == -ENODEV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) pr_warn(DRIVER_NAME ": Unable to confirm device presence - you may experience lock-ups\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) wbsd_free_mmc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) * Request resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) ret = wbsd_request_resources(host, base, irq, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) wbsd_release_resources(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) wbsd_free_mmc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * See if chip needs to be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if (pnp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if ((host->config != 0) && !wbsd_chip_validate(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) pr_warn(DRIVER_NAME ": PnP active but chip not configured! You probably have a buggy BIOS. Configuring chip manually.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) wbsd_chip_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) wbsd_chip_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * Power Management stuff. No idea how this works.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) * Not tested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (host->config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) wbsd_unlock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) wbsd_lock_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) * Allow device to initialise itself properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * Reset the chip into a known state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) wbsd_init_device(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) mmc_add_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) pr_info("%s: W83L51xD", mmc_hostname(mmc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) if (host->chip_id != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) printk(" id %x", (int)host->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) if (host->dma >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) printk(" dma %d", (int)host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) printk(" FIFO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (pnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) printk(" PnP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) static void wbsd_shutdown(struct device *dev, int pnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct mmc_host *mmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (!mmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) mmc_remove_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) * Power down the SD/MMC function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (!pnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) wbsd_chip_poweroff(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) wbsd_release_resources(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) wbsd_free_mmc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) * Non-PnP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static int wbsd_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) /* Use the module parameters for resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) static int wbsd_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) wbsd_shutdown(&dev->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) * PnP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) int io, irq, dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) * Get resources from PnP layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) io = pnp_port_start(pnpdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) irq = pnp_irq(pnpdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (pnp_dma_valid(pnpdev, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) dma = pnp_dma(pnpdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) dma = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) static void wbsd_pnp_remove(struct pnp_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) wbsd_shutdown(&dev->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) * Power management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) static int wbsd_platform_suspend(struct platform_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) struct mmc_host *mmc = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) if (mmc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) DBGF("Suspending...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) wbsd_chip_poweroff(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) static int wbsd_platform_resume(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) struct mmc_host *mmc = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (mmc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) DBGF("Resuming...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) wbsd_chip_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * Allow device to initialise itself properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) wbsd_init_device(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (mmc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) DBGF("Suspending...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) struct wbsd_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) if (mmc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) DBGF("Resuming...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) * See if chip needs to be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) if (host->config != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) if (!wbsd_chip_validate(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) pr_warn(DRIVER_NAME ": PnP active but chip not configured! You probably have a buggy BIOS. Configuring chip manually.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) wbsd_chip_config(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * Allow device to initialise itself properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) wbsd_init_device(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) #else /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) #define wbsd_platform_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) #define wbsd_platform_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) #define wbsd_pnp_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) #define wbsd_pnp_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) static struct platform_device *wbsd_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) static struct platform_driver wbsd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) .probe = wbsd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) .remove = wbsd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) .suspend = wbsd_platform_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) .resume = wbsd_platform_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) .probe_type = PROBE_PREFER_ASYNCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) static struct pnp_driver wbsd_pnp_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) .id_table = pnp_dev_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) .probe = wbsd_pnp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) .remove = wbsd_pnp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) .suspend = wbsd_pnp_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) .resume = wbsd_pnp_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) * Module loading/unloading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) static int __init wbsd_drv_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) pr_info(DRIVER_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) ": Winbond W83L51xD SD/MMC card interface driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) if (!param_nopnp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) result = pnp_register_driver(&wbsd_pnp_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) if (param_nopnp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) result = platform_driver_register(&wbsd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) wbsd_device = platform_device_alloc(DRIVER_NAME, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (!wbsd_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) platform_driver_unregister(&wbsd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) result = platform_device_add(wbsd_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) platform_device_put(wbsd_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) platform_driver_unregister(&wbsd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) static void __exit wbsd_drv_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if (!param_nopnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) pnp_unregister_driver(&wbsd_pnp_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) if (param_nopnp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) platform_device_unregister(wbsd_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) platform_driver_unregister(&wbsd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) DBG("unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) module_init(wbsd_drv_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) module_exit(wbsd_drv_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) module_param_hw_named(nopnp, param_nopnp, uint, other, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) module_param_hw_named(io, param_io, uint, ioport, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) module_param_hw_named(irq, param_irq, uint, irq, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) module_param_hw_named(dma, param_dma, int, dma, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)");