diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-07 15:16:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-07 15:16:27 -0500 |
commit | 2d51daaa615e4724f24e43fa01e705c40551080a (patch) | |
tree | 3596123890aae2645a189a75bdf45789e89ae2d9 | |
parent | fbce1c234feedb5270468aa4b1770c1cab58a960 (diff) | |
parent | e583685e998e52ebbf31fadf7d8470ae69951660 (diff) |
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
-rw-r--r-- | drivers/spi/Kconfig | 6 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 51 | ||||
-rw-r--r-- | drivers/spi/spi-topcliff-pch.c | 13 | ||||
-rw-r--r-- | drivers/spi/spi.c | 2 |
4 files changed, 44 insertions, 28 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8ba4510a9519..7587796224c8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -346,14 +346,14 @@ config SPI_TI_SSP | |||
346 | serial port. | 346 | serial port. |
347 | 347 | ||
348 | config SPI_TOPCLIFF_PCH | 348 | config SPI_TOPCLIFF_PCH |
349 | tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller" | 349 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" |
350 | depends on PCI | 350 | depends on PCI |
351 | help | 351 | help |
352 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus | 352 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus |
353 | used in some x86 embedded processors. | 353 | used in some x86 embedded processors. |
354 | 354 | ||
355 | This driver also supports the ML7213, a companion chip for the | 355 | This driver also supports the ML7213/ML7223/ML7831, a companion chip |
356 | Atom E6xx series and compatible with the Intel EG20T PCH. | 356 | for the Atom E6xx series and compatible with the Intel EG20T PCH. |
357 | 357 | ||
358 | config SPI_TXX9 | 358 | config SPI_TXX9 |
359 | tristate "Toshiba TXx9 SPI controller" | 359 | tristate "Toshiba TXx9 SPI controller" |
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 322be7aea8b4..0b0dfb71c640 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
@@ -121,6 +121,7 @@ struct omap2_mcspi { | |||
121 | /* SPI1 has 4 channels, while SPI2 has 2 */ | 121 | /* SPI1 has 4 channels, while SPI2 has 2 */ |
122 | struct omap2_mcspi_dma *dma_channels; | 122 | struct omap2_mcspi_dma *dma_channels; |
123 | struct device *dev; | 123 | struct device *dev; |
124 | struct workqueue_struct *wq; | ||
124 | }; | 125 | }; |
125 | 126 | ||
126 | struct omap2_mcspi_cs { | 127 | struct omap2_mcspi_cs { |
@@ -143,8 +144,6 @@ struct omap2_mcspi_regs { | |||
143 | 144 | ||
144 | static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL]; | 145 | static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL]; |
145 | 146 | ||
146 | static struct workqueue_struct *omap2_mcspi_wq; | ||
147 | |||
148 | #define MOD_REG_BIT(val, mask, set) do { \ | 147 | #define MOD_REG_BIT(val, mask, set) do { \ |
149 | if (set) \ | 148 | if (set) \ |
150 | val |= mask; \ | 149 | val |= mask; \ |
@@ -1043,7 +1042,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
1043 | 1042 | ||
1044 | spin_lock_irqsave(&mcspi->lock, flags); | 1043 | spin_lock_irqsave(&mcspi->lock, flags); |
1045 | list_add_tail(&m->queue, &mcspi->msg_queue); | 1044 | list_add_tail(&m->queue, &mcspi->msg_queue); |
1046 | queue_work(omap2_mcspi_wq, &mcspi->work); | 1045 | queue_work(mcspi->wq, &mcspi->work); |
1047 | spin_unlock_irqrestore(&mcspi->lock, flags); | 1046 | spin_unlock_irqrestore(&mcspi->lock, flags); |
1048 | 1047 | ||
1049 | return 0; | 1048 | return 0; |
@@ -1088,6 +1087,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1088 | struct omap2_mcspi *mcspi; | 1087 | struct omap2_mcspi *mcspi; |
1089 | struct resource *r; | 1088 | struct resource *r; |
1090 | int status = 0, i; | 1089 | int status = 0, i; |
1090 | char wq_name[20]; | ||
1091 | 1091 | ||
1092 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); | 1092 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); |
1093 | if (master == NULL) { | 1093 | if (master == NULL) { |
@@ -1111,10 +1111,17 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1111 | mcspi = spi_master_get_devdata(master); | 1111 | mcspi = spi_master_get_devdata(master); |
1112 | mcspi->master = master; | 1112 | mcspi->master = master; |
1113 | 1113 | ||
1114 | sprintf(wq_name, "omap2_mcspi/%d", master->bus_num); | ||
1115 | mcspi->wq = alloc_workqueue(wq_name, WQ_MEM_RECLAIM, 1); | ||
1116 | if (mcspi->wq == NULL) { | ||
1117 | status = -ENOMEM; | ||
1118 | goto free_master; | ||
1119 | } | ||
1120 | |||
1114 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1121 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1115 | if (r == NULL) { | 1122 | if (r == NULL) { |
1116 | status = -ENODEV; | 1123 | status = -ENODEV; |
1117 | goto err1; | 1124 | goto free_master; |
1118 | } | 1125 | } |
1119 | 1126 | ||
1120 | r->start += pdata->regs_offset; | 1127 | r->start += pdata->regs_offset; |
@@ -1123,14 +1130,14 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1123 | if (!request_mem_region(r->start, resource_size(r), | 1130 | if (!request_mem_region(r->start, resource_size(r), |
1124 | dev_name(&pdev->dev))) { | 1131 | dev_name(&pdev->dev))) { |
1125 | status = -EBUSY; | 1132 | status = -EBUSY; |
1126 | goto err1; | 1133 | goto free_master; |
1127 | } | 1134 | } |
1128 | 1135 | ||
1129 | mcspi->base = ioremap(r->start, resource_size(r)); | 1136 | mcspi->base = ioremap(r->start, resource_size(r)); |
1130 | if (!mcspi->base) { | 1137 | if (!mcspi->base) { |
1131 | dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); | 1138 | dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); |
1132 | status = -ENOMEM; | 1139 | status = -ENOMEM; |
1133 | goto err2; | 1140 | goto release_region; |
1134 | } | 1141 | } |
1135 | 1142 | ||
1136 | mcspi->dev = &pdev->dev; | 1143 | mcspi->dev = &pdev->dev; |
@@ -1145,7 +1152,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1145 | GFP_KERNEL); | 1152 | GFP_KERNEL); |
1146 | 1153 | ||
1147 | if (mcspi->dma_channels == NULL) | 1154 | if (mcspi->dma_channels == NULL) |
1148 | goto err2; | 1155 | goto unmap_io; |
1149 | 1156 | ||
1150 | for (i = 0; i < master->num_chipselect; i++) { | 1157 | for (i = 0; i < master->num_chipselect; i++) { |
1151 | char dma_ch_name[14]; | 1158 | char dma_ch_name[14]; |
@@ -1175,25 +1182,33 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1175 | mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; | 1182 | mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; |
1176 | } | 1183 | } |
1177 | 1184 | ||
1185 | if (status < 0) | ||
1186 | goto dma_chnl_free; | ||
1187 | |||
1178 | pm_runtime_enable(&pdev->dev); | 1188 | pm_runtime_enable(&pdev->dev); |
1179 | 1189 | ||
1180 | if (status || omap2_mcspi_master_setup(mcspi) < 0) | 1190 | if (status || omap2_mcspi_master_setup(mcspi) < 0) |
1181 | goto err3; | 1191 | goto disable_pm; |
1182 | 1192 | ||
1183 | status = spi_register_master(master); | 1193 | status = spi_register_master(master); |
1184 | if (status < 0) | 1194 | if (status < 0) |
1185 | goto err4; | 1195 | goto err_spi_register; |
1186 | 1196 | ||
1187 | return status; | 1197 | return status; |
1188 | 1198 | ||
1189 | err4: | 1199 | err_spi_register: |
1190 | spi_master_put(master); | 1200 | spi_master_put(master); |
1191 | err3: | 1201 | disable_pm: |
1202 | pm_runtime_disable(&pdev->dev); | ||
1203 | dma_chnl_free: | ||
1192 | kfree(mcspi->dma_channels); | 1204 | kfree(mcspi->dma_channels); |
1193 | err2: | 1205 | unmap_io: |
1194 | release_mem_region(r->start, resource_size(r)); | ||
1195 | iounmap(mcspi->base); | 1206 | iounmap(mcspi->base); |
1196 | err1: | 1207 | release_region: |
1208 | release_mem_region(r->start, resource_size(r)); | ||
1209 | free_master: | ||
1210 | kfree(master); | ||
1211 | platform_set_drvdata(pdev, NULL); | ||
1197 | return status; | 1212 | return status; |
1198 | } | 1213 | } |
1199 | 1214 | ||
@@ -1210,6 +1225,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1210 | dma_channels = mcspi->dma_channels; | 1225 | dma_channels = mcspi->dma_channels; |
1211 | 1226 | ||
1212 | omap2_mcspi_disable_clocks(mcspi); | 1227 | omap2_mcspi_disable_clocks(mcspi); |
1228 | pm_runtime_disable(&pdev->dev); | ||
1213 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1229 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1214 | release_mem_region(r->start, resource_size(r)); | 1230 | release_mem_region(r->start, resource_size(r)); |
1215 | 1231 | ||
@@ -1217,6 +1233,8 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1217 | spi_unregister_master(master); | 1233 | spi_unregister_master(master); |
1218 | iounmap(base); | 1234 | iounmap(base); |
1219 | kfree(dma_channels); | 1235 | kfree(dma_channels); |
1236 | destroy_workqueue(mcspi->wq); | ||
1237 | platform_set_drvdata(pdev, NULL); | ||
1220 | 1238 | ||
1221 | return 0; | 1239 | return 0; |
1222 | } | 1240 | } |
@@ -1275,10 +1293,6 @@ static struct platform_driver omap2_mcspi_driver = { | |||
1275 | 1293 | ||
1276 | static int __init omap2_mcspi_init(void) | 1294 | static int __init omap2_mcspi_init(void) |
1277 | { | 1295 | { |
1278 | omap2_mcspi_wq = create_singlethread_workqueue( | ||
1279 | omap2_mcspi_driver.driver.name); | ||
1280 | if (omap2_mcspi_wq == NULL) | ||
1281 | return -1; | ||
1282 | return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe); | 1296 | return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe); |
1283 | } | 1297 | } |
1284 | subsys_initcall(omap2_mcspi_init); | 1298 | subsys_initcall(omap2_mcspi_init); |
@@ -1287,7 +1301,6 @@ static void __exit omap2_mcspi_exit(void) | |||
1287 | { | 1301 | { |
1288 | platform_driver_unregister(&omap2_mcspi_driver); | 1302 | platform_driver_unregister(&omap2_mcspi_driver); |
1289 | 1303 | ||
1290 | destroy_workqueue(omap2_mcspi_wq); | ||
1291 | } | 1304 | } |
1292 | module_exit(omap2_mcspi_exit); | 1305 | module_exit(omap2_mcspi_exit); |
1293 | 1306 | ||
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 6a80749391db..7086583b9107 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SPI bus driver for the Topcliff PCH used by Intel SoCs | 2 | * SPI bus driver for the Topcliff PCH used by Intel SoCs |
3 | * | 3 | * |
4 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | 4 | * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -95,16 +95,18 @@ | |||
95 | #define PCH_CLOCK_HZ 50000000 | 95 | #define PCH_CLOCK_HZ 50000000 |
96 | #define PCH_MAX_SPBR 1023 | 96 | #define PCH_MAX_SPBR 1023 |
97 | 97 | ||
98 | /* Definition for ML7213 by OKI SEMICONDUCTOR */ | 98 | /* Definition for ML7213/ML7223/ML7831 by LAPIS Semiconductor */ |
99 | #define PCI_VENDOR_ID_ROHM 0x10DB | 99 | #define PCI_VENDOR_ID_ROHM 0x10DB |
100 | #define PCI_DEVICE_ID_ML7213_SPI 0x802c | 100 | #define PCI_DEVICE_ID_ML7213_SPI 0x802c |
101 | #define PCI_DEVICE_ID_ML7223_SPI 0x800F | 101 | #define PCI_DEVICE_ID_ML7223_SPI 0x800F |
102 | #define PCI_DEVICE_ID_ML7831_SPI 0x8816 | ||
102 | 103 | ||
103 | /* | 104 | /* |
104 | * Set the number of SPI instance max | 105 | * Set the number of SPI instance max |
105 | * Intel EG20T PCH : 1ch | 106 | * Intel EG20T PCH : 1ch |
106 | * OKI SEMICONDUCTOR ML7213 IOH : 2ch | 107 | * LAPIS Semiconductor ML7213 IOH : 2ch |
107 | * OKI SEMICONDUCTOR ML7223 IOH : 1ch | 108 | * LAPIS Semiconductor ML7223 IOH : 1ch |
109 | * LAPIS Semiconductor ML7831 IOH : 1ch | ||
108 | */ | 110 | */ |
109 | #define PCH_SPI_MAX_DEV 2 | 111 | #define PCH_SPI_MAX_DEV 2 |
110 | 112 | ||
@@ -218,6 +220,7 @@ static struct pci_device_id pch_spi_pcidev_id[] = { | |||
218 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, }, | 220 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, }, |
219 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, }, | 221 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, }, |
220 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, }, | 222 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, }, |
223 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_SPI), 1, }, | ||
221 | { } | 224 | { } |
222 | }; | 225 | }; |
223 | 226 | ||
@@ -1753,4 +1756,4 @@ MODULE_PARM_DESC(use_dma, | |||
1753 | "to use DMA for data transfers pass 1 else 0; default 1"); | 1756 | "to use DMA for data transfers pass 1 else 0; default 1"); |
1754 | 1757 | ||
1755 | MODULE_LICENSE("GPL"); | 1758 | MODULE_LICENSE("GPL"); |
1756 | MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver"); | 1759 | MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor ML7xxx IOH SPI Driver"); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 77eae99af11c..b2ccdea30cb9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -319,7 +319,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) | |||
319 | } | 319 | } |
320 | 320 | ||
321 | spi->master = master; | 321 | spi->master = master; |
322 | spi->dev.parent = dev; | 322 | spi->dev.parent = &master->dev; |
323 | spi->dev.bus = &spi_bus_type; | 323 | spi->dev.bus = &spi_bus_type; |
324 | spi->dev.release = spidev_release; | 324 | spi->dev.release = spidev_release; |
325 | device_initialize(&spi->dev); | 325 | device_initialize(&spi->dev); |