Пример #1
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
	const u8 *tx = dout;
	u8 *rx = din;
	uint bytes = bitlen / 8;
	int ret = 0;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
		slave->bus, slave->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

	/* we can only do 8 bit transfers */
	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	ret = spi_pio_xfer(bss, tx, rx, bytes);

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return ret;
}
Пример #2
0
static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen,
                             const void *dout, void *din, unsigned long flags)
{
    struct udevice *bus = dev->parent;
    struct rockchip_spi_priv *priv = dev_get_priv(bus);
    struct rockchip_spi *regs = priv->regs;
    struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
    int len = bitlen >> 3;
    const u8 *out = dout;
    u8 *in = din;
    int toread, towrite;
    int ret;

    debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din,
          len, flags);
    if (DEBUG_RK_SPI)
        rkspi_dump_regs(regs);

    /* Assert CS before transfer */
    if (flags & SPI_XFER_BEGIN)
        spi_cs_activate(dev, slave_plat->cs);

    while (len > 0) {
        int todo = min(len, 0xffff);

        rkspi_enable_chip(regs, false);
        writel(todo - 1, &regs->ctrlr1);
        rkspi_enable_chip(regs, true);

        toread = todo;
        towrite = todo;
        while (toread || towrite) {
            u32 status = readl(&regs->sr);

            if (towrite && !(status & SR_TF_FULL)) {
                writel(out ? *out++ : 0, regs->txdr);
                towrite--;
            }
            if (toread && !(status & SR_RF_EMPT)) {
                u32 byte = readl(regs->rxdr);

                if (in)
                    *in++ = byte;
                toread--;
            }
        }
        ret = rkspi_wait_till_not_busy(regs);
        if (ret)
            break;
        len -= todo;
    }

    /* Deassert CS after transfer */
    if (flags & SPI_XFER_END)
        spi_cs_deactivate(dev, slave_plat->cs);

    rkspi_enable_chip(regs, false);

    return ret;
}
Пример #3
0
int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	int num = slave->bus, ret = 0;
	unsigned int bytes = bitlen / 8;
	struct owl_spi_regs *s =
		(struct owl_spi_regs *)SPI_BASE(num);

	debug("%d %d %lx\n", __LINE__, bitlen, flags);
	if(bitlen <= 0)
		goto out;

	if (flags & SPI_XFER_BEGIN){
		spi_cs_activate(slave);
	}

	if(bytes >= 32 && bytes % 32 == 0){
		ret = owl_spi_write_read_32bit(s, bitlen, dout, din);
	}else{
		ret = owl_spi_write_read_8bit(s, bitlen, dout, din);
	}
	debug("spi_xfer ret: %d\n", ret);

