spi changes queued up for v3.3 merge window

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPBSnZAAoJEEFnBt12D9kBaDgP/3V73Uhy1yfkuOOgx9Fh5MeM
 0X7b7qGI/cIH9eAjm1CNXr6nDiPgpXnUkoxc7tTTKNuQLNPsaUg03VAkBoTc4K+R
 f88RQq41Ni82hgSI/+ls9PXvc5FIZfgESKw01yCa3aOD/uf1RWGW/95G5xHV/C2V
 VGoN7f058j7lyhH8WmeaJg0i+x/9PYie3/BdNyaz3hFIFiYPZribIiGQ1ezuM5SN
 srf+Uu0MqgXfX41kqdRTiU5UGtGOOabE8bk/3TwjwXFWKhJANkqVVZgcYDTK+brL
 ZIIO1uHAapmy4asG2DyfbK19gOkN7abO4pcbGmmQIN3RKH4QNQQBhYSpex4xMOQ5
 TeysEadQ2W/JXL7yKiHt2qJPBovg3WEK+Q0StwnCLjqnWNw4Q+W+zs6TAi7DPfZc
 plWv27FGhhWYCp8ZGKnlMGGvvHtThuBCqYVIjYbi1CRfJ9mUVdV4zcc4Fj1VJNuU
 taEIP3Ga9AOtTRbQ904Kza7CQEwBjD5y70TLymoVSk2/XBW2q/Mint9By3ZtA7aq
 GxASd4sh50x9uoGZU5T5RqA+jImSvlhudKsczNXtl+Y5FMvPNludjncNsie2NrF/
 GwYavWFI+zHrFljxOcVQftSQfiMMEAZk9g167AyAGvPxECMoTDrp0A1Q7v5ppSrr
 AMbbkfxFvo7HIeabEtHI
 =uyNO
 -----END PGP SIGNATURE-----

Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6

spi changes queued up for v3.3 merge window

* tag 'spi-for-linus-20120104' of git://git.secretlab.ca/git/linux-2.6:
  spi: Fix device unregistration when unregistering the bus master
  spi-topcliff-pch: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor
  spi-topcliff-pch: Support new device LAPIS Semiconductor ML7831 IOH
  spi/omap: Correct the error path
  spi/omap: call pm_runtime_disable in error path and remove
  spi/omap: Use a workqueue per omap2_mcspi controller
This commit is contained in:
Linus Torvalds 2012-01-07 12:16:27 -08:00
commit 2d51daaa61
4 changed files with 44 additions and 28 deletions

View File

@ -346,14 +346,14 @@ config SPI_TI_SSP
serial port. serial port.
config SPI_TOPCLIFF_PCH config SPI_TOPCLIFF_PCH
tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller" tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
depends on PCI depends on PCI
help help
SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
used in some x86 embedded processors. used in some x86 embedded processors.
This driver also supports the ML7213, a companion chip for the This driver also supports the ML7213/ML7223/ML7831, a companion chip
Atom E6xx series and compatible with the Intel EG20T PCH. for the Atom E6xx series and compatible with the Intel EG20T PCH.
config SPI_TXX9 config SPI_TXX9
tristate "Toshiba TXx9 SPI controller" tristate "Toshiba TXx9 SPI controller"

View File

