static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
{
	struct nuc900_spi *hw = to_hw(spi);
	unsigned int val;
	unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
	unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
	unsigned long flags;

	spin_lock_irqsave(&hw->lock, flags);

	val = __raw_readl(hw->regs + USI_SSR);

	if (!cs)
		val &= ~SELECTLEV;
	else
		val |= SELECTLEV;

	if (!ssr)
		val &= ~SELECTSLAVE;
	else
		val |= SELECTSLAVE;

	__raw_writel(val, hw->regs + USI_SSR);

	val = __raw_readl(hw->regs + USI_CNT);

	if (!cpol)
		val &= ~SELECTPOL;
	else
		val |= SELECTPOL;

	__raw_writel(val, hw->regs + USI_CNT);

	spin_unlock_irqrestore(&hw->lock, flags);
}
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
{
	struct s3c24xx_spi *hw = to_hw(spi);
	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
	unsigned int spcon;

	switch (value) {
	case BITBANG_CS_INACTIVE:
		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
		break;

	case BITBANG_CS_ACTIVE:
		spcon = readb(hw->regs + S3C2410_SPCON);

		if (spi->mode & SPI_CPHA)
			spcon |= S3C2410_SPCON_CPHA_FMTB;
		else
			spcon &= ~S3C2410_SPCON_CPHA_FMTB;

		if (spi->mode & SPI_CPOL)
			spcon |= S3C2410_SPCON_CPOL_HIGH;
		else
			spcon &= ~S3C2410_SPCON_CPOL_HIGH;

		spcon |= S3C2410_SPCON_ENSCK;

		/* write new configration */

		writeb(spcon, hw->regs + S3C2410_SPCON);
		hw->set_cs(hw->pdata, spi->chip_select, cspol);

		break;
	}
}
예제 #3
0
static void cns3xxx_spi_chipselect(struct spi_device *spi, int value)
{
	struct cns3xxx_spi *hw = to_hw(spi);
	unsigned int spi_config;

	switch (value) {
	case BITBANG_CS_INACTIVE:
		break;

	case BITBANG_CS_ACTIVE:
		spi_config = SPI_CONFIGURATION_REG;

		if (spi->mode & SPI_CPHA)
			spi_config |= (0x1 << 13);
		else
			spi_config &= ~(0x1 << 13);

		if (spi->mode & SPI_CPOL)
			spi_config |= (0x1 << 14);
		else
			spi_config &= ~(0x1 << 14);

		/* write new configration */
		SPI_CONFIGURATION_REG = spi_config;

		SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
		SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3);

		break;
	}
}
예제 #4
0
/*
 * s3c6410_spi_txrx  - handle for spi_message
 * @spi : spi_device sturct
 * @t   : spi_transfer struct
 *
 * bitbang driver member fuction to handle for spi_message
 * it send first message.
 */
static int s3c6410_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct s3c6410_spi *hw = to_hw(spi);
	unsigned int spi_modecfg, spi_inten;

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;
	hw->tx_done = 0;
	hw->rx_done = 0;
	hw->flag = 0;	

	init_completion(&hw->done);

	spi_modecfg = readl(hw->regs + S3C_MODE_CFG);
	spi_modecfg |= (hw->len << 5) | (hw->len << 11);
	writel(spi_modecfg, hw->regs + S3C_MODE_CFG);

	/* enable SPI Interrupt */
	if(hw->tx)
		spi_inten = SPI_INT_TX_FIFORDY_EN|SPI_INT_TX_UNDERRUN_EN|SPI_INT_TX_OVERRUN_EN;

	if(hw->rx)
		spi_inten = SPI_INT_RX_FIFORDY_EN|SPI_INT_RX_UNDERRUN_EN|SPI_INT_RX_OVERRUN_EN|SPI_INT_TRAILING_EN;

	writel(spi_inten , hw->regs + S3C_SPI_INT_EN); 

	wait_for_completion(&hw->done);

	return hw->rx_done;
}
예제 #5
0
파일: spi-s3c24xx.c 프로젝트: IDM350/linux
static int s3c24xx_spi_setup(struct spi_device *spi)
{
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
	int ret;

	/* allocate settings on the first call */
	if (!cs) {
		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
		if (!cs) {
			dev_err(&spi->dev, "no memory for controller state\n");
			return -ENOMEM;
		}

		cs->spcon = SPCON_DEFAULT;
		cs->hz = -1;
		spi->controller_state = cs;
	}

	/* initialise the state from the device */
	ret = s3c24xx_spi_update_state(spi, NULL);
	if (ret)
		return ret;

	spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {
		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
		/* need to ndelay for 0.5 clocktick ? */
	}
	spin_unlock(&hw->bitbang.lock);

	return 0;
}
예제 #6
0
/*
 * s3c6410_spi_setup  - setup spi attribute
 * @spi : spi_device sturct
 *
 * bitbang driver member fuction to setup spi attribute
 * it set bit_per_word and spi mode.
 */
