Beispiel #1
0
static void wbsd_init_device(struct wbsd_host *host)
{
	u8 setup, ier;

	/*
	 * Reset chip (SD/MMC part) and fifo.
	 */
	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
	setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);

	/*
	 * Set DAT3 to input
	 */
	setup &= ~WBSD_DAT3_H;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
	host->flags &= ~WBSD_FIGNORE_DETECT;

	/*
	 * Read back default clock.
	 */
	host->clk = wbsd_read_index(host, WBSD_IDX_CLK);

	/*
	 * Power down port.
	 */
	outb(WBSD_POWER_N, host->base + WBSD_CSR);

	/*
	 * Set maximum timeout.
	 */
	wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);

	/*
	 * Test for card presence
	 */
	if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
		host->flags |= WBSD_FCARD_PRESENT;
	else
		host->flags &= ~WBSD_FCARD_PRESENT;

	/*
	 * Enable interesting interrupts.
	 */
	ier = 0;
	ier |= WBSD_EINT_CARD;
	ier |= WBSD_EINT_FIFO_THRE;
	ier |= WBSD_EINT_CRC;
	ier |= WBSD_EINT_TIMEOUT;
	ier |= WBSD_EINT_TC;

	outb(ier, host->base + WBSD_EIR);

	/*
	 * Clear interrupts.
	 */
	inb(host->base + WBSD_ISR);
}
Beispiel #2
0
static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq)
{
	unsigned long dmaflags;

	if (host->dma >= 0) {
		/*
		 * Release ISA DMA controller.
		 */
		dmaflags = claim_dma_lock();
		disable_dma(host->dma);
		clear_dma_ff(host->dma);
		release_dma_lock(dmaflags);

		/*
		 * Disable DMA on host.
		 */
		wbsd_write_index(host, WBSD_IDX_DMA, 0);
	}

	host->mrq = NULL;

	/*
	 * MMC layer might call back into the driver so first unlock.
	 */
	spin_unlock(&host->lock);
	mmc_request_done(host->mmc, mrq);
	spin_lock(&host->lock);
}
Beispiel #3
0
static void wbsd_tasklet_fifo(unsigned long param)
{
	struct wbsd_host* host = (struct wbsd_host*)param;
	struct mmc_data* data;
	
	spin_lock(&host->lock);
		
	if (!host->mrq)
		goto end;
	
	data = wbsd_get_data(host);
	if (!data)
		goto end;

	if (data->flags & MMC_DATA_WRITE)
		wbsd_fill_fifo(host);
	else
		wbsd_empty_fifo(host);

	/*
	 * Done?
	 */
	if (host->size == data->bytes_xfered)
	{
		wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
		tasklet_schedule(&host->finish_tasklet);
	}

end:	
	spin_unlock(&host->lock);
}
Beispiel #4
0
static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
	unsigned long dmaflags;
	int count;
	
	WARN_ON(host->mrq == NULL);

	/*
	 * Send a stop command if needed.
	 */
	if (data->stop)
		wbsd_send_command(host, data->stop);
	
	/*
	 * DMA transfer?
	 */
	if (host->dma >= 0)
	{
		/*
		 * Disable DMA on the host.
		 */
		wbsd_write_index(host, WBSD_IDX_DMA, 0);
		
		/*
		 * Turn of ISA DMA controller.
		 */
		dmaflags = claim_dma_lock();
		disable_dma(host->dma);
		clear_dma_ff(host->dma);
		count = get_dma_residue(host->dma);
		release_dma_lock(dmaflags);
		
		/*
		 * Any leftover data?
		 */
		if (count)
		{
			printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
				"transfer. %d bytes left.\n", count);
			
			data->error = MMC_ERR_FAILED;
		}
		else
		{
			/*
			 * Transfer data from DMA buffer to
			 * SG list.
			 */
			if (data->flags & MMC_DATA_READ)
				wbsd_dma_to_sg(host, data);
			
			data->bytes_xfered = host->size;
		}
	}
	
	DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
	
	wbsd_request_end(host, host->mrq);
}
Beispiel #5
0
static void wbsd_init_device(struct wbsd_host* host)
{
	u8 setup, ier;
	
	/*
	 * Reset chip (SD/MMC part) and fifo.
	 */
	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
	setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
	
	/*
	 * Read back default clock.
	 */
	host->clk = wbsd_read_index(host, WBSD_IDX_CLK);

	/*
	 * Power down port.
	 */
	outb(WBSD_POWER_N, host->base + WBSD_CSR);
	
	/*
	 * Set maximum timeout.
	 */
	wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
	
	/*
	 * Enable interesting interrupts.
	 */
	ier = 0;
	ier |= WBSD_EINT_CARD;
	ier |= WBSD_EINT_FIFO_THRE;
	ier |= WBSD_EINT_CCRC;
	ier |= WBSD_EINT_TIMEOUT;
	ier |= WBSD_EINT_CRC;
	ier |= WBSD_EINT_TC;

	outb(ier, host->base + WBSD_EIR);

	/*
	 * Clear interrupts.
	 */
	inb(host->base + WBSD_ISR);
}
Beispiel #6
0
static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
{
	u16 blksize;
	u8 setup;
	unsigned long dmaflags;
	unsigned int size;

	/*
	 * Calculate size.
	 */
	size = data->blocks * data->blksz;

	/*
	 * Check timeout values for overflow.
	 * (Yes, some cards cause this value to overflow).
	 */
	if (data->timeout_ns > 127000000)
		wbsd_write_index(host, WBSD_IDX_TAAC, 127);
	else {
		wbsd_write_index(host, WBSD_IDX_TAAC,
			data->timeout_ns / 1000000);
	}

	if (data->timeout_clks > 255)
		wbsd_write_index(host, WBSD_IDX_NSAC, 255);
	else
		wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);

	/*
	 * Inform the chip of how large blocks will be
	 * sent. It needs this to determine when to
	 * calculate CRC.
	 *
	 * Space for CRC must be included in the size.
	 * Two bytes are needed for each data line.
	 */
	if (host->bus_width == MMC_BUS_WIDTH_1) {
		blksize = data->blksz + 2;

		wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
		wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
	} else if (host->bus_width == MMC_BUS_WIDTH_4) {
Beispiel #7
0
static void wbsd_reset(struct wbsd_host *host)
{
	u8 setup;

	pr_err("%s: Resetting chip\n", mmc_hostname(host->mmc));

	/*
	 * Soft reset of chip (SD/MMC part).
	 */
	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
	setup |= WBSD_SOFT_RESET;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
}
Beispiel #8
0
static void wbsd_reset(struct wbsd_host* host)
{
	u8 setup;
	
	printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
	
	/*
	 * Soft reset of chip (SD/MMC part).
	 */
	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
	setup |= WBSD_SOFT_RESET;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
}
Beispiel #9
0
static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{
	struct wbsd_host* host = mmc_priv(mmc);
	u8 clk, setup, pwr;
	
	DBGF("clock %uHz busmode %u powermode %u Vdd %u\n",
		ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);

	spin_lock_bh(&host->lock);

	/*
	 * Reset the chip on each power off.
	 * Should clear out any weird states.
	 */
	if (ios->power_mode == MMC_POWER_OFF)
		wbsd_init_device(host);
	
	if (ios->clock >= 24000000)
		clk = WBSD_CLK_24M;
	else if (ios->clock >= 16000000)
		clk = WBSD_CLK_16M;
	else if (ios->clock >= 12000000)
		clk = WBSD_CLK_12M;
	else
		clk = WBSD_CLK_375K;

	/*
	 * Only write to the clock register when
	 * there is an actual change.
	 */
	if (clk != host->clk)
	{
		wbsd_write_index(host, WBSD_IDX_CLK, clk);
		host->clk = clk;
	}

	if (ios->power_mode != MMC_POWER_OFF)
	{
		/*
		 * Power up card.
		 */
		pwr = inb(host->base + WBSD_CSR);
		pwr &= ~WBSD_POWER_N;
		outb(pwr, host->base + WBSD_CSR);

		/*
		 * This behaviour is stolen from the
		 * Windows driver. Don't know why, but
		 * it is needed.
		 */
		setup = wbsd_read_index(host, WBSD_IDX_SETUP);
		if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
			setup |= WBSD_DAT3_H;
		else
			setup &= ~WBSD_DAT3_H;
		wbsd_write_index(host, WBSD_IDX_SETUP, setup);

		mdelay(1);
	}

	spin_unlock_bh(&host->lock);
}
Beispiel #10
0
static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
{
	u16 blksize;
	u8 setup;
	unsigned long dmaflags;

	DBGF("blksz %04x blks %04x flags %08x\n",
		data->blksz, data->blocks, data->flags);
	DBGF("tsac %d ms nsac %d clk\n",
		data->timeout_ns / 1000000, data->timeout_clks);
	
	/*
	 * Calculate size.
	 */
	host->size = data->blocks * data->blksz;

	/*
	 * Check timeout values for overflow.
	 * (Yes, some cards cause this value to overflow).
	 */
	if (data->timeout_ns > 127000000)
		wbsd_write_index(host, WBSD_IDX_TAAC, 127);
	else
		wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
	
	if (data->timeout_clks > 255)
		wbsd_write_index(host, WBSD_IDX_NSAC, 255);
	else
		wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
	
	/*
	 * Inform the chip of how large blocks will be
	 * sent. It needs this to determine when to
	 * calculate CRC.
	 *
	 * Space for CRC must be included in the size.
	 */
	blksize = data->blksz + 2;
	
	wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
	wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);

	/*
	 * Clear the FIFO. This is needed even for DMA
	 * transfers since the chip still uses the FIFO
	 * internally.
	 */
	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
	setup |= WBSD_FIFO_RESET;
	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
	
	/*
	 * DMA transfer?
	 */
	if (host->dma >= 0)
	{	
		/*
		 * The buffer for DMA is only 64 kB.
		 */
		BUG_ON(host->size > 0x10000);
		if (host->size > 0x10000)
		{
			data->error = MMC_ERR_INVALID;
			return;
		}
		
		/*
		 * Transfer data from the SG list to
		 * the DMA buffer.
		 */
		if (data->flags & MMC_DATA_WRITE)
			wbsd_sg_to_dma(host, data);
		
		/*
		 * Initialise the ISA DMA controller.
		 */	
		dmaflags = claim_dma_lock();
		disable_dma(host->dma);
		clear_dma_ff(host->dma);
		if (data->flags & MMC_DATA_READ)
			set_dma_mode(host->dma, DMA_MODE_READ);
		else
			set_dma_mode(host->dma, DMA_MODE_WRITE);
		set_dma_addr(host->dma, host->dma_addr);
		set_dma_count(host->dma, host->size);

		enable_dma(host->dma);
		release_dma_lock(dmaflags);

		/*
		 * Enable DMA on the host.
		 */
		wbsd_write_index(host, WBSD_IDX_DMA,
			WBSD_DMA_SINGLE | WBSD_DMA_ENABLE);
	}
	else
	{
		/*
		 * This flag is used to keep printk
		 * output to a minimum.
		 */
		host->firsterr = 1;
		
		/*
		 * Initialise the SG list.
		 */
		wbsd_init_sg(host, data);
	
		/*
		 * Turn off DMA.
		 */
		wbsd_write_index(host, WBSD_IDX_DMA, 0);
	
		/*
		 * Set up FIFO threshold levels (and fill
		 * buffer if doing a write).
		 */
		if (data->flags & MMC_DATA_READ)
		{
			wbsd_write_index(host, WBSD_IDX_FIFOEN,
				WBSD_FIFOEN_FULL | 8);
		}
		else
		{
			wbsd_write_index(host, WBSD_IDX_FIFOEN,
				WBSD_FIFOEN_EMPTY | 8);
			wbsd_fill_fifo(host);
		}
	}	
		
	data->error = MMC_ERR_NONE;
}