aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-zynq-qspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-zynq-qspi.c')
-rw-r--r--drivers/spi/spi-zynq-qspi.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c
index e76f9c9738f0..17641157354d 100644
--- a/drivers/spi/spi-zynq-qspi.c
+++ b/drivers/spi/spi-zynq-qspi.c
@@ -114,8 +114,8 @@
*/
#define ZYNQ_QSPI_MODEBITS (SPI_CPOL | SPI_CPHA)
-/* Default number of chip selects */
-#define ZYNQ_QSPI_DEFAULT_NUM_CS 1
+/* Maximum number of chip selects */
+#define ZYNQ_QSPI_MAX_NUM_CS 2
/**
* struct zynq_qspi - Defines qspi driver instance
@@ -159,6 +159,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset,
/**
* zynq_qspi_init_hw - Initialize the hardware
* @xqspi: Pointer to the zynq_qspi structure
+ * @num_cs: Number of connected CS (to enable dual memories if needed)
*
* The default settings of the QSPI controller's configurable parameters on
* reset are
@@ -176,7 +177,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset,
* - Set the little endian mode of TX FIFO and
* - Enable the QSPI controller
*/
-static void zynq_qspi_init_hw(struct zynq_qspi *xqspi)
+static void zynq_qspi_init_hw(struct zynq_qspi *xqspi, unsigned int num_cs)
{
u32 config_reg;
@@ -184,7 +185,12 @@ static void zynq_qspi_init_hw(struct zynq_qspi *xqspi)
zynq_qspi_write(xqspi, ZYNQ_QSPI_IDIS_OFFSET, ZYNQ_QSPI_IXR_ALL_MASK);
/* Disable linear mode as the boot loader may have used it */
- zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, 0);
+ config_reg = 0;
+ /* At the same time, enable dual mode if more than 1 CS is available */
+ if (num_cs > 1)
+ config_reg |= ZYNQ_QSPI_LCFG_TWO_MEM;
+
+ zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg);
/* Clear the RX FIFO */
while (zynq_qspi_read(xqspi, ZYNQ_QSPI_STATUS_OFFSET) &
@@ -286,6 +292,17 @@ static void zynq_qspi_chipselect(struct spi_device *spi, bool assert)
struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr);
u32 config_reg;
+ /* Select the lower (CS0) or upper (CS1) memory */
+ if (ctlr->num_chipselect > 1) {
+ config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET);
+ if (!spi->chip_select)
+ config_reg &= ~ZYNQ_QSPI_LCFG_U_PAGE;
+ else
+ config_reg |= ZYNQ_QSPI_LCFG_U_PAGE;
+
+ zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg);
+ }
+
/* Ground the line to assert the CS */
config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET);
if (assert)
@@ -673,9 +690,9 @@ static int zynq_qspi_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "num-cs",
&num_cs);
if (ret < 0) {
- ctlr->num_chipselect = ZYNQ_QSPI_DEFAULT_NUM_CS;
- } else if (num_cs > ZYNQ_QSPI_DEFAULT_NUM_CS) {
- dev_err(&pdev->dev, "anything but CS0 is not yet supported\n");
+ ctlr->num_chipselect = 1;
+ } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) {
+ dev_err(&pdev->dev, "only 2 chip selects are available\n");
goto remove_master;
} else {
ctlr->num_chipselect = num_cs;
@@ -689,7 +706,7 @@ static int zynq_qspi_probe(struct platform_device *pdev)
ctlr->dev.of_node = np;
/* QSPI controller initializations */
- zynq_qspi_init_hw(xqspi);
+ zynq_qspi_init_hw(xqspi, ctlr->num_chipselect);
ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret) {