out:	
	if (flags & SPI_XFER_END){
		spi_cs_deactivate(slave);
	}
	return ret;
}
Пример #4
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);
	uint bytes = bitlen / 8;
	unsigned long limit;
	int ret = 0;

	if (bitlen == 0)
		goto done;

	/* we can only do 8 bit transfers */
	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	if (dout)
		pss->tx = dout;
	else
		pss->tx = NULL;

	if (din)
		pss->rx = din;
	else
		pss->rx = NULL;

	if (flags & SPI_XFER_BEGIN) {
		spi_cs_activate(slave);
		writel(pss->cr1 | pss->int_cr1, &pss->spi_reg->sscr1);
		writel(TIMEOUT_DEF, &pss->spi_reg->ssto);
		writel(pss->cr0, &pss->spi_reg->sscr0);
	}

	while (bytes--) {
		limit = SSP_FLUSH_NUM;
		ret = spi_armd_write(pss);
		if (ret)
			break;

		while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--)
			udelay(1);

		ret = spi_armd_read(pss);
		if (ret)
			break;
	}

 done:
	if (flags & SPI_XFER_END) {
		/* Stop SSP */
		writel(pss->clear_sr, &pss->spi_reg->sssr);
		clrbits_le32(&pss->spi_reg->sscr1, pss->int_cr1);
		writel(0, &pss->spi_reg->ssto);
		spi_cs_deactivate(slave);
	}

	return ret;
}
Пример #5
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
	const u8 *tx = dout;
	u8 *rx = din;
	uint bytes = bitlen / 8;
	int ret = 0;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
		slave->bus, slave->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

	/* we can only do 8 bit transfers */
	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	/* todo: take advantage of hardware fifos and setup RX dma */
	while (bytes--) {
		u8 value = (tx ? *tx++ : 0);
		debug("%s: tx:%x ", __func__, value);
		write_SPI_TDBR(bss, value);
		SSYNC();
		while ((read_SPI_STAT(bss) & TXS))
			if (ctrlc()) {
				ret = -1;
				goto done;
			}
		while (!(read_SPI_STAT(bss) & SPIF))
			if (ctrlc()) {
				ret = -1;
				goto done;
			}
		while (!(read_SPI_STAT(bss) & RXS))
			if (ctrlc()) {
				ret = -1;
				goto done;
			}
		value = read_SPI_RDBR(bss);
		if (rx)
			*rx++ = value;
		debug("rx:%x\n", value);
	}

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return ret;
}
Пример #6
0
static int pic32_spi_xfer(struct udevice *slave, unsigned int bitlen,
                          const void *tx_buf, void *rx_buf,
                          unsigned long flags)
{
    struct dm_spi_slave_platdata *slave_plat;
    struct udevice *bus = slave->parent;
    struct pic32_spi_priv *priv;
    int len = bitlen / 8;
    int ret = 0;
    ulong tbase;

    priv = dev_get_priv(bus);
    slave_plat = dev_get_parent_platdata(slave);

    debug("spi_xfer: bus:%i cs:%i flags:%lx\n",
          bus->seq, slave_plat->cs, flags);
    debug("msg tx %p, rx %p submitted of %d byte(s)\n",
          tx_buf, rx_buf, len);

    /* assert cs */
    if (flags & SPI_XFER_BEGIN)
        spi_cs_activate(priv);

    /* set current transfer information */
    priv->tx = tx_buf;
    priv->rx = rx_buf;
    priv->tx_end = priv->tx + len;
    priv->rx_end = priv->rx + len;
    priv->len = len;

    /* transact by polling */
    tbase = get_timer(0);
    for (;;) {
        priv->tx_fifo(priv);
        priv->rx_fifo(priv);

        /* received sufficient data */
        if (priv->rx >= priv->rx_end) {
            ret = 0;
            break;
        }

        if (get_timer(tbase) > 5 * CONFIG_SYS_HZ) {
            printf("pic32_spi: error, xfer timedout.\n");
            flags |= SPI_XFER_END;
            ret = -ETIMEDOUT;
            break;
        }
    }

    /* deassert cs */
    if (flags & SPI_XFER_END)
        spi_cs_deactivate(priv);

    return ret;
}
Пример #7
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
	/* assume spi core configured to do 8 bit transfers */
	uint bytes = bitlen / 8;
	const uchar *txp = dout;
	uchar *rxp = din;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
		slave->bus, slave->cs, bitlen, bytes, flags);
	if (bitlen == 0)
		goto done;

	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	/* empty read buffer */
	if (readl(altspi->base + ALTERA_SPI_STATUS) &
	    ALTERA_SPI_STATUS_RRDY_MSK)
		readl(altspi->base + ALTERA_SPI_RXDATA);
	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	while (bytes--) {
		uchar d = txp ? *txp++ : CONFIG_ALTERA_SPI_IDLE_VAL;
		debug("%s: tx:%x ", __func__, d);
		writel(d, altspi->base + ALTERA_SPI_TXDATA);
		while (!(readl(altspi->base + ALTERA_SPI_STATUS) &
			 ALTERA_SPI_STATUS_RRDY_MSK))
			;
		d = readl(altspi->base + ALTERA_SPI_RXDATA);
		if (rxp)
			*rxp++ = d;
		debug("rx:%x\n", d);
	}
 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return 0;
}
Пример #8
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	volatile spi8xxx_t *spi = &((immap_t *) (CFG_IMMR))->spi;
	unsigned int tmpdout, tmpdin, event;
	int numBlks = bitlen / 32 + (bitlen % 32 ? 1 : 0);
	int tm, isRead = 0;
	unsigned char charSize = 32;

	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
	      slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	spi->event = 0xffffffff;	/* Clear all SPI events */

	/* handle data in 32-bit chunks */
	while (numBlks--) {
		tmpdout = 0;
		charSize = (bitlen >= 32 ? 32 : bitlen);

		/* Shift data so it's msb-justified */
		tmpdout = *(u32 *) dout >> (32 - charSize);

		/* The LEN field of the SPMODE register is set as follows:
		 *
		 * Bit length             setting
		 * len <= 4               3
		 * 4 < len <= 16          len - 1
		 * len > 16               0
		 */

		if (bitlen <= 16) {
			if (bitlen <= 4)
				spi->mode = (spi->mode & 0xff0fffff) |
				            (3 << 20);
			else
				spi->mode = (spi->mode & 0xff0fffff) |
				            ((bitlen - 1) << 20);
		} else {
			spi->mode = (spi->mode & 0xff0fffff);
			/* Set up the next iteration if sending > 32 bits */
			bitlen -= 32;
			dout += 4;
		}

		spi->tx = tmpdout;	/* Write the data out */
		debug("*** spi_xfer: ... %08x written\n", tmpdout);

		/*
		 * Wait for SPI transmit to get out
		 * or time out (1 second = 1000 ms)
		 * The NE event must be read and cleared first
		 */
		for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
			event = spi->event;
			if (event & SPI_EV_NE) {
				tmpdin = spi->rx;
				spi->event |= SPI_EV_NE;
				isRead = 1;

				*(u32 *) din = (tmpdin << (32 - charSize));
				if (charSize == 32) {
					/* Advance output buffer by 32 bits */
					din += 4;
				}
			}
			/*
			 * Only bail when we've had both NE and NF events.
			 * This will cause timeouts on RO devices, so maybe
			 * in the future put an arbitrary delay after writing
			 * the device.  Arbitrary delays suck, though...
			 */
			if (isRead && (event & SPI_EV_NF))
				break;
		}
		if (tm >= SPI_TIMEOUT)
			puts("*** spi_xfer: Time out during SPI transfer");

		debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin);
	}

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return 0;
}
Пример #9
0
static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen,
			    const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev_get_parent(dev);
	struct xilinx_spi_priv *priv = dev_get_priv(bus);
	struct xilinx_spi_regs *regs = priv->regs;
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	/* assume spi core configured to do 8 bit transfers */
	unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
	const unsigned char *txp = dout;
	unsigned char *rxp = din;
	unsigned rxecount = 17;	/* max. 16 elements in FIFO, leftover 1 */
	unsigned global_timeout;

	debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n",
	      bus->seq, slave_plat->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

	if (bitlen % XILSPI_MAX_XFER_BITS) {
		printf("XILSPI warning: Not a multiple of %d bits\n",
		       XILSPI_MAX_XFER_BITS);
		flags |= SPI_XFER_END;
		goto done;
	}

	/* empty read buffer */
	while (rxecount && !(readl(&regs->spisr) & SPISR_RX_EMPTY)) {
		readl(&regs->spidrr);
		rxecount--;
	}

	if (!rxecount) {
		printf("XILSPI error: Rx buffer not empty\n");
		return -1;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(dev, slave_plat->cs);

	/* at least 1usec or greater, leftover 1 */
	global_timeout = priv->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
			(XILSPI_MAX_XFER_BITS * 1000000 / priv->freq) + 1;

	while (bytes--) {
		unsigned timeout = global_timeout;
		/* get Tx element from data out buffer and count up */
		unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
		debug("spi_xfer: tx:%x ", d);

		/* write out and wait for processing (receive data) */
		writel(d & SPIDTR_8BIT_MASK, &regs->spidtr);
		while (timeout && readl(&regs->spisr)
						& SPISR_RX_EMPTY) {
			timeout--;
			udelay(1);
		}

		if (!timeout) {
			printf("XILSPI error: Xfer timeout\n");
			return -1;
		}

		/* read Rx element and push into data in buffer */
		d = readl(&regs->spidrr) & SPIDRR_8BIT_MASK;
		if (rxp)
			*rxp++ = d;
		debug("spi_xfer: rx:%x\n", d);
	}

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(dev);

	return 0;
}
Пример #10
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
		void *data_in, unsigned long flags)
{
	struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
	ccsr_espi_t *espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
	unsigned int tmpdout, tmpdin, event;
	const void *dout = NULL;
	void *din = NULL;
	int len = 0;
	int num_blks, num_chunks, max_tran_len, tran_len;
	int num_bytes;
	unsigned char *ch;
	unsigned char *buffer = NULL;
	size_t buf_len;
	u8 *cmd_buf = fsl->cmd_buf;
	size_t cmd_len = fsl->cmd_len;
	size_t data_len = bitlen / 8;
	size_t rx_offset = 0;

	max_tran_len = fsl->max_transfer_length;
	switch (flags) {
	case SPI_XFER_BEGIN:
		cmd_len = fsl->cmd_len = data_len;
		memcpy(cmd_buf, data_out, cmd_len);
		return 0;
	case 0:
	case SPI_XFER_END:
		if (bitlen == 0) {
			spi_cs_deactivate(slave);
			return 0;
		}
		buf_len = 2 * cmd_len + min(data_len, max_tran_len);
		len = cmd_len + data_len;
		rx_offset = cmd_len;
		buffer = (unsigned char *)malloc(buf_len);
		if (!buffer) {
			debug("SF: Failed to malloc memory.\n");
			return 1;
		}
		memcpy(buffer, cmd_buf, cmd_len);
		if (data_in == NULL)
			memcpy(buffer + cmd_len, data_out, data_len);
		break;
	case SPI_XFER_BEGIN | SPI_XFER_END:
		len = data_len;
		buffer = (unsigned char *)malloc(len * 2);
		if (!buffer) {
			debug("SF: Failed to malloc memory.\n");
			return 1;
		}
		memcpy(buffer, data_out, len);
		rx_offset = len;
		cmd_len = 0;
		break;
	}

	debug("spi_xfer: slave %u:%u dout %08X(%p) din %08X(%p) len %u\n",
	      slave->bus, slave->cs, *(uint *) dout,
	      dout, *(uint *) din, din, len);

	num_chunks = data_len / max_tran_len +
		(data_len % max_tran_len ? 1 : 0);
	while (num_chunks--) {
		if (data_in)
			din = buffer + rx_offset;
		dout = buffer;
		tran_len = min(data_len , max_tran_len);
		num_blks = (tran_len + cmd_len) / 4 +
			((tran_len + cmd_len) % 4 ? 1 : 0);
		num_bytes = (tran_len + cmd_len) % 4;
		fsl->data_len = tran_len + cmd_len;
		spi_cs_activate(slave);

		/* Clear all eSPI events */
		out_be32(&espi->event , 0xffffffff);
		/* handle data in 32-bit chunks */
		while (num_blks--) {

			event = in_be32(&espi->event);
			if (event & ESPI_EV_TNF) {
				tmpdout = *(u32 *)dout;

				/* Set up the next iteration */
				if (len > 4) {
					len -= 4;
					dout += 4;
				}

				out_be32(&espi->tx, tmpdout);
				out_be32(&espi->event, ESPI_EV_TNF);
				debug("***spi_xfer:...%08x written\n", tmpdout);
			}

			/* Wait for eSPI transmit to get out */
			udelay(80);

			event = in_be32(&espi->event);
			if (event & ESPI_EV_RNE) {
				tmpdin = in_be32(&espi->rx);
				if (num_blks == 0 && num_bytes != 0) {
					ch = (unsigned char *)&tmpdin;
					while (num_bytes--)
						*(unsigned char *)din++ = *ch++;
				} else {
					*(u32 *) din = tmpdin;
					din += 4;
				}

				out_be32(&espi->event, in_be32(&espi->event)
						| ESPI_EV_RNE);
				debug("***spi_xfer:...%08x readed\n", tmpdin);
			}
		}
		if (data_in) {
			memcpy(data_in, buffer + 2 * cmd_len, tran_len);
			if (*buffer == 0x0b) {
				data_in += tran_len;
				data_len -= tran_len;
				*(int *)buffer += tran_len;
			}
		}
		spi_cs_deactivate(slave);
	}

	free(buffer);
	return 0;
}
Пример #11
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
	struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
	const u8 *txp = dout;
	u8 *rxp = din;
	uint bytes = bitlen / 8;
	uint i;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
		slave->bus, slave->cs, bitlen, bytes, flags);
	if (bitlen == 0)
		goto done;

	/* assume to do 8 bits transfers */
	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	/* we need to tighten the transfer loop */
	if (txp && rxp) {
		writeb(*txp++, &regs->txdata);
		if (bytes > 1) {
			writeb(*txp++, &regs->txdata);
			for (i = 2; i < bytes; i++) {
				u8 rx, tx = *txp++;
				while (!(readb(&regs->status) &
					 TINY_SPI_STATUS_TXR))
					;
				rx = readb(&regs->txdata);
				writeb(tx, &regs->txdata);
				*rxp++ = rx;
			}
			while (!(readb(&regs->status) &
				 TINY_SPI_STATUS_TXR))
				;
			*rxp++ = readb(&regs->txdata);
		}
		while (!(readb(&regs->status) &
			 TINY_SPI_STATUS_TXE))
			;
		*rxp++ = readb(&regs->rxdata);
	} else if (rxp) {
		writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
		if (bytes > 1) {
			writeb(CONFIG_TINY_SPI_IDLE_VAL,
			       &regs->txdata);
			for (i = 2; i < bytes; i++) {
				u8 rx;
				while (!(readb(&regs->status) &
					 TINY_SPI_STATUS_TXR))
					;
				rx = readb(&regs->txdata);
				writeb(CONFIG_TINY_SPI_IDLE_VAL,
				       &regs->txdata);
				*rxp++ = rx;
			}
			while (!(readb(&regs->status) &
				 TINY_SPI_STATUS_TXR))
				;
			*rxp++ = readb(&regs->txdata);
		}
		while (!(readb(&regs->status) &
			 TINY_SPI_STATUS_TXE))
			;
		*rxp++ = readb(&regs->rxdata);
	} else if (txp) {
		writeb(*txp++, &regs->txdata);
		if (bytes > 1) {
			writeb(*txp++, &regs->txdata);
			for (i = 2; i < bytes; i++) {
				u8 tx = *txp++;
				while (!(readb(&regs->status) &
					 TINY_SPI_STATUS_TXR))
					;
				writeb(tx, &regs->txdata);
			}
		}
		while (!(readb(&regs->status) &
			 TINY_SPI_STATUS_TXE))
			;
	} else {
		writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
		if (bytes > 1) {
			writeb(CONFIG_TINY_SPI_IDLE_VAL,
			       &regs->txdata);
			for (i = 2; i < bytes; i++) {
				while (!(readb(&regs->status) &
					 TINY_SPI_STATUS_TXR))
					;
				writeb(CONFIG_TINY_SPI_IDLE_VAL,
				       &regs->txdata);
			}
		}
		while (!(readb(&regs->status) &
			 TINY_SPI_STATUS_TXE))
			;
	}

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return 0;
}
Пример #12
0
static int mmc_spi_request(struct mmc *mmc, struct mmc_cmd *cmd,
		struct mmc_data *data)
{
	struct spi_slave *spi = mmc->priv;
	u8 r1;
	int i;
	int ret = 0;
	debug("%s:cmd%d %x %x\n", __func__,
	      cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
	spi_claim_bus(spi);
	spi_cs_activate(spi);
	r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
	if (r1 == 0xff) { /* no response */
		ret = NO_CARD_ERR;
		goto done;
	} else if (r1 & R1_SPI_COM_CRC) {
		ret = COMM_ERR;
		goto done;
	} else if (r1 & ~R1_SPI_IDLE) { /* other errors */
		ret = TIMEOUT;
		goto done;
	} else if (cmd->resp_type == MMC_RSP_R2) {
		r1 = mmc_spi_readdata(mmc, cmd->response, 1, 16);
		for (i = 0; i < 4; i++)
			cmd->response[i] = be32_to_cpu(cmd->response[i]);
		debug("r128 %x %x %x %x\n", cmd->response[0], cmd->response[1],
		      cmd->response[2], cmd->response[3]);
	} else if (!data) {
		switch (cmd->cmdidx) {
		case SD_CMD_APP_SEND_OP_COND:
		case MMC_CMD_SEND_OP_COND:
			cmd->response[0] = (r1 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
			break;
		case SD_CMD_SEND_IF_COND:
		case MMC_CMD_SPI_READ_OCR:
			spi_xfer(spi, 4 * 8, NULL, cmd->response, 0);
			cmd->response[0] = be32_to_cpu(cmd->response[0]);
			debug("r32 %x\n", cmd->response[0]);
			break;
		case MMC_CMD_SEND_STATUS:
			spi_xfer(spi, 1 * 8, NULL, cmd->response, 0);
			cmd->response[0] = (cmd->response[0] & 0xff) ?
				MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
			break;
		}
	} else {
		debug("%s:data %x %x %x\n", __func__,
		      data->flags, data->blocks, data->blocksize);
		if (data->flags == MMC_DATA_READ)
			r1 = mmc_spi_readdata(mmc, data->dest,
				data->blocks, data->blocksize);
		else if  (data->flags == MMC_DATA_WRITE)
			r1 = mmc_spi_writedata(mmc, data->src,
				data->blocks, data->blocksize,
				(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
		if (r1 & R1_SPI_COM_CRC)
			ret = COMM_ERR;
		else if (r1) /* other errors */
			ret = TIMEOUT;
	}
done:
	spi_cs_deactivate(spi);
	spi_release_bus(spi);
	return ret;
}
Пример #13
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
		const void *dout, void *din, unsigned long flags)
{
	struct atmel_spi_slave *as = to_atmel_spi(slave);
	unsigned int	len_tx;
	unsigned int	len_rx;
	unsigned int	len;
	u32		status;
	const u8	*txp = dout;
	u8		*rxp = din;
	u8		value;

	if (bitlen == 0)
		/* Finish any previously submitted transfers */
		goto out;

	/*
	 * TODO: The controller can do non-multiple-of-8 bit
	 * transfers, but this driver currently doesn't support it.
	 *
	 * It's also not clear how such transfers are supposed to be
	 * represented as a stream of bytes...this is a limitation of
	 * the current SPI interface.
	 */
	if (bitlen % 8) {
		/* Errors always terminate an ongoing transfer */
		flags |= SPI_XFER_END;
		goto out;
	}

	len = bitlen / 8;

	/*
	 * The controller can do automatic CS control, but it is
	 * somewhat quirky, and it doesn't really buy us much anyway
	 * in the context of U-Boot.
	 */
	if (flags & SPI_XFER_BEGIN) {
		spi_cs_activate(slave);
		/*
		 * sometimes the RDR is not empty when we get here,
		 * in theory that should not happen, but it DOES happen.
		 * Read it here to be on the safe side.
		 * That also clears the OVRES flag. Required if the
		 * following loop exits due to OVRES!
		 */
		spi_readl(as, RDR);
	}

	for (len_tx = 0, len_rx = 0; len_rx < len; ) {
		status = spi_readl(as, SR);

		if (status & ATMEL_SPI_SR_OVRES)
			return -1;

		if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) {
			if (txp)
				value = *txp++;
			else
				value = 0;
			spi_writel(as, TDR, value);
			len_tx++;
		}
		if (status & ATMEL_SPI_SR_RDRF) {
			value = spi_readl(as, RDR);
			if (rxp)
				*rxp++ = value;
			len_rx++;
		}
	}

out:
	if (flags & SPI_XFER_END) {
		/*
		 * Wait until the transfer is completely done before
		 * we deactivate CS.
		 */
		do {
			status = spi_readl(as, SR);
		} while (!(status & ATMEL_SPI_SR_TXEMPTY));

		spi_cs_deactivate(slave);
	}

	return 0;
}
static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen,
			    const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;
	struct zynq_spi_priv *priv = dev_get_priv(bus);
	struct zynq_spi_regs *regs = priv->regs;
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	u32 len = bitlen / 8;
	u32 tx_len = len, rx_len = len, tx_tvl;
	const u8 *tx_buf = dout;
	u8 *rx_buf = din, buf;
	u32 ts, status;

	debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
	      bus->seq, slave_plat->cs, bitlen, len, flags);

