summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorVipul Kumar <vipul.kumar@xilinx.com>2018-06-30 08:15:19 +0530
committerJagan Teki <jagan@amarulasolutions.com>2018-07-16 14:01:20 +0530
commit83ce646943f6bc8eb3a42e68eb53bbbe6c40123f (patch)
tree28ee1872f9c1b6dc3ceb37500bd333d3f01de911 /drivers
parent0c0de58f7b306e524225d03d8fd4fdd907a5ae5f (diff)
spi: xilinx_spi: Added support to read JEDEC-id twice at the boot time
This patch is for the startup block issue in the spi controller. SPI clock is passing through STARTUP block to FLASH. STARTUP block don't provide clock as soon as QSPI provides command. So, first command fails. This patch added support to read JEDEC id in xilinx_spi_xfer (). Signed-off-by: Vipul Kumar <vipul.kumar@xilinx.com> Reviewed-by: Jagan Teki <jagan@openedev.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/xilinx_spi.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 11b7343eb2..8621738b76 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -105,6 +105,7 @@ struct xilinx_spi_priv {
unsigned int freq;
unsigned int mode;
unsigned int fifo_depth;
+ u8 startup;
};
static int xilinx_spi_probe(struct udevice *bus)
@@ -205,6 +206,39 @@ static u32 xilinx_spi_read_rxfifo(struct udevice *bus, u8 *rxp, u32 rxbytes)
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(&regs->spicr) & ~SPICR_MASTER_INHIBIT;
+ writel(reg, &regs->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;
+ }
+ }
+}
+
static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
@@ -237,6 +271,13 @@ static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (flags & SPI_XFER_BEGIN)
spi_cs_activate(dev, slave_plat->cs);
+ /*
+ * This is the work around for the startup block issue in
+ * the spi controller. SPI clock is passing through STARTUP
+ * block to FLASH. STARTUP block don't provide clock as soon
+ * as QSPI provides command. So first command fails.
+ */
+ xilinx_spi_startup_block(dev, bytes, dout, din);
while (txbytes && rxbytes) {
count = xilinx_spi_fill_txfifo(bus, txp, txbytes);