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; }
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, ®s->ctrlr1); rkspi_enable_chip(regs, true); toread = todo; towrite = todo; while (toread || towrite) { u32 status = readl(®s->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; }
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; }
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; }
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; }
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; }
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; }
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; }
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(®s->spisr) & SPISR_RX_EMPTY)) { readl(®s->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, ®s->spidtr); while (timeout && readl(®s->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(®s->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; }
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; }
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++, ®s->txdata); if (bytes > 1) { writeb(*txp++, ®s->txdata); for (i = 2; i < bytes; i++) { u8 rx, tx = *txp++; while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; rx = readb(®s->txdata); writeb(tx, ®s->txdata); *rxp++ = rx; } while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; *rxp++ = readb(®s->txdata); } while (!(readb(®s->status) & TINY_SPI_STATUS_TXE)) ; *rxp++ = readb(®s->rxdata); } else if (rxp) { writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); if (bytes > 1) { writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); for (i = 2; i < bytes; i++) { u8 rx; while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; rx = readb(®s->txdata); writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); *rxp++ = rx; } while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; *rxp++ = readb(®s->txdata); } while (!(readb(®s->status) & TINY_SPI_STATUS_TXE)) ; *rxp++ = readb(®s->rxdata); } else if (txp) { writeb(*txp++, ®s->txdata); if (bytes > 1) { writeb(*txp++, ®s->txdata); for (i = 2; i < bytes; i++) { u8 tx = *txp++; while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; writeb(tx, ®s->txdata); } } while (!(readb(®s->status) & TINY_SPI_STATUS_TXE)) ; } else { writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); if (bytes > 1) { writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); for (i = 2; i < bytes; i++) { while (!(readb(®s->status) & TINY_SPI_STATUS_TXR)) ; writeb(CONFIG_TINY_SPI_IDLE_VAL, ®s->txdata); } } while (!(readb(®s->status) & TINY_SPI_STATUS_TXE)) ; } done: if (flags & SPI_XFER_END) spi_cs_deactivate(slave); return 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; }
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, ®s->txdr); tx_len--; tx_tvl++; } /* Check TX FIFO completion */ ts = get_timer(0); status = readl(®s->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(®s->isr); } /* Read the data from RX FIFO */ status = readl(®s->isr); while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) { buf = readl(®s->rxdr); if (rx_buf) *rx_buf++ = buf; status = readl(®s->isr); rx_len--; } } if (flags & SPI_XFER_END) spi_cs_deactivate(dev); return 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; }
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; }
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; }
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; }
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(®s->status) & ALTERA_SPI_STATUS_RRDY_MSK) readl(®s->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, ®s->txdata); start = get_timer(0); while (1) { reg = readl(®s->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(®s->rxdata); if (rxp) *rxp++ = data & 0xff; debug("rx:%x\n", data); } done: if (flags & SPI_XFER_END) spi_cs_deactivate(dev); return 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; }