[PATCH] spi: atmel: improve internal vs gpio chip-select choice

From: Mans Rullgard
Date: Thu Jan 07 2016 - 19:12:20 EST


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@xxxxxxxxx>
---
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