	if (bitlen % 8) {
		debug("spi_xfer: Non byte aligned SPI transfer\n");
		return -1;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(dev, slave_plat->cs);

	while (rx_len > 0) {
		/* Write the data into TX FIFO - tx threshold is fifo_depth */
		tx_tvl = 0;
		while ((tx_tvl < priv->fifo_depth) && tx_len) {
			if (tx_buf)
				buf = *tx_buf++;
			else
				buf = 0;
			writel(buf, &regs->txdr);
			tx_len--;
			tx_tvl++;
		}

		/* Check TX FIFO completion */
		ts = get_timer(0);
		status = readl(&regs->isr);
		while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
			if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
				printf("spi_xfer: Timeout! TX FIFO not full\n");
				return -1;
			}
			status = readl(&regs->isr);
		}

		/* Read the data from RX FIFO */
		status = readl(&regs->isr);
		while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
			buf = readl(&regs->rxdr);
			if (rx_buf)
				*rx_buf++ = buf;
			status = readl(&regs->isr);
			rx_len--;
		}
	}

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(dev);

	return 0;
}
Пример #15
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	MV_STATUS ret;
	MV_U8* pdout = (MV_U8*)dout;
	MV_U8* pdin = (MV_U8*)din;
	int tmp_bitlen = bitlen;
