Commit bd6fe9e1 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-mmc

parents 862aad56 210ce2a7
...@@ -93,7 +93,7 @@ static int dma = 2; ...@@ -93,7 +93,7 @@ static int dma = 2;
static inline void wbsd_unlock_config(struct wbsd_host* host) static inline void wbsd_unlock_config(struct wbsd_host* host)
{ {
BUG_ON(host->config == 0); BUG_ON(host->config == 0);
outb(host->unlock_code, host->config); outb(host->unlock_code, host->config);
outb(host->unlock_code, host->config); outb(host->unlock_code, host->config);
} }
...@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host) ...@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
static inline void wbsd_lock_config(struct wbsd_host* host) static inline void wbsd_lock_config(struct wbsd_host* host)
{ {
BUG_ON(host->config == 0); BUG_ON(host->config == 0);
outb(LOCK_CODE, host->config); outb(LOCK_CODE, host->config);
} }
static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
{ {
BUG_ON(host->config == 0); BUG_ON(host->config == 0);
outb(reg, host->config); outb(reg, host->config);
outb(value, host->config + 1); outb(value, host->config + 1);
} }
...@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) ...@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
{ {
BUG_ON(host->config == 0); BUG_ON(host->config == 0);
outb(reg, host->config); outb(reg, host->config);
return inb(host->config + 1); return inb(host->config + 1);
} }
...@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index) ...@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
static void wbsd_init_device(struct wbsd_host* host) static void wbsd_init_device(struct wbsd_host* host)
{ {
u8 setup, ier; u8 setup, ier;
/* /*
* Reset chip (SD/MMC part) and fifo. * Reset chip (SD/MMC part) and fifo.
*/ */
setup = wbsd_read_index(host, WBSD_IDX_SETUP); setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET; setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
/* /*
* Set DAT3 to input * Set DAT3 to input
*/ */
setup &= ~WBSD_DAT3_H; setup &= ~WBSD_DAT3_H;
wbsd_write_index(host, WBSD_IDX_SETUP, setup); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
host->flags &= ~WBSD_FIGNORE_DETECT; host->flags &= ~WBSD_FIGNORE_DETECT;
/* /*
* Read back default clock. * Read back default clock.
*/ */
...@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host) ...@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
* Power down port. * Power down port.
*/ */
outb(WBSD_POWER_N, host->base + WBSD_CSR); outb(WBSD_POWER_N, host->base + WBSD_CSR);
/* /*
* Set maximum timeout. * Set maximum timeout.
*/ */
wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F); wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
/* /*
* Test for card presence * Test for card presence
*/ */
...@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host) ...@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
host->flags |= WBSD_FCARD_PRESENT; host->flags |= WBSD_FCARD_PRESENT;
else else
host->flags &= ~WBSD_FCARD_PRESENT; host->flags &= ~WBSD_FCARD_PRESENT;
/* /*
* Enable interesting interrupts. * Enable interesting interrupts.
*/ */
...@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host) ...@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
static void wbsd_reset(struct wbsd_host* host) static void wbsd_reset(struct wbsd_host* host)
{ {
u8 setup; u8 setup;
printk(KERN_ERR DRIVER_NAME ": Resetting chip\n"); printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
/* /*
* Soft reset of chip (SD/MMC part). * Soft reset of chip (SD/MMC part).
*/ */
...@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host) ...@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq) static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
{ {
unsigned long dmaflags; unsigned long dmaflags;
DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode); DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
if (host->dma >= 0) if (host->dma >= 0)
{ {
/* /*
...@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq) ...@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
*/ */
wbsd_write_index(host, WBSD_IDX_DMA, 0); wbsd_write_index(host, WBSD_IDX_DMA, 0);
} }
host->mrq = NULL; host->mrq = NULL;
/* /*
...@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host) ...@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
host->offset = 0; host->offset = 0;
host->remain = host->cur_sg->length; host->remain = host->cur_sg->length;
} }
return host->num_sg; return host->num_sg;
} }
...@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data) ...@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg; struct scatterlist* sg;
char* dmabuf = host->dma_buffer; char* dmabuf = host->dma_buffer;
char* sgbuf; char* sgbuf;
size = host->size; size = host->size;
sg = data->sg; sg = data->sg;
len = data->sg_len; len = data->sg_len;
/* /*
* Just loop through all entries. Size might not * Just loop through all entries. Size might not
* be the entire list though so make sure that * be the entire list though so make sure that
...@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data) ...@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
memcpy(dmabuf, sgbuf, sg[i].length); memcpy(dmabuf, sgbuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length; dmabuf += sg[i].length;
if (size < sg[i].length) if (size < sg[i].length)
size = 0; size = 0;
else else
size -= sg[i].length; size -= sg[i].length;
if (size == 0) if (size == 0)
break; break;
} }
/* /*
* Check that we didn't get a request to transfer * Check that we didn't get a request to transfer
* more data than can fit into the SG list. * more data than can fit into the SG list.
*/ */
BUG_ON(size != 0); BUG_ON(size != 0);
host->size -= size; host->size -= size;
} }
...@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data) ...@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg; struct scatterlist* sg;
char* dmabuf = host->dma_buffer; char* dmabuf = host->dma_buffer;
char* sgbuf; char* sgbuf;
size = host->size; size = host->size;
sg = data->sg; sg = data->sg;
len = data->sg_len; len = data->sg_len;
/* /*
* Just loop through all entries. Size might not * Just loop through all entries. Size might not
* be the entire list though so make sure that * be the entire list though so make sure that
...@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data) ...@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
memcpy(sgbuf, dmabuf, sg[i].length); memcpy(sgbuf, dmabuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length; dmabuf += sg[i].length;
if (size < sg[i].length) if (size < sg[i].length)
size = 0; size = 0;
else else
size -= sg[i].length; size -= sg[i].length;
if (size == 0) if (size == 0)
break; break;
} }
/* /*
* Check that we didn't get a request to transfer * Check that we didn't get a request to transfer
* more data than can fit into the SG list. * more data than can fit into the SG list.
*/ */
BUG_ON(size != 0); BUG_ON(size != 0);
host->size -= size; host->size -= size;
} }
/* /*
* Command handling * Command handling
*/ */
static inline void wbsd_get_short_reply(struct wbsd_host* host, static inline void wbsd_get_short_reply(struct wbsd_host* host,
struct mmc_command* cmd) struct mmc_command* cmd)
{ {
...@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host, ...@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID; cmd->error = MMC_ERR_INVALID;
return; return;
} }
cmd->resp[0] = cmd->resp[0] =
wbsd_read_index(host, WBSD_IDX_RESP12) << 24; wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
cmd->resp[0] |= cmd->resp[0] |=
...@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host, ...@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
struct mmc_command* cmd) struct mmc_command* cmd)
{ {
int i; int i;
/* /*
* Correct response type? * Correct response type?
*/ */
...@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host, ...@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID; cmd->error = MMC_ERR_INVALID;
return; return;
} }
for (i = 0;i < 4;i++) for (i = 0;i < 4;i++)
{ {
cmd->resp[i] = cmd->resp[i] =
...@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) ...@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
{ {
int i; int i;
u8 status, isr; u8 status, isr;
DBGF("Sending cmd (%x)\n", cmd->opcode); DBGF("Sending cmd (%x)\n", cmd->opcode);
/* /*
...@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) ...@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* transfer. * transfer.
*/ */
host->isr = 0; host->isr = 0;
/* /*
* Send the command (CRC calculated by host). * Send the command (CRC calculated by host).
*/ */
outb(cmd->opcode, host->base + WBSD_CMDR); outb(cmd->opcode, host->base + WBSD_CMDR);
for (i = 3;i >= 0;i--) for (i = 3;i >= 0;i--)
outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR); outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
cmd->error = MMC_ERR_NONE; cmd->error = MMC_ERR_NONE;
/* /*
* Wait for the request to complete. * Wait for the request to complete.
*/ */
...@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) ...@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Read back status. * Read back status.
*/ */
isr = host->isr; isr = host->isr;
/* Card removed? */ /* Card removed? */
if (isr & WBSD_INT_CARD) if (isr & WBSD_INT_CARD)
cmd->error = MMC_ERR_TIMEOUT; cmd->error = MMC_ERR_TIMEOUT;
...@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host) ...@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data; struct mmc_data* data = host->mrq->cmd->data;
char* buffer; char* buffer;
int i, fsr, fifo; int i, fsr, fifo;
/* /*
* Handle excessive data. * Handle excessive data.
*/ */
if (data->bytes_xfered == host->size) if (data->bytes_xfered == host->size)
return; return;
buffer = wbsd_kmap_sg(host) + host->offset; buffer = wbsd_kmap_sg(host) + host->offset;
/* /*
...@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host) ...@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/* /*
* The size field in the FSR is broken so we have to * The size field in the FSR is broken so we have to
* do some guessing. * do some guessing.
*/ */
if (fsr & WBSD_FIFO_FULL) if (fsr & WBSD_FIFO_FULL)
fifo = 16; fifo = 16;
else if (fsr & WBSD_FIFO_FUTHRE) else if (fsr & WBSD_FIFO_FUTHRE)
fifo = 8; fifo = 8;
else else
fifo = 1; fifo = 1;
for (i = 0;i < fifo;i++) for (i = 0;i < fifo;i++)
{ {
*buffer = inb(host->base + WBSD_DFR); *buffer = inb(host->base + WBSD_DFR);
...@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host) ...@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
host->remain--; host->remain--;
data->bytes_xfered++; data->bytes_xfered++;
/* /*
* Transfer done? * Transfer done?
*/ */
if (data->bytes_xfered == host->size) if (data->bytes_xfered == host->size)
{ {
wbsd_kunmap_sg(host); wbsd_kunmap_sg(host);
return; return;
} }
/* /*
* End of scatter list entry? * End of scatter list entry?
*/ */
if (host->remain == 0) if (host->remain == 0)
{ {
wbsd_kunmap_sg(host); wbsd_kunmap_sg(host);
/* /*
* Get next entry. Check if last. * Get next entry. Check if last.
*/ */
...@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host) ...@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* into the scatter list. * into the scatter list.
*/ */
BUG_ON(1); BUG_ON(1);
host->size = data->bytes_xfered; host->size = data->bytes_xfered;
return; return;
} }
buffer = wbsd_kmap_sg(host); buffer = wbsd_kmap_sg(host);
} }
} }
} }
wbsd_kunmap_sg(host); wbsd_kunmap_sg(host);
/* /*
...@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) ...@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data; struct mmc_data* data = host->mrq->cmd->data;
char* buffer; char* buffer;
int i, fsr, fifo; int i, fsr, fifo;
/* /*
* Check that we aren't being called after the * Check that we aren't being called after the
* entire buffer has been transfered. * entire buffer has been transfered.
...@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) ...@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/* /*
* The size field in the FSR is broken so we have to * The size field in the FSR is broken so we have to
* do some guessing. * do some guessing.
*/ */
if (fsr & WBSD_FIFO_EMPTY) if (fsr & WBSD_FIFO_EMPTY)
fifo = 0; fifo = 0;
else if (fsr & WBSD_FIFO_EMTHRE) else if (fsr & WBSD_FIFO_EMTHRE)
...@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host) ...@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
buffer++; buffer++;
host->offset++; host->offset++;
host->remain--; host->remain--;
data->bytes_xfered++; data->bytes_xfered++;
/* /*
* Transfer done? * Transfer done?
*/ */
...@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) ...@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
if (host->remain == 0) if (host->remain == 0)
{ {
wbsd_kunmap_sg(host); wbsd_kunmap_sg(host);
/* /*
* Get next entry. Check if last. * Get next entry. Check if last.
*/ */
...@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host) ...@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* into the scatter list. * into the scatter list.
*/ */
BUG_ON(1); BUG_ON(1);
host->size = data->bytes_xfered; host->size = data->bytes_xfered;
return; return;
} }
buffer = wbsd_kmap_sg(host); buffer = wbsd_kmap_sg(host);
} }
} }
} }
wbsd_kunmap_sg(host); wbsd_kunmap_sg(host);
/* /*
* The controller stops sending interrupts for * The controller stops sending interrupts for
* 'FIFO empty' under certain conditions. So we * 'FIFO empty' under certain conditions. So we
...@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
1 << data->blksz_bits, data->blocks, data->flags); 1 << data->blksz_bits, data->blocks, data->flags);
DBGF("tsac %d ms nsac %d clk\n", DBGF("tsac %d ms nsac %d clk\n",
data->timeout_ns / 1000000, data->timeout_clks); data->timeout_ns / 1000000, data->timeout_clks);
/* /*
* Calculate size. * Calculate size.
*/ */
...@@ -708,12 +708,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -708,12 +708,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
wbsd_write_index(host, WBSD_IDX_TAAC, 127); wbsd_write_index(host, WBSD_IDX_TAAC, 127);
else else
wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000); wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
if (data->timeout_clks > 255) if (data->timeout_clks > 255)
wbsd_write_index(host, WBSD_IDX_NSAC, 255); wbsd_write_index(host, WBSD_IDX_NSAC, 255);
else else
wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks); wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
/* /*
* Inform the chip of how large blocks will be * Inform the chip of how large blocks will be
* sent. It needs this to determine when to * sent. It needs this to determine when to
...@@ -732,7 +732,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -732,7 +732,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
else if (host->bus_width == MMC_BUS_WIDTH_4) else if (host->bus_width == MMC_BUS_WIDTH_4)
{ {
blksize = (1 << data->blksz_bits) + 2 * 4; blksize = (1 << data->blksz_bits) + 2 * 4;
wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0) wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
| WBSD_DATA_WIDTH); | WBSD_DATA_WIDTH);
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
...@@ -751,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -751,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
setup = wbsd_read_index(host, WBSD_IDX_SETUP); setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET; setup |= WBSD_FIFO_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
/* /*
* DMA transfer? * DMA transfer?
*/ */
if (host->dma >= 0) if (host->dma >= 0)
{ {
/* /*
* The buffer for DMA is only 64 kB. * The buffer for DMA is only 64 kB.
*/ */
...@@ -766,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -766,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data->error = MMC_ERR_INVALID; data->error = MMC_ERR_INVALID;
return; return;
} }
/* /*
* Transfer data from the SG list to * Transfer data from the SG list to
* the DMA buffer. * the DMA buffer.
*/ */
if (data->flags & MMC_DATA_WRITE) if (data->flags & MMC_DATA_WRITE)
wbsd_sg_to_dma(host, data); wbsd_sg_to_dma(host, data);
/* /*
* Initialise the ISA DMA controller. * Initialise the ISA DMA controller.
*/ */
dmaflags = claim_dma_lock(); dmaflags = claim_dma_lock();
disable_dma(host->dma); disable_dma(host->dma);
clear_dma_ff(host->dma); clear_dma_ff(host->dma);
...@@ -802,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -802,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* output to a minimum. * output to a minimum.
*/ */
host->firsterr = 1; host->firsterr = 1;
/* /*
* Initialise the SG list. * Initialise the SG list.
*/ */
wbsd_init_sg(host, data); wbsd_init_sg(host, data);
/* /*
* Turn off DMA. * Turn off DMA.
*/ */
wbsd_write_index(host, WBSD_IDX_DMA, 0); wbsd_write_index(host, WBSD_IDX_DMA, 0);
/* /*
* Set up FIFO threshold levels (and fill * Set up FIFO threshold levels (and fill
* buffer if doing a write). * buffer if doing a write).
...@@ -828,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -828,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
WBSD_FIFOEN_EMPTY | 8); WBSD_FIFOEN_EMPTY | 8);
wbsd_fill_fifo(host); wbsd_fill_fifo(host);
} }
} }
data->error = MMC_ERR_NONE; data->error = MMC_ERR_NONE;
} }
...@@ -838,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -838,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
unsigned long dmaflags; unsigned long dmaflags;
int count; int count;
u8 status; u8 status;
WARN_ON(host->mrq == NULL); WARN_ON(host->mrq == NULL);
/* /*
...@@ -855,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -855,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{ {
status = wbsd_read_index(host, WBSD_IDX_STATUS); status = wbsd_read_index(host, WBSD_IDX_STATUS);
} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE)); } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
/* /*
* DMA transfer? * DMA transfer?
*/ */
...@@ -865,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -865,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Disable DMA on the host. * Disable DMA on the host.
*/ */
wbsd_write_index(host, WBSD_IDX_DMA, 0); wbsd_write_index(host, WBSD_IDX_DMA, 0);
/* /*
* Turn of ISA DMA controller. * Turn of ISA DMA controller.
*/ */
...@@ -874,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -874,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
clear_dma_ff(host->dma); clear_dma_ff(host->dma);
count = get_dma_residue(host->dma); count = get_dma_residue(host->dma);
release_dma_lock(dmaflags); release_dma_lock(dmaflags);
/* /*
* Any leftover data? * Any leftover data?
*/ */
...@@ -882,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -882,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{ {
printk(KERN_ERR DRIVER_NAME ": Incomplete DMA " printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
"transfer. %d bytes left.\n", count); "transfer. %d bytes left.\n", count);
data->error = MMC_ERR_FAILED; data->error = MMC_ERR_FAILED;
} }
else else
...@@ -893,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) ...@@ -893,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
*/ */
if (data->flags & MMC_DATA_READ) if (data->flags & MMC_DATA_READ)
wbsd_dma_to_sg(host, data); wbsd_dma_to_sg(host, data);
data->bytes_xfered = host->size; data->bytes_xfered = host->size;
} }
} }
DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered); DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
wbsd_request_end(host, host->mrq); wbsd_request_end(host, host->mrq);
} }
...@@ -924,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) ...@@ -924,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
cmd = mrq->cmd; cmd = mrq->cmd;
host->mrq = mrq; host->mrq = mrq;
/* /*
* If there is no card in the slot then * If there is no card in the slot then
* timeout immediatly. * timeout immediatly.
...@@ -941,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) ...@@ -941,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
if (cmd->data) if (cmd->data)
{ {
wbsd_prepare_data(host, cmd->data); wbsd_prepare_data(host, cmd->data);
if (cmd->data->error != MMC_ERR_NONE) if (cmd->data->error != MMC_ERR_NONE)
goto done; goto done;
} }
wbsd_send_command(host, cmd); wbsd_send_command(host, cmd);
/* /*
* If this is a data transfer the request * If this is a data transfer the request
* will be finished after the data has * will be finished after the data has
* transfered. * transfered.
*/ */
if (cmd->data && (cmd->error == MMC_ERR_NONE)) if (cmd->data && (cmd->error == MMC_ERR_NONE))
{ {
/* /*
...@@ -965,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) ...@@ -965,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
return; return;
} }
done: done:
wbsd_request_end(host, mrq); wbsd_request_end(host, mrq);
...@@ -976,7 +976,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -976,7 +976,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{ {
struct wbsd_host* host = mmc_priv(mmc); struct wbsd_host* host = mmc_priv(mmc);
u8 clk, setup, pwr; u8 clk, setup, pwr;
DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
ios->vdd, ios->bus_width); ios->vdd, ios->bus_width);
...@@ -989,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -989,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
*/ */
if (ios->power_mode == MMC_POWER_OFF) if (ios->power_mode == MMC_POWER_OFF)
wbsd_init_device(host); wbsd_init_device(host);
if (ios->clock >= 24000000) if (ios->clock >= 24000000)
clk = WBSD_CLK_24M; clk = WBSD_CLK_24M;
else if (ios->clock >= 16000000) else if (ios->clock >= 16000000)
...@@ -1042,7 +1042,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -1042,7 +1042,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
mod_timer(&host->ignore_timer, jiffies + HZ/100); mod_timer(&host->ignore_timer, jiffies + HZ/100);
} }
wbsd_write_index(host, WBSD_IDX_SETUP, setup); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
/* /*
* Store bus width for later. Will be used when * Store bus width for later. Will be used when
* setting up the data transfer. * setting up the data transfer.
...@@ -1128,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host) ...@@ -1128,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
WARN_ON(!host->mrq->cmd->data); WARN_ON(!host->mrq->cmd->data);
if (!host->mrq->cmd->data) if (!host->mrq->cmd->data)
return NULL; return NULL;
return host->mrq->cmd->data; return host->mrq->cmd->data;
} }
...@@ -1136,72 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1136,72 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr; u8 csr;
int delay = -1;
spin_lock(&host->lock); spin_lock(&host->lock);
if (host->flags & WBSD_FIGNORE_DETECT) if (host->flags & WBSD_FIGNORE_DETECT)
{ {
spin_unlock(&host->lock); spin_unlock(&host->lock);
return; return;
} }
csr = inb(host->base + WBSD_CSR); csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff); WARN_ON(csr == 0xff);
if (csr & WBSD_CARDPRESENT) if (csr & WBSD_CARDPRESENT)
{ {
if (!(host->flags & WBSD_FCARD_PRESENT)) if (!(host->flags & WBSD_FCARD_PRESENT))
{ {
DBG("Card inserted\n"); DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT; host->flags |= WBSD_FCARD_PRESENT;
spin_unlock(&host->lock);
/* delay = 500;
* Delay card detection to allow electrical connections
* to stabilise.
*/
mmc_detect_change(host->mmc, msecs_to_jiffies(500));
} }
else
spin_unlock(&host->lock);
} }
else if (host->flags & WBSD_FCARD_PRESENT) else if (host->flags & WBSD_FCARD_PRESENT)
{ {
DBG("Card removed\n"); DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT; host->flags &= ~WBSD_FCARD_PRESENT;
if (host->mrq) if (host->mrq)
{ {
printk(KERN_ERR DRIVER_NAME printk(KERN_ERR DRIVER_NAME
": Card removed during transfer!\n"); ": Card removed during transfer!\n");
wbsd_reset(host); wbsd_reset(host);
host->mrq->cmd->error = MMC_ERR_FAILED; host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
} }
/*
* Unlock first since we might get a call back.
*/
spin_unlock(&host->lock);
mmc_detect_change(host->mmc, 0); delay = 0;
} }
else
spin_unlock(&host->lock); /*
* Unlock first since we might get a call back.
*/
spin_unlock(&host->lock);
if (delay != -1)
mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
} }
static void wbsd_tasklet_fifo(unsigned long param) static void wbsd_tasklet_fifo(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data; struct mmc_data* data;
spin_lock(&host->lock); spin_lock(&host->lock);
if (!host->mrq) if (!host->mrq)
goto end; goto end;
data = wbsd_get_data(host); data = wbsd_get_data(host);
if (!data) if (!data)
goto end; goto end;
...@@ -1220,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param) ...@@ -1220,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
} }
end: end:
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
...@@ -1228,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param) ...@@ -1228,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data; struct mmc_data* data;
spin_lock(&host->lock); spin_lock(&host->lock);
if (!host->mrq) if (!host->mrq)
goto end; goto end;
data = wbsd_get_data(host); data = wbsd_get_data(host);
if (!data) if (!data)
goto end; goto end;
DBGF("CRC error\n"); DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC; data->error = MMC_ERR_BADCRC;
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
end: end:
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
...@@ -1252,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param) ...@@ -1252,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data; struct mmc_data* data;
spin_lock(&host->lock); spin_lock(&host->lock);
if (!host->mrq) if (!host->mrq)
goto end; goto end;
data = wbsd_get_data(host); data = wbsd_get_data(host);
if (!data) if (!data)
goto end; goto end;
DBGF("Timeout\n"); DBGF("Timeout\n");
data->error = MMC_ERR_TIMEOUT; data->error = MMC_ERR_TIMEOUT;
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
end: end:
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
...@@ -1276,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param) ...@@ -1276,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data; struct mmc_data* data;
spin_lock(&host->lock); spin_lock(&host->lock);
WARN_ON(!host->mrq); WARN_ON(!host->mrq);
if (!host->mrq) if (!host->mrq)
goto end; goto end;
data = wbsd_get_data(host); data = wbsd_get_data(host);
if (!data) if (!data)
goto end; goto end;
wbsd_finish_data(host, data); wbsd_finish_data(host, data);
end: end:
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
...@@ -1297,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param) ...@@ -1297,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data; struct mmc_data* data;
spin_lock(&host->lock); spin_lock(&host->lock);
if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) != if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
...@@ -1306,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param) ...@@ -1306,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param)
data = wbsd_get_data(host); data = wbsd_get_data(host);
if (!data) if (!data)
goto end; goto end;
DBGF("CRC error\n"); DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC; data->error = MMC_ERR_BADCRC;
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
} }
end: end:
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
...@@ -1326,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1326,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct wbsd_host* host = dev_id; struct wbsd_host* host = dev_id;
int isr; int isr;
isr = inb(host->base + WBSD_ISR); isr = inb(host->base + WBSD_ISR);
/* /*
...@@ -1334,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1334,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
*/ */
if (isr == 0xff || isr == 0x00) if (isr == 0xff || isr == 0x00)
return IRQ_NONE; return IRQ_NONE;
host->isr |= isr; host->isr |= isr;
/* /*
...@@ -1352,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1352,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
tasklet_hi_schedule(&host->block_tasklet); tasklet_hi_schedule(&host->block_tasklet);
if (isr & WBSD_INT_TC) if (isr & WBSD_INT_TC)
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1370,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) ...@@ -1370,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
{ {
struct mmc_host* mmc; struct mmc_host* mmc;
struct wbsd_host* host; struct wbsd_host* host;
/* /*
* Allocate MMC structure. * Allocate MMC structure.
*/ */
mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
if (!mmc) if (!mmc)
return -ENOMEM; return -ENOMEM;
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; host->mmc = mmc;
...@@ -1391,37 +1386,37 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) ...@@ -1391,37 +1386,37 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc->f_max = 24000000; mmc->f_max = 24000000;
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
mmc->caps = MMC_CAP_4_BIT_DATA; mmc->caps = MMC_CAP_4_BIT_DATA;
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
/* /*
* Set up timers * Set up timers
*/ */
init_timer(&host->ignore_timer); init_timer(&host->ignore_timer);
host->ignore_timer.data = (unsigned long)host; host->ignore_timer.data = (unsigned long)host;
host->ignore_timer.function = wbsd_reset_ignore; host->ignore_timer.function = wbsd_reset_ignore;
/* /*
* Maximum number of segments. Worst case is one sector per segment * Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512. * so this will be 64kB/512.
*/ */
mmc->max_hw_segs = 128; mmc->max_hw_segs = 128;
mmc->max_phys_segs = 128; mmc->max_phys_segs = 128;
/* /*
* Maximum number of sectors in one transfer. Also limited by 64kB * Maximum number of sectors in one transfer. Also limited by 64kB
* buffer. * buffer.
*/ */
mmc->max_sectors = 128; mmc->max_sectors = 128;
/* /*
* Maximum segment size. Could be one segment with the maximum number * Maximum segment size. Could be one segment with the maximum number
* of segments. * of segments.
*/ */
mmc->max_seg_size = mmc->max_sectors * 512; mmc->max_seg_size = mmc->max_sectors * 512;
dev_set_drvdata(dev, mmc); dev_set_drvdata(dev, mmc);
return 0; return 0;
} }
...@@ -1429,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev) ...@@ -1429,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
{ {
struct mmc_host* mmc; struct mmc_host* mmc;
struct wbsd_host* host; struct wbsd_host* host;
mmc = dev_get_drvdata(dev); mmc = dev_get_drvdata(dev);
if (!mmc) if (!mmc)
return; return;
host = mmc_priv(mmc); host = mmc_priv(mmc);
BUG_ON(host == NULL); BUG_ON(host == NULL);
del_timer_sync(&host->ignore_timer); del_timer_sync(&host->ignore_timer);
mmc_free_host(mmc); mmc_free_host(mmc);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
} }
...@@ -1452,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1452,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{ {
int i, j, k; int i, j, k;
int id; int id;
/* /*
* Iterate through all ports, all codes to * Iterate through all ports, all codes to
* find hardware that is in our known list. * find hardware that is in our known list.
...@@ -1461,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1461,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{ {
if (!request_region(config_ports[i], 2, DRIVER_NAME)) if (!request_region(config_ports[i], 2, DRIVER_NAME))
continue; continue;
for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++) for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
{ {
id = 0xFFFF; id = 0xFFFF;
outb(unlock_codes[j], config_ports[i]); outb(unlock_codes[j], config_ports[i]);
outb(unlock_codes[j], config_ports[i]); outb(unlock_codes[j], config_ports[i]);
outb(WBSD_CONF_ID_HI, config_ports[i]); outb(WBSD_CONF_ID_HI, config_ports[i]);
id = inb(config_ports[i] + 1) << 8; id = inb(config_ports[i] + 1) << 8;
outb(WBSD_CONF_ID_LO, config_ports[i]); outb(WBSD_CONF_ID_LO, config_ports[i]);
id |= inb(config_ports[i] + 1); id |= inb(config_ports[i] + 1);
for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++) for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
{ {
if (id == valid_ids[k]) if (id == valid_ids[k])
{ {
host->chip_id = id; host->chip_id = id;
host->config = config_ports[i]; host->config = config_ports[i];
host->unlock_code = unlock_codes[i]; host->unlock_code = unlock_codes[i];
return 0; return 0;
} }
} }
if (id != 0xFFFF) if (id != 0xFFFF)
{ {
DBG("Unknown hardware (id %x) found at %x\n", DBG("Unknown hardware (id %x) found at %x\n",
...@@ -1495,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1495,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
outb(LOCK_CODE, config_ports[i]); outb(LOCK_CODE, config_ports[i]);
} }
release_region(config_ports[i], 2); release_region(config_ports[i], 2);
} }
return -ENODEV; return -ENODEV;
} }
...@@ -1510,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base) ...@@ -1510,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
{ {
if (io & 0x7) if (io & 0x7)
return -EINVAL; return -EINVAL;
if (!request_region(base, 8, DRIVER_NAME)) if (!request_region(base, 8, DRIVER_NAME))
return -EIO; return -EIO;
host->base = io; host->base = io;
return 0; return 0;
} }
...@@ -1523,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host) ...@@ -1523,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
{ {
if (host->base) if (host->base)
release_region(host->base, 8); release_region(host->base, 8);
host->base = 0; host->base = 0;
if (host->config) if (host->config)
release_region(host->config, 2); release_region(host->config, 2);
host->config = 0; host->config = 0;
} }
...@@ -1540,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) ...@@ -1540,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
{ {
if (dma < 0) if (dma < 0)
return; return;
if (request_dma(dma, DRIVER_NAME)) if (request_dma(dma, DRIVER_NAME))
goto err; goto err;
/* /*
* We need to allocate a special buffer in * We need to allocate a special buffer in
* order for ISA to be able to DMA to it. * order for ISA to be able to DMA to it.
...@@ -1558,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) ...@@ -1558,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
*/ */
host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer, host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
/* /*
* ISA DMA must be aligned on a 64k basis. * ISA DMA must be aligned on a 64k basis.
*/ */
...@@ -1571,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) ...@@ -1571,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
goto kfree; goto kfree;
host->dma = dma; host->dma = dma;
return; return;
kfree: kfree:
/* /*
* If we've gotten here then there is some kind of alignment bug * If we've gotten here then there is some kind of alignment bug
*/ */
BUG_ON(1); BUG_ON(1);
dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL; host->dma_addr = (dma_addr_t)NULL;
kfree(host->dma_buffer); kfree(host->dma_buffer);
host->dma_buffer = NULL; host->dma_buffer = NULL;
...@@ -1604,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host) ...@@ -1604,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
kfree(host->dma_buffer); kfree(host->dma_buffer);
if (host->dma >= 0) if (host->dma >= 0)
free_dma(host->dma); free_dma(host->dma);
host->dma = -1; host->dma = -1;
host->dma_buffer = NULL; host->dma_buffer = NULL;
host->dma_addr = (dma_addr_t)NULL; host->dma_addr = (dma_addr_t)NULL;
...@@ -1617,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host) ...@@ -1617,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
{ {
int ret; int ret;
/* /*
* Allocate interrupt. * Allocate interrupt.
*/ */
...@@ -1625,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) ...@@ -1625,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
if (ret) if (ret)
return ret; return ret;
host->irq = irq; host->irq = irq;
/* /*
...@@ -1637,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) ...@@ -1637,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
return 0; return 0;
} }
...@@ -1647,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host) ...@@ -1647,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
return; return;
free_irq(host->irq, host); free_irq(host->irq, host);
host->irq = 0; host->irq = 0;
tasklet_kill(&host->card_tasklet); tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->fifo_tasklet); tasklet_kill(&host->fifo_tasklet);
tasklet_kill(&host->crc_tasklet); tasklet_kill(&host->crc_tasklet);
...@@ -1666,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host, ...@@ -1666,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
int base, int irq, int dma) int base, int irq, int dma)
{ {
int ret; int ret;
/* /*
* Allocate I/O ports. * Allocate I/O ports.
*/ */
...@@ -1685,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host, ...@@ -1685,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Allocate DMA. * Allocate DMA.
*/ */
wbsd_request_dma(host, dma); wbsd_request_dma(host, dma);
return 0; return 0;
} }
...@@ -1708,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) ...@@ -1708,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
{ {
/* /*
* Reset the chip. * Reset the chip.
*/ */
wbsd_write_config(host, WBSD_CONF_SWRST, 1); wbsd_write_config(host, WBSD_CONF_SWRST, 1);
wbsd_write_config(host, WBSD_CONF_SWRST, 0); wbsd_write_config(host, WBSD_CONF_SWRST, 0);
...@@ -1716,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) ...@@ -1716,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
* Select SD/MMC function. * Select SD/MMC function.
*/ */
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
/* /*
* Set up card detection. * Set up card detection.
*/ */
wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11); wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
/* /*
* Configure chip * Configure chip
*/ */
wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8); wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff); wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
if (host->dma >= 0) if (host->dma >= 0)
wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
/* /*
* Enable and power up chip. * Enable and power up chip.
*/ */
...@@ -1743,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) ...@@ -1743,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
/* /*
* Check that configured resources are correct. * Check that configured resources are correct.
*/ */
static int __devinit wbsd_chip_validate(struct wbsd_host* host) static int __devinit wbsd_chip_validate(struct wbsd_host* host)
{ {
int base, irq, dma; int base, irq, dma;
/* /*
* Select SD/MMC function. * Select SD/MMC function.
*/ */
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
/* /*
* Read configuration. * Read configuration.
*/ */
base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8; base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
base |= wbsd_read_config(host, WBSD_CONF_PORT_LO); base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
irq = wbsd_read_config(host, WBSD_CONF_IRQ); irq = wbsd_read_config(host, WBSD_CONF_IRQ);
dma = wbsd_read_config(host, WBSD_CONF_DRQ); dma = wbsd_read_config(host, WBSD_CONF_DRQ);
/* /*
* Validate against given configuration. * Validate against given configuration.
*/ */
...@@ -1772,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host) ...@@ -1772,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
return 0; return 0;
if ((dma != host->dma) && (host->dma != -1)) if ((dma != host->dma) && (host->dma != -1))
return 0; return 0;
return 1; return 1;
} }
...@@ -1788,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1788,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
struct wbsd_host* host = NULL; struct wbsd_host* host = NULL;
struct mmc_host* mmc = NULL; struct mmc_host* mmc = NULL;
int ret; int ret;
ret = wbsd_alloc_mmc(dev); ret = wbsd_alloc_mmc(dev);
if (ret) if (ret)
return ret; return ret;
mmc = dev_get_drvdata(dev); mmc = dev_get_drvdata(dev);
host = mmc_priv(mmc); host = mmc_priv(mmc);
/* /*
* Scan for hardware. * Scan for hardware.
*/ */
...@@ -1814,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1814,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return ret; return ret;
} }
} }
/* /*
* Request resources. * Request resources.
*/ */
...@@ -1825,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1825,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
wbsd_free_mmc(dev); wbsd_free_mmc(dev);
return ret; return ret;
} }
/* /*
* See if chip needs to be configured. * See if chip needs to be configured.
*/ */
...@@ -1842,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1842,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
} }
else else
wbsd_chip_config(host); wbsd_chip_config(host);
/* /*
* Power Management stuff. No idea how this works. * Power Management stuff. No idea how this works.
* Not tested. * Not tested.
...@@ -1860,7 +1855,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1860,7 +1855,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Reset the chip into a known state. * Reset the chip into a known state.
*/ */
wbsd_init_device(host); wbsd_init_device(host);
mmc_add_host(mmc); mmc_add_host(mmc);
printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc)); printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
...@@ -1882,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp) ...@@ -1882,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
{ {
struct mmc_host* mmc = dev_get_drvdata(dev); struct mmc_host* mmc = dev_get_drvdata(dev);
struct wbsd_host* host; struct wbsd_host* host;
if (!mmc) if (!mmc)
return; return;
host = mmc_priv(mmc); host = mmc_priv(mmc);
mmc_remove_host(mmc); mmc_remove_host(mmc);
if (!pnp) if (!pnp)
...@@ -1900,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp) ...@@ -1900,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
wbsd_write_config(host, WBSD_CONF_ENABLE, 0); wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
wbsd_lock_config(host); wbsd_lock_config(host);
} }
wbsd_release_resources(host); wbsd_release_resources(host);
wbsd_free_mmc(dev); wbsd_free_mmc(dev);
} }
...@@ -1932,7 +1927,7 @@ static int __devinit ...@@ -1932,7 +1927,7 @@ static int __devinit
wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
{ {
int io, irq, dma; int io, irq, dma;
/* /*
* Get resources from PnP layer. * Get resources from PnP layer.
*/ */
...@@ -1942,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) ...@@ -1942,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
dma = pnp_dma(pnpdev, 0); dma = pnp_dma(pnpdev, 0);
else else
dma = -1; dma = -1;
DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma); DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
return wbsd_init(&pnpdev->dev, io, irq, dma, 1); return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
} }
...@@ -1985,7 +1980,7 @@ static struct device_driver wbsd_driver = { ...@@ -1985,7 +1980,7 @@ static struct device_driver wbsd_driver = {
.bus = &platform_bus_type, .bus = &platform_bus_type,
.probe = wbsd_probe, .probe = wbsd_probe,
.remove = wbsd_remove, .remove = wbsd_remove,
.suspend = wbsd_suspend, .suspend = wbsd_suspend,
.resume = wbsd_resume, .resume = wbsd_resume,
}; };
...@@ -2008,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = { ...@@ -2008,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = {
static int __init wbsd_drv_init(void) static int __init wbsd_drv_init(void)
{ {
int result; int result;
printk(KERN_INFO DRIVER_NAME printk(KERN_INFO DRIVER_NAME
": Winbond W83L51xD SD/MMC card interface driver, " ": Winbond W83L51xD SD/MMC card interface driver, "
DRIVER_VERSION "\n"); DRIVER_VERSION "\n");
...@@ -2023,8 +2018,8 @@ static int __init wbsd_drv_init(void) ...@@ -2023,8 +2018,8 @@ static int __init wbsd_drv_init(void)
return result; return result;
} }
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
if (nopnp) if (nopnp)
{ {
result = driver_register(&wbsd_driver); result = driver_register(&wbsd_driver);
...@@ -2046,13 +2041,13 @@ static void __exit wbsd_drv_exit(void) ...@@ -2046,13 +2041,13 @@ static void __exit wbsd_drv_exit(void)
if (!nopnp) if (!nopnp)
pnp_unregister_driver(&wbsd_pnp_driver); pnp_unregister_driver(&wbsd_pnp_driver);
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
if (nopnp) if (nopnp)
{ {
platform_device_unregister(wbsd_device); platform_device_unregister(wbsd_device);
driver_unregister(&wbsd_driver); driver_unregister(&wbsd_driver);
} }
......
...@@ -139,51 +139,50 @@ ...@@ -139,51 +139,50 @@
struct wbsd_host struct wbsd_host
{ {
struct mmc_host* mmc; /* MMC structure */ struct mmc_host* mmc; /* MMC structure */
spinlock_t lock; /* Mutex */ spinlock_t lock; /* Mutex */
int flags; /* Driver states */ int flags; /* Driver states */
#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */ #define WBSD_FCARD_PRESENT (1<<0) /* Card is present */
#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */ #define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */
struct mmc_request* mrq; /* Current request */ struct mmc_request* mrq; /* Current request */
u8 isr; /* Accumulated ISR */ u8 isr; /* Accumulated ISR */
struct scatterlist* cur_sg; /* Current SG entry */ struct scatterlist* cur_sg; /* Current SG entry */
unsigned int num_sg; /* Number of entries left */ unsigned int num_sg; /* Number of entries left */
void* mapped_sg; /* vaddr of mapped sg */ void* mapped_sg; /* vaddr of mapped sg */
unsigned int offset; /* Offset into current entry */ unsigned int offset; /* Offset into current entry */
unsigned int remain; /* Data left in curren entry */ unsigned int remain; /* Data left in curren entry */
int size; /* Total size of transfer */ int size; /* Total size of transfer */
char* dma_buffer; /* ISA DMA buffer */ char* dma_buffer; /* ISA DMA buffer */
dma_addr_t dma_addr; /* Physical address for same */ dma_addr_t dma_addr; /* Physical address for same */
int firsterr; /* See fifo functions */ int firsterr; /* See fifo functions */
u8 clk; /* Current clock speed */ u8 clk; /* Current clock speed */
unsigned char bus_width; /* Current bus width */ unsigned char bus_width; /* Current bus width */
int config; /* Config port */ int config; /* Config port */
u8 unlock_code; /* Code to unlock config */ u8 unlock_code; /* Code to unlock config */
int chip_id; /* ID of controller */ int chip_id; /* ID of controller */
int base; /* I/O port base */ int base; /* I/O port base */
int irq; /* Interrupt */ int irq; /* Interrupt */
int dma; /* DMA channel */ int dma; /* DMA channel */
struct tasklet_struct card_tasklet; /* Tasklet structures */ struct tasklet_struct card_tasklet; /* Tasklet structures */
struct tasklet_struct fifo_tasklet; struct tasklet_struct fifo_tasklet;
struct tasklet_struct crc_tasklet; struct tasklet_struct crc_tasklet;
struct tasklet_struct timeout_tasklet; struct tasklet_struct timeout_tasklet;
struct tasklet_struct finish_tasklet; struct tasklet_struct finish_tasklet;
struct tasklet_struct block_tasklet; struct tasklet_struct block_tasklet;
struct timer_list detect_timer; /* Card detection timer */
struct timer_list ignore_timer; /* Ignore detection timer */ struct timer_list ignore_timer; /* Ignore detection timer */
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment