aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-pxa2xx.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2016-09-26 08:19:50 -0400
committerMark Brown <broonie@kernel.org>2016-09-26 12:11:14 -0400
commit99f499cd650405bbe6a9b5386d4b11ee81514fb7 (patch)
tree48882d1cafee7da91e34946f6666104d21b0ff4a /drivers/spi/spi-pxa2xx.c
parent7c7289a40425d48bbfcaacc454a8caf5b47f63b0 (diff)
spi: pxa2xx: Add support for GPIO descriptor chip selects
The driver uses custom chip_info coming from platform data for chip selects implemented as GPIOs. If the system lacks board files setting up the platform data, it is not possible to use GPIOs as chip selects. This adds support for GPIO descriptors so that regardless of the underlying firmware interface (DT, ACPI or platform data) the driver can request GPIOs used as chip selects and configure them accordingly. The custom chip_info GPIO support is still left there to make sure the existing systems keep working as expected. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-pxa2xx.c')
-rw-r--r--drivers/spi/spi-pxa2xx.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index cab39b06bc89..5e2ed7d34487 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1194,9 +1194,26 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
1194static int setup_cs(struct spi_device *spi, struct chip_data *chip, 1194static int setup_cs(struct spi_device *spi, struct chip_data *chip,
1195 struct pxa2xx_spi_chip *chip_info) 1195 struct pxa2xx_spi_chip *chip_info)
1196{ 1196{
1197 struct driver_data *drv_data = spi_master_get_devdata(spi->master);
1197 int err = 0; 1198 int err = 0;
1198 1199
1199 if (chip == NULL || chip_info == NULL) 1200 if (chip == NULL)
1201 return 0;
1202
1203 if (drv_data->cs_gpiods) {
1204 struct gpio_desc *gpiod;
1205
1206 gpiod = drv_data->cs_gpiods[spi->chip_select];
1207 if (gpiod) {
1208 chip->gpio_cs = desc_to_gpio(gpiod);
1209 chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
1210 gpiod_set_value(gpiod, chip->gpio_cs_inverted);
1211 }
1212
1213 return 0;
1214 }
1215
1216 if (chip_info == NULL)
1200 return 0; 1217 return 0;
1201 1218
1202 /* NOTE: setup() can be called multiple times, possibly with 1219 /* NOTE: setup() can be called multiple times, possibly with
@@ -1379,7 +1396,8 @@ static void cleanup(struct spi_device *spi)
1379 if (!chip) 1396 if (!chip)
1380 return; 1397 return;
1381 1398
1382 if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs)) 1399 if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods &&
1400 gpio_is_valid(chip->gpio_cs))
1383 gpio_free(chip->gpio_cs); 1401 gpio_free(chip->gpio_cs);
1384 1402
1385 kfree(chip); 1403 kfree(chip);
@@ -1557,7 +1575,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1557 struct driver_data *drv_data; 1575 struct driver_data *drv_data;
1558 struct ssp_device *ssp; 1576 struct ssp_device *ssp;
1559 const struct lpss_config *config; 1577 const struct lpss_config *config;
1560 int status; 1578 int status, count;
1561 u32 tmp; 1579 u32 tmp;
1562 1580
1563 platform_info = dev_get_platdata(dev); 1581 platform_info = dev_get_platdata(dev);
@@ -1701,6 +1719,39 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1701 } 1719 }
1702 master->num_chipselect = platform_info->num_chipselect; 1720 master->num_chipselect = platform_info->num_chipselect;
1703 1721
1722 count = gpiod_count(&pdev->dev, "cs");
1723 if (count > 0) {
1724 int i;
1725
1726 master->num_chipselect = max_t(int, count,
1727 master->num_chipselect);
1728
1729 drv_data->cs_gpiods = devm_kcalloc(&pdev->dev,
1730 master->num_chipselect, sizeof(struct gpio_desc *),
1731 GFP_KERNEL);
1732 if (!drv_data->cs_gpiods) {
1733 status = -ENOMEM;
1734 goto out_error_clock_enabled;
1735 }
1736
1737 for (i = 0; i < master->num_chipselect; i++) {
1738 struct gpio_desc *gpiod;
1739
1740 gpiod = devm_gpiod_get_index(dev, "cs", i,
1741 GPIOD_OUT_HIGH);
1742 if (IS_ERR(gpiod)) {
1743 /* Means use native chip select */
1744 if (PTR_ERR(gpiod) == -ENOENT)
1745 continue;
1746
1747 status = (int)PTR_ERR(gpiod);
1748 goto out_error_clock_enabled;
1749 } else {
1750 drv_data->cs_gpiods[i] = gpiod;
1751 }
1752 }
1753 }
1754
1704 tasklet_init(&drv_data->pump_transfers, pump_transfers, 1755 tasklet_init(&drv_data->pump_transfers, pump_transfers,
1705 (unsigned long)drv_data); 1756 (unsigned long)drv_data);
1706 1757