Beispiel #1
0
static irqreturn_t nuc970_spi0_irq(int irq, void *dev)
{
	struct nuc970_spi *hw = dev;
	unsigned int status, i, offset;
	unsigned int count = hw->count;
    
    hw->count += hw->pdata->txnum+1;

    if (hw->rx) {
        for(i=0, offset=0; i<hw->pdata->txnum+1 ;i++,offset+=4)
            hw_rx(hw, __raw_readl(hw->regs + REG_RX0 + offset), count++);
    }
    
    count = hw->count;
    if (count < hw->len) {
        for(i=0, offset=0; i<hw->pdata->txnum+1 ;i++,offset+=4) {
            __raw_writel(hw_tx(hw, count++), hw->regs + REG_TX0 + offset);
        }
        nuc970_spi0_gobusy(hw);
    } else {
        complete(&hw->done);
    }

    status = __raw_readl(hw->regs + REG_CNTRL);
	__raw_writel(status, hw->regs + REG_CNTRL);

    return IRQ_HANDLED;
}
Beispiel #2
0
static int nuc970_spi0_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct nuc970_spi *hw = (struct nuc970_spi *)to_hw(spi);
    int i, offset;
    
	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;
 
    if(t->tx_nbits & SPI_NBITS_DUAL) {
        __raw_writel(__raw_readl(hw->regs + REG_CNTRL) | (0x5 << 20), hw->regs + REG_CNTRL);
    } else if(t->tx_nbits & SPI_NBITS_QUAD) {
        __raw_writel(__raw_readl(hw->regs + REG_CNTRL) | (0x3 << 20), hw->regs + REG_CNTRL);
    }
    
    if(t->rx_nbits & SPI_NBITS_DUAL) {
        __raw_writel(__raw_readl(hw->regs + REG_CNTRL) | (0x4 << 20), hw->regs + REG_CNTRL);
    } else if(t->rx_nbits & SPI_NBITS_QUAD) {
        __raw_writel(__raw_readl(hw->regs + REG_CNTRL) | (0x2 << 20), hw->regs + REG_CNTRL);
    }   
    
    for(i=0, offset=0; i<hw->pdata->txnum+1 ;i++,offset+=4)
        __raw_writel(hw_tx(hw, i), hw->regs + REG_TX0 + offset);        
	nuc970_spi0_gobusy(hw);

	wait_for_completion(&hw->done);
    
    if(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD))
        __raw_writel(__raw_readl(hw->regs + REG_CNTRL) & ~(0x7 << 20), hw->regs + REG_CNTRL);

	return hw->count;
}
Beispiel #3
0
/*
 * s3c6410_spi_interrupt  - spi fifo interrupt handler
 * @irq    : interrupt number
 * @dev    : device instance
 *
 * spi fifo interrupt handler
 */
static irqreturn_t s3c6410_spi_irq(int irq, void *dev)
{
	struct s3c6410_spi *hw = dev;
	unsigned int pend = readl(hw->regs + S3C_SPI_STATUS);
	unsigned int w_tmp;
	unsigned int r_tmp;
	int err = 0;

	spin_lock(&hw->lock);

	if(pend & SPI_STUS_RX_OVERRUN_ERR)
	{
		printk("spi%d: RX FIFO overrun error\n", hw->id);
		writel(SPI_PND_RX_OVERRUN_CLR, hw->regs + S3C_PENDING_CLR);
		err = 1;
	}
	if(pend & SPI_STUS_RX_UNDERRUN_ERR)
	{
		printk("spi%d: RX FIFO underrun error\n", hw->id);
		writel(SPI_PND_RX_UNDERRUN_CLR, hw->regs + S3C_PENDING_CLR);
		err = 1;
	}
	if(pend & SPI_STUS_TX_OVERRUN_ERR)
	{
		printk("spi%d: TX FIFO overrun error\n", hw->id);
		writel(SPI_PND_TX_OVERRUN_CLR, hw->regs + S3C_PENDING_CLR);
		err = 1;
	}
	if(pend & SPI_STUS_TX_UNDERRUN_ERR)
	{
		printk("spi%d: TX FIFO underrun error\n", hw->id);
		writel(SPI_PND_TX_UNDERRUN_CLR, hw->regs + S3C_PENDING_CLR);
		err = 1;
	}

	if(err)
	{
		complete(&hw->done);
		return IRQ_HANDLED;
	}
	
	if((pend & SPI_STUS_TX_FIFORDY) && (hw->tx_done < hw->len))
	{
		w_tmp = hw_tx(hw);
        writel(w_tmp, hw->regs + S3C_SPI_TX_DATA);
		udelay(30);
		
		hw->flag = 1;
	    hw->tx_done++;
	}
	
	if(pend & (SPI_STUS_RX_FIFOLVL)) 
	{
		r_tmp = readl(hw->regs + S3C_SPI_RX_DATA);
        hw_rx(hw, r_tmp);
		hw->flag = 0;
		hw->rx_done++;
	}

	if(hw->rx_done == hw->len && hw->tx_done == hw->len)
	{
		writel(SPI_INT_ALL_DISABLE, hw->regs + S3C_SPI_INT_EN);
		udelay(30);
		complete(&hw->done);
	}
	
	spin_unlock(&hw->lock);

	return IRQ_HANDLED;
}