linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/3] mtd: spi-nor: Add Octal SPI support to Cadence QSPI driver.
@ 2017-03-06 12:32 Artur Jedrysek
  2017-03-06 21:21 ` Boris Brezillon
  0 siblings, 1 reply; 3+ messages in thread
From: Artur Jedrysek @ 2017-03-06 12:32 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, Cyrille Pitchen, Marek Vasut, David Woodhouse,
	Brian Norris, Boris Brezillon, Richard Weinberger,
	Artur Jedrysek

Recent versions of Cadence QSPI controller support Octal SPI transfers
as well. This patch updates existing driver to support such feature.

It is not possible to determine whether or not octal mode is supported
just by looking at revision register alone. To solve that, an additional
property in Device Tree is added to indicate such capability.
Both (revision and DT property) are used to determine, which mode to
pass to spi_nor_scan() call.

Additionally, the driver works on Xtensa CPU, hence Kconfig update.

Signed-off-by: Artur Jedrysek <jartur@cadence.com>
---
 drivers/mtd/spi-nor/Kconfig           |  2 +-
 drivers/mtd/spi-nor/cadence-quadspi.c | 40 ++++++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 7252087..f195749 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -50,7 +50,7 @@ config SPI_ATMEL_QUADSPI
 
 config SPI_CADENCE_QUADSPI
 	tristate "Cadence Quad SPI controller"
-	depends on OF && (ARM || COMPILE_TEST)
+	depends on OF && (ARM || XTENSA || COMPILE_TEST)
 	help
 	  Enable support for the Cadence Quad SPI Flash controller.
 
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
index 9f8102d..5c06102 100644
--- a/drivers/mtd/spi-nor/cadence-quadspi.c
+++ b/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -87,6 +87,7 @@ struct cqspi_st {
 #define CQSPI_INST_TYPE_SINGLE			0
 #define CQSPI_INST_TYPE_DUAL			1
 #define CQSPI_INST_TYPE_QUAD			2
+#define CQSPI_INST_TYPE_OCTAL			3
 
 #define CQSPI_DUMMY_CLKS_PER_BYTE		8
 #define CQSPI_DUMMY_BYTES_MAX			4
@@ -204,6 +205,14 @@ struct cqspi_st {
 #define CQSPI_REG_CMDWRITEDATALOWER		0xA8
 #define CQSPI_REG_CMDWRITEDATAUPPER		0xAC
 
+#define CQSPI_REG_MODULEID			0xFC
+#define CQSPI_REG_MODULEID_CONF_ID_MASK		0x3
+#define CQSPI_REG_MODULEID_CONF_ID_LSB		0
+#define CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY	0x0
+#define CQSPI_REG_MODULEID_CONF_ID_OCTAL	0x1
+#define CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY	0x2
+#define CQSPI_REG_MODULEID_CONF_ID_QUAD		0x3
+
 /* Interrupt status bits */
 #define CQSPI_REG_IRQ_MODE_ERR			BIT(0)
 #define CQSPI_REG_IRQ_UNDERFLOW			BIT(1)
@@ -866,6 +875,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read)
 		case SPI_NOR_QUAD:
 			f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
 			break;
+		case SPI_NOR_OCTAL:
+			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -1074,9 +1086,35 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
 	struct cqspi_flash_pdata *f_pdata;
 	struct spi_nor *nor;
 	struct mtd_info *mtd;
+	enum read_mode mode;
+	enum read_mode dt_mode = SPI_NOR_QUAD;
 	unsigned int cs;
+	unsigned int rev_reg;
 	int i, ret;
 
+	/* Determine, whether or not octal transfer MAY be supported */
+	rev_reg = readl(cqspi->iobase + CQSPI_REG_MODULEID);
+	dev_info(dev, "CQSPI Module id %x\n", rev_reg);
+
+	switch (rev_reg & CQSPI_REG_MODULEID_CONF_ID_MASK) {
+	case CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY:
+	case CQSPI_REG_MODULEID_CONF_ID_OCTAL:
+		mode = SPI_NOR_OCTAL;
+		break;
+	case CQSPI_REG_MODULEID_CONF_ID_QUAD:
+	case CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY:
+		mode = SPI_NOR_QUAD;
+		break;
+	}
+
+	if (of_property_read_bool(np, "cdns,octal-controller"))
+		dt_mode = SPI_NOR_OCTAL;
+
+	if (mode == SPI_NOR_QUAD && dt_mode == SPI_NOR_OCTAL)
+		dev_warn(dev, "Requested octal mode is not supported by the device.");
+	else if (mode == SPI_NOR_OCTAL && dt_mode == SPI_NOR_QUAD)
+		mode = SPI_NOR_QUAD;
+
 	/* Get flash device data */
 	for_each_available_child_of_node(dev->of_node, np) {
 		ret = of_property_read_u32(np, "reg", &cs);
@@ -1123,7 +1161,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
 			goto err;
 		}
 
-		ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+		ret = spi_nor_scan(nor, NULL, mode);
 		if (ret)
 			goto err;
 
-- 
2.2.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add Octal SPI support to Cadence QSPI driver.
  2017-03-06 12:32 [PATCH 2/3] mtd: spi-nor: Add Octal SPI support to Cadence QSPI driver Artur Jedrysek
@ 2017-03-06 21:21 ` Boris Brezillon
  2017-03-07  8:26   ` Artur Jedrysek
  0 siblings, 1 reply; 3+ messages in thread
From: Boris Brezillon @ 2017-03-06 21:21 UTC (permalink / raw)
  To: Artur Jedrysek
  Cc: linux-mtd, linux-kernel, Cyrille Pitchen, Marek Vasut,
	David Woodhouse, Brian Norris, Richard Weinberger

On Mon, 6 Mar 2017 12:32:25 +0000
Artur Jedrysek <jartur@cadence.com> wrote:

> Recent versions of Cadence QSPI controller support Octal SPI transfers
> as well. This patch updates existing driver to support such feature.
> 
> It is not possible to determine whether or not octal mode is supported
> just by looking at revision register alone. To solve that, an additional
> property in Device Tree is added to indicate such capability.
> Both (revision and DT property) are used to determine, which mode to
> pass to spi_nor_scan() call.

Hm, can we add a new compatible instead? Adding extra properties to
describe the set of functionalities supported by an IP is usually a
bad idea.

> 
> Additionally, the driver works on Xtensa CPU, hence Kconfig update.

This should be done in a separate commit (it has nothing to do with
octal mode support).

> 
> Signed-off-by: Artur Jedrysek <jartur@cadence.com>
> ---
>  drivers/mtd/spi-nor/Kconfig           |  2 +-
>  drivers/mtd/spi-nor/cadence-quadspi.c | 40 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
> index 7252087..f195749 100644
> --- a/drivers/mtd/spi-nor/Kconfig
> +++ b/drivers/mtd/spi-nor/Kconfig
> @@ -50,7 +50,7 @@ config SPI_ATMEL_QUADSPI
>  
>  config SPI_CADENCE_QUADSPI
>  	tristate "Cadence Quad SPI controller"
> -	depends on OF && (ARM || COMPILE_TEST)
> +	depends on OF && (ARM || XTENSA || COMPILE_TEST)
>  	help
>  	  Enable support for the Cadence Quad SPI Flash controller.
>  
> diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
> index 9f8102d..5c06102 100644
> --- a/drivers/mtd/spi-nor/cadence-quadspi.c
> +++ b/drivers/mtd/spi-nor/cadence-quadspi.c
> @@ -87,6 +87,7 @@ struct cqspi_st {
>  #define CQSPI_INST_TYPE_SINGLE			0
>  #define CQSPI_INST_TYPE_DUAL			1
>  #define CQSPI_INST_TYPE_QUAD			2
> +#define CQSPI_INST_TYPE_OCTAL			3
>  
>  #define CQSPI_DUMMY_CLKS_PER_BYTE		8
>  #define CQSPI_DUMMY_BYTES_MAX			4
> @@ -204,6 +205,14 @@ struct cqspi_st {
>  #define CQSPI_REG_CMDWRITEDATALOWER		0xA8
>  #define CQSPI_REG_CMDWRITEDATAUPPER		0xAC
>  
> +#define CQSPI_REG_MODULEID			0xFC
> +#define CQSPI_REG_MODULEID_CONF_ID_MASK		0x3
> +#define CQSPI_REG_MODULEID_CONF_ID_LSB		0
> +#define CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY	0x0
> +#define CQSPI_REG_MODULEID_CONF_ID_OCTAL	0x1
> +#define CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY	0x2
> +#define CQSPI_REG_MODULEID_CONF_ID_QUAD		0x3
> +
>  /* Interrupt status bits */
>  #define CQSPI_REG_IRQ_MODE_ERR			BIT(0)
>  #define CQSPI_REG_IRQ_UNDERFLOW			BIT(1)
> @@ -866,6 +875,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read)
>  		case SPI_NOR_QUAD:
>  			f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
>  			break;
> +		case SPI_NOR_OCTAL:
> +			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
> +			break;
>  		default:
>  			return -EINVAL;
>  		}
> @@ -1074,9 +1086,35 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
>  	struct cqspi_flash_pdata *f_pdata;
>  	struct spi_nor *nor;
>  	struct mtd_info *mtd;
> +	enum read_mode mode;
> +	enum read_mode dt_mode = SPI_NOR_QUAD;
>  	unsigned int cs;
> +	unsigned int rev_reg;
>  	int i, ret;
>  
> +	/* Determine, whether or not octal transfer MAY be supported */
> +	rev_reg = readl(cqspi->iobase + CQSPI_REG_MODULEID);
> +	dev_info(dev, "CQSPI Module id %x\n", rev_reg);
> +
> +	switch (rev_reg & CQSPI_REG_MODULEID_CONF_ID_MASK) {
> +	case CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY:
> +	case CQSPI_REG_MODULEID_CONF_ID_OCTAL:
> +		mode = SPI_NOR_OCTAL;
> +		break;
> +	case CQSPI_REG_MODULEID_CONF_ID_QUAD:
> +	case CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY:
> +		mode = SPI_NOR_QUAD;
> +		break;
> +	}
> +
> +	if (of_property_read_bool(np, "cdns,octal-controller"))
> +		dt_mode = SPI_NOR_OCTAL;
> +
> +	if (mode == SPI_NOR_QUAD && dt_mode == SPI_NOR_OCTAL)
> +		dev_warn(dev, "Requested octal mode is not supported by the device.");
> +	else if (mode == SPI_NOR_OCTAL && dt_mode == SPI_NOR_QUAD)
> +		mode = SPI_NOR_QUAD;
> +
>  	/* Get flash device data */
>  	for_each_available_child_of_node(dev->of_node, np) {
>  		ret = of_property_read_u32(np, "reg", &cs);
> @@ -1123,7 +1161,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
>  			goto err;
>  		}
>  
> -		ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
> +		ret = spi_nor_scan(nor, NULL, mode);
>  		if (ret)
>  			goto err;
>  

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCH 2/3] mtd: spi-nor: Add Octal SPI support to Cadence QSPI driver.
  2017-03-06 21:21 ` Boris Brezillon