static int s3c6410_spi_setup(struct spi_device *spi)
{
	struct s3c6410_spi *hw = to_hw(spi);
	int ret;

	if (!spi->bits_per_word)
		spi->bits_per_word = 16;

	/* Set Swap Config Reg */
	if(spi->mode & SPI_LSB_FIRST) 
		writel(SPI_SWAP_RX_BIT |
		       SPI_SWAP_RX_EN  |
		       SPI_SWAP_TX_BIT |
		       SPI_SWAP_TX_EN, hw->regs + S3C_SWAP_CFG);
	else 
		writel(0, hw->regs + S3C_SWAP_CFG);		

	ret = s3c6410_spi_setupxfer(spi, NULL);
	if (ret < 0) {
		dev_err(&spi->dev, "setupxfer returned %d\n", ret);
		return ret;
	}

	printk("spi:  mode %d, %u bpw, %d hz\n",
		spi->mode, spi->bits_per_word,spi->max_speed_hz);

	return ret;
}
예제 #7
0
static inline void nuc970_slave_select(struct spi_device *spi, unsigned int ssr)
{
	struct nuc970_spi *hw = (struct nuc970_spi *)to_hw(spi);
	unsigned int val;
	unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
	unsigned long flags;

	spin_lock_irqsave(&hw->lock, flags);

	val = __raw_readl(hw->regs + REG_SSR);
               
	if (!cs)
		val &= ~SELECTLEV;
	else
		val |= SELECTLEV;
    
    if(spi->chip_select == 0) {        
        if (!ssr)
            val &= ~SELECTSLAVE0;
        else
            val |= SELECTSLAVE0;
    } else {
        if (!ssr)
            val &= ~SELECTSLAVE1;
        else
            val |= SELECTSLAVE1;
    }

	__raw_writel(val, hw->regs + REG_SSR);

	spin_unlock_irqrestore(&hw->lock, flags);
}
static int s3c24xx_spi_setup(struct spi_device *spi)
{
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
	int ret;

	
	if (!cs) {
		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
		if (!cs) {
			dev_err(&spi->dev, "no memory for controller state\n");
			return -ENOMEM;
		}

		cs->spcon = SPCON_DEFAULT;
		cs->hz = -1;
		spi->controller_state = cs;
	}

	
	ret = s3c24xx_spi_update_state(spi, NULL);
	if (ret)
		return ret;

	spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {
		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
		
	}
	spin_unlock(&hw->bitbang.lock);

	return 0;
}
예제 #9
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;
}
예제 #10
0
/*
 * s3c6410_spi_setupxfer  - setup spi control
 * @spi : spi_device sturct
 * @t   : spi_transfer struct
 *
 * bitbang driver member fuction to setup spi control
 * it set bit_per_word and serial clock rate.
 */
static int s3c6410_spi_setupxfer(struct spi_device *spi,
				 struct spi_transfer *t)
{
	struct s3c6410_spi *hw = to_hw(spi);
	unsigned int bpw, mode, spi_chcfg;
	int scr, ret = 0;
	unsigned int bit_rate, reg = 0;
	unsigned long pclk;

	/*	bpw = t ? t->bits_per_word : spi->bits_per_word; */
	bpw = spi->bits_per_word;
	bit_rate  = t ? t->speed_hz : spi->max_speed_hz;

	/* set bits per word */
	if (bpw > 32 || bpw < 8) {
		dev_err(&spi->dev, "spi:  invalid bits-per-word (%d)\n", bpw);
		return -EINVAL;
	}

	/* Set SPI_SCALER :
	   bit rate = PCLK / ( 2 * (1 + SPI_SCALER)) 
	   SPI_SCALER = (PCLK / bit rate / 2) -1	
	   SPI_SCALER = 0 (default)	*/

	writel(readl(hw->regs + S3C_CLK_CFG) & (~SPI_ENCLK_ENABLE), hw->regs + S3C_CLK_CFG );	

	pclk =  hw->in_clk;
	scr = (pclk / bit_rate / 2) - 1;