#if 0
	unsigned int tmpdout, tmpdin;
	int tm, isread = 0;

	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
	      slave->bus, slave->cs, dout, din, bitlen);

#endif

	//printf("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
	  //    slave->bus, slave->cs, dout, din, bitlen);

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

#if 0
	MV_STATUS ret;
	MV_U32 bytesLeft = buffSize;
	MV_U16* txPtr = (MV_U16*)pTxBuff;


	/* Check that the buffer pointer and the buffer size are 16bit aligned */
	if (((bitlen & 1) == 0) && ((dout & 1) == 0))
	{
	/* Verify that the SPI mode is in 16bit mode */
	MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);

	/* TX/RX as long we have complete 16bit chunks */
	while (bitlen >= MV_SPI_16_BIT_CHUNK_SIZE)
	{
        /* Transmitted and wait for the transfer to be completed */
		if ((ret = mvSpi16bitDataTxRx(*dout, *din)) != MV_OK)
			return ret;

		/* increment the pointers */
		txPtr++;
		bitlen -= MV_SPI_16_BIT_CHUNK_SIZE;
	}
    }
    else
    {
#endif
	
	/* Verify that the SPI mode is in 8bit mode */
	MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(0), MV_SPI_BYTE_LENGTH_MASK);

	/* TX/RX in 8bit chanks */
	
	while (tmp_bitlen > 0)
	{
		/* Transmitted and wait for the transfer to be completed */
		if ((ret = mvSpi8bitDataTxRx(0,*pdout, pdin)) != MV_OK)
			return ret;
		
		/* increment the pointers */
		//printf("in=[0x%x]",*pdin);
		if (pdin)
			pdin++;
		//printf("out=[0x%x]",*pdout);
		if (pdout)
			pdout++;

		tmp_bitlen-=8;
	}

