diff options
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 51 | 
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 322be7aea8b..0b0dfb71c64 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -121,6 +121,7 @@ struct omap2_mcspi {  	/* SPI1 has 4 channels, while SPI2 has 2 */  	struct omap2_mcspi_dma	*dma_channels;  	struct  device		*dev; +	struct workqueue_struct *wq;  };  struct omap2_mcspi_cs { @@ -143,8 +144,6 @@ struct omap2_mcspi_regs {  static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL]; -static struct workqueue_struct *omap2_mcspi_wq; -  #define MOD_REG_BIT(val, mask, set) do { \  	if (set) \  		val |= mask; \ @@ -1043,7 +1042,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)  	spin_lock_irqsave(&mcspi->lock, flags);  	list_add_tail(&m->queue, &mcspi->msg_queue); -	queue_work(omap2_mcspi_wq, &mcspi->work); +	queue_work(mcspi->wq, &mcspi->work);  	spin_unlock_irqrestore(&mcspi->lock, flags);  	return 0; @@ -1088,6 +1087,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  	struct omap2_mcspi	*mcspi;  	struct resource		*r;  	int			status = 0, i; +	char			wq_name[20];  	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);  	if (master == NULL) { @@ -1111,10 +1111,17 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  	mcspi = spi_master_get_devdata(master);  	mcspi->master = master; +	sprintf(wq_name, "omap2_mcspi/%d", master->bus_num); +	mcspi->wq = alloc_workqueue(wq_name, WQ_MEM_RECLAIM, 1); +	if (mcspi->wq == NULL) { +		status = -ENOMEM; +		goto free_master; +	} +  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (r == NULL) {  		status = -ENODEV; -		goto err1; +		goto free_master;  	}  	r->start += pdata->regs_offset; @@ -1123,14 +1130,14 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  	if (!request_mem_region(r->start, resource_size(r),  				dev_name(&pdev->dev))) {  		status = -EBUSY; -		goto err1; +		goto free_master;  	}  	mcspi->base = ioremap(r->start, resource_size(r));  	if (!mcspi->base) {  		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");  		status = -ENOMEM; -		goto err2; +		goto release_region;  	}  	mcspi->dev = &pdev->dev; @@ -1145,7 +1152,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  			GFP_KERNEL);  	if (mcspi->dma_channels == NULL) -		goto err2; +		goto unmap_io;  	for (i = 0; i < master->num_chipselect; i++) {  		char dma_ch_name[14]; @@ -1175,25 +1182,33 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;  	} +	if (status < 0) +		goto dma_chnl_free; +  	pm_runtime_enable(&pdev->dev);  	if (status || omap2_mcspi_master_setup(mcspi) < 0) -		goto err3; +		goto disable_pm;  	status = spi_register_master(master);  	if (status < 0) -		goto err4; +		goto err_spi_register;  	return status; -err4: +err_spi_register:  	spi_master_put(master); -err3: +disable_pm: +	pm_runtime_disable(&pdev->dev); +dma_chnl_free:  	kfree(mcspi->dma_channels); -err2: -	release_mem_region(r->start, resource_size(r)); +unmap_io:  	iounmap(mcspi->base); -err1: +release_region: +	release_mem_region(r->start, resource_size(r)); +free_master: +	kfree(master); +	platform_set_drvdata(pdev, NULL);  	return status;  } @@ -1210,6 +1225,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)  	dma_channels = mcspi->dma_channels;  	omap2_mcspi_disable_clocks(mcspi); +	pm_runtime_disable(&pdev->dev);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	release_mem_region(r->start, resource_size(r)); @@ -1217,6 +1233,8 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)  	spi_unregister_master(master);  	iounmap(base);  	kfree(dma_channels); +	destroy_workqueue(mcspi->wq); +	platform_set_drvdata(pdev, NULL);  	return 0;  } @@ -1275,10 +1293,6 @@ static struct platform_driver omap2_mcspi_driver = {  static int __init omap2_mcspi_init(void)  { -	omap2_mcspi_wq = create_singlethread_workqueue( -				omap2_mcspi_driver.driver.name); -	if (omap2_mcspi_wq == NULL) -		return -1;  	return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);  }  subsys_initcall(omap2_mcspi_init); @@ -1287,7 +1301,6 @@ static void __exit omap2_mcspi_exit(void)  {  	platform_driver_unregister(&omap2_mcspi_driver); -	destroy_workqueue(omap2_mcspi_wq);  }  module_exit(omap2_mcspi_exit);  |