	if(scr < 0) 	scr = 0;
	if(scr > 0xff) 	scr = 0xff;

	bit_rate = (unsigned int) (pclk / ( 2 * (scr + 1)));
	printk("spi:  setting serial clock rate to %d (bit rate = %d hz, pclk = %d)\n", scr, bit_rate, (int)pclk);
	reg = readl(hw->regs + S3C_CLK_CFG);
	writel(reg | scr | SPI_ENCLK_ENABLE, hw->regs + S3C_CLK_CFG );	

	if	   (bpw > 16)	mode = SPI_MODE_CH_TSZ_WORD | SPI_MODE_BUS_TSZ_WORD;
	else if(bpw > 8) 	mode = SPI_MODE_CH_TSZ_HALFWORD | SPI_MODE_BUS_TSZ_HALFWORD;
	else 				mode = SPI_MODE_CH_TSZ_BYTE | SPI_MODE_BUS_TSZ_BYTE;

	mode |= (SPI_MODE_RXDMA_OFF | SPI_MODE_TXDMA_OFF);
	writel(mode, hw->regs + S3C_MODE_CFG);
	mode = readl( hw->regs + S3C_MODE_CFG);

	spi_chcfg = readl(hw->regs + S3C_CH_CFG);
	spi_chcfg |= SPI_CH_TXCH_ON | SPI_CH_RXCH_ON;
	writel(spi_chcfg , hw->regs + S3C_CH_CFG);

	spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {
		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
		/* need to ndelay for 0.5 clocktick */
	}
	spin_unlock(&hw->bitbang.lock);

	return ret;
}
예제 #11
0
파일: spi-s3c24xx.c 프로젝트: IDM350/linux
static int s3c24xx_spi_update_state(struct spi_device *spi,
				    struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	unsigned int bpw;
	unsigned int hz;
	unsigned int div;
	unsigned long clk;

	bpw = t ? t->bits_per_word : spi->bits_per_word;
	hz  = t ? t->speed_hz : spi->max_speed_hz;

	if (!bpw)
		bpw = 8;

	if (!hz)
		hz = spi->max_speed_hz;

	if (bpw != 8) {
		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
		return -EINVAL;
	}

	if (spi->mode != cs->mode) {
		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;

		if (spi->mode & SPI_CPHA)
			spcon |= S3C2410_SPCON_CPHA_FMTB;

		if (spi->mode & SPI_CPOL)
			spcon |= S3C2410_SPCON_CPOL_HIGH;

		cs->mode = spi->mode;
		cs->spcon = spcon;
	}

	if (cs->hz != hz) {
		clk = clk_get_rate(hw->clk);
		div = DIV_ROUND_UP(clk, hz * 2) - 1;

		if (div > 255)
			div = 255;

		dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
			div, hz, clk / (2 * (div + 1)));

		cs->hz = hz;
		cs->sppre = div;
	}

	return 0;
}
예제 #12
0
파일: spi-s3c24xx.c 프로젝트: IDM350/linux
static int s3c24xx_spi_setupxfer(struct spi_device *spi,
				 struct spi_transfer *t)
{
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
	int ret;

	ret = s3c24xx_spi_update_state(spi, t);
	if (!ret)
		writeb(cs->sppre, hw->regs + S3C2410_SPPRE);

	return ret;
}
예제 #13
0
static int nuc970_spi0_update_state(struct spi_device *spi,
				    struct spi_transfer *t)
{
    struct nuc970_spi *hw = (struct nuc970_spi *)to_hw(spi);
    unsigned int clk;
    unsigned int div;
    unsigned int bpw;
	unsigned int hz;
    unsigned char spimode;
 
    bpw = t ? t->bits_per_word : spi->bits_per_word;
	hz  = t ? t->speed_hz : spi->max_speed_hz;
    
    if(hw->pdata->txbitlen != bpw)
        hw->pdata->txbitlen = bpw;
 
    if(hw->pdata->hz != hz) {
        clk = clk_get_rate(hw->clk);
        div = DIV_ROUND_UP(clk, hz * 2) - 1;
        hw->pdata->hz = hz;
        hw->pdata->divider = div;        
    }
        
    //Mode 0: CPOL=0, CPHA=0; active high
    //Mode 1: CPOL=0, CPHA=1 ;active low
    //Mode 2: CPOL=1, CPHA=0 ;active low
    //Mode 3: POL=1, CPHA=1;active high
    if (spi->mode & SPI_CPOL)
        hw->pdata->clkpol = 1;
    else
        hw->pdata->clkpol = 0;
    