@ -121,6 +121,7 @@ struct omap2_mcspi {
/* SPI1 has 4 channels, while SPI2 has 2 */ /* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels; struct omap2_mcspi_dma *dma_channels;
struct device *dev; struct device *dev;
struct workqueue_struct *wq;
}; };
struct omap2_mcspi_cs { 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 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 { \ #define MOD_REG_BIT(val, mask, set) do { \
if (set) \ if (set) \
val |= mask; \ 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); spin_lock_irqsave(&mcspi->lock, flags);
list_add_tail(&m->queue, &mcspi->msg_queue); 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); spin_unlock_irqrestore(&mcspi->lock, flags);
return 0; return 0;
@ -1088,6 +1087,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct resource *r; struct resource *r;
int status = 0, i; int status = 0, i;
char wq_name[20];
master = spi_alloc_master(&pdev->dev, sizeof *mcspi); master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
if (master == NULL) { if (master == NULL) {
@ -1111,10 +1111,17 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
mcspi = spi_master_get_devdata(master); mcspi = spi_master_get_devdata(master);
mcspi->master = 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); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) { if (r == NULL) {
status = -ENODEV; status = -ENODEV;
goto err1; goto free_master;
} }
r->start += pdata->regs_offset; 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), if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) { dev_name(&pdev->dev))) {
status = -EBUSY; status = -EBUSY;
goto err1; goto free_master;
} }
mcspi->base = ioremap(r->start, resource_size(r)); mcspi->base = ioremap(r->start, resource_size(r));
if (!mcspi->base) { if (!mcspi->base) {
dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
status = -ENOMEM; status = -ENOMEM;
goto err2; goto release_region;
} }
mcspi->dev = &pdev->dev; mcspi->dev = &pdev->dev;
@ -1145,7 +1152,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
GFP_KERNEL); GFP_KERNEL);
if (mcspi->dma_channels == NULL) if (mcspi->dma_channels == NULL)
goto err2; goto unmap_io;
for (i = 0; i < master->num_chipselect; i++) { for (i = 0; i < master->num_chipselect; i++) {
char dma_ch_name[14]; 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; mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
} }
if (status < 0)
goto dma_chnl_free;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (status || omap2_mcspi_master_setup(mcspi) < 0) if (status || omap2_mcspi_master_setup(mcspi) < 0)
goto err3; goto disable_pm;
status = spi_register_master(master); status = spi_register_master(master);
if (status < 0) if (status < 0)
goto err4; goto err_spi_register;
return status; return status;
err4: err_spi_register:
spi_master_put(master); spi_master_put(master);
err3: disable_pm:
pm_runtime_disable(&pdev->dev);
dma_chnl_free:
kfree(mcspi->dma_channels); kfree(mcspi->dma_channels);
err2: unmap_io:
release_mem_region(r->start, resource_size(r));
iounmap(mcspi->base); 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; return status;
} }
@ -1210,6 +1225,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
dma_channels = mcspi->dma_channels; dma_channels = mcspi->dma_channels;
omap2_mcspi_disable_clocks(mcspi); omap2_mcspi_disable_clocks(mcspi);
pm_runtime_disable(&pdev->dev);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, resource_size(r)); 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); spi_unregister_master(master);
iounmap(base); iounmap(base);
kfree(dma_channels); kfree(dma_channels);
destroy_workqueue(mcspi->wq);
platform_set_drvdata(pdev, NULL);
return 0; return 0;
} }
@ -1275,10 +1293,6 @@ static struct platform_driver omap2_mcspi_driver = {
static int __init omap2_mcspi_init(void) 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); return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
} }
subsys_initcall(omap2_mcspi_init); subsys_initcall(omap2_mcspi_init);
@ -1287,7 +1301,6 @@ static void __exit omap2_mcspi_exit(void)
{ {
platform_driver_unregister(&omap2_mcspi_driver); platform_driver_unregister(&omap2_mcspi_driver);
destroy_workqueue(omap2_mcspi_wq);
} }
module_exit(omap2_mcspi_exit); module_exit(omap2_mcspi_exit);

View File

@ -1,7 +1,7 @@
/* /*
* SPI bus driver for the Topcliff PCH used by Intel SoCs * SPI bus driver for the Topcliff PCH used by Intel SoCs
* *
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -95,16 +95,18 @@
#define PCH_CLOCK_HZ 50000000 #define PCH_CLOCK_HZ 50000000
#define PCH_MAX_SPBR 1023 #define PCH_MAX_SPBR 1023
/* Definition for ML7213 by OKI SEMICONDUCTOR */ /* Definition for ML7213/ML7223/ML7831 by LAPIS Semiconductor */
#define PCI_VENDOR_ID_ROHM 0x10DB #define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_SPI 0x802c #define PCI_DEVICE_ID_ML7213_SPI 0x802c
#define PCI_DEVICE_ID_ML7223_SPI 0x800F #define PCI_DEVICE_ID_ML7223_SPI 0x800F
#define PCI_DEVICE_ID_ML7831_SPI 0x8816
/* /*
* Set the number of SPI instance max * Set the number of SPI instance max
* Intel EG20T PCH : 1ch * Intel EG20T PCH : 1ch
* OKI SEMICONDUCTOR ML7213 IOH : 2ch * LAPIS Semiconductor ML7213 IOH : 2ch
* OKI SEMICONDUCTOR ML7223 IOH : 1ch * LAPIS Semiconductor ML7223 IOH : 1ch
* LAPIS Semiconductor ML7831 IOH : 1ch
*/ */
#define PCH_SPI_MAX_DEV 2 #define PCH_SPI_MAX_DEV 2
@ -218,6 +220,7 @@ static struct pci_device_id pch_spi_pcidev_id[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_SPI), 1, },
{ } { }
}; };
@ -1753,4 +1756,4 @@ MODULE_PARM_DESC(use_dma,
"to use DMA for data transfers pass 1 else 0; default 1"); "to use DMA for data transfers pass 1 else 0; default 1");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver"); MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor ML7xxx IOH SPI Driver");

View File

@ -319,7 +319,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
} }
spi->master = master; spi->master = master;
spi->dev.parent = dev; spi->dev.parent = &master->dev;
spi->dev.bus = &spi_bus_type; spi->dev.bus = &spi_bus_type;
spi->dev.release = spidev_release; spi->dev.release = spidev_release;
device_initialize(&spi->dev); device_initialize(&spi->dev);