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 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 | ||