    spimode = spi->mode & 0xff; //remove dual/quad bit

    if ((spimode == SPI_MODE_0) || (spimode == SPI_MODE_3)) {
        hw->pdata->txneg = 1;
        hw->pdata->rxneg = 0;
    } else {
        hw->pdata->txneg = 0;
        hw->pdata->rxneg = 1;
    }
    
    if (spi->mode & SPI_LSB_FIRST)
        hw->pdata->lsb = 1;
    else
        hw->pdata->lsb = 0;
    
    return 0;
}
예제 #14
0
static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct nuc900_spi *hw = to_hw(spi);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

	__raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);

	nuc900_spi_gobusy(hw);

	wait_for_completion(&hw->done);

	return hw->count;
}
예제 #15
0
static int nuc970_spi0_setup(struct spi_device *spi)
{
	struct nuc970_spi *hw = (struct nuc970_spi *)to_hw(spi);
    int ret;

    ret = nuc970_spi0_update_state(spi, NULL);
    if (ret)
		return ret;
    
    spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {       
        nuc970_set_divider(hw);
        nuc970_slave_select(spi, 0);
    }
    spin_unlock(&hw->bitbang.lock);
    
    return 0;
}
예제 #16
0
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);

	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
		t->tx_buf, t->rx_buf, t->len);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

	/* send the first byte */
	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
	wait_for_completion(&hw->done);

	return hw->count;
}
예제 #17
0
static int nuc970_spi0_setupxfer(struct spi_device *spi,
				 struct spi_transfer *t)
{	
    struct nuc970_spi *hw = (struct nuc970_spi *)to_hw(spi);
    int ret;
          
    ret = nuc970_spi0_update_state(spi, t);
    if (ret)
		return ret;
   
    nuc970_spi0_setup_txbitlen(hw, hw->pdata->txbitlen);
    nuc970_tx_edge(hw, hw->pdata->txneg);
    nuc970_rx_edge(hw, hw->pdata->rxneg);
    nuc970_set_clock_polarity(hw, hw->pdata->clkpol);
    nuc970_send_first(hw, hw->pdata->lsb);
    
    return 0;
}
예제 #18
0
static int s3c24xx_spi_setupxfer(struct spi_device *spi,
				 struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);
	unsigned int bpw;
	unsigned int hz;
	unsigned int div;

	bpw = t ? t->bits_per_word : spi->bits_per_word;
	hz  = t ? t->speed_hz : spi->max_speed_hz;

	if (bpw != 8) {
		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
		return -EINVAL;
	}

	div = clk_get_rate(hw->clk) / hz;

	/* is clk = pclk / (2 * (pre+1)), or is it
	 *    clk = (pclk * 2) / ( pre + 1) */

	div /= 2;

	if (div > 0)
		div -= 1;

	if (div > 255)
		div = 255;

	dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
	writeb(div, hw->regs + S3C2410_SPPRE);

	spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {
		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
		/* need to ndelay for 0.5 clocktick ? */
	}
	spin_unlock(&hw->bitbang.lock);

	return 0;
}
예제 #19
0
파일: spi-s3c24xx.c 프로젝트: IDM350/linux
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
{
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;

	/* change the chipselect state and the state of the spi engine clock */

	switch (value) {
	case BITBANG_CS_INACTIVE:
		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
		writeb(cs->spcon, hw->regs + S3C2410_SPCON);
		break;

	case BITBANG_CS_ACTIVE:
		writeb(cs->spcon | S3C2410_SPCON_ENSCK,
		       hw->regs + S3C2410_SPCON);
		hw->set_cs(hw->pdata, spi->chip_select, cspol);
		break;
	}
}
예제 #20
0
파일: spi-s3c24xx.c 프로젝트: IDM350/linux
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

	init_completion(&hw->done);

	hw->fiq_inuse = 0;
	if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
		s3c24xx_spi_tryfiq(hw);

	/* send the first byte */
	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);

	wait_for_completion(&hw->done);
	return hw->count;
}
예제 #21
0
/*
 * s3c6410_spi_chipsel  - select spi slave chip
 * @spi   : spi_device sturct
 * @value : chipselect value
 *
 * bitbang driver member fuction to select spi slave chip 
 */
