diff options
-rw-r--r-- | drivers/spi/spi-orion.c | 47 |
1 files changed, 44 insertions, 3 deletions
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 { | |||
96 | struct clk *clk; | 96 | struct clk *clk; |
97 | struct clk *axi_clk; | 97 | struct clk *axi_clk; |
98 | const struct orion_spi_dev *devdata; | 98 | const struct orion_spi_dev *devdata; |
99 | int unused_hw_gpio; | ||
99 | 100 | ||
100 | struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS]; | 101 | struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS]; |
101 | }; | 102 | }; |
@@ -324,13 +325,13 @@ static void orion_spi_set_cs(struct spi_device *spi, bool enable) | |||
324 | struct orion_spi *orion_spi; | 325 | struct orion_spi *orion_spi; |
325 | int cs; | 326 | int cs; |
326 | 327 | ||
328 | orion_spi = spi_master_get_devdata(spi->master); | ||
329 | |||
327 | if (gpio_is_valid(spi->cs_gpio)) | 330 | if (gpio_is_valid(spi->cs_gpio)) |
328 | cs = 0; | 331 | cs = orion_spi->unused_hw_gpio; |
329 | else | 332 | else |
330 | cs = spi->chip_select; | 333 | cs = spi->chip_select; |
331 | 334 | ||
332 | orion_spi = spi_master_get_devdata(spi->master); | ||
333 | |||
334 | orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); | 335 | orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); |
335 | orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, | 336 | orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, |
336 | ORION_SPI_CS(cs)); | 337 | ORION_SPI_CS(cs)); |
@@ -498,6 +499,9 @@ static int orion_spi_transfer_one(struct spi_master *master, | |||
498 | 499 | ||
499 | static int orion_spi_setup(struct spi_device *spi) | 500 | static int orion_spi_setup(struct spi_device *spi) |
500 | { | 501 | { |
502 | if (gpio_is_valid(spi->cs_gpio)) { | ||
503 | gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); | ||
504 | } | ||
501 | return orion_spi_setup_transfer(spi, NULL); | 505 | return orion_spi_setup_transfer(spi, NULL); |
502 | } | 506 | } |
503 | 507 | ||
@@ -620,6 +624,7 @@ static int orion_spi_probe(struct platform_device *pdev) | |||
620 | 624 | ||
621 | spi = spi_master_get_devdata(master); | 625 | spi = spi_master_get_devdata(master); |
622 | spi->master = master; | 626 | spi->master = master; |
627 | spi->unused_hw_gpio = -1; | ||
623 | 628 | ||
624 | of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); | 629 | of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); |
625 | devdata = (of_id) ? of_id->data : &orion_spi_dev_data; | 630 | devdata = (of_id) ? of_id->data : &orion_spi_dev_data; |
@@ -731,8 +736,44 @@ static int orion_spi_probe(struct platform_device *pdev) | |||
731 | if (status < 0) | 736 | if (status < 0) |
732 | goto out_rel_pm; | 737 | goto out_rel_pm; |
733 | 738 | ||
739 | if (master->cs_gpios) { | ||
740 | int i; | ||
741 | for (i = 0; i < master->num_chipselect; ++i) { | ||
742 | char *gpio_name; | ||
743 | |||
744 | if (!gpio_is_valid(master->cs_gpios[i])) { | ||
745 | continue; | ||
746 | } | ||
747 | |||
748 | gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, | ||
749 | "%s-CS%d", dev_name(&pdev->dev), i); | ||
750 | if (!gpio_name) { | ||
751 | status = -ENOMEM; | ||
752 | goto out_rel_master; | ||
753 | } | ||
754 | |||
755 | status = devm_gpio_request(&pdev->dev, | ||
756 | master->cs_gpios[i], gpio_name); | ||
757 | if (status) { | ||
758 | dev_err(&pdev->dev, | ||
759 | "Can't request GPIO for CS %d\n", | ||
760 | master->cs_gpios[i]); | ||
761 | goto out_rel_master; | ||
762 | } | ||
763 | if (spi->unused_hw_gpio == -1) { | ||
764 | dev_info(&pdev->dev, | ||
765 | "Selected unused HW CS#%d " | ||
766 | "for any GPIO CSes\n", i); | ||
767 | spi->unused_hw_gpio = i; | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | |||
772 | |||
734 | return status; | 773 | return status; |
735 | 774 | ||
775 | out_rel_master: | ||
776 | spi_unregister_master(master); | ||
736 | out_rel_pm: | 777 | out_rel_pm: |
737 | pm_runtime_disable(&pdev->dev); | 778 | pm_runtime_disable(&pdev->dev); |
738 | out_rel_axi_clk: | 779 | out_rel_axi_clk: |