#if 0
    }
#endif
	
#if 0
/*
	 * handle data in 8-bit chunks
	 * TBD: 2byte xfer mode to be enabled
	 */
	writel(((readl(&spireg->cfg) & ~KWSPI_XFERLEN_MASK) |
		KWSPI_XFERLEN_1BYTE), &spireg->cfg);

	while (bitlen > 4) {
		debug("loopstart bitlen %d\n", bitlen);
		tmpdout = 0;

		/* Shift data so it's msb-justified */
		if (dout)
			tmpdout = *(u32 *) dout & 0x0ff;

		writel(~KWSPI_SMEMRDIRQ, &spireg->irq_cause);
		writel(tmpdout, &spireg->dout);	/* Write the data out */
		debug("*** spi_xfer: ... %08x written, bitlen %d\n",
		      tmpdout, bitlen);

		/*
		 * Wait for SPI transmit to get out
		 * or time out (1 second = 1000 ms)
		 * The NE event must be read and cleared first
		 */
		for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
			if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) {
				isread = 1;
				tmpdin = readl(&spireg->din);
				debug
					("spi_xfer: din %08x..%08x read\n",
					din, tmpdin);

				if (din) {
					*((u8 *) din) = (u8) tmpdin;
					din += 1;
				}
				if (dout)
					dout += 1;
				bitlen -= 8;
			}
			if (isread)
				break;
		}
		if (tm >= KWSPI_TIMEOUT)
			printf("*** spi_xfer: Time out during SPI transfer\n");

		debug("loopend bitlen %d\n", bitlen);
	}



