Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22c76326 authored by Felix Fietkau's avatar Felix Fietkau Committed by Mark Brown
Browse files

spi: spi-ath79: support multiple internal chip select lines



Several devices with multiple flash chips use the internal chip select
lines. Don't assume that chip select 1 and above are GPIO lines.

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent fafd6794
Loading
Loading
Loading
Loading
+11 −10
Original line number Original line Diff line number Diff line
@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}
	}


	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		/* SPI is normally active-low */
		/* SPI is normally active-low */
		gpio_set_value(spi->cs_gpio, cs_high);
		gpio_set_value(spi->cs_gpio, cs_high);
	} else {
	} else {
		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);

		if (cs_high)
		if (cs_high)
			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
			sp->ioc_base |= cs_bit;
		else
		else
			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
			sp->ioc_base &= ~cs_bit;


		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}
	}
@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
	int status;
	int status;


	if (spi->chip_select && !gpio_is_valid(spi->cs_gpio))
		return -EINVAL;

	status = 0;
	status = 0;
	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		unsigned long flags;
		unsigned long flags;


		flags = GPIOF_DIR_OUT;
		flags = GPIOF_DIR_OUT;
@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
		status = gpio_request_one(spi->cs_gpio, flags,
		status = gpio_request_one(spi->cs_gpio, flags,
					  dev_name(&spi->dev));
					  dev_name(&spi->dev));
	} else {
	} else {
		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);

		if (spi->mode & SPI_CS_HIGH)
		if (spi->mode & SPI_CS_HIGH)
			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
			sp->ioc_base &= ~cs_bit;
		else
		else
			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
			sp->ioc_base |= cs_bit;


		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}
	}
@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi)


static void ath79_spi_cleanup_cs(struct spi_device *spi)
static void ath79_spi_cleanup_cs(struct spi_device *spi)
{
{
	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		gpio_free(spi->cs_gpio);
		gpio_free(spi->cs_gpio);
	}
	}
}
}