Skip to content

Commit 676a4e3

Browse files
jan-kiszkabroonie
authored andcommitted
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 <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 5771a8c commit 676a4e3

File tree

1 file changed

+21
-38
lines changed

1 file changed

+21
-38
lines changed

drivers/spi/spi-pxa2xx.c

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,21 +1213,33 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
12131213
struct pxa2xx_spi_chip *chip_info)
12141214
{
12151215
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
1216+
struct device *pdev = &drv_data->pdev->dev;
1217+
struct gpio_desc *gpiod;
12161218
int err = 0;
1219+
int count;
12171220

12181221
if (chip == NULL)
12191222
return 0;
12201223

1221-
if (drv_data->cs_gpiods) {
1222-
struct gpio_desc *gpiod;
1224+
count = gpiod_count(pdev, "cs");
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;
12231235

1224-
gpiod = drv_data->cs_gpiods[spi->chip_select];
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);
1236+
return PTR_ERR(gpiod);
12291237
}
12301238

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+
12311243
return 0;
12321244
}
12331245

@@ -1415,8 +1427,7 @@ static void cleanup(struct spi_device *spi)
14151427
if (!chip)
14161428
return;
14171429

1418-
if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods &&
1419-
gpio_is_valid(chip->gpio_cs))
1430+
if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
14201431
gpio_free(chip->gpio_cs);
14211432

14221433
kfree(chip);
@@ -1752,38 +1763,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
17521763
master->num_chipselect = platform_info->num_chipselect;
17531764

17541765
count = gpiod_count(&pdev->dev, "cs");
1755-
if (count > 0) {
1756-
int i;
1757-
1766+
if (count > 0)
17581767
master->num_chipselect = max_t(int, count,
17591768
master->num_chipselect);
17601769

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-
17871770
tasklet_init(&drv_data->pump_transfers, pump_transfers,
17881771
(unsigned long)drv_data);
17891772

0 commit comments

Comments
 (0)