2.13. pl08x_probe

static int pl08x_probe1(struct amba_device *amba_dev, void *id)
{
	int ret = 0;

	ret = pl08x_make_LLIs();2
	if (ret)
		return -ENOMEM;

	ret = amba_request_regions3(amba_dev, NULL);
	if (ret)
		return ret;

	pd.max_num_llis = 0;

	/*
	 * We have our own work queue for cleaning memory
	 */
	INIT_WORK(&pd.dwork, pl08x_wqfunc);
	pd.waitq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
	init_waitqueue_head(pd.waitq);

	spin_lock_init(&pd.lock);

	pd.base = ioremap(amba_dev->res.start, SZ_4K);
	if (!pd.base) {
		ret = -ENOMEM;
		goto out1;
	}
	/*
	 * Attach the interrupt handler
	 */
	writel(0x000000FF, pd.base + PL08X_OS_ICLR_ERR);
	writel(0x000000FF, pd.base + PL08X_OS_ICLR_TC);
	mb();

	ret = request_irq(amba_dev->irq[0], pl08x_irq, IRQF_DISABLED,
			DRIVER_NAME, &amba_dev->dev);
	if (ret) {
		dev_err(&pd.dmac->dev, "%s - Failed to attach interrupt %d\n",
				__func__, amba_dev->irq[0]);
		goto out2;
	}
	/*
	 * Data exchange
	 */
	pd.dmac = amba_dev;
	amba_set_drvdata(amba_dev, &pd);
	pd.pd = (struct pl08x_platform_data *)(amba_dev->dev.platform_data);
	/*
	 * Negotiate for channels with the platform
	 * and its DMA requirements
	 */
	dmac.dev = &amba_dev->dev;

	ret = pl08x_dma_enumerate_channels();

	if (!ret) {
		dev_warn(&pd.dmac->dev,
			"%s - failed to enumerate channels - %d\n",
				__func__, ret);
		goto out2;
	} else {
		ret = dma_async_device_register4(&dmac);
		if (ret) {
			dev_warn(&pd.dmac->dev,
				"%s - failed to register as an async device - %d\n",
					__func__, ret);
			goto out2;
		}
	}
	pl08x_ensure_on();5
	dev_info(&pd.dmac->dev,
		"%s - ARM(R) PL08X DMA driver found\n",
			__func__);

	goto out;
out2:
	iounmap(pd.base);
out1:
	amba_release_regions(amba_dev);
out:
	return ret;
}
        

1

经典的probe函数,对驱动进行必要的软件和硬件的初始化

2

为后面要用到的LLI申请空间

3

获得自己资源,其是你开始进行amba设备注册时候的,已经初始化好的对应的资源,包括基地址,中断号等

4

将自己这个pl08x的DMA驱动,注册到DMA Engine 框架中

别处看到某人评论说是这个DMA Engine驱动框架属于老的了,有更好的新的,不了解,有空去看看

5

硬件上确保启动DMA了