static int __init sdma_get_firmware(struct sdma_engine *sdma, const char *cpu_name, int to_version) { const struct firmware *fw; char *fwname; const struct sdma_firmware_header *header; int ret; const struct sdma_script_start_addrs *addr; unsigned short *ram_code; fwname = kasprintf(GFP_KERNEL, "imx/sdma/sdma-%s-to%d.bin", cpu_name, to_version); if (!fwname) return -ENOMEM; ret = request_firmware(&fw, fwname, sdma->dev); if (ret) { kfree(fwname); return ret; } kfree(fwname); if (fw->size < sizeof(*header)) goto err_firmware; header = (struct sdma_firmware_header *)fw->data; if (header->magic != SDMA_FIRMWARE_MAGIC) goto err_firmware; if (header->ram_code_start + header->ram_code_size > fw->size) goto err_firmware; addr = (void *)header + header->script_addrs_start; ram_code = (void *)header + header->ram_code_start; clk_enable(sdma->clk); /* download the RAM image for SDMA */ sdma_load_script(sdma, ram_code, header->ram_code_size, addr->ram_code_start_addr); clk_disable(sdma->clk); sdma_add_scripts(sdma, addr); dev_info(sdma->dev, "loaded firmware %d.%d\n", header->version_major, header->version_minor); err_firmware: release_firmware(fw); return ret; }
static int __init sdma_probe(struct platform_device *pdev) { int ret; int irq; struct resource *iores; struct sdma_platform_data *pdata = pdev->dev.platform_data; int i; struct sdma_engine *sdma; sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); if (!sdma) return -ENOMEM; sdma->dev = &pdev->dev; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (!iores || irq < 0 || !pdata) { ret = -EINVAL; goto err_irq; } if (!request_mem_region(iores->start, resource_size(iores), pdev->name)) { ret = -EBUSY; goto err_request_region; } sdma->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(sdma->clk)) { ret = PTR_ERR(sdma->clk); goto err_clk; } sdma->regs = ioremap(iores->start, resource_size(iores)); if (!sdma->regs) { ret = -ENOMEM; goto err_ioremap; } ret = request_irq(irq, sdma_int_handler, 0, "sdma", sdma); if (ret) goto err_request_irq; sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL); if (!sdma->script_addrs) goto err_alloc; sdma->version = pdata->sdma_version; dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask); dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); INIT_LIST_HEAD(&sdma->dma_device.channels); /* Initialize channel parameters */ for (i = 0; i < MAX_DMA_CHANNELS; i++) { struct sdma_channel *sdmac = &sdma->channel[i]; sdmac->sdma = sdma; spin_lock_init(&sdmac->lock); sdmac->chan.device = &sdma->dma_device; sdmac->channel = i; /* * Add the channel to the DMAC list. Do not add channel 0 though * because we need it internally in the SDMA driver. This also means * that channel 0 in dmaengine counting matches sdma channel 1. */ if (i) list_add_tail(&sdmac->chan.device_node, &sdma->dma_device.channels); } ret = sdma_init(sdma); if (ret) goto err_init; if (pdata->script_addrs) sdma_add_scripts(sdma, pdata->script_addrs); sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version); sdma->dma_device.dev = &pdev->dev; sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources; sdma->dma_device.device_free_chan_resources = sdma_free_chan_resources; sdma->dma_device.device_tx_status = sdma_tx_status; sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg; sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic; sdma->dma_device.device_control = sdma_control; sdma->dma_device.device_issue_pending = sdma_issue_pending; sdma->dma_device.dev->dma_parms = &sdma->dma_parms; dma_set_max_seg_size(sdma->dma_device.dev, 65535); ret = dma_async_device_register(&sdma->dma_device); if (ret) { dev_err(&pdev->dev, "unable to register\n"); goto err_init; } dev_info(sdma->dev, "initialized\n"); return 0; err_init: kfree(sdma->script_addrs); err_alloc: free_irq(irq, sdma); err_request_irq: iounmap(sdma->regs); err_ioremap: clk_put(sdma->clk); err_clk: release_mem_region(iores->start, resource_size(iores)); err_request_region: err_irq: kfree(sdma); return ret; }