All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-08  0:11 ` Mans Rullgard
  0 siblings, 0 replies; 23+ messages in thread
From: Mans Rullgard @ 2016-01-08  0:11 UTC (permalink / raw)
  To: Nicolas Ferre, Mark Brown, linux-spi, linux-kernel

The driver currently chooses between internal chip-select or gpio
based on the existence of the cs-gpios DT property which fails on
non-DT systems and also enforces the same choice for all devices.

This patch makes the method per device instead of per controller
and fixes the selection on non-DT systems.  With these changes,
the chip-select method for each device is chosen according to the
following priority:

1. GPIO from device tree
2. GPIO from platform data
3. Internal chip-select

Tested on AVR32 ATSTK1000.

Signed-off-by: Mans Rullgard <mans@mansr.com>
---
 drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index aebad36391c9..8be07fb67d4d 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -310,7 +310,6 @@ struct atmel_spi {
 
 	bool			use_dma;
 	bool			use_pdc;
-	bool			use_cs_gpios;
 	/* dmaengine data */
 	struct atmel_spi_dma	dma;
 
@@ -324,6 +323,7 @@ struct atmel_spi {
 struct atmel_spi_device {
 	unsigned int		npcs_pin;
 	u32			csr;
+	bool			use_cs_gpio;
 };
 
 #define BUFFER_SIZE		PAGE_SIZE
@@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 		}
 
 		mr = spi_readl(as, MR);
-		if (as->use_cs_gpios)
+		if (asd->use_cs_gpio)
 			gpio_set_value(asd->npcs_pin, active);
 	} else {
 		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
@@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 
 		mr = spi_readl(as, MR);
 		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
-		if (as->use_cs_gpios && spi->chip_select != 0)
+		if (asd->use_cs_gpio && spi->chip_select != 0)
 			gpio_set_value(asd->npcs_pin, active);
 		spi_writel(as, MR, mr);
 	}
@@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 			asd->npcs_pin, active ? " (low)" : "",
 			mr);
 
-	if (!as->use_cs_gpios)
+	if (!asd->use_cs_gpio)
 		spi_writel(as, CR, SPI_BIT(LASTXFER));
 	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
 		gpio_set_value(asd->npcs_pin, !active);
@@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
 		csr |= SPI_BIT(CPOL);
 	if (!(spi->mode & SPI_CPHA))
 		csr |= SPI_BIT(NCPHA);
-	if (!as->use_cs_gpios)
-		csr |= SPI_BIT(CSAAT);
 
 	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
 	 *
@@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
 	csr |= SPI_BF(DLYBS, 0);
 	csr |= SPI_BF(DLYBCT, 0);
 
-	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned long)spi->controller_data;
-
-	if (!as->use_cs_gpios)
-		npcs_pin = spi->chip_select;
-	else if (gpio_is_valid(spi->cs_gpio))
-		npcs_pin = spi->cs_gpio;
-
 	asd = spi->controller_state;
 	if (!asd) {
 		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
 		if (!asd)
 			return -ENOMEM;
 
-		if (as->use_cs_gpios) {
+		npcs_pin = (unsigned long)spi->controller_data;
+
+		if (gpio_is_valid(spi->cs_gpio)) {
+			/* GPIO from DT */
+			npcs_pin = spi->cs_gpio;
+			asd->use_cs_gpio = true;
+		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
+			/* GPIO from platform data */
+			asd->use_cs_gpio = true;
+		} else {
+			/* internal chip-select */
+			npcs_pin = spi->chip_select;
+			asd->use_cs_gpio = false;
+		}
+
+		if (asd->use_cs_gpio) {
 			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
 			if (ret) {
 				kfree(asd);
@@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
 		spi->controller_state = asd;
 	}
 
+	if (!asd->use_cs_gpio)
+		csr |= SPI_BIT(CSAAT);
 	asd->csr = csr;
 
 	dev_dbg(&spi->dev,
@@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
 	atmel_get_caps(as);
 
-	as->use_cs_gpios = true;
-	if (atmel_spi_is_v2(as) &&
-	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
-		as->use_cs_gpios = false;
-		master->num_chipselect = 4;
-	}
-
 	as->use_dma = false;
 	as->use_pdc = false;
 	if (as->caps.has_dma_support) {
-- 
2.7.0

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-08  0:11 ` Mans Rullgard
  0 siblings, 0 replies; 23+ messages in thread
From: Mans Rullgard @ 2016-01-08  0:11 UTC (permalink / raw)
  To: Nicolas Ferre, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

The driver currently chooses between internal chip-select or gpio
based on the existence of the cs-gpios DT property which fails on
non-DT systems and also enforces the same choice for all devices.

This patch makes the method per device instead of per controller
and fixes the selection on non-DT systems.  With these changes,
the chip-select method for each device is chosen according to the
following priority:

1. GPIO from device tree
2. GPIO from platform data
3. Internal chip-select

Tested on AVR32 ATSTK1000.

Signed-off-by: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
---
 drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index aebad36391c9..8be07fb67d4d 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -310,7 +310,6 @@ struct atmel_spi {
 
 	bool			use_dma;
 	bool			use_pdc;
-	bool			use_cs_gpios;
 	/* dmaengine data */
 	struct atmel_spi_dma	dma;
 
@@ -324,6 +323,7 @@ struct atmel_spi {
 struct atmel_spi_device {
 	unsigned int		npcs_pin;
 	u32			csr;
+	bool			use_cs_gpio;
 };
 
 #define BUFFER_SIZE		PAGE_SIZE
@@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 		}
 
 		mr = spi_readl(as, MR);
-		if (as->use_cs_gpios)
+		if (asd->use_cs_gpio)
 			gpio_set_value(asd->npcs_pin, active);
 	} else {
 		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
@@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 
 		mr = spi_readl(as, MR);
 		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
-		if (as->use_cs_gpios && spi->chip_select != 0)
+		if (asd->use_cs_gpio && spi->chip_select != 0)
 			gpio_set_value(asd->npcs_pin, active);
 		spi_writel(as, MR, mr);
 	}
@@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 			asd->npcs_pin, active ? " (low)" : "",
 			mr);
 
-	if (!as->use_cs_gpios)
+	if (!asd->use_cs_gpio)
 		spi_writel(as, CR, SPI_BIT(LASTXFER));
 	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
 		gpio_set_value(asd->npcs_pin, !active);
@@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
 		csr |= SPI_BIT(CPOL);
 	if (!(spi->mode & SPI_CPHA))
 		csr |= SPI_BIT(NCPHA);
-	if (!as->use_cs_gpios)
-		csr |= SPI_BIT(CSAAT);
 
 	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
 	 *
@@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
 	csr |= SPI_BF(DLYBS, 0);
 	csr |= SPI_BF(DLYBCT, 0);
 