@ 2017-03-07  8:26   ` Artur Jedrysek
  0 siblings, 0 replies; 3+ messages in thread
From: Artur Jedrysek @ 2017-03-07  8:26 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: linux-mtd, linux-kernel, Cyrille Pitchen, Marek Vasut,
	David Woodhouse, Brian Norris, Richard Weinberger

From: Boris Brezillon [mailto:boris.brezillon@free-electrons.com]
Sent: 6 march 2017 22:21

> On Mon, 6 Mar 2017 12:32:25 +0000
> Artur Jedrysek <jartur@cadence.com> wrote:
> 
> > Recent versions of Cadence QSPI controller support Octal SPI transfers
> > as well. This patch updates existing driver to support such feature.
> >
> > It is not possible to determine whether or not octal mode is supported
> > just by looking at revision register alone. To solve that, an
> > additional property in Device Tree is added to indicate such capability.
> > Both (revision and DT property) are used to determine, which mode to
> > pass to spi_nor_scan() call.
> 
> Hm, can we add a new compatible instead? Adding extra properties to describe the set of
> functionalities supported by an IP is usually a bad idea.
> 

Thank you for the suggestion. I will try that approach, and if it succeeds, I will use it in the next version of the patch.

> >
> > Additionally, the driver works on Xtensa CPU, hence Kconfig update.
> 
> This should be done in a separate commit (it has nothing to do with octal mode support).
> 

It will be done in separate commit in the next version of the patch.

> >
> > Signed-off-by: Artur Jedrysek <jartur@cadence.com>
> > ---
> >  drivers/mtd/spi-nor/Kconfig           |  2 +-
> >  drivers/mtd/spi-nor/cadence-quadspi.c | 40
> > ++++++++++++++++++++++++++++++++++-
> >  2 files changed, 40 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
> > index 7252087..f195749 100644
> > --- a/drivers/mtd/spi-nor/Kconfig
> > +++ b/drivers/mtd/spi-nor/Kconfig
> > @@ -50,7 +50,7 @@ config SPI_ATMEL_QUADSPI
> >
> >  config SPI_CADENCE_QUADSPI
> >  	tristate "Cadence Quad SPI controller"
> > -	depends on OF && (ARM || COMPILE_TEST)
> > +	depends on OF && (ARM || XTENSA || COMPILE_TEST)
> >  	help
> >  	  Enable support for the Cadence Quad SPI Flash controller.
> >
> > diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c
> > b/drivers/mtd/spi-nor/cadence-quadspi.c
> > index 9f8102d..5c06102 100644
> > --- a/drivers/mtd/spi-nor/cadence-quadspi.c
> > +++ b/drivers/mtd/spi-nor/cadence-quadspi.c
> > @@ -87,6 +87,7 @@ struct cqspi_st {
> >  #define CQSPI_INST_TYPE_SINGLE			0
> >  #define CQSPI_INST_TYPE_DUAL			1
> >  #define CQSPI_INST_TYPE_QUAD			2
> > +#define CQSPI_INST_TYPE_OCTAL			3
> >
> >  #define CQSPI_DUMMY_CLKS_PER_BYTE		8
> >  #define CQSPI_DUMMY_BYTES_MAX			4
> > @@ -204,6 +205,14 @@ struct cqspi_st {
> >  #define CQSPI_REG_CMDWRITEDATALOWER		0xA8
> >  #define CQSPI_REG_CMDWRITEDATAUPPER		0xAC
> >
> > +#define CQSPI_REG_MODULEID			0xFC
> > +#define CQSPI_REG_MODULEID_CONF_ID_MASK		0x3
> > +#define CQSPI_REG_MODULEID_CONF_ID_LSB		0
> > +#define CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY	0x0
> > +#define CQSPI_REG_MODULEID_CONF_ID_OCTAL	0x1
> > +#define CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY	0x2
> > +#define CQSPI_REG_MODULEID_CONF_ID_QUAD		0x3
> > +
> >  /* Interrupt status bits */
> >  #define CQSPI_REG_IRQ_MODE_ERR			BIT(0)
> >  #define CQSPI_REG_IRQ_UNDERFLOW			BIT(1)
> > @@ -866,6 +875,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read)
> >  		case SPI_NOR_QUAD:
> >  			f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
> >  			break;
> > +		case SPI_NOR_OCTAL:
> > +			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
> > +			break;
> >  		default:
> >  			return -EINVAL;
> >  		}
> > @@ -1074,9 +1086,35 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
> >  	struct cqspi_flash_pdata *f_pdata;
> >  	struct spi_nor *nor;
> >  	struct mtd_info *mtd;
> > +	enum read_mode mode;
> > +	enum read_mode dt_mode = SPI_NOR_QUAD;
> >  	unsigned int cs;
> > +	unsigned int rev_reg;
> >  	int i, ret;
> >
> > +	/* Determine, whether or not octal transfer MAY be supported */
> > +	rev_reg = readl(cqspi->iobase + CQSPI_REG_MODULEID);
> > +	dev_info(dev, "CQSPI Module id %x\n", rev_reg);
> > +
> > +	switch (rev_reg & CQSPI_REG_MODULEID_CONF_ID_MASK) {
> > +	case CQSPI_REG_MODULEID_CONF_ID_OCTAL_PHY:
> > +	case CQSPI_REG_MODULEID_CONF_ID_OCTAL:
> > +		mode = SPI_NOR_OCTAL;
> > +		break;
> > +	case CQSPI_REG_MODULEID_CONF_ID_QUAD:
> > +	case CQSPI_REG_MODULEID_CONF_ID_QUAD_PHY:
> > +		mode = SPI_NOR_QUAD;
> > +		break;
> > +	}
> > +
> > +	if (of_property_read_bool(np, "cdns,octal-controller"))
> > +		dt_mode = SPI_NOR_OCTAL;
> > +
> > +	if (mode == SPI_NOR_QUAD && dt_mode == SPI_NOR_OCTAL)
> > +		dev_warn(dev, "Requested octal mode is not supported by the device.");
> > +	else if (mode == SPI_NOR_OCTAL && dt_mode == SPI_NOR_QUAD)
> > +		mode = SPI_NOR_QUAD;
> > +
> >  	/* Get flash device data */
> >  	for_each_available_child_of_node(dev->of_node, np) {
> >  		ret = of_property_read_u32(np, "reg", &cs); @@ -1123,7 +1161,7 @@
> > static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
> >  			goto err;
> >  		}
> >
> > -		ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
> > +		ret = spi_nor_scan(nor, NULL, mode);
> >  		if (ret)
> >  			goto err;
> >

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-03-07  8:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-06 12:32 [PATCH 2/3] mtd: spi-nor: Add Octal SPI support to Cadence QSPI driver Artur Jedrysek
2017-03-06 21:21 ` Boris Brezillon
2017-03-07  8:26   ` Artur Jedrysek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).