提交 2d51daaa 编写于 作者: L Linus Torvalds

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
...@@ -346,14 +346,14 @@ config SPI_TI_SSP ...@@ -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"
......
...@@ -121,6 +121,7 @@ struct omap2_mcspi { ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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);
......
/* /*
* 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 @@ ...@@ -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[] = { ...@@ -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, ...@@ -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");
...@@ -319,7 +319,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册