+static u32 xilinx_spi_fill_txfifo(struct udevice *bus, const u8 *txp,
+ u32 txbytes)
+{
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
+ unsigned char d;
+ u32 i = 0;
+
+ while (txbytes && !(readl(®s->spisr) & SPISR_TX_FULL) &&
+ i < priv->fifo_depth) {
+ 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);
+ txbytes--;
+ i++;
+ }
+
+ return i;
+}
+
+static u32 xilinx_spi_read_rxfifo(struct udevice *bus, u8 *rxp, u32 rxbytes)
+{
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
+ unsigned char d;
+ unsigned int i = 0;
+
+ while (rxbytes && !(readl(®s->spisr) & SPISR_RX_EMPTY)) {
+ d = readl(®s->spidrr) & SPIDRR_8BIT_MASK;
+ if (rxp)
+ *rxp++ = d;
+ debug("spi_xfer: rx:%x\n", d);
+ rxbytes--;
+ i++;
+ }
+ debug("Rx_done\n");
+
+ return i;
+}
+
+static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes,
+ const void *dout, void *din)
+{
+ 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);
+ const unsigned char *txp = dout;
+ unsigned char *rxp = din;
+ u32 reg, count;
+ u32 txbytes = bytes;
+ u32 rxbytes = bytes;
+
+ /*
+ * This loop runs two times. First time to send the command.
+ * Second time to transfer data. After transferring data,
+ * it sets txp to the initial value for the normal operation.
+ */
+ for ( ; priv->startup < 2; priv->startup++) {
+ count = xilinx_spi_fill_txfifo(bus, txp, txbytes);
+ reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT;
+ writel(reg, ®s->spicr);
+ count = xilinx_spi_read_rxfifo(bus, rxp, rxbytes);
+ txp = din;
+
+ if (priv->startup) {
+ spi_cs_deactivate(dev);
+ spi_cs_activate(dev, slave_plat->cs);
+ txp = dout;
+ }
+ }
+}
+