diff options
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r-- | drivers/dma/imx-sdma.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index b939e163f3b1..f993955a640c 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | 22 | #include <linux/types.h> |
22 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
@@ -319,6 +320,7 @@ struct sdma_engine { | |||
319 | dma_addr_t context_phys; | 320 | dma_addr_t context_phys; |
320 | struct dma_device dma_device; | 321 | struct dma_device dma_device; |
321 | struct clk *clk; | 322 | struct clk *clk; |
323 | struct mutex channel_0_lock; | ||
322 | struct sdma_script_start_addrs *script_addrs; | 324 | struct sdma_script_start_addrs *script_addrs; |
323 | }; | 325 | }; |
324 | 326 | ||
@@ -416,11 +418,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, | |||
416 | dma_addr_t buf_phys; | 418 | dma_addr_t buf_phys; |
417 | int ret; | 419 | int ret; |
418 | 420 | ||
421 | mutex_lock(&sdma->channel_0_lock); | ||
422 | |||
419 | buf_virt = dma_alloc_coherent(NULL, | 423 | buf_virt = dma_alloc_coherent(NULL, |
420 | size, | 424 | size, |
421 | &buf_phys, GFP_KERNEL); | 425 | &buf_phys, GFP_KERNEL); |
422 | if (!buf_virt) | 426 | if (!buf_virt) { |
423 | return -ENOMEM; | 427 | ret = -ENOMEM; |
428 | goto err_out; | ||
429 | } | ||
424 | 430 | ||
425 | bd0->mode.command = C0_SETPM; | 431 | bd0->mode.command = C0_SETPM; |
426 | bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; | 432 | bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; |
@@ -434,6 +440,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, | |||
434 | 440 | ||
435 | dma_free_coherent(NULL, size, buf_virt, buf_phys); | 441 | dma_free_coherent(NULL, size, buf_virt, buf_phys); |
436 | 442 | ||
443 | err_out: | ||
444 | mutex_unlock(&sdma->channel_0_lock); | ||
445 | |||
437 | return ret; | 446 | return ret; |
438 | } | 447 | } |
439 | 448 | ||
@@ -657,6 +666,8 @@ static int sdma_load_context(struct sdma_channel *sdmac) | |||
657 | dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0); | 666 | dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0); |
658 | dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1); | 667 | dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1); |
659 | 668 | ||
669 | mutex_lock(&sdma->channel_0_lock); | ||
670 | |||
660 | memset(context, 0, sizeof(*context)); | 671 | memset(context, 0, sizeof(*context)); |
661 | context->channel_state.pc = load_address; | 672 | context->channel_state.pc = load_address; |
662 | 673 | ||
@@ -677,6 +688,8 @@ static int sdma_load_context(struct sdma_channel *sdmac) | |||
677 | 688 | ||
678 | ret = sdma_run_channel(&sdma->channel[0]); | 689 | ret = sdma_run_channel(&sdma->channel[0]); |
679 | 690 | ||
691 | mutex_unlock(&sdma->channel_0_lock); | ||
692 | |||
680 | return ret; | 693 | return ret; |
681 | } | 694 | } |
682 | 695 | ||
@@ -1132,18 +1145,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma, | |||
1132 | saddr_arr[i] = addr_arr[i]; | 1145 | saddr_arr[i] = addr_arr[i]; |
1133 | } | 1146 | } |
1134 | 1147 | ||
1135 | static int __init sdma_get_firmware(struct sdma_engine *sdma, | 1148 | static void sdma_load_firmware(const struct firmware *fw, void *context) |
1136 | const char *fw_name) | ||
1137 | { | 1149 | { |
1138 | const struct firmware *fw; | 1150 | struct sdma_engine *sdma = context; |
1139 | const struct sdma_firmware_header *header; | 1151 | const struct sdma_firmware_header *header; |
1140 | int ret; | ||
1141 | const struct sdma_script_start_addrs *addr; | 1152 | const struct sdma_script_start_addrs *addr; |
1142 | unsigned short *ram_code; | 1153 | unsigned short *ram_code; |
1143 | 1154 | ||
1144 | ret = request_firmware(&fw, fw_name, sdma->dev); | 1155 | if (!fw) { |
1145 | if (ret) | 1156 | dev_err(sdma->dev, "firmware not found\n"); |
1146 | return ret; | 1157 | return; |
1158 | } | ||
1147 | 1159 | ||
1148 | if (fw->size < sizeof(*header)) | 1160 | if (fw->size < sizeof(*header)) |
1149 | goto err_firmware; | 1161 | goto err_firmware; |
@@ -1173,6 +1185,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma, | |||
1173 | 1185 | ||
1174 | err_firmware: | 1186 | err_firmware: |
1175 | release_firmware(fw); | 1187 | release_firmware(fw); |
1188 | } | ||
1189 | |||
1190 | static int __init sdma_get_firmware(struct sdma_engine *sdma, | ||
1191 | const char *fw_name) | ||
1192 | { | ||
1193 | int ret; | ||
1194 | |||
1195 | ret = request_firmware_nowait(THIS_MODULE, | ||
1196 | FW_ACTION_HOTPLUG, fw_name, sdma->dev, | ||
1197 | GFP_KERNEL, sdma, sdma_load_firmware); | ||
1176 | 1198 | ||
1177 | return ret; | 1199 | return ret; |
1178 | } | 1200 | } |
@@ -1270,11 +1292,14 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1270 | struct sdma_platform_data *pdata = pdev->dev.platform_data; | 1292 | struct sdma_platform_data *pdata = pdev->dev.platform_data; |
1271 | int i; | 1293 | int i; |
1272 | struct sdma_engine *sdma; | 1294 | struct sdma_engine *sdma; |
1295 | s32 *saddr_arr; | ||
1273 | 1296 | ||
1274 | sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); | 1297 | sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); |
1275 | if (!sdma) | 1298 | if (!sdma) |
1276 | return -ENOMEM; | 1299 | return -ENOMEM; |
1277 | 1300 | ||
1301 | mutex_init(&sdma->channel_0_lock); | ||
1302 | |||
1278 | sdma->dev = &pdev->dev; | 1303 | sdma->dev = &pdev->dev; |
1279 | 1304 | ||
1280 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1305 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1311,6 +1336,11 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1311 | goto err_alloc; | 1336 | goto err_alloc; |
1312 | } | 1337 | } |
1313 | 1338 | ||
1339 | /* initially no scripts available */ | ||
1340 | saddr_arr = (s32 *)sdma->script_addrs; | ||
1341 | for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++) | ||
1342 | saddr_arr[i] = -EINVAL; | ||
1343 | |||
1314 | if (of_id) | 1344 | if (of_id) |
1315 | pdev->id_entry = of_id->data; | 1345 | pdev->id_entry = of_id->data; |
1316 | sdma->devtype = pdev->id_entry->driver_data; | 1346 | sdma->devtype = pdev->id_entry->driver_data; |