diff options
Diffstat (limited to 'drivers/spi/spi-pxa2xx.c')
| -rw-r--r-- | drivers/spi/spi-pxa2xx.c | 93 | 
1 files changed, 49 insertions, 44 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 2eb06ee0b32..fe792106bdc 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -27,7 +27,6 @@  #include <linux/platform_device.h>  #include <linux/spi/pxa2xx_spi.h>  #include <linux/spi/spi.h> -#include <linux/workqueue.h>  #include <linux/delay.h>  #include <linux/gpio.h>  #include <linux/slab.h> @@ -119,6 +118,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data)  	 */  	orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); +	/* Test SPI_CS_CONTROL_SW_MODE bit enabling */  	value = orig | SPI_CS_CONTROL_SW_MODE;  	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);  	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); @@ -127,10 +127,13 @@ static void lpss_ssp_setup(struct driver_data *drv_data)  		goto detection_done;  	} -	value &= ~SPI_CS_CONTROL_SW_MODE; +	orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); + +	/* Test SPI_CS_CONTROL_SW_MODE bit disabling */ +	value = orig & ~SPI_CS_CONTROL_SW_MODE;  	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);  	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); -	if (value != orig) { +	if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) {  		offset = 0x800;  		goto detection_done;  	} @@ -362,8 +365,7 @@ static void giveback(struct driver_data *drv_data)  	drv_data->cur_msg = NULL;  	drv_data->cur_transfer = NULL; -	last_transfer = list_entry(msg->transfers.prev, -					struct spi_transfer, +	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,  					transfer_list);  	/* Delay if requested before any change in chip select */ @@ -546,8 +548,17 @@ static irqreturn_t ssp_int(int irq, void *dev_id)  	if (pm_runtime_suspended(&drv_data->pdev->dev))  		return IRQ_NONE; -	sccr1_reg = read_SSCR1(reg); +	/* +	 * If the device is not yet in RPM suspended state and we get an +	 * interrupt that is meant for another device, check if status bits +	 * are all set to one. That means that the device is already +	 * powered off. +	 */  	status = read_SSSR(reg); +	if (status == ~0) +		return IRQ_NONE; + +	sccr1_reg = read_SSCR1(reg);  	/* Ignore possible writes if we don't need to write */  	if (!(sccr1_reg & SSCR1_TIE)) @@ -564,8 +575,8 @@ static irqreturn_t ssp_int(int irq, void *dev_id)  			write_SSTO(0, reg);  		write_SSSR_CS(drv_data, drv_data->clear_sr); -		dev_err(&drv_data->pdev->dev, "bad message state " -			"in interrupt handler\n"); +		dev_err(&drv_data->pdev->dev, +			"bad message state in interrupt handler\n");  		/* Never fail */  		return IRQ_HANDLED; @@ -642,8 +653,8 @@ static void pump_transfers(unsigned long data)  		if (message->is_dma_mapped  				|| transfer->rx_dma || transfer->tx_dma) {  			dev_err(&drv_data->pdev->dev, -				"pump_transfers: mapped transfer length " -				"of %u is greater than %d\n", +				"pump_transfers: mapped transfer length of " +				"%u is greater than %d\n",  				transfer->len, MAX_DMA_LEN);  			message->status = -EINVAL;  			giveback(drv_data); @@ -651,11 +662,10 @@ static void pump_transfers(unsigned long data)  		}  		/* warn ... we force this to PIO mode */ -		if (printk_ratelimit()) -			dev_warn(&message->spi->dev, "pump_transfers: " -				"DMA disabled for transfer length %ld " -				"greater than %d\n", -				(long)drv_data->len, MAX_DMA_LEN); +		dev_warn_ratelimited(&message->spi->dev, +				     "pump_transfers: DMA disabled for transfer length %ld " +				     "greater than %d\n", +				     (long)drv_data->len, MAX_DMA_LEN);  	}  	/* Setup the transfer state based on the type of transfer */ @@ -717,11 +727,8 @@ static void pump_transfers(unsigned long data)  							message->spi,  							bits, &dma_burst,  							&dma_thresh)) -				if (printk_ratelimit()) -					dev_warn(&message->spi->dev, -						"pump_transfers: " -						"DMA burst size reduced to " -						"match bits_per_word\n"); +				dev_warn_ratelimited(&message->spi->dev, +						     "pump_transfers: DMA burst size reduced to match bits_per_word\n");  		}  		cr0 = clk_div @@ -845,8 +852,8 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,  	if (gpio_is_valid(chip_info->gpio_cs)) {  		err = gpio_request(chip_info->gpio_cs, "SPI_CS");  		if (err) { -			dev_err(&spi->dev, "failed to request chip select " -					"GPIO%d\n", chip_info->gpio_cs); +			dev_err(&spi->dev, "failed to request chip select GPIO%d\n", +				chip_info->gpio_cs);  			return err;  		} @@ -882,16 +889,13 @@ static int setup(struct spi_device *spi)  	chip = spi_get_ctldata(spi);  	if (!chip) {  		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); -		if (!chip) { -			dev_err(&spi->dev, -				"failed setup: can't allocate chip data\n"); +		if (!chip)  			return -ENOMEM; -		}  		if (drv_data->ssp_type == CE4100_SSP) {  			if (spi->chip_select > 4) { -				dev_err(&spi->dev, "failed setup: " -				"cs number must not be > 4.\n"); +				dev_err(&spi->dev, +					"failed setup: cs number must not be > 4.\n");  				kfree(chip);  				return -EINVAL;  			} @@ -947,8 +951,8 @@ static int setup(struct spi_device *spi)  						spi->bits_per_word,  						&chip->dma_burst_size,  						&chip->dma_threshold)) { -			dev_warn(&spi->dev, "in setup: DMA burst size reduced " -					"to match bits_per_word\n"); +			dev_warn(&spi->dev, +				 "in setup: DMA burst size reduced to match bits_per_word\n");  		}  	} @@ -1033,11 +1037,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)  		return NULL;  	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); -	if (!pdata) { -		dev_err(&pdev->dev, -			"failed to allocate memory for platform data\n"); +	if (!pdata)  		return NULL; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) @@ -1061,6 +1062,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)  	pdata->num_chipselect = 1;  	pdata->enable_dma = true; +	pdata->tx_chan_id = -1; +	pdata->rx_chan_id = -1;  	return pdata;  } @@ -1068,6 +1071,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)  static struct acpi_device_id pxa2xx_spi_acpi_match[] = {  	{ "INT33C0", 0 },  	{ "INT33C1", 0 }, +	{ "INT3430", 0 }, +	{ "INT3431", 0 },  	{ "80860F0E", 0 },  	{ },  }; @@ -1194,19 +1199,19 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)  	tasklet_init(&drv_data->pump_transfers, pump_transfers,  		     (unsigned long)drv_data); +	pm_runtime_set_autosuspend_delay(&pdev->dev, 50); +	pm_runtime_use_autosuspend(&pdev->dev); +	pm_runtime_set_active(&pdev->dev); +	pm_runtime_enable(&pdev->dev); +  	/* Register with the SPI framework */  	platform_set_drvdata(pdev, drv_data); -	status = spi_register_master(master); +	status = devm_spi_register_master(&pdev->dev, master);  	if (status != 0) {  		dev_err(&pdev->dev, "problem registering spi master\n");  		goto out_error_clock_enabled;  	} -	pm_runtime_set_autosuspend_delay(&pdev->dev, 50); -	pm_runtime_use_autosuspend(&pdev->dev); -	pm_runtime_set_active(&pdev->dev); -	pm_runtime_enable(&pdev->dev); -  	return status;  out_error_clock_enabled: @@ -1248,9 +1253,6 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)  	/* Release SSP */  	pxa_ssp_free(ssp); -	/* Disconnect from the SPI framework */ -	spi_unregister_master(drv_data->master); -  	return 0;  } @@ -1262,7 +1264,7 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev)  		dev_err(&pdev->dev, "shutdown failed with %d\n", status);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int pxa2xx_spi_suspend(struct device *dev)  {  	struct driver_data *drv_data = dev_get_drvdata(dev); @@ -1289,6 +1291,9 @@ static int pxa2xx_spi_resume(struct device *dev)  	/* Enable the SSP clock */  	clk_prepare_enable(ssp->clk); +	/* Restore LPSS private register bits */ +	lpss_ssp_setup(drv_data); +  	/* Start the queue running */  	status = spi_master_resume(drv_data->master);  	if (status != 0) {  | 
