static int pl08x_probe(struct amba_device *amba_dev, void *id)
{
int ret = 0;
ret = pl08x_make_LLIs();
if (ret)
return -ENOMEM;
ret = amba_request_regions(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_register(&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();
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;
}
| 经典的probe函数,对驱动进行必要的软件和硬件的初始化 |
| 为后面要用到的LLI申请空间 |
| 获得自己资源,其是你开始进行amba设备注册时候的,已经初始化好的对应的资源,包括基地址,中断号等 |
| 将自己这个pl08x的DMA驱动,注册到DMA Engine 框架中 别处看到某人评论说是这个DMA Engine驱动框架属于老的了,有更好的新的,不了解,有空去看看 |
| 硬件上确保启动DMA了 |