Commit 66eb2289 authored by Linus Walleij's avatar Linus Walleij Committed by Mark Brown

spi: orion: Convert to use GPIO descriptors

This converts the Orion SPI master to use GPIO descriptors.
The SPI core will obtain and manage the CS GPIOs, if any
are defined.

I make one sematic change: when a certain chip select is using
a GPIO line instead of the native CS I simply just enable the
1:1 mapped native CS that would have been used if the GPIO
was not there. As we set the SPI_MASTER_GPIO_SS the .set_cs()
callback will be called for all chip selects whether native
or not, and the important thing for the driver is that the
previous native chip select (if any) is deasserted, which
other chip select is asserted instead does not really matter.

The previous code went to great lengths to ascertain that the
first hw CS which was hiding behind a GPIO line was used for
all cases when the line is not using native chip select but
this should not matter at all, just use the one "underneath"
the GPIO at all times.

When a GPIO is used for CS, the SPI_CS_HIGH flag is enforced,
so the native chip select is also inverted. But that should
not matter since we are not using it anyways.
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Cc: Gregory CLEMENT <gregory.clement@bootlin.com>
Cc: Tomas Paukrt <tomaspaukrt@email.cz>
Cc: Jan Kundrát <jan.kundrat@cesnet.cz>
Link: https://lore.kernel.org/r/20200415175613.220767-1-linus.walleij@linaro.orgSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 59fc9ad5
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/gpio.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define DRIVER_NAME "orion_spi" #define DRIVER_NAME "orion_spi"
...@@ -98,7 +96,6 @@ struct orion_spi { ...@@ -98,7 +96,6 @@ struct orion_spi {
struct clk *clk; struct clk *clk;
struct clk *axi_clk; struct clk *axi_clk;
const struct orion_spi_dev *devdata; const struct orion_spi_dev *devdata;
int unused_hw_gpio;
struct orion_child_options child[ORION_NUM_CHIPSELECTS]; struct orion_child_options child[ORION_NUM_CHIPSELECTS];
}; };
...@@ -325,20 +322,27 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -325,20 +322,27 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
static void orion_spi_set_cs(struct spi_device *spi, bool enable) static void orion_spi_set_cs(struct spi_device *spi, bool enable)
{ {
struct orion_spi *orion_spi; struct orion_spi *orion_spi;
int cs;
orion_spi = spi_master_get_devdata(spi->master); orion_spi = spi_master_get_devdata(spi->master);
if (gpio_is_valid(spi->cs_gpio)) /*
cs = orion_spi->unused_hw_gpio; * If this line is using a GPIO to control chip select, this internal
else * .set_cs() function will still be called, so we clear any previous
cs = spi->chip_select; * chip select. The CS we activate will not have any elecrical effect,
* as it is handled by a GPIO, but that doesn't matter. What we need
* is to deassert the old chip select and assert some other chip select.
*/
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
ORION_SPI_CS(cs)); ORION_SPI_CS(spi->chip_select));
/* Chip select logic is inverted from spi_set_cs */ /*
* Chip select logic is inverted from spi_set_cs(). For lines using a
* GPIO to do chip select SPI_CS_HIGH is enforced and inversion happens
* in the GPIO library, but we don't care about that, because in those
* cases we are dealing with an unused native CS anyways so the polarity
* doesn't matter.
*/
if (!enable) if (!enable)
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1); orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
else else
...@@ -503,9 +507,6 @@ static int orion_spi_transfer_one(struct spi_master *master, ...@@ -503,9 +507,6 @@ static int orion_spi_transfer_one(struct spi_master *master,
static int orion_spi_setup(struct spi_device *spi) static int orion_spi_setup(struct spi_device *spi)
{ {
if (gpio_is_valid(spi->cs_gpio)) {
gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
}
return orion_spi_setup_transfer(spi, NULL); return orion_spi_setup_transfer(spi, NULL);
} }
...@@ -622,13 +623,13 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -622,13 +623,13 @@ static int orion_spi_probe(struct platform_device *pdev)
master->setup = orion_spi_setup; master->setup = orion_spi_setup;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->use_gpio_descriptors = true;
master->flags = SPI_MASTER_GPIO_SS; master->flags = SPI_MASTER_GPIO_SS;
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
spi = spi_master_get_devdata(master); spi = spi_master_get_devdata(master);
spi->master = master; spi->master = master;
spi->unused_hw_gpio = -1;
of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); of_id = of_match_device(orion_spi_of_match_table, &pdev->dev);
devdata = (of_id) ? of_id->data : &orion_spi_dev_data; devdata = (of_id) ? of_id->data : &orion_spi_dev_data;
...@@ -683,7 +684,6 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -683,7 +684,6 @@ static int orion_spi_probe(struct platform_device *pdev)
for_each_available_child_of_node(pdev->dev.of_node, np) { for_each_available_child_of_node(pdev->dev.of_node, np) {
struct orion_direct_acc *dir_acc; struct orion_direct_acc *dir_acc;
u32 cs; u32 cs;
int cs_gpio;
/* Get chip-select number from the "reg" property */ /* Get chip-select number from the "reg" property */
status = of_property_read_u32(np, "reg", &cs); status = of_property_read_u32(np, "reg", &cs);
...@@ -694,44 +694,6 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -694,44 +694,6 @@ static int orion_spi_probe(struct platform_device *pdev)
continue; continue;
} }
/*
* Initialize the CS GPIO:
* - properly request the actual GPIO signal
* - de-assert the logical signal so that all GPIO CS lines
* are inactive when probing for slaves
* - find an unused physical CS which will be driven for any
* slave which uses a CS GPIO
*/
cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", cs);
if (cs_gpio > 0) {
char *gpio_name;
int cs_flags;
if (spi->unused_hw_gpio == -1) {
dev_info(&pdev->dev,
"Selected unused HW CS#%d for any GPIO CSes\n",
cs);
spi->unused_hw_gpio = cs;
}
gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-CS%d", dev_name(&pdev->dev), cs);
if (!gpio_name) {
status = -ENOMEM;
goto out_rel_axi_clk;
}
cs_flags = of_property_read_bool(np, "spi-cs-high") ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
status = devm_gpio_request_one(&pdev->dev, cs_gpio,
cs_flags, gpio_name);
if (status) {
dev_err(&pdev->dev,
"Can't request GPIO for CS %d\n", cs);
goto out_rel_axi_clk;
}
}
/* /*
* Check if an address is configured for this SPI device. If * Check if an address is configured for this SPI device. If
* not, the MBus mapping via the 'ranges' property in the 'soc' * not, the MBus mapping via the 'ranges' property in the 'soc'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment