diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 13 | ||||
-rw-r--r-- | drivers/spi/spi-ath79.c | 1 | ||||
-rw-r--r-- | drivers/spi/spi-atmel.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi-gpio.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-nuc900.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 51 | ||||
-rw-r--r-- | drivers/spi/spi-pl022.c | 151 | ||||
-rw-r--r-- | drivers/spi/spi-topcliff-pch.c | 13 | ||||
-rw-r--r-- | drivers/spi/spi.c | 2 |
9 files changed, 150 insertions, 93 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a1fd73df5416..56abf55e49da 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -174,8 +174,7 @@ config SPI_LM70_LLP | |||
174 | 174 | ||
175 | config SPI_MPC52xx | 175 | config SPI_MPC52xx |
176 | tristate "Freescale MPC52xx SPI (non-PSC) controller support" | 176 | tristate "Freescale MPC52xx SPI (non-PSC) controller support" |
177 | depends on PPC_MPC52xx && SPI | 177 | depends on PPC_MPC52xx |
178 | select SPI_MASTER_OF | ||
179 | help | 178 | help |
180 | This drivers supports the MPC52xx SPI controller in master SPI | 179 | This drivers supports the MPC52xx SPI controller in master SPI |
181 | mode. | 180 | mode. |
@@ -199,7 +198,7 @@ config SPI_FSL_LIB | |||
199 | depends on FSL_SOC | 198 | depends on FSL_SOC |
200 | 199 | ||
201 | config SPI_FSL_SPI | 200 | config SPI_FSL_SPI |
202 | tristate "Freescale SPI controller" | 201 | bool "Freescale SPI controller" |
203 | depends on FSL_SOC | 202 | depends on FSL_SOC |
204 | select SPI_FSL_LIB | 203 | select SPI_FSL_LIB |
205 | help | 204 | help |
@@ -208,7 +207,7 @@ config SPI_FSL_SPI | |||
208 | MPC8569 uses the controller in QE mode, MPC8610 in cpu mode. | 207 | MPC8569 uses the controller in QE mode, MPC8610 in cpu mode. |
209 | 208 | ||
210 | config SPI_FSL_ESPI | 209 | config SPI_FSL_ESPI |
211 | tristate "Freescale eSPI controller" | 210 | bool "Freescale eSPI controller" |
212 | depends on FSL_SOC | 211 | depends on FSL_SOC |
213 | select SPI_FSL_LIB | 212 | select SPI_FSL_LIB |
214 | help | 213 | help |
@@ -346,14 +345,14 @@ config SPI_TI_SSP | |||
346 | serial port. | 345 | serial port. |
347 | 346 | ||
348 | config SPI_TOPCLIFF_PCH | 347 | config SPI_TOPCLIFF_PCH |
349 | tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller" | 348 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" |
350 | depends on PCI | 349 | depends on PCI |
351 | help | 350 | help |
352 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus | 351 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus |
353 | used in some x86 embedded processors. | 352 | used in some x86 embedded processors. |
354 | 353 | ||
355 | This driver also supports the ML7213, a companion chip for the | 354 | This driver also supports the ML7213/ML7223/ML7831, a companion chip |
356 | Atom E6xx series and compatible with the Intel EG20T PCH. | 355 | for the Atom E6xx series and compatible with the Intel EG20T PCH. |
357 | 356 | ||
358 | config SPI_TXX9 | 357 | config SPI_TXX9 |
359 | tristate "Toshiba TXx9 SPI controller" | 358 | tristate "Toshiba TXx9 SPI controller" |
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 024b48aed5ca..acc88b4d2869 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 79665e2e6ec5..16d6a839c7fa 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -907,7 +907,7 @@ static void atmel_spi_cleanup(struct spi_device *spi) | |||
907 | 907 | ||
908 | /*-------------------------------------------------------------------------*/ | 908 | /*-------------------------------------------------------------------------*/ |
909 | 909 | ||
910 | static int __init atmel_spi_probe(struct platform_device *pdev) | 910 | static int __devinit atmel_spi_probe(struct platform_device *pdev) |
911 | { | 911 | { |
912 | struct resource *regs; | 912 | struct resource *regs; |
913 | int irq; | 913 | int irq; |
@@ -1003,7 +1003,7 @@ out_free: | |||
1003 | return ret; | 1003 | return ret; |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | static int __exit atmel_spi_remove(struct platform_device *pdev) | 1006 | static int __devexit atmel_spi_remove(struct platform_device *pdev) |
1007 | { | 1007 | { |
1008 | struct spi_master *master = platform_get_drvdata(pdev); | 1008 | struct spi_master *master = platform_get_drvdata(pdev); |
1009 | struct atmel_spi *as = spi_master_get_devdata(master); | 1009 | struct atmel_spi *as = spi_master_get_devdata(master); |
@@ -1072,6 +1072,7 @@ static struct platform_driver atmel_spi_driver = { | |||
1072 | }, | 1072 | }, |
1073 | .suspend = atmel_spi_suspend, | 1073 | .suspend = atmel_spi_suspend, |
1074 | .resume = atmel_spi_resume, | 1074 | .resume = atmel_spi_resume, |
1075 | .probe = atmel_spi_probe, | ||
1075 | .remove = __exit_p(atmel_spi_remove), | 1076 | .remove = __exit_p(atmel_spi_remove), |
1076 | }; | 1077 | }; |
1077 | module_platform_driver(atmel_spi_driver); | 1078 | module_platform_driver(atmel_spi_driver); |
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index e093d3ec41ba..0094c645ff0d 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c | |||
@@ -256,7 +256,7 @@ static void spi_gpio_cleanup(struct spi_device *spi) | |||
256 | spi_bitbang_cleanup(spi); | 256 | spi_bitbang_cleanup(spi); |
257 | } | 257 | } |
258 | 258 | ||
259 | static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) | 259 | static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in) |
260 | { | 260 | { |
261 | int value; | 261 | int value; |
262 | 262 | ||
@@ -270,7 +270,7 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) | |||
270 | return value; | 270 | return value; |
271 | } | 271 | } |
272 | 272 | ||
273 | static int __init | 273 | static int __devinit |
274 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, | 274 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, |
275 | u16 *res_flags) | 275 | u16 *res_flags) |
276 | { | 276 | { |
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index e763254741c2..182e9c873822 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
13 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
@@ -426,7 +427,7 @@ static int __devinit nuc900_spi_probe(struct platform_device *pdev) | |||
426 | goto err_clk; | 427 | goto err_clk; |
427 | } | 428 | } |
428 | 429 | ||
429 | mfp_set_groupg(&pdev->dev); | 430 | mfp_set_groupg(&pdev->dev, NULL); |
430 | nuc900_init_spi(hw); | 431 | nuc900_init_spi(hw); |
431 | 432 | ||
432 | err = spi_bitbang_start(&hw->bitbang); | 433 | err = spi_bitbang_start(&hw->bitbang); |
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-pl022.c b/drivers/spi/spi-pl022.c index f103e470cb63..f1f5efbc3404 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c | |||
@@ -340,6 +340,10 @@ struct vendor_data { | |||
340 | * @cur_msg: Pointer to current spi_message being processed | 340 | * @cur_msg: Pointer to current spi_message being processed |
341 | * @cur_transfer: Pointer to current spi_transfer | 341 | * @cur_transfer: Pointer to current spi_transfer |
342 | * @cur_chip: pointer to current clients chip(assigned from controller_state) | 342 | * @cur_chip: pointer to current clients chip(assigned from controller_state) |
343 | * @next_msg_cs_active: the next message in the queue has been examined | ||
344 | * and it was found that it uses the same chip select as the previous | ||
345 | * message, so we left it active after the previous transfer, and it's | ||
346 | * active already. | ||
343 | * @tx: current position in TX buffer to be read | 347 | * @tx: current position in TX buffer to be read |
344 | * @tx_end: end position in TX buffer to be read | 348 | * @tx_end: end position in TX buffer to be read |
345 | * @rx: current position in RX buffer to be written | 349 | * @rx: current position in RX buffer to be written |
@@ -373,6 +377,7 @@ struct pl022 { | |||
373 | struct spi_message *cur_msg; | 377 | struct spi_message *cur_msg; |
374 | struct spi_transfer *cur_transfer; | 378 | struct spi_transfer *cur_transfer; |
375 | struct chip_data *cur_chip; | 379 | struct chip_data *cur_chip; |
380 | bool next_msg_cs_active; | ||
376 | void *tx; | 381 | void *tx; |
377 | void *tx_end; | 382 | void *tx_end; |
378 | void *rx; | 383 | void *rx; |
@@ -445,23 +450,9 @@ static void giveback(struct pl022 *pl022) | |||
445 | struct spi_transfer *last_transfer; | 450 | struct spi_transfer *last_transfer; |
446 | unsigned long flags; | 451 | unsigned long flags; |
447 | struct spi_message *msg; | 452 | struct spi_message *msg; |
448 | void (*curr_cs_control) (u32 command); | 453 | pl022->next_msg_cs_active = false; |
449 | 454 | ||
450 | /* | 455 | last_transfer = list_entry(pl022->cur_msg->transfers.prev, |
451 | * This local reference to the chip select function | ||
452 | * is needed because we set curr_chip to NULL | ||
453 | * as a step toward termininating the message. | ||
454 | */ | ||
455 | curr_cs_control = pl022->cur_chip->cs_control; | ||
456 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
457 | msg = pl022->cur_msg; | ||
458 | pl022->cur_msg = NULL; | ||
459 | pl022->cur_transfer = NULL; | ||
460 | pl022->cur_chip = NULL; | ||
461 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
462 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
463 | |||
464 | last_transfer = list_entry(msg->transfers.prev, | ||
465 | struct spi_transfer, | 456 | struct spi_transfer, |
466 | transfer_list); | 457 | transfer_list); |
467 | 458 | ||
@@ -473,18 +464,13 @@ static void giveback(struct pl022 *pl022) | |||
473 | */ | 464 | */ |
474 | udelay(last_transfer->delay_usecs); | 465 | udelay(last_transfer->delay_usecs); |
475 | 466 | ||
476 | /* | 467 | if (!last_transfer->cs_change) { |
477 | * Drop chip select UNLESS cs_change is true or we are returning | ||
478 | * a message with an error, or next message is for another chip | ||
479 | */ | ||
480 | if (!last_transfer->cs_change) | ||
481 | curr_cs_control(SSP_CHIP_DESELECT); | ||
482 | else { | ||
483 | struct spi_message *next_msg; | 468 | struct spi_message *next_msg; |
484 | 469 | ||
485 | /* Holding of cs was hinted, but we need to make sure | 470 | /* |
486 | * the next message is for the same chip. Don't waste | 471 | * cs_change was not set. We can keep the chip select |
487 | * time with the following tests unless this was hinted. | 472 | * enabled if there is message in the queue and it is |
473 | * for the same spi device. | ||
488 | * | 474 | * |
489 | * We cannot postpone this until pump_messages, because | 475 | * We cannot postpone this until pump_messages, because |
490 | * after calling msg->complete (below) the driver that | 476 | * after calling msg->complete (below) the driver that |
@@ -501,19 +487,29 @@ static void giveback(struct pl022 *pl022) | |||
501 | struct spi_message, queue); | 487 | struct spi_message, queue); |
502 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 488 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
503 | 489 | ||
504 | /* see if the next and current messages point | 490 | /* |
505 | * to the same chip | 491 | * see if the next and current messages point |
492 | * to the same spi device. | ||
506 | */ | 493 | */ |
507 | if (next_msg && next_msg->spi != msg->spi) | 494 | if (next_msg && next_msg->spi != pl022->cur_msg->spi) |
508 | next_msg = NULL; | 495 | next_msg = NULL; |
509 | if (!next_msg || msg->state == STATE_ERROR) | 496 | if (!next_msg || pl022->cur_msg->state == STATE_ERROR) |
510 | curr_cs_control(SSP_CHIP_DESELECT); | 497 | pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); |
498 | else | ||
499 | pl022->next_msg_cs_active = true; | ||
511 | } | 500 | } |
501 | |||
502 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
503 | msg = pl022->cur_msg; | ||
504 | pl022->cur_msg = NULL; | ||
505 | pl022->cur_transfer = NULL; | ||
506 | pl022->cur_chip = NULL; | ||
507 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
508 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
509 | |||
512 | msg->state = NULL; | 510 | msg->state = NULL; |
513 | if (msg->complete) | 511 | if (msg->complete) |
514 | msg->complete(msg->context); | 512 | msg->complete(msg->context); |
515 | /* This message is completed, so let's turn off the clocks & power */ | ||
516 | pm_runtime_put(&pl022->adev->dev); | ||
517 | } | 513 | } |
518 | 514 | ||
519 | /** | 515 | /** |
@@ -1244,9 +1240,9 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) | |||
1244 | 1240 | ||
1245 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { | 1241 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { |
1246 | flag = 1; | 1242 | flag = 1; |
1247 | /* Disable Transmit interrupt */ | 1243 | /* Disable Transmit interrupt, enable receive interrupt */ |
1248 | writew(readw(SSP_IMSC(pl022->virtbase)) & | 1244 | writew((readw(SSP_IMSC(pl022->virtbase)) & |
1249 | (~SSP_IMSC_MASK_TXIM), | 1245 | ~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM, |
1250 | SSP_IMSC(pl022->virtbase)); | 1246 | SSP_IMSC(pl022->virtbase)); |
1251 | } | 1247 | } |
1252 | 1248 | ||
@@ -1352,7 +1348,7 @@ static void pump_transfers(unsigned long data) | |||
1352 | */ | 1348 | */ |
1353 | udelay(previous->delay_usecs); | 1349 | udelay(previous->delay_usecs); |
1354 | 1350 | ||
1355 | /* Drop chip select only if cs_change is requested */ | 1351 | /* Reselect chip select only if cs_change was requested */ |
1356 | if (previous->cs_change) | 1352 | if (previous->cs_change) |
1357 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1353 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); |
1358 | } else { | 1354 | } else { |
@@ -1379,15 +1375,22 @@ static void pump_transfers(unsigned long data) | |||
1379 | } | 1375 | } |
1380 | 1376 | ||
1381 | err_config_dma: | 1377 | err_config_dma: |
1382 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | 1378 | /* enable all interrupts except RX */ |
1379 | writew(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM, SSP_IMSC(pl022->virtbase)); | ||
1383 | } | 1380 | } |
1384 | 1381 | ||
1385 | static void do_interrupt_dma_transfer(struct pl022 *pl022) | 1382 | static void do_interrupt_dma_transfer(struct pl022 *pl022) |
1386 | { | 1383 | { |
1387 | u32 irqflags = ENABLE_ALL_INTERRUPTS; | 1384 | /* |
1385 | * Default is to enable all interrupts except RX - | ||
1386 | * this will be enabled once TX is complete | ||
1387 | */ | ||
1388 | u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM; | ||
1389 | |||
1390 | /* Enable target chip, if not already active */ | ||
1391 | if (!pl022->next_msg_cs_active) | ||
1392 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1388 | 1393 | ||
1389 | /* Enable target chip */ | ||
1390 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1391 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | 1394 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { |
1392 | /* Error path */ | 1395 | /* Error path */ |
1393 | pl022->cur_msg->state = STATE_ERROR; | 1396 | pl022->cur_msg->state = STATE_ERROR; |
@@ -1442,7 +1445,8 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1442 | } else { | 1445 | } else { |
1443 | /* STATE_START */ | 1446 | /* STATE_START */ |
1444 | message->state = STATE_RUNNING; | 1447 | message->state = STATE_RUNNING; |
1445 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1448 | if (!pl022->next_msg_cs_active) |
1449 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1446 | } | 1450 | } |
1447 | 1451 | ||
1448 | /* Configuration Changing Per Transfer */ | 1452 | /* Configuration Changing Per Transfer */ |
@@ -1504,14 +1508,28 @@ static void pump_messages(struct work_struct *work) | |||
1504 | struct pl022 *pl022 = | 1508 | struct pl022 *pl022 = |
1505 | container_of(work, struct pl022, pump_messages); | 1509 | container_of(work, struct pl022, pump_messages); |
1506 | unsigned long flags; | 1510 | unsigned long flags; |
1511 | bool was_busy = false; | ||
1507 | 1512 | ||
1508 | /* Lock queue and check for queue work */ | 1513 | /* Lock queue and check for queue work */ |
1509 | spin_lock_irqsave(&pl022->queue_lock, flags); | 1514 | spin_lock_irqsave(&pl022->queue_lock, flags); |
1510 | if (list_empty(&pl022->queue) || !pl022->running) { | 1515 | if (list_empty(&pl022->queue) || !pl022->running) { |
1516 | if (pl022->busy) { | ||
1517 | /* nothing more to do - disable spi/ssp and power off */ | ||
1518 | writew((readw(SSP_CR1(pl022->virtbase)) & | ||
1519 | (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); | ||
1520 | |||
1521 | if (pl022->master_info->autosuspend_delay > 0) { | ||
1522 | pm_runtime_mark_last_busy(&pl022->adev->dev); | ||
1523 | pm_runtime_put_autosuspend(&pl022->adev->dev); | ||
1524 | } else { | ||
1525 | pm_runtime_put(&pl022->adev->dev); | ||
1526 | } | ||
1527 | } | ||
1511 | pl022->busy = false; | 1528 | pl022->busy = false; |
1512 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1529 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1513 | return; | 1530 | return; |
1514 | } | 1531 | } |
1532 | |||
1515 | /* Make sure we are not already running a message */ | 1533 | /* Make sure we are not already running a message */ |
1516 | if (pl022->cur_msg) { | 1534 | if (pl022->cur_msg) { |
1517 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1535 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
@@ -1522,7 +1540,10 @@ static void pump_messages(struct work_struct *work) | |||
1522 | list_entry(pl022->queue.next, struct spi_message, queue); | 1540 | list_entry(pl022->queue.next, struct spi_message, queue); |
1523 | 1541 | ||
1524 | list_del_init(&pl022->cur_msg->queue); | 1542 | list_del_init(&pl022->cur_msg->queue); |
1525 | pl022->busy = true; | 1543 | if (pl022->busy) |
1544 | was_busy = true; | ||
1545 | else | ||
1546 | pl022->busy = true; | ||
1526 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1547 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1527 | 1548 | ||
1528 | /* Initial message state */ | 1549 | /* Initial message state */ |
@@ -1532,12 +1553,14 @@ static void pump_messages(struct work_struct *work) | |||
1532 | 1553 | ||
1533 | /* Setup the SPI using the per chip configuration */ | 1554 | /* Setup the SPI using the per chip configuration */ |
1534 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1555 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
1535 | /* | 1556 | if (!was_busy) |
1536 | * We enable the core voltage and clocks here, then the clocks | 1557 | /* |
1537 | * and core will be disabled when giveback() is called in each method | 1558 | * We enable the core voltage and clocks here, then the clocks |
1538 | * (poll/interrupt/DMA) | 1559 | * and core will be disabled when this workqueue is run again |
1539 | */ | 1560 | * and there is no more work to be done. |
1540 | pm_runtime_get_sync(&pl022->adev->dev); | 1561 | */ |
1562 | pm_runtime_get_sync(&pl022->adev->dev); | ||
1563 | |||
1541 | restore_state(pl022); | 1564 | restore_state(pl022); |
1542 | flush(pl022); | 1565 | flush(pl022); |
1543 | 1566 | ||
@@ -1582,6 +1605,7 @@ static int start_queue(struct pl022 *pl022) | |||
1582 | pl022->cur_msg = NULL; | 1605 | pl022->cur_msg = NULL; |
1583 | pl022->cur_transfer = NULL; | 1606 | pl022->cur_transfer = NULL; |
1584 | pl022->cur_chip = NULL; | 1607 | pl022->cur_chip = NULL; |
1608 | pl022->next_msg_cs_active = false; | ||
1585 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1609 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1586 | 1610 | ||
1587 | queue_work(pl022->workqueue, &pl022->pump_messages); | 1611 | queue_work(pl022->workqueue, &pl022->pump_messages); |
@@ -1881,7 +1905,7 @@ static int pl022_setup(struct spi_device *spi) | |||
1881 | { | 1905 | { |
1882 | struct pl022_config_chip const *chip_info; | 1906 | struct pl022_config_chip const *chip_info; |
1883 | struct chip_data *chip; | 1907 | struct chip_data *chip; |
1884 | struct ssp_clock_params clk_freq = {0, }; | 1908 | struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0}; |
1885 | int status = 0; | 1909 | int status = 0; |
1886 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | 1910 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); |
1887 | unsigned int bits = spi->bits_per_word; | 1911 | unsigned int bits = spi->bits_per_word; |
@@ -2184,6 +2208,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2184 | goto err_clk_prep; | 2208 | goto err_clk_prep; |
2185 | } | 2209 | } |
2186 | 2210 | ||
2211 | status = clk_enable(pl022->clk); | ||
2212 | if (status) { | ||
2213 | dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n"); | ||
2214 | goto err_no_clk_en; | ||
2215 | } | ||
2216 | |||
2187 | /* Disable SSP */ | 2217 | /* Disable SSP */ |
2188 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), | 2218 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), |
2189 | SSP_CR1(pl022->virtbase)); | 2219 | SSP_CR1(pl022->virtbase)); |
@@ -2225,7 +2255,17 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2225 | dev_dbg(dev, "probe succeeded\n"); | 2255 | dev_dbg(dev, "probe succeeded\n"); |
2226 | 2256 | ||
2227 | /* let runtime pm put suspend */ | 2257 | /* let runtime pm put suspend */ |
2228 | pm_runtime_put(dev); | 2258 | if (platform_info->autosuspend_delay > 0) { |
2259 | dev_info(&adev->dev, | ||
2260 | "will use autosuspend for runtime pm, delay %dms\n", | ||
2261 | platform_info->autosuspend_delay); | ||
2262 | pm_runtime_set_autosuspend_delay(dev, | ||
2263 | platform_info->autosuspend_delay); | ||
2264 | pm_runtime_use_autosuspend(dev); | ||
2265 | pm_runtime_put_autosuspend(dev); | ||
2266 | } else { | ||
2267 | pm_runtime_put(dev); | ||
2268 | } | ||
2229 | return 0; | 2269 | return 0; |
2230 | 2270 | ||
2231 | err_spi_register: | 2271 | err_spi_register: |
@@ -2237,6 +2277,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2237 | 2277 | ||
2238 | free_irq(adev->irq[0], pl022); | 2278 | free_irq(adev->irq[0], pl022); |
2239 | err_no_irq: | 2279 | err_no_irq: |
2280 | clk_disable(pl022->clk); | ||
2281 | err_no_clk_en: | ||
2240 | clk_unprepare(pl022->clk); | 2282 | clk_unprepare(pl022->clk); |
2241 | err_clk_prep: | 2283 | err_clk_prep: |
2242 | clk_put(pl022->clk); | 2284 | clk_put(pl022->clk); |
@@ -2297,11 +2339,6 @@ static int pl022_suspend(struct device *dev) | |||
2297 | return status; | 2339 | return status; |
2298 | } | 2340 | } |
2299 | 2341 | ||
2300 | amba_vcore_enable(pl022->adev); | ||
2301 | amba_pclk_enable(pl022->adev); | ||
2302 | load_ssp_default_config(pl022); | ||
2303 | amba_pclk_disable(pl022->adev); | ||
2304 | amba_vcore_disable(pl022->adev); | ||
2305 | dev_dbg(dev, "suspended\n"); | 2342 | dev_dbg(dev, "suspended\n"); |
2306 | return 0; | 2343 | return 0; |
2307 | } | 2344 | } |
@@ -2424,6 +2461,8 @@ static struct amba_id pl022_ids[] = { | |||
2424 | { 0, 0 }, | 2461 | { 0, 0 }, |
2425 | }; | 2462 | }; |
2426 | 2463 | ||
2464 | MODULE_DEVICE_TABLE(amba, pl022_ids); | ||
2465 | |||
2427 | static struct amba_driver pl022_driver = { | 2466 | static struct amba_driver pl022_driver = { |
2428 | .drv = { | 2467 | .drv = { |
2429 | .name = "ssp-pl022", | 2468 | .name = "ssp-pl022", |
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); |