From 544248623b95eefbe4bea5fa5c68ab0da495eaae Mon Sep 17 00:00:00 2001 From: Jan Kundrát Date: Fri, 26 Jan 2018 23:56:10 +0100 Subject: spi: orion: Rework GPIO CS handling - Claim the GPIO from the driver, not via DT bindings or through the platform code - Find an unused HW CS signal because Orion needs to drive one for each SPI transaction The spi-orion.c was the only driver which supported (or cared about) the CS GPIO, while it wasn't actually requesting it. This change means that the DT bindings should stop hogging the GPIO CS pins because it's now being handled by the driver. Signed-off-by: Jan Kundrát Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index deca63e82ff6..b341235d2947 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -96,6 +96,7 @@ struct orion_spi { struct clk *clk; struct clk *axi_clk; const struct orion_spi_dev *devdata; + int unused_hw_gpio; struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS]; }; @@ -324,13 +325,13 @@ static void orion_spi_set_cs(struct spi_device *spi, bool enable) struct orion_spi *orion_spi; int cs; + orion_spi = spi_master_get_devdata(spi->master); + if (gpio_is_valid(spi->cs_gpio)) - cs = 0; + cs = orion_spi->unused_hw_gpio; else cs = spi->chip_select; - orion_spi = spi_master_get_devdata(spi->master); - 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_CS(cs)); @@ -498,6 +499,9 @@ static int orion_spi_transfer_one(struct spi_master *master, 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); } @@ -620,6 +624,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi = spi_master_get_devdata(master); spi->master = master; + spi->unused_hw_gpio = -1; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = (of_id) ? of_id->data : &orion_spi_dev_data; @@ -731,8 +736,44 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; + if (master->cs_gpios) { + int i; + for (i = 0; i < master->num_chipselect; ++i) { + char *gpio_name; + + if (!gpio_is_valid(master->cs_gpios[i])) { + continue; + } + + gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%s-CS%d", dev_name(&pdev->dev), i); + if (!gpio_name) { + status = -ENOMEM; + goto out_rel_master; + } + + status = devm_gpio_request(&pdev->dev, + master->cs_gpios[i], gpio_name); + if (status) { + dev_err(&pdev->dev, + "Can't request GPIO for CS %d\n", + master->cs_gpios[i]); + goto out_rel_master; + } + if (spi->unused_hw_gpio == -1) { + dev_info(&pdev->dev, + "Selected unused HW CS#%d " + "for any GPIO CSes\n", i); + spi->unused_hw_gpio = i; + } + } + } + + return status; +out_rel_master: + spi_unregister_master(master); out_rel_pm: pm_runtime_disable(&pdev->dev); out_rel_axi_clk: -- cgit v1.2.3-55-g7522