]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
spi: xilinx-qps: Add support for dual stack and parallel configurations
authorSuneel Garapati <suneel.garapati@xilinx.com>
Tue, 18 Jun 2013 11:11:59 +0000 (16:41 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 20 Jun 2013 05:40:29 +0000 (07:40 +0200)
Added support in the driver to update accordingly the linear qspi
cfg register based on is-dual property.

is-dual=1 implies dual parallel configuration and is-dual=0 could be
single or dual stack and user has to manually enable
CONFIG_SPI_XILINX_PS_QSPI_DUAL_STACKED as Kconfig parameter to
use dual stack configuration.

Created CONFIG_SPI_XILINX_PS_QSPI_DUAL_STACKED Kconfig entry to
provide support for Dual Stack configuration.

Based on SPI_MASTER_U_PAGE bitmask in the transfer flags, choice is
made to select upper/lower flash.

Signed-off-by: Suneel Garapati <suneel.garapati@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/spi/Kconfig
drivers/spi/spi-xilinx-qps.c
include/linux/spi/spi.h

index b5d7bab22e31b7c8a7f6ebea12b0ad9e4cb66f77..d0112d7c7e493693f1020e11aa420d8520f34988 100644 (file)
@@ -460,6 +460,14 @@ config SPI_XILINX_PS_QSPI
        help
          This selects the PS Quad SPI controller master driver from the Xilinx.
 
+config SPI_XILINX_PS_QSPI_DUAL_STACKED
+       bool "Xilinx PS QSPI Dual stacked configuration"
+       depends on SPI_XILINX_PS_QSPI
+       help
+         This selects the PS Quad SPI controller in dual stacked mode.
+         Enable this option if your hw design is using dual stacked
+         configuration.
+
 config SPI_XILINX_PS_SPI
        tristate "Xilinx PS SPI controller"
        depends on ARCH_ZYNQ
index 270d951e3f139120e9db5dc2d8a06f8d1e7f1e25..fa6d20fbcdd555a6bd741a5e83a8a4d921cf75c5 100644 (file)
@@ -188,7 +188,7 @@ struct xqspips {
        u8 dev_busy;
        struct completion done;
        bool is_inst;
-       bool is_dual;
+       u32 is_dual;
 };
 
 /**
@@ -282,7 +282,13 @@ static void xqspips_init_hw(void __iomem *regs_base, int is_dual)
                         XQSPIPS_LCFG_SEP_BUS_MASK |
                         (1 << XQSPIPS_LCFG_DUMMY_SHIFT) |
                         XQSPIPS_FAST_READ_QOUT_CODE));
-
+#ifdef CONFIG_SPI_XILINX_PS_QSPI_DUAL_STACKED
+       /* Enable two memories on shared bus */
+       xqspips_write(regs_base + XQSPIPS_LINEAR_CFG_OFFSET,
+                (XQSPIPS_LCFG_TWO_MEM_MASK |
+                (1 << XQSPIPS_LCFG_DUMMY_SHIFT) |
+                XQSPIPS_FAST_READ_QOUT_CODE));
+#endif
        xqspips_write(regs_base + XQSPIPS_ENABLE_OFFSET,
                        XQSPIPS_ENABLE_ENABLE_MASK);
 }
@@ -624,31 +630,6 @@ static int xqspips_start_transfer(struct spi_device *qspi,
 
                curr_inst = &flash_inst[index];
 
-               /* In case of dual memories, convert 25 bit address to 24 bit
-                * address before transmitting to the 2 memories
-                */
-               if ((xqspi->is_dual == 1) &&
-                   ((instruction == XQSPIPS_FLASH_OPCODE_PP) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_SE) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_BE_32K) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_BE_4K) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_BE) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_NORM_READ) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_FAST_READ) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_DUAL_READ) ||
-                    (instruction == XQSPIPS_FLASH_OPCODE_QUAD_READ))) {
-
-                       u8 *ptr = (u8 *) (xqspi->txbuf);
-                       data = ((u32) ptr[1] << 24) | ((u32) ptr[2] << 16) |
-                               ((u32) ptr[3] << 8) | ((u32) ptr[4]);
-                       data = data >> 1;
-                       ptr[1] = (u8) (data >> 16);
-                       ptr[2] = (u8) (data >> 8);
-                       ptr[3] = (u8) (data);
-                       xqspi->bytes_to_transfer -= 1;
-                       xqspi->bytes_to_receive -= 1;
-               }
-
                /* Get the instruction */
                data = 0;
                xqspips_copy_write_data(xqspi, &data,
@@ -698,6 +679,9 @@ static void xqspips_work_queue(struct work_struct *work)
 {
        struct xqspips *xqspi = container_of(work, struct xqspips, work);
        unsigned long flags;
+#ifdef CONFIG_SPI_XILINX_PS_QSPI_DUAL_STACKED
+       u32 lqspi_cfg_reg;
+#endif
 
        spin_lock_irqsave(&xqspi->trans_queue_lock, flags);
        xqspi->dev_busy = 1;
@@ -724,6 +708,18 @@ static void xqspips_work_queue(struct work_struct *work)
                spin_unlock_irqrestore(&xqspi->trans_queue_lock, flags);
                qspi = msg->spi;
 
+#ifdef CONFIG_SPI_XILINX_PS_QSPI_DUAL_STACKED
+               lqspi_cfg_reg = xqspips_read(xqspi->regs +
+                                       XQSPIPS_LINEAR_CFG_OFFSET);
+               if (qspi->master->flags & SPI_MASTER_U_PAGE)
+                       lqspi_cfg_reg |= XQSPIPS_LCFG_U_PAGE_MASK;
+               else {
+                       lqspi_cfg_reg &= ~XQSPIPS_LCFG_U_PAGE_MASK;
+                       xqspips_write(xqspi->regs + XQSPIPS_LINEAR_CFG_OFFSET,
+                                       lqspi_cfg_reg);
+               }
+#endif
+
                list_for_each_entry(transfer, &msg->transfers, transfer_list) {
                        if (transfer->bits_per_word || transfer->speed_hz) {
                                status = xqspips_setup_transfer(qspi, transfer);
@@ -1063,10 +1059,7 @@ static int xqspips_probe(struct platform_device *dev)
                goto unmap_io;
        }
 
-       prop = of_get_property(dev->dev.of_node, "is-dual", NULL);
-       if (prop)
-               xqspi->is_dual = be32_to_cpup(prop);
-       else
+       if (of_property_read_u32(dev->dev.of_node, "is-dual", &xqspi->is_dual))
                dev_warn(&dev->dev, "couldn't determine configuration info "
                         "about dual memories. defaulting to single memory\n");
 
index 38c2b925923d5c2d0423ce8956beecede08078fc..b9ed552c2e427e69ff622358b8491d365a8b6fd6 100644 (file)
@@ -306,6 +306,7 @@ struct spi_master {
 #define SPI_MASTER_HALF_DUPLEX BIT(0)          /* can't do full duplex */
 #define SPI_MASTER_NO_RX       BIT(1)          /* can't do buffer read */
 #define SPI_MASTER_NO_TX       BIT(2)          /* can't do buffer write */
+#define SPI_MASTER_U_PAGE      BIT(3)          /* select upper flash */
 
        /* lock and mutex for SPI bus locking */
        spinlock_t              bus_lock_spinlock;