71 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
		
		
			
		
	
	
			71 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
| 
								 | 
							
								From: Felix Fietkau <nbd@nbd.name>
							 | 
						||
| 
								 | 
							
								Date: Fri, 9 Dec 2016 20:09:16 +0100
							 | 
						||
| 
								 | 
							
								Subject: [PATCH] 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: Felix Fietkau <nbd@nbd.name>
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								--- a/drivers/spi/spi-ath79.c
							 | 
						||
| 
								 | 
							
								+++ b/drivers/spi/spi-ath79.c
							 | 
						||
| 
								 | 
							
								@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct
							 | 
						||
| 
								 | 
							
								 		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 */
							 | 
						||
| 
								 | 
							
								 		gpio_set_value(spi->cs_gpio, cs_high);
							 | 
						||
| 
								 | 
							
								 	} else {
							 | 
						||
| 
								 | 
							
								+		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								 		if (cs_high)
							 | 
						||
| 
								 | 
							
								-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
							 | 
						||
| 
								 | 
							
								+			sp->ioc_base |= cs_bit;
							 | 
						||
| 
								 | 
							
								 		else
							 | 
						||
| 
								 | 
							
								-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
							 | 
						||
| 
								 | 
							
								+			sp->ioc_base &= ~cs_bit;
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
							 | 
						||
| 
								 | 
							
								 	}
							 | 
						||
| 
								 | 
							
								@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi
							 | 
						||
| 
								 | 
							
								 	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
							 | 
						||
| 
								 | 
							
								 	int status;
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								-	if (spi->chip_select && !gpio_is_valid(spi->cs_gpio))
							 | 
						||
| 
								 | 
							
								-		return -EINVAL;
							 | 
						||
| 
								 | 
							
								-
							 | 
						||
| 
								 | 
							
								 	status = 0;
							 | 
						||
| 
								 | 
							
								-	if (spi->chip_select) {
							 | 
						||
| 
								 | 
							
								+	if (gpio_is_valid(spi->cs_gpio)) {
							 | 
						||
| 
								 | 
							
								 		unsigned long flags;
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 		flags = GPIOF_DIR_OUT;
							 | 
						||
| 
								 | 
							
								@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi
							 | 
						||
| 
								 | 
							
								 		status = gpio_request_one(spi->cs_gpio, flags,
							 | 
						||
| 
								 | 
							
								 					  dev_name(&spi->dev));
							 | 
						||
| 
								 | 
							
								 	} else {
							 | 
						||
| 
								 | 
							
								+		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								 		if (spi->mode & SPI_CS_HIGH)
							 | 
						||
| 
								 | 
							
								-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
							 | 
						||
| 
								 | 
							
								+			sp->ioc_base &= ~cs_bit;
							 | 
						||
| 
								 | 
							
								 		else
							 | 
						||
| 
								 | 
							
								-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
							 | 
						||
| 
								 | 
							
								+			sp->ioc_base |= cs_bit;
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
							 | 
						||
| 
								 | 
							
								 	}
							 | 
						||
| 
								 | 
							
								@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct 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);
							 | 
						||
| 
								 | 
							
								 	}
							 | 
						||
| 
								 | 
							
								 }
							 |