#endif

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return 0;
}
Пример #16
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
	     const void *dout, void *din, unsigned long flags)
{ 
 struct davinci_spi_slave *ds = to_davinci_spi(slave);
 //struct pl022 *pl022 = (struct pl022 *)ps->regs; 
 u32 len_tx = 0, len_rx = 0, len; 
 u32 ret = 0; 
 const u8 *txp = dout; 
 u8 *rxp = din, value; 
 
 if (bitlen == 0) 
 /* Finish any previously submitted transfers */ 
 goto out; 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 /* 
 * TODO: The controller can do non-multiple-of-8 bit 
 * transfers, but this driver currently doesn't support it. 
 * 
 * It's also not clear how such transfers are supposed to be 
 * represented as a stream of bytes...this is a limitation of 
 * the current SPI interface. 
 */ 
 if (bitlen % 8) { 
 ret = -1; 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 /* Errors always terminate an ongoing transfer */ 
 flags |= SPI_XFER_END; 
 goto out; 
 } 
 
 len = bitlen / 8; 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 if (flags & SPI_XFER_BEGIN) 
 spi_cs_activate(slave); 
 
 while (len_tx < len) { 
 if (readl(&ds->regs->flg) & 0x200) { 
 value = (txp != NULL) ? *txp++ : 0; 
 //writew(value, SSP_DR_REG); 
   //printf("ssp_sr=%x\n",IO_READ(SSP_SR_REG));
  writel(value, &ds->regs->dat1);
 len_tx++; 
 } 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 if (readl(&ds->regs->flg) & 0x100)  { 
 value = readl(&ds->regs->buf); 
 //printf("read back=%x\n",value);
 if (rxp) 
 *rxp++ = value; 
 len_rx++; 
 } 
 } 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 while (len_rx < len_tx) { 
 if (readl(&ds->regs->flg) & 0x100)  { 
 value = readl(&ds->regs->buf); 
 if (rxp) 
 *rxp++ = value; 
 len_rx++; 
 } 
 } 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
out: 
 if (flags & SPI_XFER_END) 
 spi_cs_deactivate(slave); 
  //printf("%s:%d\n",__FUNCTION__,__LINE__);
 return ret; 
} 
Пример #17
0
int spi_xfer(unsigned int len, const void *dout,
             void *din, unsigned long flags)
{
    unsigned int	len_tx;
    unsigned int	len_rx;
    const unsigned char	*txp = dout;
    unsigned char		*rxp = din;
    unsigned int 	status;
    unsigned char	value;

    if (len == 0)
        goto out;

    /*
     * The controller can do automatic CS control, but it is
     * somewhat quirky, and it doesn't really buy us much anyway
     * in the context of U-Boot.
     */
    if (flags & SPI_XFER_BEGIN) {
        spi_cs_activate();
        /*
         * sometimes the RDR is not empty when we get here,
         * in theory that should not happen, but it DOES happen.
         * Read it here to be on the safe side.
         * That also clears the OVRES flag. Required if the
         * following loop exits due to OVRES!
         */
        spi_readl(SPI_RDR);
        spi_readl(SPI_SR);
    }

    for (len_tx = 0, len_rx = 0; len_rx < len; ) {
        /* send data */
        if (len_tx < len) {
            do {
                status = spi_readl(SPI_SR);
            } while ((status & AT91C_SPI_TDRE) == 0);

            if (txp)
                value = *txp++;
            else
                value = 0;

            spi_writel(SPI_TDR, value);
            len_tx++;
        }

        /* recv data */
        do {
            status = spi_readl(SPI_SR);
            if (status & AT91C_SPI_OVRES) {
                spi_cs_deactivate();
                return -1;
            }
        } while ((status & AT91C_SPI_RDRF) == 0);

        value = spi_readl(SPI_RDR);
        if (rxp)
            *rxp++ = value;
        len_rx++;
    }

out:
    if (flags & SPI_XFER_END) {
        /*
         * Wait until the transfer is completely done before
         * we deactivate CS.
         */
        do {
            status = spi_readl(SPI_SR);
        } while (!(status & AT91C_SPI_TXEMPTY));

        spi_cs_deactivate();
    }

    return 0;
}
Пример #18
0
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	unsigned int tmpdout, tmpdin;
	int tm, isread = 0;

	debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n",
	      slave->bus, slave->cs, dout, din, bitlen);

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	/*
	 * handle data in 8-bit chunks
	 * TBD: 2byte xfer mode to be enabled
	 */
	writel(((readl(&spireg->cfg) & ~KWSPI_XFERLEN_MASK) |
		KWSPI_XFERLEN_1BYTE), &spireg->cfg);

	while (bitlen > 4) {
		debug("loopstart bitlen %d\n", bitlen);
		tmpdout = 0;

		/* Shift data so it's msb-justified */
		if (dout)
			tmpdout = *(u32 *) dout & 0x0ff;

		writel(~KWSPI_SMEMRDIRQ, &spireg->irq_cause);
		writel(tmpdout, &spireg->dout);	/* Write the data out */
		debug("*** spi_xfer: ... %08x written, bitlen %d\n",
		      tmpdout, bitlen);

		/*
		 * Wait for SPI transmit to get out
		 * or time out (1 second = 1000 ms)
		 * The NE event must be read and cleared first
		 */
		for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
			if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) {
				isread = 1;
				tmpdin = readl(&spireg->din);
				debug
					("spi_xfer: din %p..%08x read\n",
					din, tmpdin);

				if (din) {
					*((u8 *) din) = (u8) tmpdin;
					din += 1;
				}
				if (dout)
					dout += 1;
				bitlen -= 8;
			}
			if (isread)
				break;
		}
		if (tm >= KWSPI_TIMEOUT)
			printf("*** spi_xfer: Time out during SPI transfer\n");

		debug("loopend bitlen %d\n", bitlen);
	}

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return 0;
}
Пример #19
0
static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen,
			    const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;
	struct altera_spi_priv *priv = dev_get_priv(bus);
	struct altera_spi_regs *const regs = priv->regs;
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);

	/* assume spi core configured to do 8 bit transfers */
	unsigned int bytes = bitlen / 8;
	const unsigned char *txp = dout;
	unsigned char *rxp = din;
	uint32_t reg, data, start;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
	      bus->seq, slave_plat->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	/* empty read buffer */
	if (readl(&regs->status) & ALTERA_SPI_STATUS_RRDY_MSK)
		readl(&regs->rxdata);

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(dev, slave_plat->cs);

	while (bytes--) {
		if (txp)
			data = *txp++;
		else
			data = CONFIG_ALTERA_SPI_IDLE_VAL;

		debug("%s: tx:%x ", __func__, data);
		writel(data, &regs->txdata);

		start = get_timer(0);
		while (1) {
			reg = readl(&regs->status);
			if (reg & ALTERA_SPI_STATUS_RRDY_MSK)
				break;
			if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
				debug("%s: Transmission timed out!\n", __func__);
				return -1;
			}
		}

		data = readl(&regs->rxdata);
		if (rxp)
			*rxp++ = data & 0xff;

		debug("rx:%x\n", data);
	}

