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) {