-	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned long)spi->controller_data;
-
-	if (!as->use_cs_gpios)
-		npcs_pin = spi->chip_select;
-	else if (gpio_is_valid(spi->cs_gpio))
-		npcs_pin = spi->cs_gpio;
-
 	asd = spi->controller_state;
 	if (!asd) {
 		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
 		if (!asd)
 			return -ENOMEM;
 
-		if (as->use_cs_gpios) {
+		npcs_pin = (unsigned long)spi->controller_data;
+
+		if (gpio_is_valid(spi->cs_gpio)) {
+			/* GPIO from DT */
+			npcs_pin = spi->cs_gpio;
+			asd->use_cs_gpio = true;
+		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
+			/* GPIO from platform data */
+			asd->use_cs_gpio = true;
+		} else {
+			/* internal chip-select */
+			npcs_pin = spi->chip_select;
+			asd->use_cs_gpio = false;
+		}
+
+		if (asd->use_cs_gpio) {
 			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
 			if (ret) {
 				kfree(asd);
@@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
 		spi->controller_state = asd;
 	}
 
+	if (!asd->use_cs_gpio)
+		csr |= SPI_BIT(CSAAT);
 	asd->csr = csr;
 
 	dev_dbg(&spi->dev,
@@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
 	atmel_get_caps(as);
 
-	as->use_cs_gpios = true;
-	if (atmel_spi_is_v2(as) &&
-	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
-		as->use_cs_gpios = false;
-		master->num_chipselect = 4;
-	}
-
 	as->use_dma = false;
 	as->use_pdc = false;
 	if (as->caps.has_dma_support) {
-- 
2.7.0

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Applied "spi: atmel: improve internal vs gpio chip-select choice" to the spi tree
       [not found] ` <1452211907-16074-1-git-send-email-mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
@ 2016-01-08 13:44   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2016-01-08 13:44 UTC (permalink / raw)
  To: Mans Rullgard, Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

The patch

   spi: atmel: improve internal vs gpio chip-select choice

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 3fe5e14919b7ef2792aed8cacd7d1ae3e30adcd2 Mon Sep 17 00:00:00 2001
From: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
Date: Fri, 8 Jan 2016 00:11:47 +0000
Subject: [PATCH] spi: atmel: improve internal vs gpio chip-select choice

The driver currently chooses between internal chip-select or gpio
based on the existence of the cs-gpios DT property which fails on
non-DT systems and also enforces the same choice for all devices.

This patch makes the method per device instead of per controller
and fixes the selection on non-DT systems.  With these changes,
the chip-select method for each device is chosen according to the
following priority:

1. GPIO from device tree
2. GPIO from platform data
3. Internal chip-select

Tested on AVR32 ATSTK1000.

Signed-off-by: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index aebad36391c9..8be07fb67d4d 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -310,7 +310,6 @@ struct atmel_spi {
 
 	bool			use_dma;
 	bool			use_pdc;
-	bool			use_cs_gpios;
 	/* dmaengine data */
 	struct atmel_spi_dma	dma;
 
@@ -324,6 +323,7 @@ struct atmel_spi {
 struct atmel_spi_device {
 	unsigned int		npcs_pin;
 	u32			csr;
+	bool			use_cs_gpio;
 };
 
 #define BUFFER_SIZE		PAGE_SIZE
@@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 		}
 
 		mr = spi_readl(as, MR);
-		if (as->use_cs_gpios)
+		if (asd->use_cs_gpio)
 			gpio_set_value(asd->npcs_pin, active);
 	} else {
 		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
@@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 
 		mr = spi_readl(as, MR);
 		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
-		if (as->use_cs_gpios && spi->chip_select != 0)
+		if (asd->use_cs_gpio && spi->chip_select != 0)
 			gpio_set_value(asd->npcs_pin, active);
 		spi_writel(as, MR, mr);
 	}
@@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 			asd->npcs_pin, active ? " (low)" : "",
 			mr);
 
-	if (!as->use_cs_gpios)
+	if (!asd->use_cs_gpio)
 		spi_writel(as, CR, SPI_BIT(LASTXFER));
 	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
 		gpio_set_value(asd->npcs_pin, !active);
@@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
 		csr |= SPI_BIT(CPOL);
 	if (!(spi->mode & SPI_CPHA))
 		csr |= SPI_BIT(NCPHA);
-	if (!as->use_cs_gpios)
-		csr |= SPI_BIT(CSAAT);
 
 	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
 	 *
@@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
 	csr |= SPI_BF(DLYBS, 0);
 	csr |= SPI_BF(DLYBCT, 0);
 
-	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned long)spi->controller_data;
-
-	if (!as->use_cs_gpios)
-		npcs_pin = spi->chip_select;
-	else if (gpio_is_valid(spi->cs_gpio))
-		npcs_pin = spi->cs_gpio;
-
 	asd = spi->controller_state;
 	if (!asd) {
 		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
 		if (!asd)
 			return -ENOMEM;
 
-		if (as->use_cs_gpios) {
+		npcs_pin = (unsigned long)spi->controller_data;
+
+		if (gpio_is_valid(spi->cs_gpio)) {
+			/* GPIO from DT */
+			npcs_pin = spi->cs_gpio;
+			asd->use_cs_gpio = true;
+		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
+			/* GPIO from platform data */
+			asd->use_cs_gpio = true;
+		} else {
+			/* internal chip-select */
+			npcs_pin = spi->chip_select;
+			asd->use_cs_gpio = false;
+		}
+
+		if (asd->use_cs_gpio) {
 			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
 			if (ret) {
 				kfree(asd);
@@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
 		spi->controller_state = asd;
 	}
 
+	if (!asd->use_cs_gpio)
+		csr |= SPI_BIT(CSAAT);
 	asd->csr = csr;
 
 	dev_dbg(&spi->dev,
@@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
 	atmel_get_caps(as);
 
-	as->use_cs_gpios = true;
-	if (atmel_spi_is_v2(as) &&
-	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
-		as->use_cs_gpios = false;
-		master->num_chipselect = 4;
-	}
-
 	as->use_dma = false;
 	as->use_pdc = false;
 	if (as->caps.has_dma_support) {
-- 
2.7.0.rc3

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
       [not found] ` <1452211907-16074-1-git-send-email-mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
  2016-01-08 13:44   ` Applied "spi: atmel: improve internal vs gpio chip-select choice" to the spi tree Mark Brown
@ 2016-01-11 15:26   ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-11 15:26 UTC (permalink / raw)
  To: Mans Rullgard, Mark Brown, linux-spi, linux-kernel,
	linux-arm-kernel, Cyrille Pitchen, Yang, Wenyou

Le 08/01/2016 01:11, Mans Rullgard a écrit :
> The driver currently chooses between internal chip-select or gpio
> based on the existence of the cs-gpios DT property which fails on
> non-DT systems and also enforces the same choice for all devices.

Well, I fear that such a per-device choice may impact further the driver
than just moving a field from one structure to another... Moreover, I
have the feeling that it was not the objective of this patch.

> This patch makes the method per device instead of per controller
> and fixes the selection on non-DT systems.  With these changes,
> the chip-select method for each device is chosen according to the
> following priority:
> 
> 1. GPIO from device tree
> 2. GPIO from platform data
> 3. Internal chip-select
> 
> Tested on AVR32 ATSTK1000.

This patch breaks the SAMA5D2 SPI support at least on most recent
linux-next (tested by Cyrille).

more remarks below...

> Signed-off-by: Mans Rullgard <mans@mansr.com>
> ---
>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>  1 file changed, 22 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index aebad36391c9..8be07fb67d4d 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -310,7 +310,6 @@ struct atmel_spi {
>  
>  	bool			use_dma;
>  	bool			use_pdc;
> -	bool			use_cs_gpios;
>  	/* dmaengine data */
>  	struct atmel_spi_dma	dma;
>  
> @@ -324,6 +323,7 @@ struct atmel_spi {
>  struct atmel_spi_device {
>  	unsigned int		npcs_pin;
>  	u32			csr;
> +	bool			use_cs_gpio;
>  };
>  
>  #define BUFFER_SIZE		PAGE_SIZE
> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  		}
>  
>  		mr = spi_readl(as, MR);
> -		if (as->use_cs_gpios)
> +		if (asd->use_cs_gpio)
>  			gpio_set_value(asd->npcs_pin, active);
>  	} else {
>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  
>  		mr = spi_readl(as, MR);
>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
> -		if (as->use_cs_gpios && spi->chip_select != 0)
> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>  			gpio_set_value(asd->npcs_pin, active);
>  		spi_writel(as, MR, mr);
>  	}
> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>  			asd->npcs_pin, active ? " (low)" : "",
>  			mr);
>  
> -	if (!as->use_cs_gpios)
> +	if (!asd->use_cs_gpio)
>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>  		gpio_set_value(asd->npcs_pin, !active);
> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		csr |= SPI_BIT(CPOL);
>  	if (!(spi->mode & SPI_CPHA))
>  		csr |= SPI_BIT(NCPHA);
> -	if (!as->use_cs_gpios)
> -		csr |= SPI_BIT(CSAAT);
>  
>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>  	 *
> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	csr |= SPI_BF(DLYBS, 0);
>  	csr |= SPI_BF(DLYBCT, 0);
>  
> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
> -	npcs_pin = (unsigned long)spi->controller_data;
> -
> -	if (!as->use_cs_gpios)
> -		npcs_pin = spi->chip_select;
> -	else if (gpio_is_valid(spi->cs_gpio))
> -		npcs_pin = spi->cs_gpio;
> -
>  	asd = spi->controller_state;
>  	if (!asd) {
>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>  		if (!asd)
>  			return -ENOMEM;
>  
> -		if (as->use_cs_gpios) {
> +		npcs_pin = (unsigned long)spi->controller_data;
> +
> +		if (gpio_is_valid(spi->cs_gpio)) {

The bug may come from here as the logic is somehow inverted and a "0" is
a valid gpio according to this gpio_is_valid() function. So we may take
this conditional branch instead of the third one in the sama5d2 case.

> +			/* GPIO from DT */
> +			npcs_pin = spi->cs_gpio;
> +			asd->use_cs_gpio = true;
> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
> +			/* GPIO from platform data */
> +			asd->use_cs_gpio = true;
> +		} else {
> +			/* internal chip-select */
> +			npcs_pin = spi->chip_select;
> +			asd->use_cs_gpio = false;
> +		}
> +
> +		if (asd->use_cs_gpio) {
>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>  			if (ret) {
>  				kfree(asd);
> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		spi->controller_state = asd;
>  	}
>  
> +	if (!asd->use_cs_gpio)
> +		csr |= SPI_BIT(CSAAT);
>  	asd->csr = csr;
>  
>  	dev_dbg(&spi->dev,
> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>  
>  	atmel_get_caps(as);
>  
> -	as->use_cs_gpios = true;
> -	if (atmel_spi_is_v2(as) &&

I don't see this atmel_spi_is_v2() test in the resulting code anymore:
did you make sure that the v1 of the peripheral is protected?

> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
> -		as->use_cs_gpios = false;
> -		master->num_chipselect = 4;

This line is pretty important: you mustn't remove it blindly!


> -	}
> -
>  	as->use_dma = false;
>  	as->use_pdc = false;
>  	if (as->caps.has_dma_support) {
> 

So, sorry but it's a NACK for me.

Bye,
-- 
Nicolas Ferre

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 15:26   ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-11 15:26 UTC (permalink / raw)
  To: Mans Rullgard, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Le 08/01/2016 01:11, Mans Rullgard a écrit :
> The driver currently chooses between internal chip-select or gpio
> based on the existence of the cs-gpios DT property which fails on
> non-DT systems and also enforces the same choice for all devices.

Well, I fear that such a per-device choice may impact further the driver
than just moving a field from one structure to another... Moreover, I
have the feeling that it was not the objective of this patch.

> This patch makes the method per device instead of per controller
> and fixes the selection on non-DT systems.  With these changes,
> the chip-select method for each device is chosen according to the
> following priority:
> 
> 1. GPIO from device tree
> 2. GPIO from platform data
> 3. Internal chip-select
> 
> Tested on AVR32 ATSTK1000.

This patch breaks the SAMA5D2 SPI support at least on most recent
linux-next (tested by Cyrille).

more remarks below...

> Signed-off-by: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>  1 file changed, 22 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index aebad36391c9..8be07fb67d4d 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -310,7 +310,6 @@ struct atmel_spi {
>  
>  	bool			use_dma;
>  	bool			use_pdc;
> -	bool			use_cs_gpios;
>  	/* dmaengine data */
>  	struct atmel_spi_dma	dma;
>  
> @@ -324,6 +323,7 @@ struct atmel_spi {
>  struct atmel_spi_device {
>  	unsigned int		npcs_pin;
>  	u32			csr;
> +	bool			use_cs_gpio;
>  };
>  
>  #define BUFFER_SIZE		PAGE_SIZE
> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  		}
>  
>  		mr = spi_readl(as, MR);
> -		if (as->use_cs_gpios)
> +		if (asd->use_cs_gpio)
>  			gpio_set_value(asd->npcs_pin, active);
>  	} else {
>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  
>  		mr = spi_readl(as, MR);
>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
> -		if (as->use_cs_gpios && spi->chip_select != 0)
> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>  			gpio_set_value(asd->npcs_pin, active);
>  		spi_writel(as, MR, mr);
>  	}
> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>  			asd->npcs_pin, active ? " (low)" : "",
>  			mr);
>  
> -	if (!as->use_cs_gpios)
> +	if (!asd->use_cs_gpio)
>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>  		gpio_set_value(asd->npcs_pin, !active);
> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		csr |= SPI_BIT(CPOL);
>  	if (!(spi->mode & SPI_CPHA))
>  		csr |= SPI_BIT(NCPHA);
> -	if (!as->use_cs_gpios)
> -		csr |= SPI_BIT(CSAAT);
>  
>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>  	 *
> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	csr |= SPI_BF(DLYBS, 0);
>  	csr |= SPI_BF(DLYBCT, 0);
>  
> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
> -	npcs_pin = (unsigned long)spi->controller_data;
> -
> -	if (!as->use_cs_gpios)
> -		npcs_pin = spi->chip_select;
> -	else if (gpio_is_valid(spi->cs_gpio))
> -		npcs_pin = spi->cs_gpio;
> -
>  	asd = spi->controller_state;
>  	if (!asd) {
>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>  		if (!asd)
>  			return -ENOMEM;
>  
> -		if (as->use_cs_gpios) {
> +		npcs_pin = (unsigned long)spi->controller_data;
> +
> +		if (gpio_is_valid(spi->cs_gpio)) {

The bug may come from here as the logic is somehow inverted and a "0" is
a valid gpio according to this gpio_is_valid() function. So we may take
this conditional branch instead of the third one in the sama5d2 case.

> +			/* GPIO from DT */
> +			npcs_pin = spi->cs_gpio;
> +			asd->use_cs_gpio = true;
> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
> +			/* GPIO from platform data */
> +			asd->use_cs_gpio = true;
> +		} else {
> +			/* internal chip-select */
> +			npcs_pin = spi->chip_select;
> +			asd->use_cs_gpio = false;
> +		}
> +
> +		if (asd->use_cs_gpio) {
>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>  			if (ret) {
>  				kfree(asd);
> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		spi->controller_state = asd;
>  	}
>  
> +	if (!asd->use_cs_gpio)
> +		csr |= SPI_BIT(CSAAT);
>  	asd->csr = csr;
>  
>  	dev_dbg(&spi->dev,
> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>  
>  	atmel_get_caps(as);
>  
> -	as->use_cs_gpios = true;
> -	if (atmel_spi_is_v2(as) &&

I don't see this atmel_spi_is_v2() test in the resulting code anymore:
did you make sure that the v1 of the peripheral is protected?

> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
> -		as->use_cs_gpios = false;
> -		master->num_chipselect = 4;

This line is pretty important: you mustn't remove it blindly!


> -	}
> -
>  	as->use_dma = false;
>  	as->use_pdc = false;
>  	if (as->caps.has_dma_support) {
> 

So, sorry but it's a NACK for me.

Bye,
-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 15:26   ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-11 15:26 UTC (permalink / raw)
  To: linux-arm-kernel

Le 08/01/2016 01:11, Mans Rullgard a ?crit :
> The driver currently chooses between internal chip-select or gpio
> based on the existence of the cs-gpios DT property which fails on
> non-DT systems and also enforces the same choice for all devices.

Well, I fear that such a per-device choice may impact further the driver
than just moving a field from one structure to another... Moreover, I
have the feeling that it was not the objective of this patch.

> This patch makes the method per device instead of per controller
> and fixes the selection on non-DT systems.  With these changes,
> the chip-select method for each device is chosen according to the
> following priority:
> 
> 1. GPIO from device tree
> 2. GPIO from platform data
> 3. Internal chip-select
> 
> Tested on AVR32 ATSTK1000.

This patch breaks the SAMA5D2 SPI support at least on most recent
linux-next (tested by Cyrille).

more remarks below...

> Signed-off-by: Mans Rullgard <mans@mansr.com>
> ---
>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>  1 file changed, 22 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index aebad36391c9..8be07fb67d4d 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -310,7 +310,6 @@ struct atmel_spi {
>  
>  	bool			use_dma;
>  	bool			use_pdc;
> -	bool			use_cs_gpios;
>  	/* dmaengine data */
>  	struct atmel_spi_dma	dma;
>  
> @@ -324,6 +323,7 @@ struct atmel_spi {
>  struct atmel_spi_device {
>  	unsigned int		npcs_pin;
>  	u32			csr;
> +	bool			use_cs_gpio;
>  };
>  
>  #define BUFFER_SIZE		PAGE_SIZE
> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  		}
>  
>  		mr = spi_readl(as, MR);
> -		if (as->use_cs_gpios)
> +		if (asd->use_cs_gpio)
>  			gpio_set_value(asd->npcs_pin, active);
>  	} else {
>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  
>  		mr = spi_readl(as, MR);
>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
> -		if (as->use_cs_gpios && spi->chip_select != 0)
> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>  			gpio_set_value(asd->npcs_pin, active);
>  		spi_writel(as, MR, mr);
>  	}
> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>  			asd->npcs_pin, active ? " (low)" : "",
>  			mr);
>  
> -	if (!as->use_cs_gpios)
> +	if (!asd->use_cs_gpio)
>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>  		gpio_set_value(asd->npcs_pin, !active);
> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		csr |= SPI_BIT(CPOL);
>  	if (!(spi->mode & SPI_CPHA))
>  		csr |= SPI_BIT(NCPHA);
> -	if (!as->use_cs_gpios)
> -		csr |= SPI_BIT(CSAAT);
>  
>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>  	 *
> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	csr |= SPI_BF(DLYBS, 0);
>  	csr |= SPI_BF(DLYBCT, 0);
>  
> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
> -	npcs_pin = (unsigned long)spi->controller_data;
> -
> -	if (!as->use_cs_gpios)
> -		npcs_pin = spi->chip_select;
> -	else if (gpio_is_valid(spi->cs_gpio))
> -		npcs_pin = spi->cs_gpio;
> -
>  	asd = spi->controller_state;
>  	if (!asd) {
>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>  		if (!asd)
>  			return -ENOMEM;
>  
> -		if (as->use_cs_gpios) {
> +		npcs_pin = (unsigned long)spi->controller_data;
> +
> +		if (gpio_is_valid(spi->cs_gpio)) {

The bug may come from here as the logic is somehow inverted and a "0" is
a valid gpio according to this gpio_is_valid() function. So we may take
this conditional branch instead of the third one in the sama5d2 case.

> +			/* GPIO from DT */
> +			npcs_pin = spi->cs_gpio;
> +			asd->use_cs_gpio = true;
> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
> +			/* GPIO from platform data */
> +			asd->use_cs_gpio = true;
> +		} else {
> +			/* internal chip-select */
> +			npcs_pin = spi->chip_select;
> +			asd->use_cs_gpio = false;
> +		}
> +
> +		if (asd->use_cs_gpio) {
>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>  			if (ret) {
>  				kfree(asd);
> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		spi->controller_state = asd;
>  	}
>  
> +	if (!asd->use_cs_gpio)
> +		csr |= SPI_BIT(CSAAT);
>  	asd->csr = csr;
>  
>  	dev_dbg(&spi->dev,
> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>  
>  	atmel_get_caps(as);
>  
> -	as->use_cs_gpios = true;
> -	if (atmel_spi_is_v2(as) &&

I don't see this atmel_spi_is_v2() test in the resulting code anymore:
did you make sure that the v1 of the peripheral is protected?

> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
> -		as->use_cs_gpios = false;
> -		master->num_chipselect = 4;

This line is pretty important: you mustn't remove it blindly!


> -	}
> -
>  	as->use_dma = false;
>  	as->use_pdc = false;
>  	if (as->caps.has_dma_support) {
> 

So, sorry but it's a NACK for me.

Bye,
-- 
Nicolas Ferre

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 15:43     ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-11 15:43 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi, linux-kernel, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>> The driver currently chooses between internal chip-select or gpio
>> based on the existence of the cs-gpios DT property which fails on
>> non-DT systems and also enforces the same choice for all devices.
>
> Well, I fear that such a per-device choice may impact further the driver
> than just moving a field from one structure to another...

Could you please elaborate?

> Moreover, I have the feeling that it was not the objective of this
> patch.

Your feeling is mistaken.  If it's somehow impossible to mix CS types,
please explain why.

>> This patch makes the method per device instead of per controller
>> and fixes the selection on non-DT systems.  With these changes,
>> the chip-select method for each device is chosen according to the
>> following priority:
>> 
>> 1. GPIO from device tree
>> 2. GPIO from platform data
>> 3. Internal chip-select
>> 
>> Tested on AVR32 ATSTK1000.
>
> This patch breaks the SAMA5D2 SPI support at least on most recent
> linux-next (tested by Cyrille).

How did it fail?

> more remarks below...
>
>> Signed-off-by: Mans Rullgard <mans@mansr.com>
>> ---
>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>  1 file changed, 22 insertions(+), 22 deletions(-)
>> 
>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>> index aebad36391c9..8be07fb67d4d 100644
>> --- a/drivers/spi/spi-atmel.c
>> +++ b/drivers/spi/spi-atmel.c
>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>  
>>  	bool			use_dma;
>>  	bool			use_pdc;
>> -	bool			use_cs_gpios;
>>  	/* dmaengine data */
>>  	struct atmel_spi_dma	dma;
>>  
>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>  struct atmel_spi_device {
>>  	unsigned int		npcs_pin;
>>  	u32			csr;
>> +	bool			use_cs_gpio;
>>  };
>>  
>>  #define BUFFER_SIZE		PAGE_SIZE
>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  		}
>>  
>>  		mr = spi_readl(as, MR);
>> -		if (as->use_cs_gpios)
>> +		if (asd->use_cs_gpio)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  	} else {
>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  
>>  		mr = spi_readl(as, MR);
>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  		spi_writel(as, MR, mr);
>>  	}
>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>  			asd->npcs_pin, active ? " (low)" : "",
>>  			mr);
>>  
>> -	if (!as->use_cs_gpios)
>> +	if (!asd->use_cs_gpio)
>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>  		gpio_set_value(asd->npcs_pin, !active);
>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		csr |= SPI_BIT(CPOL);
>>  	if (!(spi->mode & SPI_CPHA))
>>  		csr |= SPI_BIT(NCPHA);
>> -	if (!as->use_cs_gpios)
>> -		csr |= SPI_BIT(CSAAT);
>>  
>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>  	 *
>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  	csr |= SPI_BF(DLYBS, 0);
>>  	csr |= SPI_BF(DLYBCT, 0);
>>  
>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>> -	npcs_pin = (unsigned long)spi->controller_data;
>> -
>> -	if (!as->use_cs_gpios)
>> -		npcs_pin = spi->chip_select;
>> -	else if (gpio_is_valid(spi->cs_gpio))
>> -		npcs_pin = spi->cs_gpio;
>> -
>>  	asd = spi->controller_state;
>>  	if (!asd) {
>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>  		if (!asd)
>>  			return -ENOMEM;
>>  
>> -		if (as->use_cs_gpios) {
>> +		npcs_pin = (unsigned long)spi->controller_data;
>> +
>> +		if (gpio_is_valid(spi->cs_gpio)) {
>
> The bug may come from here as the logic is somehow inverted and a "0" is
> a valid gpio according to this gpio_is_valid() function. So we may take
> this conditional branch instead of the third one in the sama5d2 case.

spi->cs_gpio is set to -ENOENT if none is specified so I don't think
this should be a problem.

>> +			/* GPIO from DT */
>> +			npcs_pin = spi->cs_gpio;
>> +			asd->use_cs_gpio = true;
>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>> +			/* GPIO from platform data */
>> +			asd->use_cs_gpio = true;
>> +		} else {
>> +			/* internal chip-select */
>> +			npcs_pin = spi->chip_select;
>> +			asd->use_cs_gpio = false;
>> +		}
>> +
>> +		if (asd->use_cs_gpio) {
>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>  			if (ret) {
>>  				kfree(asd);
>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		spi->controller_state = asd;
>>  	}
>>  
>> +	if (!asd->use_cs_gpio)
>> +		csr |= SPI_BIT(CSAAT);
>>  	asd->csr = csr;
>>  
>>  	dev_dbg(&spi->dev,
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
>
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?

You're right, that check seems to have fallen by the wayside.

>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
>
> This line is pretty important: you mustn't remove it blindly!

That may be the real cause of whatever problem you saw.

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>> 
>
> So, sorry but it's a NACK for me.

Thanks for reviewing.

-- 
Måns Rullgård

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 15:43     ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-11 15:43 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:

> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>> The driver currently chooses between internal chip-select or gpio
>> based on the existence of the cs-gpios DT property which fails on
>> non-DT systems and also enforces the same choice for all devices.
>
> Well, I fear that such a per-device choice may impact further the driver
> than just moving a field from one structure to another...

Could you please elaborate?

> Moreover, I have the feeling that it was not the objective of this
> patch.

Your feeling is mistaken.  If it's somehow impossible to mix CS types,
please explain why.

>> This patch makes the method per device instead of per controller
>> and fixes the selection on non-DT systems.  With these changes,
>> the chip-select method for each device is chosen according to the
>> following priority:
>> 
>> 1. GPIO from device tree
>> 2. GPIO from platform data
>> 3. Internal chip-select
>> 
>> Tested on AVR32 ATSTK1000.
>
> This patch breaks the SAMA5D2 SPI support at least on most recent
> linux-next (tested by Cyrille).

How did it fail?

> more remarks below...
>
>> Signed-off-by: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
>> ---
>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>  1 file changed, 22 insertions(+), 22 deletions(-)
>> 
>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>> index aebad36391c9..8be07fb67d4d 100644
>> --- a/drivers/spi/spi-atmel.c
>> +++ b/drivers/spi/spi-atmel.c
>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>  
>>  	bool			use_dma;
>>  	bool			use_pdc;
>> -	bool			use_cs_gpios;
>>  	/* dmaengine data */
>>  	struct atmel_spi_dma	dma;
>>  
>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>  struct atmel_spi_device {
>>  	unsigned int		npcs_pin;
>>  	u32			csr;
>> +	bool			use_cs_gpio;
>>  };
>>  
>>  #define BUFFER_SIZE		PAGE_SIZE
>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  		}
>>  
>>  		mr = spi_readl(as, MR);
>> -		if (as->use_cs_gpios)
>> +		if (asd->use_cs_gpio)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  	} else {
>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  
>>  		mr = spi_readl(as, MR);
>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  		spi_writel(as, MR, mr);
>>  	}
>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>  			asd->npcs_pin, active ? " (low)" : "",
>>  			mr);
>>  
>> -	if (!as->use_cs_gpios)
>> +	if (!asd->use_cs_gpio)
>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>  		gpio_set_value(asd->npcs_pin, !active);
>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		csr |= SPI_BIT(CPOL);
>>  	if (!(spi->mode & SPI_CPHA))
>>  		csr |= SPI_BIT(NCPHA);
>> -	if (!as->use_cs_gpios)
>> -		csr |= SPI_BIT(CSAAT);
>>  
>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>  	 *
>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  	csr |= SPI_BF(DLYBS, 0);
>>  	csr |= SPI_BF(DLYBCT, 0);
>>  
>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>> -	npcs_pin = (unsigned long)spi->controller_data;
>> -
>> -	if (!as->use_cs_gpios)
>> -		npcs_pin = spi->chip_select;
>> -	else if (gpio_is_valid(spi->cs_gpio))
>> -		npcs_pin = spi->cs_gpio;
>> -
>>  	asd = spi->controller_state;
>>  	if (!asd) {
>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>  		if (!asd)
>>  			return -ENOMEM;
>>  
>> -		if (as->use_cs_gpios) {
>> +		npcs_pin = (unsigned long)spi->controller_data;
>> +
>> +		if (gpio_is_valid(spi->cs_gpio)) {
>
> The bug may come from here as the logic is somehow inverted and a "0" is
> a valid gpio according to this gpio_is_valid() function. So we may take
> this conditional branch instead of the third one in the sama5d2 case.

spi->cs_gpio is set to -ENOENT if none is specified so I don't think
this should be a problem.

>> +			/* GPIO from DT */
>> +			npcs_pin = spi->cs_gpio;
>> +			asd->use_cs_gpio = true;
>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>> +			/* GPIO from platform data */
>> +			asd->use_cs_gpio = true;
>> +		} else {
>> +			/* internal chip-select */
>> +			npcs_pin = spi->chip_select;
>> +			asd->use_cs_gpio = false;
>> +		}
>> +
>> +		if (asd->use_cs_gpio) {
>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>  			if (ret) {
>>  				kfree(asd);
>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		spi->controller_state = asd;
>>  	}
>>  
>> +	if (!asd->use_cs_gpio)
>> +		csr |= SPI_BIT(CSAAT);
>>  	asd->csr = csr;
>>  
>>  	dev_dbg(&spi->dev,
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
>
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?

You're right, that check seems to have fallen by the wayside.

>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
>
> This line is pretty important: you mustn't remove it blindly!

That may be the real cause of whatever problem you saw.

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>> 
>
> So, sorry but it's a NACK for me.

Thanks for reviewing.

-- 
Måns Rullgård
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 15:43     ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-11 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
>> The driver currently chooses between internal chip-select or gpio
>> based on the existence of the cs-gpios DT property which fails on
>> non-DT systems and also enforces the same choice for all devices.
>
> Well, I fear that such a per-device choice may impact further the driver
> than just moving a field from one structure to another...

Could you please elaborate?

> Moreover, I have the feeling that it was not the objective of this
> patch.

Your feeling is mistaken.  If it's somehow impossible to mix CS types,
please explain why.

>> This patch makes the method per device instead of per controller
>> and fixes the selection on non-DT systems.  With these changes,
>> the chip-select method for each device is chosen according to the
>> following priority:
>> 
>> 1. GPIO from device tree
>> 2. GPIO from platform data
>> 3. Internal chip-select
>> 
>> Tested on AVR32 ATSTK1000.
>
> This patch breaks the SAMA5D2 SPI support at least on most recent
> linux-next (tested by Cyrille).

How did it fail?

> more remarks below...
>
>> Signed-off-by: Mans Rullgard <mans@mansr.com>
>> ---
>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>  1 file changed, 22 insertions(+), 22 deletions(-)
>> 
>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>> index aebad36391c9..8be07fb67d4d 100644
>> --- a/drivers/spi/spi-atmel.c
>> +++ b/drivers/spi/spi-atmel.c
>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>  
>>  	bool			use_dma;
>>  	bool			use_pdc;
>> -	bool			use_cs_gpios;
>>  	/* dmaengine data */
>>  	struct atmel_spi_dma	dma;
>>  
>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>  struct atmel_spi_device {
>>  	unsigned int		npcs_pin;
>>  	u32			csr;
>> +	bool			use_cs_gpio;
>>  };
>>  
>>  #define BUFFER_SIZE		PAGE_SIZE
>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  		}
>>  
>>  		mr = spi_readl(as, MR);
>> -		if (as->use_cs_gpios)
>> +		if (asd->use_cs_gpio)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  	} else {
>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>  
>>  		mr = spi_readl(as, MR);
>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>  			gpio_set_value(asd->npcs_pin, active);
>>  		spi_writel(as, MR, mr);
>>  	}
>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>  			asd->npcs_pin, active ? " (low)" : "",
>>  			mr);
>>  
>> -	if (!as->use_cs_gpios)
>> +	if (!asd->use_cs_gpio)
>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>  		gpio_set_value(asd->npcs_pin, !active);
>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		csr |= SPI_BIT(CPOL);
>>  	if (!(spi->mode & SPI_CPHA))
>>  		csr |= SPI_BIT(NCPHA);
>> -	if (!as->use_cs_gpios)
>> -		csr |= SPI_BIT(CSAAT);
>>  
>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>  	 *
>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  	csr |= SPI_BF(DLYBS, 0);
>>  	csr |= SPI_BF(DLYBCT, 0);
>>  
>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>> -	npcs_pin = (unsigned long)spi->controller_data;
>> -
>> -	if (!as->use_cs_gpios)
>> -		npcs_pin = spi->chip_select;
>> -	else if (gpio_is_valid(spi->cs_gpio))
>> -		npcs_pin = spi->cs_gpio;
>> -
>>  	asd = spi->controller_state;
>>  	if (!asd) {
>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>  		if (!asd)
>>  			return -ENOMEM;
>>  
>> -		if (as->use_cs_gpios) {
>> +		npcs_pin = (unsigned long)spi->controller_data;
>> +
>> +		if (gpio_is_valid(spi->cs_gpio)) {
>
> The bug may come from here as the logic is somehow inverted and a "0" is
> a valid gpio according to this gpio_is_valid() function. So we may take
> this conditional branch instead of the third one in the sama5d2 case.

spi->cs_gpio is set to -ENOENT if none is specified so I don't think
this should be a problem.

>> +			/* GPIO from DT */
>> +			npcs_pin = spi->cs_gpio;
>> +			asd->use_cs_gpio = true;
>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>> +			/* GPIO from platform data */
>> +			asd->use_cs_gpio = true;
>> +		} else {
>> +			/* internal chip-select */
>> +			npcs_pin = spi->chip_select;
>> +			asd->use_cs_gpio = false;
>> +		}
>> +
>> +		if (asd->use_cs_gpio) {
>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>  			if (ret) {
>>  				kfree(asd);
>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>  		spi->controller_state = asd;
>>  	}
>>  
>> +	if (!asd->use_cs_gpio)
>> +		csr |= SPI_BIT(CSAAT);
>>  	asd->csr = csr;
>>  
>>  	dev_dbg(&spi->dev,
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
>
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?

You're right, that check seems to have fallen by the wayside.

>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
>
> This line is pretty important: you mustn't remove it blindly!

That may be the real cause of whatever problem you saw.

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>> 
>
> So, sorry but it's a NACK for me.

Thanks for reviewing.

-- 
M?ns Rullg?rd

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 16:33     ` Cyrille Pitchen
  0 siblings, 0 replies; 23+ messages in thread
From: Cyrille Pitchen @ 2016-01-11 16:33 UTC (permalink / raw)
  To: Nicolas Ferre, Mans Rullgard, Mark Brown, linux-spi,
	linux-kernel, linux-arm-kernel, Yang, Wenyou

Hi Mans,

Le 11/01/2016 16:26, Nicolas Ferre a écrit :
> Le 08/01/2016 01:11, Mans Rullgard a écrit :
[...]
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
> 
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?
> 
>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
> 
> This line is pretty important: you mustn't remove it blindly!
> 
> 

Actually, few lines above master->num_chipselect is initialized with:
	master->dev.of_node = pdev->dev.of_node;
[...]
	master->num_chipselect = master->dev.of_node ? 0 : 4;


So 0 in the case of DT support, 4 otherwise.


Now looking at the source code of spi_register_master(), this function:

1 - calls of_spi_register_master(), which initializes master->num_chipselect:
	nb = of_gpio_name_count(np, "cs-gpios");
	master->num_chipselect = max_t(int, nb, master->num_chipselect);

	if (nb == 0 || nb == -ENOENT)
		return 0;

2 - check master->num_chipselect with:
	if (master->num_chipselect == 0)
		return -EINVAL;

It means that in the case of DT support, master->num_chipselect was initialized
according to the value of the "cs-gpios" DT property. Hence this property used
to be mandatory but now we want it to be optional for hardware version 2 and
later.

This is why we added a check "hw version >= 2 and cs-gpios missing". In such
a case the master->num_chipselect was initialized to 4 so spi_register_master()
does not fail with -EINVAL.

I have applied the following fix after your patch and now the driver works
again on sama5d2:

--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1576,6 +1576,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
        atmel_get_caps(as);
 
+       if (atmel_spi_is_v2(as) &&
+           master->dev.of_node &&
+           !of_get_property(master->dev.of_node, "cs-gpios", NULL))
+               master->num_chipselect = 4;
+
        as->use_dma = false;
        as->use_pdc = false;
        if (as->caps.has_dma_support) {

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>>
> 
> So, sorry but it's a NACK for me.
> 
> Bye,
> 

Best regards,

Cyrille

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 16:33     ` Cyrille Pitchen
  0 siblings, 0 replies; 23+ messages in thread
From: Cyrille Pitchen @ 2016-01-11 16:33 UTC (permalink / raw)
  To: Nicolas Ferre, Mans Rullgard, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel, Yang,
	Wenyou

Hi Mans,

Le 11/01/2016 16:26, Nicolas Ferre a écrit :
> Le 08/01/2016 01:11, Mans Rullgard a écrit :
[...]
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
> 
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?
> 
>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
> 
> This line is pretty important: you mustn't remove it blindly!
> 
> 

Actually, few lines above master->num_chipselect is initialized with:
	master->dev.of_node = pdev->dev.of_node;
[...]
	master->num_chipselect = master->dev.of_node ? 0 : 4;


So 0 in the case of DT support, 4 otherwise.


Now looking at the source code of spi_register_master(), this function:

1 - calls of_spi_register_master(), which initializes master->num_chipselect:
	nb = of_gpio_name_count(np, "cs-gpios");
	master->num_chipselect = max_t(int, nb, master->num_chipselect);

	if (nb == 0 || nb == -ENOENT)
		return 0;

2 - check master->num_chipselect with:
	if (master->num_chipselect == 0)
		return -EINVAL;

It means that in the case of DT support, master->num_chipselect was initialized
according to the value of the "cs-gpios" DT property. Hence this property used
to be mandatory but now we want it to be optional for hardware version 2 and
later.

This is why we added a check "hw version >= 2 and cs-gpios missing". In such
a case the master->num_chipselect was initialized to 4 so spi_register_master()
does not fail with -EINVAL.

I have applied the following fix after your patch and now the driver works
again on sama5d2:

--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1576,6 +1576,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
        atmel_get_caps(as);
 
+       if (atmel_spi_is_v2(as) &&
+           master->dev.of_node &&
+           !of_get_property(master->dev.of_node, "cs-gpios", NULL))
+               master->num_chipselect = 4;
+
        as->use_dma = false;
        as->use_pdc = false;
        if (as->caps.has_dma_support) {

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>>
> 
> So, sorry but it's a NACK for me.
> 
> Bye,
> 

Best regards,

Cyrille
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 16:33     ` Cyrille Pitchen
  0 siblings, 0 replies; 23+ messages in thread
From: Cyrille Pitchen @ 2016-01-11 16:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mans,

Le 11/01/2016 16:26, Nicolas Ferre a ?crit :
> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
[...]
>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>  
>>  	atmel_get_caps(as);
>>  
>> -	as->use_cs_gpios = true;
>> -	if (atmel_spi_is_v2(as) &&
> 
> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
> did you make sure that the v1 of the peripheral is protected?
> 
>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>> -		as->use_cs_gpios = false;
>> -		master->num_chipselect = 4;
> 
> This line is pretty important: you mustn't remove it blindly!
> 
> 

Actually, few lines above master->num_chipselect is initialized with:
	master->dev.of_node = pdev->dev.of_node;
[...]
	master->num_chipselect = master->dev.of_node ? 0 : 4;


So 0 in the case of DT support, 4 otherwise.


Now looking at the source code of spi_register_master(), this function:

1 - calls of_spi_register_master(), which initializes master->num_chipselect:
	nb = of_gpio_name_count(np, "cs-gpios");
	master->num_chipselect = max_t(int, nb, master->num_chipselect);

	if (nb == 0 || nb == -ENOENT)
		return 0;

2 - check master->num_chipselect with:
	if (master->num_chipselect == 0)
		return -EINVAL;

It means that in the case of DT support, master->num_chipselect was initialized
according to the value of the "cs-gpios" DT property. Hence this property used
to be mandatory but now we want it to be optional for hardware version 2 and
later.

This is why we added a check "hw version >= 2 and cs-gpios missing". In such
a case the master->num_chipselect was initialized to 4 so spi_register_master()
does not fail with -EINVAL.

I have applied the following fix after your patch and now the driver works
again on sama5d2:

--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1576,6 +1576,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
        atmel_get_caps(as);
 
+       if (atmel_spi_is_v2(as) &&
+           master->dev.of_node &&
+           !of_get_property(master->dev.of_node, "cs-gpios", NULL))
+               master->num_chipselect = 4;
+
        as->use_dma = false;
        as->use_pdc = false;
        if (as->caps.has_dma_support) {

>> -	}
>> -
>>  	as->use_dma = false;
>>  	as->use_pdc = false;
>>  	if (as->caps.has_dma_support) {
>>
> 
> So, sorry but it's a NACK for me.
> 
> Bye,
> 

Best regards,

Cyrille

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
  2016-01-11 16:33     ` Cyrille Pitchen
@ 2016-01-11 16:37       ` Måns Rullgård
  -1 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-11 16:37 UTC (permalink / raw)
  To: Cyrille Pitchen
  Cc: Nicolas Ferre, Mark Brown, linux-spi, linux-kernel,
	linux-arm-kernel, Yang, Wenyou

Cyrille Pitchen <cyrille.pitchen@atmel.com> writes:

> Hi Mans,
>
> Le 11/01/2016 16:26, Nicolas Ferre a écrit :
>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
> [...]
>>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>>  
>>>  	atmel_get_caps(as);
>>>  
>>> -	as->use_cs_gpios = true;
>>> -	if (atmel_spi_is_v2(as) &&
>> 
>> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
>> did you make sure that the v1 of the peripheral is protected?
>> 
>>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>>> -		as->use_cs_gpios = false;
>>> -		master->num_chipselect = 4;
>> 
>> This line is pretty important: you mustn't remove it blindly!
>> 
>> 
>
> Actually, few lines above master->num_chipselect is initialized with:
> 	master->dev.of_node = pdev->dev.of_node;
> [...]
> 	master->num_chipselect = master->dev.of_node ? 0 : 4;
>
> So 0 in the case of DT support, 4 otherwise.
>
> Now looking at the source code of spi_register_master(), this function:
>
> 1 - calls of_spi_register_master(), which initializes master->num_chipselect:
> 	nb = of_gpio_name_count(np, "cs-gpios");
> 	master->num_chipselect = max_t(int, nb, master->num_chipselect);
>
> 	if (nb == 0 || nb == -ENOENT)
> 		return 0;
>
> 2 - check master->num_chipselect with:
> 	if (master->num_chipselect == 0)
> 		return -EINVAL;
>
> It means that in the case of DT support, master->num_chipselect was
> initialized according to the value of the "cs-gpios" DT
> property. Hence this property used to be mandatory but now we want it
> to be optional for hardware version 2 and later.
>
> This is why we added a check "hw version >= 2 and cs-gpios
> missing". In such a case the master->num_chipselect was initialized to
> 4 so spi_register_master() does not fail with -EINVAL.
>
> I have applied the following fix after your patch and now the driver works
> again on sama5d2:
>
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -1576,6 +1576,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
>
>         atmel_get_caps(as);
>
> +       if (atmel_spi_is_v2(as) &&
> +           master->dev.of_node &&
> +           !of_get_property(master->dev.of_node, "cs-gpios", NULL))
> +               master->num_chipselect = 4;
> +
>         as->use_dma = false;
>         as->use_pdc = false;
>         if (as->caps.has_dma_support) {

That's pretty much what I did (left the original alone) in v2 of the
patch.

Thanks for testing.

-- 
Måns Rullgård

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-11 16:37       ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-11 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

Cyrille Pitchen <cyrille.pitchen@atmel.com> writes:

> Hi Mans,
>
> Le 11/01/2016 16:26, Nicolas Ferre a ?crit :
>> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
> [...]
>>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>>  
>>>  	atmel_get_caps(as);
>>>  
>>> -	as->use_cs_gpios = true;
>>> -	if (atmel_spi_is_v2(as) &&
>> 
>> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
>> did you make sure that the v1 of the peripheral is protected?
>> 
>>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>>> -		as->use_cs_gpios = false;
>>> -		master->num_chipselect = 4;
>> 
>> This line is pretty important: you mustn't remove it blindly!
>> 
>> 
>
> Actually, few lines above master->num_chipselect is initialized with:
> 	master->dev.of_node = pdev->dev.of_node;
> [...]
> 	master->num_chipselect = master->dev.of_node ? 0 : 4;
>
> So 0 in the case of DT support, 4 otherwise.
>
> Now looking at the source code of spi_register_master(), this function:
>
> 1 - calls of_spi_register_master(), which initializes master->num_chipselect:
> 	nb = of_gpio_name_count(np, "cs-gpios");
> 	master->num_chipselect = max_t(int, nb, master->num_chipselect);
>
> 	if (nb == 0 || nb == -ENOENT)
> 		return 0;
>
> 2 - check master->num_chipselect with:
> 	if (master->num_chipselect == 0)
> 		return -EINVAL;
>
> It means that in the case of DT support, master->num_chipselect was
> initialized according to the value of the "cs-gpios" DT
> property. Hence this property used to be mandatory but now we want it
> to be optional for hardware version 2 and later.
>
> This is why we added a check "hw version >= 2 and cs-gpios
> missing". In such a case the master->num_chipselect was initialized to
> 4 so spi_register_master() does not fail with -EINVAL.
>
> I have applied the following fix after your patch and now the driver works
> again on sama5d2:
>
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -1576,6 +1576,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
>
>         atmel_get_caps(as);
>
> +       if (atmel_spi_is_v2(as) &&
> +           master->dev.of_node &&
> +           !of_get_property(master->dev.of_node, "cs-gpios", NULL))
> +               master->num_chipselect = 4;
> +
>         as->use_dma = false;
>         as->use_pdc = false;
>         if (as->caps.has_dma_support) {

That's pretty much what I did (left the original alone) in v2 of the
patch.

Thanks for testing.

-- 
M?ns Rullg?rd

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  8:49       ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-12  8:49 UTC (permalink / raw)
  To: Måns Rullgård
  Cc: Mark Brown, linux-spi, linux-kernel, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Le 11/01/2016 16:43, Måns Rullgård a écrit :
> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
> 
>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>> The driver currently chooses between internal chip-select or gpio
>>> based on the existence of the cs-gpios DT property which fails on
>>> non-DT systems and also enforces the same choice for all devices.
>>
>> Well, I fear that such a per-device choice may impact further the driver
>> than just moving a field from one structure to another...
> 
> Could you please elaborate?

Well, the first thing that comes to my mind is that the DT property may
need to be  to the SPI device node and not the controller anymore, for a
need of coherency.
That would imply modifying the binding and I don't want that for such an
useless "improvement".

>> Moreover, I have the feeling that it was not the objective of this
>> patch.
> 
> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
> please explain why.

Please only fix the avr32 issue with CS gpio selection that I admit we
have. I don't need nor want to mix CS types: it just doesn't make sense
to allow it.


>>> This patch makes the method per device instead of per controller
>>> and fixes the selection on non-DT systems.  With these changes,
>>> the chip-select method for each device is chosen according to the
>>> following priority:
>>>
>>> 1. GPIO from device tree
>>> 2. GPIO from platform data
>>> 3. Internal chip-select
>>>
>>> Tested on AVR32 ATSTK1000.
>>
>> This patch breaks the SAMA5D2 SPI support at least on most recent
>> linux-next (tested by Cyrille).
> 
> How did it fail?
> 
>> more remarks below...
>>
>>> Signed-off-by: Mans Rullgard <mans@mansr.com>
>>> ---
>>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>>  1 file changed, 22 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>>> index aebad36391c9..8be07fb67d4d 100644
>>> --- a/drivers/spi/spi-atmel.c
>>> +++ b/drivers/spi/spi-atmel.c
>>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>>  
>>>  	bool			use_dma;
>>>  	bool			use_pdc;
>>> -	bool			use_cs_gpios;
>>>  	/* dmaengine data */
>>>  	struct atmel_spi_dma	dma;
>>>  
>>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>>  struct atmel_spi_device {
>>>  	unsigned int		npcs_pin;
>>>  	u32			csr;
>>> +	bool			use_cs_gpio;
>>>  };
>>>  
>>>  #define BUFFER_SIZE		PAGE_SIZE
>>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  		}
>>>  
>>>  		mr = spi_readl(as, MR);
>>> -		if (as->use_cs_gpios)
>>> +		if (asd->use_cs_gpio)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  	} else {
>>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  
>>>  		mr = spi_readl(as, MR);
>>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  		spi_writel(as, MR, mr);
>>>  	}
>>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>>  			asd->npcs_pin, active ? " (low)" : "",
>>>  			mr);
>>>  
>>> -	if (!as->use_cs_gpios)
>>> +	if (!asd->use_cs_gpio)
>>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>>  		gpio_set_value(asd->npcs_pin, !active);
>>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		csr |= SPI_BIT(CPOL);
>>>  	if (!(spi->mode & SPI_CPHA))
>>>  		csr |= SPI_BIT(NCPHA);
>>> -	if (!as->use_cs_gpios)
>>> -		csr |= SPI_BIT(CSAAT);
>>>  
>>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>>  	 *
>>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  	csr |= SPI_BF(DLYBS, 0);
>>>  	csr |= SPI_BF(DLYBCT, 0);
>>>  
>>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>>> -	npcs_pin = (unsigned long)spi->controller_data;
>>> -
>>> -	if (!as->use_cs_gpios)
>>> -		npcs_pin = spi->chip_select;
>>> -	else if (gpio_is_valid(spi->cs_gpio))
>>> -		npcs_pin = spi->cs_gpio;
>>> -
>>>  	asd = spi->controller_state;
>>>  	if (!asd) {
>>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>>  		if (!asd)
>>>  			return -ENOMEM;
>>>  
>>> -		if (as->use_cs_gpios) {
>>> +		npcs_pin = (unsigned long)spi->controller_data;
>>> +
>>> +		if (gpio_is_valid(spi->cs_gpio)) {
>>
>> The bug may come from here as the logic is somehow inverted and a "0" is
>> a valid gpio according to this gpio_is_valid() function. So we may take
>> this conditional branch instead of the third one in the sama5d2 case.
> 
> spi->cs_gpio is set to -ENOENT if none is specified so I don't think
> this should be a problem.
> 
>>> +			/* GPIO from DT */
>>> +			npcs_pin = spi->cs_gpio;
>>> +			asd->use_cs_gpio = true;
>>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>>> +			/* GPIO from platform data */
>>> +			asd->use_cs_gpio = true;
>>> +		} else {
>>> +			/* internal chip-select */
>>> +			npcs_pin = spi->chip_select;
>>> +			asd->use_cs_gpio = false;
>>> +		}
>>> +
>>> +		if (asd->use_cs_gpio) {
>>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>>  			if (ret) {
>>>  				kfree(asd);
>>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		spi->controller_state = asd;
>>>  	}
>>>  
>>> +	if (!asd->use_cs_gpio)
>>> +		csr |= SPI_BIT(CSAAT);
>>>  	asd->csr = csr;
>>>  
>>>  	dev_dbg(&spi->dev,
>>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>>  
>>>  	atmel_get_caps(as);
>>>  
>>> -	as->use_cs_gpios = true;
>>> -	if (atmel_spi_is_v2(as) &&
>>
>> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
>> did you make sure that the v1 of the peripheral is protected?
> 
> You're right, that check seems to have fallen by the wayside.
> 
>>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>>> -		as->use_cs_gpios = false;
>>> -		master->num_chipselect = 4;
>>
>> This line is pretty important: you mustn't remove it blindly!
> 
> That may be the real cause of whatever problem you saw.
> 
>>> -	}
>>> -
>>>  	as->use_dma = false;
>>>  	as->use_pdc = false;
>>>  	if (as->caps.has_dma_support) {
>>>
>>
>> So, sorry but it's a NACK for me.
> 
> Thanks for reviewing.
> 


-- 
Nicolas Ferre

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  8:49       ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-12  8:49 UTC (permalink / raw)
  To: Måns Rullgård
  Cc: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Le 11/01/2016 16:43, Måns Rullgård a écrit :
> Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:
> 
>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>> The driver currently chooses between internal chip-select or gpio
>>> based on the existence of the cs-gpios DT property which fails on
>>> non-DT systems and also enforces the same choice for all devices.
>>
>> Well, I fear that such a per-device choice may impact further the driver
>> than just moving a field from one structure to another...
> 
> Could you please elaborate?

Well, the first thing that comes to my mind is that the DT property may
need to be  to the SPI device node and not the controller anymore, for a
need of coherency.
That would imply modifying the binding and I don't want that for such an
useless "improvement".

>> Moreover, I have the feeling that it was not the objective of this
>> patch.
> 
> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
> please explain why.

Please only fix the avr32 issue with CS gpio selection that I admit we
have. I don't need nor want to mix CS types: it just doesn't make sense
to allow it.


>>> This patch makes the method per device instead of per controller
>>> and fixes the selection on non-DT systems.  With these changes,
>>> the chip-select method for each device is chosen according to the
>>> following priority:
>>>
>>> 1. GPIO from device tree
>>> 2. GPIO from platform data
>>> 3. Internal chip-select
>>>
>>> Tested on AVR32 ATSTK1000.
>>
>> This patch breaks the SAMA5D2 SPI support at least on most recent
>> linux-next (tested by Cyrille).
> 
> How did it fail?
> 
>> more remarks below...
>>
>>> Signed-off-by: Mans Rullgard <mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
>>> ---
>>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>>  1 file changed, 22 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>>> index aebad36391c9..8be07fb67d4d 100644
>>> --- a/drivers/spi/spi-atmel.c
>>> +++ b/drivers/spi/spi-atmel.c
>>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>>  
>>>  	bool			use_dma;
>>>  	bool			use_pdc;
>>> -	bool			use_cs_gpios;
>>>  	/* dmaengine data */
>>>  	struct atmel_spi_dma	dma;
>>>  
>>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>>  struct atmel_spi_device {
>>>  	unsigned int		npcs_pin;
>>>  	u32			csr;
>>> +	bool			use_cs_gpio;
>>>  };
>>>  
>>>  #define BUFFER_SIZE		PAGE_SIZE
>>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  		}
>>>  
>>>  		mr = spi_readl(as, MR);
>>> -		if (as->use_cs_gpios)
>>> +		if (asd->use_cs_gpio)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  	} else {
>>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  
>>>  		mr = spi_readl(as, MR);
>>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  		spi_writel(as, MR, mr);
>>>  	}
>>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>>  			asd->npcs_pin, active ? " (low)" : "",
>>>  			mr);
>>>  
>>> -	if (!as->use_cs_gpios)
>>> +	if (!asd->use_cs_gpio)
>>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>>  		gpio_set_value(asd->npcs_pin, !active);
>>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		csr |= SPI_BIT(CPOL);
>>>  	if (!(spi->mode & SPI_CPHA))
>>>  		csr |= SPI_BIT(NCPHA);
>>> -	if (!as->use_cs_gpios)
>>> -		csr |= SPI_BIT(CSAAT);
>>>  
>>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>>  	 *
>>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  	csr |= SPI_BF(DLYBS, 0);
>>>  	csr |= SPI_BF(DLYBCT, 0);
>>>  
>>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>>> -	npcs_pin = (unsigned long)spi->controller_data;
>>> -
>>> -	if (!as->use_cs_gpios)
>>> -		npcs_pin = spi->chip_select;
>>> -	else if (gpio_is_valid(spi->cs_gpio))
>>> -		npcs_pin = spi->cs_gpio;
>>> -
>>>  	asd = spi->controller_state;
>>>  	if (!asd) {
>>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>>  		if (!asd)
>>>  			return -ENOMEM;
>>>  
>>> -		if (as->use_cs_gpios) {
>>> +		npcs_pin = (unsigned long)spi->controller_data;
>>> +
>>> +		if (gpio_is_valid(spi->cs_gpio)) {
>>
>> The bug may come from here as the logic is somehow inverted and a "0" is
>> a valid gpio according to this gpio_is_valid() function. So we may take
>> this conditional branch instead of the third one in the sama5d2 case.
> 
> spi->cs_gpio is set to -ENOENT if none is specified so I don't think
> this should be a problem.
> 
>>> +			/* GPIO from DT */
>>> +			npcs_pin = spi->cs_gpio;
>>> +			asd->use_cs_gpio = true;
>>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>>> +			/* GPIO from platform data */
>>> +			asd->use_cs_gpio = true;
>>> +		} else {
>>> +			/* internal chip-select */
>>> +			npcs_pin = spi->chip_select;
>>> +			asd->use_cs_gpio = false;
>>> +		}
>>> +
>>> +		if (asd->use_cs_gpio) {
>>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>>  			if (ret) {
>>>  				kfree(asd);
>>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		spi->controller_state = asd;
>>>  	}
>>>  
>>> +	if (!asd->use_cs_gpio)
>>> +		csr |= SPI_BIT(CSAAT);
>>>  	asd->csr = csr;
>>>  
>>>  	dev_dbg(&spi->dev,
>>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>>  
>>>  	atmel_get_caps(as);
>>>  
>>> -	as->use_cs_gpios = true;
>>> -	if (atmel_spi_is_v2(as) &&
>>
>> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
>> did you make sure that the v1 of the peripheral is protected?
> 
> You're right, that check seems to have fallen by the wayside.
> 
>>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>>> -		as->use_cs_gpios = false;
>>> -		master->num_chipselect = 4;
>>
>> This line is pretty important: you mustn't remove it blindly!
> 
> That may be the real cause of whatever problem you saw.
> 
>>> -	}
>>> -
>>>  	as->use_dma = false;
>>>  	as->use_pdc = false;
>>>  	if (as->caps.has_dma_support) {
>>>
>>
>> So, sorry but it's a NACK for me.
> 
> Thanks for reviewing.
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  8:49       ` Nicolas Ferre
  0 siblings, 0 replies; 23+ messages in thread
From: Nicolas Ferre @ 2016-01-12  8:49 UTC (permalink / raw)
  To: linux-arm-kernel

Le 11/01/2016 16:43, M?ns Rullg?rd a ?crit :
> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
> 
>> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
>>> The driver currently chooses between internal chip-select or gpio
>>> based on the existence of the cs-gpios DT property which fails on
>>> non-DT systems and also enforces the same choice for all devices.
>>
>> Well, I fear that such a per-device choice may impact further the driver
>> than just moving a field from one structure to another...
> 
> Could you please elaborate?

Well, the first thing that comes to my mind is that the DT property may
need to be  to the SPI device node and not the controller anymore, for a
need of coherency.
That would imply modifying the binding and I don't want that for such an
useless "improvement".

>> Moreover, I have the feeling that it was not the objective of this
>> patch.
> 
> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
> please explain why.

Please only fix the avr32 issue with CS gpio selection that I admit we
have. I don't need nor want to mix CS types: it just doesn't make sense
to allow it.


>>> This patch makes the method per device instead of per controller
>>> and fixes the selection on non-DT systems.  With these changes,
>>> the chip-select method for each device is chosen according to the
>>> following priority:
>>>
>>> 1. GPIO from device tree
>>> 2. GPIO from platform data
>>> 3. Internal chip-select
>>>
>>> Tested on AVR32 ATSTK1000.
>>
>> This patch breaks the SAMA5D2 SPI support at least on most recent
>> linux-next (tested by Cyrille).
> 
> How did it fail?
> 
>> more remarks below...
>>
>>> Signed-off-by: Mans Rullgard <mans@mansr.com>
>>> ---
>>>  drivers/spi/spi-atmel.c | 44 ++++++++++++++++++++++----------------------
>>>  1 file changed, 22 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
>>> index aebad36391c9..8be07fb67d4d 100644
>>> --- a/drivers/spi/spi-atmel.c
>>> +++ b/drivers/spi/spi-atmel.c
>>> @@ -310,7 +310,6 @@ struct atmel_spi {
>>>  
>>>  	bool			use_dma;
>>>  	bool			use_pdc;
>>> -	bool			use_cs_gpios;
>>>  	/* dmaengine data */
>>>  	struct atmel_spi_dma	dma;
>>>  
>>> @@ -324,6 +323,7 @@ struct atmel_spi {
>>>  struct atmel_spi_device {
>>>  	unsigned int		npcs_pin;
>>>  	u32			csr;
>>> +	bool			use_cs_gpio;
>>>  };
>>>  
>>>  #define BUFFER_SIZE		PAGE_SIZE
>>> @@ -388,7 +388,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  		}
>>>  
>>>  		mr = spi_readl(as, MR);
>>> -		if (as->use_cs_gpios)
>>> +		if (asd->use_cs_gpio)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  	} else {
>>>  		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
>>> @@ -405,7 +405,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>>>  
>>>  		mr = spi_readl(as, MR);
>>>  		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
>>> -		if (as->use_cs_gpios && spi->chip_select != 0)
>>> +		if (asd->use_cs_gpio && spi->chip_select != 0)
>>>  			gpio_set_value(asd->npcs_pin, active);
>>>  		spi_writel(as, MR, mr);
>>>  	}
>>> @@ -434,7 +434,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>>>  			asd->npcs_pin, active ? " (low)" : "",
>>>  			mr);
>>>  
>>> -	if (!as->use_cs_gpios)
>>> +	if (!asd->use_cs_gpio)
>>>  		spi_writel(as, CR, SPI_BIT(LASTXFER));
>>>  	else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>>>  		gpio_set_value(asd->npcs_pin, !active);
>>> @@ -1221,8 +1221,6 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		csr |= SPI_BIT(CPOL);
>>>  	if (!(spi->mode & SPI_CPHA))
>>>  		csr |= SPI_BIT(NCPHA);
>>> -	if (!as->use_cs_gpios)
>>> -		csr |= SPI_BIT(CSAAT);
>>>  
>>>  	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
>>>  	 *
>>> @@ -1233,21 +1231,28 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  	csr |= SPI_BF(DLYBS, 0);
>>>  	csr |= SPI_BF(DLYBCT, 0);
>>>  
>>> -	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
>>> -	npcs_pin = (unsigned long)spi->controller_data;
>>> -
>>> -	if (!as->use_cs_gpios)
>>> -		npcs_pin = spi->chip_select;
>>> -	else if (gpio_is_valid(spi->cs_gpio))
>>> -		npcs_pin = spi->cs_gpio;
>>> -
>>>  	asd = spi->controller_state;
>>>  	if (!asd) {
>>>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
>>>  		if (!asd)
>>>  			return -ENOMEM;
>>>  
>>> -		if (as->use_cs_gpios) {
>>> +		npcs_pin = (unsigned long)spi->controller_data;
>>> +
>>> +		if (gpio_is_valid(spi->cs_gpio)) {
>>
>> The bug may come from here as the logic is somehow inverted and a "0" is
>> a valid gpio according to this gpio_is_valid() function. So we may take
>> this conditional branch instead of the third one in the sama5d2 case.
> 
> spi->cs_gpio is set to -ENOENT if none is specified so I don't think
> this should be a problem.
> 
>>> +			/* GPIO from DT */
>>> +			npcs_pin = spi->cs_gpio;
>>> +			asd->use_cs_gpio = true;
>>> +		} else if (npcs_pin && gpio_is_valid(npcs_pin)) {
>>> +			/* GPIO from platform data */
>>> +			asd->use_cs_gpio = true;
>>> +		} else {
>>> +			/* internal chip-select */
>>> +			npcs_pin = spi->chip_select;
>>> +			asd->use_cs_gpio = false;
>>> +		}
>>> +
>>> +		if (asd->use_cs_gpio) {
>>>  			ret = gpio_request(npcs_pin, dev_name(&spi->dev));
>>>  			if (ret) {
>>>  				kfree(asd);
>>> @@ -1262,6 +1267,8 @@ static int atmel_spi_setup(struct spi_device *spi)
>>>  		spi->controller_state = asd;
>>>  	}
>>>  
>>> +	if (!asd->use_cs_gpio)
>>> +		csr |= SPI_BIT(CSAAT);
>>>  	asd->csr = csr;
>>>  
>>>  	dev_dbg(&spi->dev,
>>> @@ -1569,13 +1576,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
>>>  
>>>  	atmel_get_caps(as);
>>>  
>>> -	as->use_cs_gpios = true;
>>> -	if (atmel_spi_is_v2(as) &&
>>
>> I don't see this atmel_spi_is_v2() test in the resulting code anymore:
>> did you make sure that the v1 of the peripheral is protected?
> 
> You're right, that check seems to have fallen by the wayside.
> 
>>> -	    !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
>>> -		as->use_cs_gpios = false;
>>> -		master->num_chipselect = 4;
>>
>> This line is pretty important: you mustn't remove it blindly!
> 
> That may be the real cause of whatever problem you saw.
> 
>>> -	}
>>> -
>>>  	as->use_dma = false;
>>>  	as->use_pdc = false;
>>>  	if (as->caps.has_dma_support) {
>>>
>>
>> So, sorry but it's a NACK for me.
> 
> Thanks for reviewing.
> 


-- 
Nicolas Ferre

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  9:08         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-12  9:08 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi, linux-kernel, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 11/01/2016 16:43, Måns Rullgård a écrit :
>> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

OK, fine.  I thought it could be useful (and it works), but apparently
you disagree.

Now the trouble with a global gpio vs internal setting is that we don't
know whether the non-DT platform data provides a gpio for the slave
devices when the master device is probed.  One possibility is to make
the choice based on the first slave to be registered and insist that the
rest follow suit.  I don't really like it, but I can't think of anything
else off the top of my head.  Do you have any better suggestions?

-- 
Måns Rullgård

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  9:08         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-12  9:08 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:

> Le 11/01/2016 16:43, Måns Rullgård a écrit :
>> Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

OK, fine.  I thought it could be useful (and it works), but apparently
you disagree.

Now the trouble with a global gpio vs internal setting is that we don't
know whether the non-DT platform data provides a gpio for the slave
devices when the master device is probed.  One possibility is to make
the choice based on the first slave to be registered and insist that the
rest follow suit.  I don't really like it, but I can't think of anything
else off the top of my head.  Do you have any better suggestions?

-- 
Måns Rullgård
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-12  9:08         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-12  9:08 UTC (permalink / raw)
  To: linux-arm-kernel

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 11/01/2016 16:43, M?ns Rullg?rd a ?crit :
>> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

OK, fine.  I thought it could be useful (and it works), but apparently
you disagree.

Now the trouble with a global gpio vs internal setting is that we don't
know whether the non-DT platform data provides a gpio for the slave
devices when the master device is probed.  One possibility is to make
the choice based on the first slave to be registered and insist that the
rest follow suit.  I don't really like it, but I can't think of anything
else off the top of my head.  Do you have any better suggestions?

-- 
M?ns Rullg?rd

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-13  2:07         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-13  2:07 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi, linux-kernel, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 11/01/2016 16:43, Måns Rullgård a écrit :
>> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

There's also this comment in spi.h regarding struct spi_master:

 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 *	number. Any individual value may be -ENOENT for CS lines that
 *	are not GPIOs (driven by the SPI controller itself).


-- 
Måns Rullgård

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

* Re: [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-13  2:07         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-13  2:07 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	Cyrille Pitchen, Yang, Wenyou

Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:

> Le 11/01/2016 16:43, Måns Rullgård a écrit :
>> Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a écrit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

There's also this comment in spi.h regarding struct spi_master:

 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 *	number. Any individual value may be -ENOENT for CS lines that
 *	are not GPIOs (driven by the SPI controller itself).


-- 
Måns Rullgård
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] spi: atmel: improve internal vs gpio chip-select choice
@ 2016-01-13  2:07         ` Måns Rullgård
  0 siblings, 0 replies; 23+ messages in thread
From: Måns Rullgård @ 2016-01-13  2:07 UTC (permalink / raw)
  To: linux-arm-kernel

Nicolas Ferre <nicolas.ferre@atmel.com> writes:

> Le 11/01/2016 16:43, M?ns Rullg?rd a ?crit :
>> Nicolas Ferre <nicolas.ferre@atmel.com> writes:
>> 
>>> Le 08/01/2016 01:11, Mans Rullgard a ?crit :
>>>> The driver currently chooses between internal chip-select or gpio
>>>> based on the existence of the cs-gpios DT property which fails on
>>>> non-DT systems and also enforces the same choice for all devices.
>>>
>>> Well, I fear that such a per-device choice may impact further the driver
>>> than just moving a field from one structure to another...
>> 
>> Could you please elaborate?
>
> Well, the first thing that comes to my mind is that the DT property may
> need to be  to the SPI device node and not the controller anymore, for a
> need of coherency.
> That would imply modifying the binding and I don't want that for such an
> useless "improvement".
>
>>> Moreover, I have the feeling that it was not the objective of this
>>> patch.
>> 
>> Your feeling is mistaken.  If it's somehow impossible to mix CS types,
>> please explain why.
>
> Please only fix the avr32 issue with CS gpio selection that I admit we
> have. I don't need nor want to mix CS types: it just doesn't make sense
> to allow it.

There's also this comment in spi.h regarding struct spi_master:

 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 *	number. Any individual value may be -ENOENT for CS lines that
 *	are not GPIOs (driven by the SPI controller itself).


-- 
M?ns Rullg?rd

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

end of thread, other threads:[~2016-01-13  2:07 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-08  0:11 [PATCH] spi: atmel: improve internal vs gpio chip-select choice Mans Rullgard
2016-01-08  0:11 ` Mans Rullgard
     [not found] ` <1452211907-16074-1-git-send-email-mans-2StjZFpD7GcAvxtiuMwx3w@public.gmane.org>
2016-01-08 13:44   ` Applied "spi: atmel: improve internal vs gpio chip-select choice" to the spi tree Mark Brown
2016-01-11 15:26 ` [PATCH] spi: atmel: improve internal vs gpio chip-select choice Nicolas Ferre
2016-01-11 15:26   ` Nicolas Ferre
2016-01-11 15:26   ` Nicolas Ferre
2016-01-11 15:43   ` Måns Rullgård
2016-01-11 15:43     ` Måns Rullgård
2016-01-11 15:43     ` Måns Rullgård
2016-01-12  8:49     ` Nicolas Ferre
2016-01-12  8:49       ` Nicolas Ferre
2016-01-12  8:49       ` Nicolas Ferre
2016-01-12  9:08       ` Måns Rullgård
2016-01-12  9:08         ` Måns Rullgård
2016-01-12  9:08         ` Måns Rullgård
2016-01-13  2:07       ` Måns Rullgård
2016-01-13  2:07         ` Måns Rullgård
2016-01-13  2:07         ` Måns Rullgård
2016-01-11 16:33   ` Cyrille Pitchen
2016-01-11 16:33     ` Cyrille Pitchen
2016-01-11 16:33     ` Cyrille Pitchen
2016-01-11 16:37     ` Måns Rullgård
2016-01-11 16:37       ` Måns Rullgård

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.