static int sdma_probe()

in imx-sdma.c [2053:2227]


static int sdma_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *spba_bus;
	const char *fw_name;
	int ret;
	int irq;
	struct resource *iores;
	struct resource spba_res;
	int i;
	struct sdma_engine *sdma;
	s32 *saddr_arr;

	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
	if (ret)
		return ret;

	sdma = devm_kzalloc(&pdev->dev, sizeof(*sdma), GFP_KERNEL);
	if (!sdma)
		return -ENOMEM;

	spin_lock_init(&sdma->channel_0_lock);

	sdma->dev = &pdev->dev;
	sdma->drvdata = of_device_get_match_data(sdma->dev);

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	sdma->regs = devm_ioremap_resource(&pdev->dev, iores);
	if (IS_ERR(sdma->regs))
		return PTR_ERR(sdma->regs);

	sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
	if (IS_ERR(sdma->clk_ipg))
		return PTR_ERR(sdma->clk_ipg);

	sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
	if (IS_ERR(sdma->clk_ahb))
		return PTR_ERR(sdma->clk_ahb);

	ret = clk_prepare(sdma->clk_ipg);
	if (ret)
		return ret;

	ret = clk_prepare(sdma->clk_ahb);
	if (ret)
		goto err_clk;

	ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, "sdma",
			       sdma);
	if (ret)
		goto err_irq;

	sdma->irq = irq;

	sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
	if (!sdma->script_addrs) {
		ret = -ENOMEM;
		goto err_irq;
	}

	/* initially no scripts available */
	saddr_arr = (s32 *)sdma->script_addrs;
	for (i = 0; i < sizeof(*sdma->script_addrs) / sizeof(s32); i++)
		saddr_arr[i] = -EINVAL;

	dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
	dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
	dma_cap_set(DMA_MEMCPY, 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;

		sdmac->channel = i;
		sdmac->vc.desc_free = sdma_desc_free;
		INIT_LIST_HEAD(&sdmac->terminated);
		INIT_WORK(&sdmac->terminate_worker,
				sdma_channel_terminate_work);
		/*
		 * 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)
			vchan_init(&sdmac->vc, &sdma->dma_device);
	}

	ret = sdma_init(sdma);
	if (ret)
		goto err_init;

	ret = sdma_event_remap(sdma);
	if (ret)
		goto err_init;

	if (sdma->drvdata->script_addrs)
		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);

	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_config = sdma_config;
	sdma->dma_device.device_terminate_all = sdma_terminate_all;
	sdma->dma_device.device_synchronize = sdma_channel_synchronize;
	sdma->dma_device.src_addr_widths = SDMA_DMA_BUSWIDTHS;
	sdma->dma_device.dst_addr_widths = SDMA_DMA_BUSWIDTHS;
	sdma->dma_device.directions = SDMA_DMA_DIRECTIONS;
	sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
	sdma->dma_device.device_prep_dma_memcpy = sdma_prep_memcpy;
	sdma->dma_device.device_issue_pending = sdma_issue_pending;
	sdma->dma_device.copy_align = 2;
	dma_set_max_seg_size(sdma->dma_device.dev, SDMA_BD_MAX_CNT);

	platform_set_drvdata(pdev, sdma);

	ret = dma_async_device_register(&sdma->dma_device);
	if (ret) {
		dev_err(&pdev->dev, "unable to register\n");
		goto err_init;
	}

	if (np) {
		ret = of_dma_controller_register(np, sdma_xlate, sdma);
		if (ret) {
			dev_err(&pdev->dev, "failed to register controller\n");
			goto err_register;
		}

		spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
		ret = of_address_to_resource(spba_bus, 0, &spba_res);
		if (!ret) {
			sdma->spba_start_addr = spba_res.start;
			sdma->spba_end_addr = spba_res.end;
		}
		of_node_put(spba_bus);
	}

	/*
	 * Because that device tree does not encode ROM script address,
	 * the RAM script in firmware is mandatory for device tree
	 * probe, otherwise it fails.
	 */
	ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
				      &fw_name);
	if (ret) {
		dev_warn(&pdev->dev, "failed to get firmware name\n");
	} else {
		ret = sdma_get_firmware(sdma, fw_name);
		if (ret)
			dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
	}

	return 0;

err_register:
	dma_async_device_unregister(&sdma->dma_device);
err_init:
	kfree(sdma->script_addrs);
err_irq:
	clk_unprepare(sdma->clk_ahb);
err_clk:
	clk_unprepare(sdma->clk_ipg);
	return ret;
}