aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2017-07-08 04:41:18 -0400
committerMark Brown <broonie@kernel.org>2017-07-17 07:09:52 -0400
commit676a4e3bab445d53fca4756865e2c0e2a87c38d6 (patch)
treed0852607196169bbd483ec63564fd8e73cea496a
parent5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff)
spi: pxa2xx: Only claim CS GPIOs when the slave device is created
Avoid hogging chip select GPIOs just because they are listed for the master. They might be mulitplexed and, if no slave device is attached, used for different purposes. Moreover, this strategy avoids having to allocate a cs_gpiods structure. Tested on the IOT2000 where the second SPI bus is connected to an Arduino-compatible connector and multiplexed between SPI, GPIO and PWM usage. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-pxa2xx.c59
1 files changed, 21 insertions, 38 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 38d053682892..be991266a6ce 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1213,21 +1213,33 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
1213 struct pxa2xx_spi_chip *chip_info) 1213 struct pxa2xx_spi_chip *chip_info)
1214{ 1214{
1215 struct driver_data *drv_data = spi_master_get_devdata(spi->master); 1215 struct driver_data *drv_data = spi_master_get_devdata(spi->master);
1216 struct device *pdev = &drv_data->pdev->dev;
1217 struct gpio_desc *gpiod;
1216 int err = 0; 1218 int err = 0;
1219 int count;
1217 1220
1218 if (chip == NULL) 1221 if (chip == NULL)
1219 return 0; 1222 return 0;
1220 1223
1221 if (drv_data->cs_gpiods) { 1224 count = gpiod_count(pdev, "cs");
1222 struct gpio_desc *gpiod; 1225 if (count > 0) {
1226 if (spi->chip_select >= count)
1227 return -EINVAL;
1228
1229 gpiod = gpiod_get_index(pdev, "cs", spi->chip_select,
1230 GPIOD_OUT_HIGH);
1231 if (IS_ERR(gpiod)) {
1232 /* Means use native chip select */
1233 if (PTR_ERR(gpiod) == -ENOENT)
1234 return 0;
1223 1235
1224 gpiod = drv_data->cs_gpiods[spi->chip_select]; 1236 return PTR_ERR(gpiod);
1225 if (gpiod) {
1226 chip->gpio_cs = desc_to_gpio(gpiod);
1227 chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
1228 gpiod_set_value(gpiod, chip->gpio_cs_inverted);
1229 } 1237 }
1230 1238
1239 chip->gpio_cs = desc_to_gpio(gpiod);
1240 chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
1241 gpiod_set_value(gpiod, chip->gpio_cs_inverted);
1242
1231 return 0; 1243 return 0;
1232 } 1244 }
1233 1245
@@ -1415,8 +1427,7 @@ static void cleanup(struct spi_device *spi)
1415 if (!chip) 1427 if (!chip)
1416 return; 1428 return;
1417 1429
1418 if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods && 1430 if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
1419 gpio_is_valid(chip->gpio_cs))
1420 gpio_free(chip->gpio_cs); 1431 gpio_free(chip->gpio_cs);
1421 1432
1422 kfree(chip); 1433 kfree(chip);
@@ -1752,38 +1763,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1752 master->num_chipselect = platform_info->num_chipselect; 1763 master->num_chipselect = platform_info->num_chipselect;
1753 1764
1754 count = gpiod_count(&pdev->dev, "cs"); 1765 count = gpiod_count(&pdev->dev, "cs");
1755 if (count > 0) { 1766 if (count > 0)
1756 int i;
1757
1758 master->num_chipselect = max_t(int, count, 1767 master->num_chipselect = max_t(int, count,
1759 master->num_chipselect); 1768 master->num_chipselect);
1760 1769
1761 drv_data->cs_gpiods = devm_kcalloc(&pdev->dev,
1762 master->num_chipselect, sizeof(struct gpio_desc *),
1763 GFP_KERNEL);
1764 if (!drv_data->cs_gpiods) {
1765 status = -ENOMEM;
1766 goto out_error_clock_enabled;
1767 }
1768
1769 for (i = 0; i < master->num_chipselect; i++) {
1770 struct gpio_desc *gpiod;
1771
1772 gpiod = devm_gpiod_get_index(dev, "cs", i,
1773 GPIOD_OUT_HIGH);
1774 if (IS_ERR(gpiod)) {
1775 /* Means use native chip select */
1776 if (PTR_ERR(gpiod) == -ENOENT)
1777 continue;
1778
1779 status = (int)PTR_ERR(gpiod);
1780 goto out_error_clock_enabled;
1781 } else {
1782 drv_data->cs_gpiods[i] = gpiod;
1783 }
1784 }
1785 }
1786
1787 tasklet_init(&drv_data->pump_transfers, pump_transfers, 1770 tasklet_init(&drv_data->pump_transfers, pump_transfers,
1788 (unsigned long)drv_data); 1771 (unsigned long)drv_data);
1789 1772