コード例 #1
0
static void dw_writer(struct dw_spi *dws)
{
	u32 max = tx_max(dws);
	u16 txw = 0;	
	
	DBG_SPI("%dbyte tx:",dws->n_bytes);
	while (max--) {
		/* Set the tx word if the transfer's original "tx" is not null */
		if (dws->tx_end - dws->len) {
			if (dws->n_bytes == 1)
			{
				txw = *(u8 *)(dws->tx);	
				DBG_SPI("0x%02x,", *(u8 *)(dws->tx));
			}
			else
			{
				txw = *(u16 *)(dws->tx);
				DBG_SPI("0x%02x,", *(u16 *)(dws->tx));
			}
		}
		dw_writew(dws, SPIM_TXDR, txw);
		dws->tx += dws->n_bytes;
	}
	
	//it is neccessary
	wait_till_not_busy(dws);
	
	DBG_SPI("\n");
}
コード例 #2
0
static ssize_t spi_write_proc_data(struct file *file, const char __user *buffer,
			   size_t count, loff_t *data)
{	
	struct dw_spi *dws;
	char *buf;
	ssize_t ret;
	int reg = 0,value = 0;
	
	dws = file->private_data;

	buf = kzalloc(32, GFP_KERNEL);
	if (!buf)
	return 0;
	
	ret = copy_from_user(buf, buffer, count);
	if (ret)
	{
		return ret; 
	}

	if((strstr(buf, "debug") != NULL) || (strstr(buf, "DEBUG") != NULL))
	{		
		atomic_set(&dws->debug_flag, 1);		
		kfree(buf);
		printk("%s:open debug\n",__func__);
		return count;
	}
	else if((strstr(buf, "stop") != NULL) || (strstr(buf, "STOP") != NULL))
	{		
		atomic_set(&dws->debug_flag, 0);
		printk("%s:close debug\n",__func__);
	}
	else if((strstr(buf, "=") != NULL))
	{
		printk("%s:invalid command\n",__func__);	
		return count;
	}

	sscanf(buf, "0x%x=0x%x", &reg, &value);

	if((reg >= SPIM_CTRLR0) && (reg <= SPIM_DMARDLR))	
	{
		dw_writew(dws, reg, value);
		printk("%s:write data[0x%x] to reg[0x%x] succesfully\n",__func__, value, reg);
	}
	else
	{
		printk("%s:data[0x%x] or reg[0x%x] is out of range\n",__func__, value, reg);
	}
	
	kfree(buf);
		
	return count; 
}
コード例 #3
0
ファイル: dw_spi.c プロジェクト: LittleForker/linux-2.6
static int u16_writer(struct dw_spi *dws)
{
	if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
		|| (dws->tx == dws->tx_end))
		return 0;

	dw_writew(dws, dr, *(u16 *)(dws->tx));
	dws->tx += 2;

	wait_till_not_busy(dws);
	return 1;
}
コード例 #4
0
ファイル: dw_spi.c プロジェクト: LittleForker/linux-2.6
static int null_writer(struct dw_spi *dws)
{
	u8 n_bytes = dws->n_bytes;

	if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
		|| (dws->tx == dws->tx_end))
		return 0;
	dw_writew(dws, dr, 0);
	dws->tx += n_bytes;

	wait_till_not_busy(dws);
	return 1;
}
コード例 #5
0
ファイル: spi-dw.c プロジェクト: michabs/linux-imx6-3.14
static void dw_writer(struct dw_spi *dws)
{
    u32 max = tx_max(dws);
    u16 txw = 0;

    while (max--) {
        /* Set the tx word if the transfer's original "tx" is not null */
        if (dws->tx_end - dws->len) {
            if (dws->n_bytes == 1)
                txw = *(u8 *)(dws->tx);
            else
                txw = *(u16 *)(dws->tx);
        }
        dw_writew(dws, DW_SPI_DR, txw);
        dws->tx += dws->n_bytes;
    }
}
コード例 #6
0
ファイル: spi-dw-pl330.c プロジェクト: scshepard/terasic_MTL
static int spi_pl330_dma_transfer(struct dw_spi *dws, int cs_change)
{
	struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
	struct dma_chan *txchan, *rxchan;
	struct dma_slave_config txconf, rxconf;
	u16 dma_ctrl = 0;

	/* 1. setup DMA related registers */
	if (cs_change) {
		spi_enable_chip(dws, 0);
		/* Setup peripheral's burst watermark for TX and RX FIFO */
		dw_writew(dws, DW_SPI_DMARDLR, SSI_DMA_MAXBURST - 1);
		dw_writew(dws, DW_SPI_DMATDLR, SSI_FIFO_DEPTH - SSI_DMA_MAXBURST);

		if (dws->tx_dma)
			dma_ctrl |= 0x2;
		if (dws->rx_dma)
			dma_ctrl |= 0x1;
		dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
		spi_enable_chip(dws, 1);
	}

	dws->dma_chan_done = 0;
	txchan = dws->txchan;
	rxchan = dws->rxchan;

	/* 2. Prepare the TX dma transfer */
	txconf.direction = DMA_MEM_TO_DEV;
	txconf.dst_addr = dws->dma_addr;
	/* Note: By default the burst_len (dst_maxburst) for DMA_MEM_TO_DEV is set
			 to 1 and the burst_size (src_addr_width) for memory is set to
			 peripheral's configuration in PL330 driver (driver/dma/pl330.c).
			 Therefore the config listed below can be skipped
				i. txconf.dst_maxburst
				ii. txconf.src_addr_width
			 Max DMA width is 16-bit
	*/
	if (dws->dma_width == 1)
		txconf.dst_addr_width = PL330_DMA_BRSTSZ_1B;
	else
		txconf.dst_addr_width = PL330_DMA_BRSTSZ_2B;

	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
				       (unsigned long) &txconf);

	memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
	dws->tx_sgl.dma_address = dws->tx_dma;
	dws->tx_sgl.length = dws->len;

	txdesc = txchan->device->device_prep_slave_sg(txchan,
				&dws->tx_sgl,
				1,
				DMA_MEM_TO_DEV,
				DMA_PREP_INTERRUPT,
				NULL);
	txdesc->callback = spi_pl330_dma_done;
	txdesc->callback_param = dws;

	/* 3. Prepare the RX dma transfer */
	rxconf.direction = DMA_DEV_TO_MEM;
	rxconf.src_addr = dws->dma_addr;
	/* Note: By default the burst_len (src_maxburst) for DMA_DEV_TO_MEM is set
			 to 1 and the burst_size (dst_addr_width) for memory is set to
			 peripheral's configuration in PL330 driver (driver/dma/pl330.c).
			 Therefore the config listed below can be skipped
		txconf.src_maxburst
		txconf.dst_addr_width
	*/
	if (dws->dma_width == 1)
		rxconf.src_addr_width = PL330_DMA_BRSTSZ_1B;
	else
		rxconf.src_addr_width = PL330_DMA_BRSTSZ_2B;

	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
				       (unsigned long) &rxconf);

	memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
	dws->rx_sgl.dma_address = dws->rx_dma;
	dws->rx_sgl.length = dws->len;

	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
				&dws->rx_sgl,
				1,
				DMA_DEV_TO_MEM,
				DMA_PREP_INTERRUPT,
				NULL);
	rxdesc->callback = spi_pl330_dma_done;
	rxdesc->callback_param = dws;

	/* rx must be started before tx due to spi instinct */
	rxdesc->tx_submit(rxdesc);
	dma_async_issue_pending(rxchan);
	txdesc->tx_submit(txdesc);
	dma_async_issue_pending(txchan);

	return 0;
}