done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(dev);

	return 0;
}
Пример #20
0
/*
 * SPI transfer:
 *
 * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf
 * for more informations.
 */
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	s32 val = SPI_RETRY_TIMES;
	u32 *p_buf;
	u32 reg;
	s32 len = 0, ret_val = 0;
	s32 burst_bytes = bitlen >> 3;
	struct imx_spi_dev_t *dev = to_imx_spi_slave(slave);
	struct spi_reg_t *spi_reg = &(dev->reg);

	if (!slave)
		return -1;

	if ((bitlen % 8) != 0)
		burst_bytes++;

	if (burst_bytes > (dev->fifo_sz)) {
		printf("Error: maximum burst size is 0x%x bytes, asking 0x%x\n",
		       dev->fifo_sz, burst_bytes);
		return -1;
	}

	if (flags & SPI_XFER_BEGIN) {
		spi_cs_activate(slave);

		if (spi_reg->ctrl_reg == 0) {
			printf
			    ("Error: spi(base=0x%x) has not been initialized\n",
			     dev->base);
			return -1;
		}

		spi_reg->ctrl_reg = (spi_reg->ctrl_reg & ~SPI_CTRL_BURST_MASK) |
		    ((bitlen - 1) << SPI_CTRL_BURST_OFF);
		writel(spi_reg->ctrl_reg | SPI_CTRL_EN,
		       dev->base + SPI_CON_REG);
		debug("ctrl_reg=0x%x\n", readl(dev->base + SPI_CON_REG));

		/* move data to the tx fifo */
		if (dout) {
			for (p_buf = (u32 *) dout, len = burst_bytes; len > 0;
			     p_buf++, len -= 4)
				writel(*p_buf, dev->base + SPI_TX_DATA);
		}

		reg = readl(dev->base + SPI_CON_REG);
		reg |= SPI_CTRL_REG_XCH_BIT;	/* set xch bit */
		debug("control reg = 0x%08x\n", reg);
		writel(reg, dev->base + SPI_CON_REG);

		/* poll on the TC bit (transfer complete) */
		while ((val-- > 0) &&
		       (((reg =
			  readl(dev->base + SPI_STAT_REG)) & SPI_INT_STAT_TC) ==
			0));

		/* clear the TC bit */
		writel(reg | SPI_INT_STAT_TC, dev->base + SPI_STAT_REG);
		if (val <= 0) {
			printf
			    ("Error: re-tried %d times without response. Give up\n",
			     SPI_RETRY_TIMES);
			ret_val = -1;
			goto error;
		}
	}

	/* move data in the rx buf */
	if (flags & SPI_XFER_END) {
		if (din) {
			for (p_buf = (u32 *) din, len = burst_bytes; len > 0;
			     p_buf++, len -= 4)
				*p_buf = readl(dev->base + SPI_RX_DATA);
		}
	}
error:
	spi_cs_deactivate(slave);
	return ret_val;
}