Приветствую.
Плата zc706, системой управляет Linux.
Может кто подскажет, как "правильно прикрутить" PL DDR memory, чтобы был доступ из Kernel Space?
PL DDR используется под буферы данных и дескрипторы для AXI DMA (s2mm + mm2s), ядро Linux должно только обновлять дескрипторы DMA (DMA будет гонять данные между IP-блоками в FPGA).
Пока сделал так:
1) добавил в devicetree
Код
mig7series_ddr3: mig7series_ddr3 {
compatible = "xlnx,mig7series_ddr3";
device_type = "mig7series_ddr3";
reg = <0x80000000 0x40000000>;
};
2) драйвер выполняет
CODE
static int mig7series_probe(struct platform_device *pdev)
{
// struct resource *r_irq; /* Interrupt resources */
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev;
struct mig7series_local *lp = NULL;
int rc = 0, i;
dev_info(dev, "Device Tree Probing\n");
/* Get iospace for the device */
r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pr_info("r_mem = %p\n", r_mem);
if (!r_mem) {
dev_err(dev, "invalid address\n");
return -ENODEV;
}
lp = (struct mig7series_local *) kmalloc(sizeof(struct mig7series_local), GFP_KERNEL);
if (!lp) {
dev_err(dev, "Cound not allocate axidma_ddrmaster device\n");
return -ENOMEM;
}
dev_set_drvdata(dev, lp);
pr_info("r_mem->start = %p\n", r_mem->start);
pr_info("r_mem->end = %p\n", r_mem->end);
lp->mem_start = r_mem->start;
lp->mem_end = r_mem->end;
pr_info("lp->mem_start = %p\n", lp->mem_start);
pr_info("lp->mem_end = %p\n", lp->mem_end);
if (!request_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1, MIG7SERIES_DRIVER_NAME)) {
dev_err(dev, "Couldn't lock memory region at %p\n", (void *)lp->mem_start);
rc = -EBUSY;
goto error1;
}
lp->base_addr = ioremap(lp->mem_start, /*lp->mem_end - lp->mem_start + 1*/126*1024*1024);
if (!lp->base_addr) {
dev_err(dev, "axidma_ddrmaster: Could not allocate iomem\n");
rc = -EIO;
goto error2;
}
dev_info(dev, "mig7series_ddr3 at 0x%08x mapped to 0x%08x\n",
(unsigned int __force)lp->mem_start,
(unsigned int __force)lp->base_addr);
pl_ddr3 = lp;
return 0;
error2:
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
error1:
kfree(lp);
dev_set_drvdata(dev, NULL);
return rc;
}
данный кусок памяти становится доступен на запись/чтение, но отдает не всё адресное пространство DDR (1 GB), а только 126*1024*1024 байт (вроде бы и достаточно, но как заполучить всю память?).
И вообще, правильный ли подход?
Стартануть DMA и обновлять дескрипторы пока не пробовал.