static void s3c6410_spi_chipsel(struct spi_device *spi, int value)
{
	struct s3c6410_spi *hw = to_hw(spi);
	int reg;

	switch (value) {
	/* Select */
	case BITBANG_CS_ACTIVE:  
		reg = readl(hw->regs + S3C_SLAVE_SEL);
		reg &= ~(SPI_SLAVE_SIG_INACT);
		writel(reg, hw->regs + S3C_SLAVE_SEL);
		udelay(30);
		break;
	
	/* Non-Select */
	case BITBANG_CS_INACTIVE: 
		reg = readl(hw->regs + S3C_SLAVE_SEL);
		reg |= SPI_SLAVE_SIG_INACT;
		writel(reg, hw->regs + S3C_SLAVE_SEL);
		break;
	}
}
예제 #22
0
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);
	int i=0;
	//static int flag=1;
	//unsigned char data1,data2;
	//char cmd[4]={0x38,0x80,0xab,0xcd};
	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

	//init_completion(&hw->done);

	//hw->fiq_inuse = 0;
	//if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
	//	s3c24xx_spi_tryfiq(hw);
	//writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);

	//wait_for_completion(&hw->done);
	for (i = 0; i < t->len; i=i+1) 
	{
		spi_write8(hw,hw_txbyte(hw,i));
		if(hw->rx)
			hw->rx[i]=spi_read8(hw);
	//	udelay(2);
    }
	hw->count = hw->len;
	#if 0
	//for(i=0;i<hw->len;i++)
	//printk("%02x ",hw->tx[i]);
	//printk("==>\n");
	/* send the first byte */
	if(flag){
	for (i = 0; i < 4; i=i+2) 
	{
		spi_write8(hw,cmd[i]);
		spi_write8(hw,cmd[i+1]);
		udelay(2);
    }
	flag=0;
	
	//s3c24xx_spi_chipsel(spi,BITBANG_CS_INACTIVE);
		}
	else
		{
	//s3c24xx_spi_chipsel(spi,BITBANG_CS_INACTIVE);
	//udelay(500);
	//s3c24xx_spi_chipsel(spi,BITBANG_CS_ACTIVE);
	spi_write8(hw,0x38);
	spi_write8(hw,0x80);
	udelay(2);
	for(i=0;i<3;i++){
	spi_write8(hw,0xff);
	data1=spi_read8(hw);
	spi_write8(hw,0xff);
	data2=spi_read8(hw);
	udelay(2);
		}
	printk("1<== %02x\n",data1);	
	printk("2<== %02x\n",data2);	
	flag=1;
		}
		//udelay(2);
	
	//if ((hw->len % 4) != 0) {
	//	spi_write8(hw,0);
	//	spi_write8(hw,0);
	//	udelay(2);
	//}
	hw->count = hw->len;
	//writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);

	//wait_for_completion(&hw->done);
	#endif
	return hw->count;
}
예제 #23
0
static int cns3xxx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct cns3xxx_spi *hw = to_hw(spi);

	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf,
		t->len);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;
	hw->last_in_message_list = t->last_in_message_list;

	init_completion(&hw->done);

	if (hw->tx) {
		int i;
		u32 rx_data;
		for (i = 0; i < (hw->len - 1); i++) {
			dev_dbg(&spi->dev,
				"[SPI_CNS3XXX_DEBUG] hw->tx[%02d]: 0x%02x\n", i,
				hw->tx[i]);
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 0, hw->tx[i],
					  &rx_data);
			if (hw->rx) {
				hw->rx[i] = rx_data;
				dev_dbg(&spi->dev,
					"[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
					i, hw->rx[i]);
			}
		}

		if (t->last_in_message_list) {
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 1, hw->tx[i],
					  &rx_data);
			if (hw->rx) {
				hw->rx[i] = rx_data;
				dev_dbg(&spi->dev,
					"[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
					i, hw->rx[i]);
			}
		} else {
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 0, hw->tx[i],
					  &rx_data);
		}
		goto done;
	}

	if (hw->rx) {
		int i;
		u32 rx_data;
		for (i = 0; i < (hw->len - 1); i++) {
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 0, 0xff, &rx_data);
			hw->rx[i] = rx_data;
			dev_dbg(&spi->dev,
				"[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n", i,
				hw->rx[i]);
		}

		if (t->last_in_message_list) {
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 1, 0xff, &rx_data);
		} else {
			cns3xxx_spi_tx_rx(hw, spi->chip_select, 0, 0xff, &rx_data);
		}
		hw->rx[i] = rx_data;
		dev_dbg(&spi->dev, "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
			i, hw->rx[i]);
	}
done:
	return hw->len;
}