Commit d5584335 authored by Andrey Filippov's avatar Andrey Filippov

added more mrmory regions from CMA

parent ebeecb50
...@@ -59,7 +59,18 @@ static struct elphel_buf_t _elphel_buf = { ...@@ -59,7 +59,18 @@ static struct elphel_buf_t _elphel_buf = {
// Bidirectional stream DMA buffer // Bidirectional stream DMA buffer
.bidir_vaddr = NULL, .bidir_vaddr = NULL,
.bidir_paddr = 0, .bidir_paddr = 0,
.bidir_size = 1024 .bidir_size = 1024,
// Device to host stream DMA buffer for histograms
.histograms_vaddr = NULL,
.histograms_paddr = 0,
.histograms_size = 1024,
// Device to host stream DMA buffer for the logger
.logger_vaddr = NULL,
.logger_paddr = 0,
.logger_size = 1024
}; };
struct elphel_buf_t *pElphel_buf; // static can not be extern struct elphel_buf_t *pElphel_buf; // static can not be extern
...@@ -83,40 +94,6 @@ static int __init elphelmem_init(void) ...@@ -83,40 +94,6 @@ static int __init elphelmem_init(void)
bufsize_be = (__be32 *)of_get_property(node, "memsize", NULL); bufsize_be = (__be32 *)of_get_property(node, "memsize", NULL);
_elphel_buf.size = be32_to_cpup(bufsize_be); _elphel_buf.size = be32_to_cpup(bufsize_be);
/*
// Coherent DMA buffer
void *vaddr;
dma_addr_t paddr;
ssize_t size;
// Host to device stream DMA buffer
void *h2d_vaddr;
dma_addr_t h2d_paddr;
ssize_t h2d_size;
// Device to host stream DMA buffer
void *d2h_vaddr;
dma_addr_t d2h_paddr;
ssize_t d2h_size;
// Bidirectional stream DMA buffer
void *bidir_vaddr;
dma_addr_t bidir_paddr;
ssize_t bidir_size;
_elphel_buf.vaddr = dma_alloc_coherent(NULL,(_elphel_buf.size*PAGE_SIZE),&(_elphel_buf.paddr),GFP_KERNEL);
if(_elphel_buf.paddr)
{
printk("Allocated %u pages for DMA at address 0x%x\n", (u32)_elphel_buf.size, (u32)_elphel_buf.paddr);
}
else printk("ERROR allocating memory buffer");
http://linuxkernelhacker.blogspot.com/2014/07/arm-dma-mapping-explained.html
*/
// Alternative way to allocate memory for DMA
// allocate continuous virtual memory range
// _elphel_buf.vaddr = kmalloc((_elphel_buf.size*PAGE_SIZE) ,GFP_KERNEL);
_elphel_buf.vaddr = dma_alloc_coherent(NULL,(_elphel_buf.size*PAGE_SIZE),&(_elphel_buf.paddr),GFP_KERNEL); _elphel_buf.vaddr = dma_alloc_coherent(NULL,(_elphel_buf.size*PAGE_SIZE),&(_elphel_buf.paddr),GFP_KERNEL);
if(_elphel_buf.vaddr) { if(_elphel_buf.vaddr) {
pr_info("Allocated %u pages for DMA at address 0x%x\n", (u32)_elphel_buf.size, (u32)_elphel_buf.paddr); pr_info("Allocated %u pages for DMA at address 0x%x\n", (u32)_elphel_buf.size, (u32)_elphel_buf.paddr);
...@@ -136,6 +113,18 @@ static int __init elphelmem_init(void) ...@@ -136,6 +113,18 @@ static int __init elphelmem_init(void)
pr_err("ERROR allocating D2H DMA memory buffer\n"); pr_err("ERROR allocating D2H DMA memory buffer\n");
} }
_elphel_buf.histograms_vaddr = kzalloc((_elphel_buf.histograms_size*PAGE_SIZE) ,GFP_KERNEL);
if (!_elphel_buf.histograms_vaddr){
_elphel_buf.histograms_size = 0;
pr_err("ERROR allocating HISTOGRAMS memory buffer\n");
}
_elphel_buf.logger_vaddr = kzalloc((_elphel_buf.logger_size*PAGE_SIZE) ,GFP_KERNEL);
if (!_elphel_buf.logger_vaddr){
_elphel_buf.logger_size = 0;
pr_err("ERROR allocating LOGGER memory buffer\n");
}
_elphel_buf.bidir_vaddr = kzalloc((_elphel_buf.bidir_size*PAGE_SIZE) ,GFP_KERNEL); _elphel_buf.bidir_vaddr = kzalloc((_elphel_buf.bidir_size*PAGE_SIZE) ,GFP_KERNEL);
if (!_elphel_buf.bidir_vaddr){ if (!_elphel_buf.bidir_vaddr){
_elphel_buf.bidir_size = 0; _elphel_buf.bidir_size = 0;
...@@ -148,21 +137,13 @@ static int __init elphelmem_init(void) ...@@ -148,21 +137,13 @@ static int __init elphelmem_init(void)
return 0; return 0;
} }
/*
dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
*/
static void __exit elphelmem_exit(void) static void __exit elphelmem_exit(void)
{ {
pr_info("DMA buffer disabled\n"); pr_info("DMA buffer disabled\n");
} }
// SYSFS
static ssize_t get_paddr(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t get_paddr(struct device *dev, struct device_attribute *attr, char *buf)
{ {
return sprintf(buf,"0x%x\n", (u32)_elphel_buf.paddr); return sprintf(buf,"0x%x\n", (u32)_elphel_buf.paddr);
...@@ -203,6 +184,26 @@ static ssize_t get_size_bidir(struct device *dev, struct device_attribute *attr, ...@@ -203,6 +184,26 @@ static ssize_t get_size_bidir(struct device *dev, struct device_attribute *attr,
return sprintf(buf,"%u\n", _elphel_buf.bidir_size); return sprintf(buf,"%u\n", _elphel_buf.bidir_size);
} }
static ssize_t get_paddr_histograms(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%x\n", (u32)_elphel_buf.histograms_paddr);
}
static ssize_t get_size_histograms(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%u\n", _elphel_buf.histograms_size);
}
static ssize_t get_paddr_logger(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%x\n", (u32)_elphel_buf.logger_paddr);
}
static ssize_t get_size_logger(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%u\n", _elphel_buf.logger_size);
}
static ssize_t sync_for_cpu_h2d(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) static ssize_t sync_for_cpu_h2d(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{ {
dma_addr_t paddr; dma_addr_t paddr;
...@@ -265,6 +266,7 @@ static ssize_t sync_for_device_d2h(struct device *dev, struct device_attribute * ...@@ -265,6 +266,7 @@ static ssize_t sync_for_device_d2h(struct device *dev, struct device_attribute *
return count; return count;
} }
static ssize_t sync_for_cpu_bidir(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) static ssize_t sync_for_cpu_bidir(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{ {
dma_addr_t paddr; dma_addr_t paddr;
...@@ -297,6 +299,72 @@ static ssize_t sync_for_device_bidir(struct device *dev, struct device_attribute ...@@ -297,6 +299,72 @@ static ssize_t sync_for_device_bidir(struct device *dev, struct device_attribute
return count; return count;
} }
static ssize_t sync_for_cpu_histograms(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
dma_addr_t paddr;
size_t len;
int num_items;
num_items=sscanf(buf, "%u %u", &paddr, &len);
if (num_items<2) {
paddr = _elphel_buf.histograms_paddr;
len = _elphel_buf.histograms_size * PAGE_SIZE;
}
pr_info("\naddr=0x%08x, size = 0x%08x\n", paddr, len);
dma_sync_single_for_cpu(dev, paddr, len, DMA_FROM_DEVICE);
return count;
}
static ssize_t sync_for_device_histograms(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
dma_addr_t paddr;
size_t len;
int num_items;
num_items=sscanf(buf, "%u %u", &paddr, &len);
if (num_items<2) {
paddr = _elphel_buf.histograms_paddr;
len = _elphel_buf.histograms_size * PAGE_SIZE;
}
pr_info("\naddr=0x%08x, size = 0x%08x\n", paddr, len);
dma_sync_single_for_device(dev, paddr, len, DMA_FROM_DEVICE);
return count;
}
static ssize_t sync_for_cpu_logger(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
dma_addr_t paddr;
size_t len;
int num_items;
num_items=sscanf(buf, "%u %u", &paddr, &len);
if (num_items<2) {
paddr = _elphel_buf.logger_paddr;
len = _elphel_buf.logger_size * PAGE_SIZE;
}
pr_info("\naddr=0x%08x, size = 0x%08x\n", paddr, len);
dma_sync_single_for_cpu(dev, paddr, len, DMA_FROM_DEVICE);
return count;
}
static ssize_t sync_for_device_logger(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
dma_addr_t paddr;
size_t len;
int num_items;
num_items=sscanf(buf, "%u %u", &paddr, &len);
if (num_items<2) {
paddr = _elphel_buf.logger_paddr;
len = _elphel_buf.logger_size * PAGE_SIZE;
}
pr_info("\naddr=0x%08x, size = 0x%08x\n", paddr, len);
dma_sync_single_for_device(dev, paddr, len, DMA_FROM_DEVICE);
return count;
}
static ssize_t get_sync_for_device_h2d(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t get_sync_for_device_h2d(struct device *dev, struct device_attribute *attr, char *buf)
{ {
return sprintf(buf,"Write address/length pair into this file to hand this region of the host to device DMA buffer to device (after CPU writes).\n"); return sprintf(buf,"Write address/length pair into this file to hand this region of the host to device DMA buffer to device (after CPU writes).\n");
...@@ -322,20 +390,47 @@ static ssize_t get_sync_for_cpu_bidir(struct device *dev, struct device_attribut ...@@ -322,20 +390,47 @@ static ssize_t get_sync_for_cpu_bidir(struct device *dev, struct device_attribut
return sprintf(buf,"Write address/length pair into this file to hand this region of the bidirectional DMA buffer to CPU (before CPU reads).\n"); return sprintf(buf,"Write address/length pair into this file to hand this region of the bidirectional DMA buffer to CPU (before CPU reads).\n");
} }
static DEVICE_ATTR(buffer_address, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr, NULL);
static DEVICE_ATTR(buffer_pages, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size, NULL); static ssize_t get_sync_for_device_histograms(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(buffer_address_h2d, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_h2d, NULL); {
static DEVICE_ATTR(buffer_pages_h2d, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_h2d, NULL); return sprintf(buf,"Write address/length pair into this file to hand this region of the histograms buffer to device (after CPU writes).\n");
static DEVICE_ATTR(buffer_address_d2h, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_d2h, NULL); }
static DEVICE_ATTR(buffer_pages_d2h, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_d2h, NULL); static ssize_t get_sync_for_cpu_histograms(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(buffer_address_bidir, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_bidir, NULL); {
static DEVICE_ATTR(buffer_pages_bidir, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_bidir, NULL); return sprintf(buf,"Write address/length pair into this file to hand this region of the histograms buffer to CPU (before CPU reads).\n");
static DEVICE_ATTR(sync_for_cpu_h2d, SYSFS_PERMISSIONS, get_sync_for_cpu_h2d, sync_for_cpu_h2d); }
static DEVICE_ATTR(sync_for_device_h2d, SYSFS_PERMISSIONS, get_sync_for_device_h2d, sync_for_device_h2d); static ssize_t get_sync_for_device_logger(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(sync_for_cpu_d2h, SYSFS_PERMISSIONS, get_sync_for_cpu_d2h, sync_for_cpu_d2h); {
static DEVICE_ATTR(sync_for_device_d2h, SYSFS_PERMISSIONS, get_sync_for_device_d2h, sync_for_device_d2h); return sprintf(buf,"Write address/length pair into this file to hand this region of the logger buffer to device (after CPU writes).\n");
static DEVICE_ATTR(sync_for_cpu_bidir, SYSFS_PERMISSIONS, get_sync_for_cpu_bidir, sync_for_cpu_bidir); }
static DEVICE_ATTR(sync_for_device_bidir, SYSFS_PERMISSIONS, get_sync_for_device_bidir, sync_for_device_bidir); static ssize_t get_sync_for_cpu_logger(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"Write address/length pair into this file to hand this region of the logger buffer to CPU (before CPU reads).\n");
}
static DEVICE_ATTR(buffer_address, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr, NULL);
static DEVICE_ATTR(buffer_pages, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size, NULL);
static DEVICE_ATTR(buffer_address_h2d, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_h2d, NULL);
static DEVICE_ATTR(buffer_pages_h2d, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_h2d, NULL);
static DEVICE_ATTR(buffer_address_d2h, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_d2h, NULL);
static DEVICE_ATTR(buffer_pages_d2h, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_d2h, NULL);
static DEVICE_ATTR(buffer_address_bidir, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_bidir, NULL);
static DEVICE_ATTR(buffer_pages_bidir, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_bidir, NULL);
static DEVICE_ATTR(buffer_address_histograms, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_histograms, NULL);
static DEVICE_ATTR(buffer_pages_histograms, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_histograms, NULL);
static DEVICE_ATTR(buffer_address_logger, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr_logger, NULL);
static DEVICE_ATTR(buffer_pages_logger, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size_logger, NULL);
static DEVICE_ATTR(sync_for_cpu_h2d, SYSFS_PERMISSIONS, get_sync_for_cpu_h2d, sync_for_cpu_h2d);
static DEVICE_ATTR(sync_for_device_h2d, SYSFS_PERMISSIONS, get_sync_for_device_h2d, sync_for_device_h2d);
static DEVICE_ATTR(sync_for_cpu_d2h, SYSFS_PERMISSIONS, get_sync_for_cpu_d2h, sync_for_cpu_d2h);
static DEVICE_ATTR(sync_for_device_d2h, SYSFS_PERMISSIONS, get_sync_for_device_d2h, sync_for_device_d2h);
static DEVICE_ATTR(sync_for_cpu_bidir, SYSFS_PERMISSIONS, get_sync_for_cpu_bidir, sync_for_cpu_bidir);
static DEVICE_ATTR(sync_for_device_bidir, SYSFS_PERMISSIONS, get_sync_for_device_bidir, sync_for_device_bidir);
static DEVICE_ATTR(sync_for_cpu_histograms, SYSFS_PERMISSIONS, get_sync_for_cpu_histograms, sync_for_cpu_histograms);
static DEVICE_ATTR(sync_for_device_histograms,SYSFS_PERMISSIONS, get_sync_for_device_histograms, sync_for_device_histograms);
static DEVICE_ATTR(sync_for_cpu_logger, SYSFS_PERMISSIONS, get_sync_for_cpu_logger, sync_for_cpu_logger);
static DEVICE_ATTR(sync_for_device_logger, SYSFS_PERMISSIONS, get_sync_for_device_logger, sync_for_device_logger);
static struct attribute *root_dev_attrs[] = { static struct attribute *root_dev_attrs[] = {
&dev_attr_buffer_address.attr, &dev_attr_buffer_address.attr,
...@@ -346,12 +441,20 @@ static struct attribute *root_dev_attrs[] = { ...@@ -346,12 +441,20 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_buffer_pages_d2h.attr, &dev_attr_buffer_pages_d2h.attr,
&dev_attr_buffer_address_bidir.attr, &dev_attr_buffer_address_bidir.attr,
&dev_attr_buffer_pages_bidir.attr, &dev_attr_buffer_pages_bidir.attr,
&dev_attr_buffer_address_histograms.attr,
&dev_attr_buffer_pages_histograms.attr,
&dev_attr_buffer_address_logger.attr,
&dev_attr_buffer_pages_logger.attr,
&dev_attr_sync_for_cpu_h2d.attr, &dev_attr_sync_for_cpu_h2d.attr,
&dev_attr_sync_for_device_h2d.attr, &dev_attr_sync_for_device_h2d.attr,
&dev_attr_sync_for_cpu_d2h.attr, &dev_attr_sync_for_cpu_d2h.attr,
&dev_attr_sync_for_device_d2h.attr, &dev_attr_sync_for_device_d2h.attr,
&dev_attr_sync_for_cpu_bidir.attr, &dev_attr_sync_for_cpu_bidir.attr,
&dev_attr_sync_for_device_bidir.attr, &dev_attr_sync_for_device_bidir.attr,
&dev_attr_sync_for_cpu_histograms.attr,
&dev_attr_sync_for_device_histograms.attr,
&dev_attr_sync_for_cpu_logger.attr,
&dev_attr_sync_for_device_logger.attr,
NULL NULL
}; };
...@@ -379,7 +482,7 @@ static int elphel393_mem_probe(struct platform_device *pdev) ...@@ -379,7 +482,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back // mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf->h2d_paddr = dma_map_single(&pdev->dev, _elphel_buf.h2d_vaddr, (_elphel_buf.h2d_size*PAGE_SIZE), DMA_TO_DEVICE); pElphel_buf->h2d_paddr = dma_map_single(&pdev->dev, _elphel_buf.h2d_vaddr, (_elphel_buf.h2d_size*PAGE_SIZE), DMA_TO_DEVICE);
if (!pElphel_buf->h2d_paddr){ if (!pElphel_buf->h2d_paddr){
pr_err("ERROR in dma_map_single() for bidirectional buffer\n"); pr_err("ERROR in dma_map_single() for h2d buffer\n");
return 0; return 0;
} }
// printk("H2D DMA buffer location:\t\t0x%08X\n", pElphel_buf->h2d_paddr); // printk("H2D DMA buffer location:\t\t0x%08X\n", pElphel_buf->h2d_paddr);
...@@ -389,15 +492,27 @@ static int elphel393_mem_probe(struct platform_device *pdev) ...@@ -389,15 +492,27 @@ static int elphel393_mem_probe(struct platform_device *pdev)
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back // mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf->d2h_paddr = dma_map_single(&pdev->dev, _elphel_buf.d2h_vaddr, (_elphel_buf.d2h_size*PAGE_SIZE), DMA_FROM_DEVICE); pElphel_buf->d2h_paddr = dma_map_single(&pdev->dev, _elphel_buf.d2h_vaddr, (_elphel_buf.d2h_size*PAGE_SIZE), DMA_FROM_DEVICE);
if (!pElphel_buf->d2h_paddr){ if (!pElphel_buf->d2h_paddr){
pr_err("ERROR in dma_map_single() for bidirectional buffer\n"); pr_err("ERROR in dma_map_single() for d2h buffer\n");
return 0; return 0;
} }
// printk("D2H DMA buffer location:\t\t0x%08X\n", pElphel_buf->d2h_paddr);
} }
if (_elphel_buf.histograms_vaddr){
pElphel_buf->histograms_paddr = dma_map_single(&pdev->dev, _elphel_buf.histograms_vaddr, (_elphel_buf.histograms_size*PAGE_SIZE), DMA_FROM_DEVICE);
if (!pElphel_buf->histograms_paddr){
pr_err("ERROR in dma_map_single() for histograms buffer\n");
return 0;
}
}
if (_elphel_buf.logger_vaddr){
pElphel_buf->logger_paddr = dma_map_single(&pdev->dev, _elphel_buf.logger_vaddr, (_elphel_buf.logger_size*PAGE_SIZE), DMA_FROM_DEVICE);
if (!pElphel_buf->logger_paddr){
pr_err("ERROR in dma_map_single() for the logger buffer\n");
return 0;
}
}
if (_elphel_buf.bidir_vaddr){ if (_elphel_buf.bidir_vaddr){
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf->bidir_paddr = dma_map_single(&pdev->dev, _elphel_buf.bidir_vaddr, (_elphel_buf.bidir_size*PAGE_SIZE), DMA_BIDIRECTIONAL); pElphel_buf->bidir_paddr = dma_map_single(&pdev->dev, _elphel_buf.bidir_vaddr, (_elphel_buf.bidir_size*PAGE_SIZE), DMA_BIDIRECTIONAL);
if (!pElphel_buf->bidir_paddr){ if (!pElphel_buf->bidir_paddr){
pr_err("ERROR in dma_map_single() for bidirectional buffer\n"); pr_err("ERROR in dma_map_single() for bidirectional buffer\n");
...@@ -418,7 +533,13 @@ static int elphel393_mem_probe(struct platform_device *pdev) ...@@ -418,7 +533,13 @@ static int elphel393_mem_probe(struct platform_device *pdev)
printk("Bidirectional stream buffer paddr: 0x%08X\n",(u32) pElphel_buf -> bidir_paddr); printk("Bidirectional stream buffer paddr: 0x%08X\n",(u32) pElphel_buf -> bidir_paddr);
printk("Bidirectional stream buffer length: 0x%08X\n",(u32) pElphel_buf -> bidir_size * PAGE_SIZE); printk("Bidirectional stream buffer length: 0x%08X\n",(u32) pElphel_buf -> bidir_size * PAGE_SIZE);
printk("HISTOGRAMS stream buffer vaddr: 0x%08X\n",(u32) pElphel_buf -> histograms_vaddr);
printk("HISTOGRAMS stream buffer paddr: 0x%08X\n",(u32) pElphel_buf -> histograms_paddr);
printk("HISTOGRAMS stream buffer length: 0x%08X\n",(u32) pElphel_buf -> histograms_size * PAGE_SIZE);
printk("LOGGER stream buffer vaddr: 0x%08X\n",(u32) pElphel_buf -> logger_vaddr);
printk("LOGGER stream buffer paddr: 0x%08X\n",(u32) pElphel_buf -> logger_paddr);
printk("LOGGER stream buffer length: 0x%08X\n",(u32) pElphel_buf -> logger_size * PAGE_SIZE);
return 0; return 0;
} }
......
...@@ -199,8 +199,8 @@ int histograms_init_hardware(void) ...@@ -199,8 +199,8 @@ int histograms_init_hardware(void)
int port, chn; int port, chn;
x393_hist_saxi_addr_t saxi_addr; x393_hist_saxi_addr_t saxi_addr;
// fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned! // fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned!
fpga_hist_data = (u32 *) pElphel_buf->d2h_vaddr; // must be page-aligned! fpga_hist_data = (u32 *) pElphel_buf->histograms_vaddr; // d2h_vaddr; // must be page-aligned!
fpga_hist_phys = pElphel_buf->d2h_paddr; fpga_hist_phys = pElphel_buf->histograms_paddr; //d2h_paddr;
for (port=0; port<SENSOR_PORTS; port++) for (chn=0; chn < MAX_SENSORS; chn++) { for (port=0; port<SENSOR_PORTS; port++) for (chn=0; chn < MAX_SENSORS; chn++) {
saxi_addr.page=(fpga_hist_phys >> PAGE_SHIFT)+ PARS_FRAMES * (chn + MAX_SENSORS *port);// table for 4 colors is exactly 1 page; saxi_addr.page=(fpga_hist_phys >> PAGE_SHIFT)+ PARS_FRAMES * (chn + MAX_SENSORS *port);// table for 4 colors is exactly 1 page;
set_x393_hist_saxi_addr (saxi_addr, chn); // Histogram DMA addresses (in 4096 byte pages) set_x393_hist_saxi_addr (saxi_addr, chn); // Histogram DMA addresses (in 4096 byte pages)
......
...@@ -109,60 +109,63 @@ ...@@ -109,60 +109,63 @@
#define bytePtrMask ((CCAM_DMA1_SIZE << 2)-1) // and byte pointer in the dma buffer to get index in the array #define bytePtrMask ((CCAM_DMA1_SIZE << 2)-1) // and byte pointer in the dma buffer to get index in the array
#ifdef NC353 #ifdef NC353
#define XCLK_RATE 80000000 // 80MHz clock in NC353 #define XCLK_RATE 80000000 ///< 80MHz clock in NC353
#else #else
#define XCLK_RATE 100000000 // 100MHz clock in NC393 #define XCLK_RATE 100000000 ///< 100MHz clock in NC393
#endif #endif
#define RS232_RATE 19200 #define RS232_RATE 19200 ///< RS232 bps
#define IMU_MODULE_DESCRIPTION "IMU logger for 10365 ext. board" #define IMU_MODULE_DESCRIPTION "IMU logger for 10365 ext. board"
#define IMU_DRIVER_NAME "imu_logger" #define IMU_DRIVER_NAME "imu_logger"
#define IMU_MAXMINOR 10 #define IMU_MAXMINOR 10
#define X313_WA_IOPINS 0x70 // bits [31:24] - enable channels (channel 0 -software, enabled at FPGA init) #ifdef NC353
#define X313_WA_IOPINS_EN_IMU 0xc0000000 #define X313_WA_IOPINS 0x70 // bits [31:24] - enable channels (channel 0 -software, enabled at FPGA init)
#define X313_WA_IOPINS_DIS_IMU 0x80000000 #define X313_WA_IOPINS_EN_IMU 0xc0000000
#define X313_WA_IMU_DATA 0x7e #define X313_WA_IOPINS_DIS_IMU 0x80000000
#define X313_WA_IMU_CTRL 0x7f #define X313_WA_IMU_DATA 0x7e
#define X313_WA_IMU_CTRL 0x7f
#define X313_RA_IMU_COUNT 0x7e // number of 64-byte samples recorded (24 bit counter)
#endif
// #define X313_RA_IMU_DATA 0x7e // use csp4 // #define X313_RA_IMU_DATA 0x7e // use csp4
// #define X313_RA_IMU_STATUS 0x7f // use csp4 // #define X313_RA_IMU_STATUS 0x7f // use csp4
#define IMU_COUNT_OVERFLOW 0x1000000 // number of records written is modulo IMU_COUNT_OVERFLOW // Is it the same for 393?
#define X313_RA_IMU_COUNT 0x7e // number of 64-byte samples recorded (24 bit counter) #define IMU_COUNT_OVERFLOW 0x1000000 ///< number of records written is modulo IMU_COUNT_OVERFLOW
#define X313_IMU_PERIOD_ADDR 0x0 // request period for IMU (in SPI bit periods) #define X313_IMU_PERIOD_ADDR 0x0 ///< request period for IMU (in SPI bit periods)
#define X313_IMU_DIVISOR_ADDR 0x1 // xclk (80MHz) clock divisor for half SPI bit period 393: clock is Now clock is logger_clk=100MHz (200 MHz?) #define X313_IMU_DIVISOR_ADDR 0x1 ///< xclk (80MHz) clock divisor for half SPI bit period 393: clock is Now clock is logger_clk=100MHz (200 MHz?)
#define X313_IMU_RS232DIV_ADDR 0x2 // serial gps bit duration in xclk (80MHz) periods - 16 bits #define X313_IMU_RS232DIV_ADDR 0x2 ///< serial gps bit duration in xclk (80MHz) periods - 16 bits
#define X313_IMU_CONFIGURE_ADDR 0x3 // IMU logger configuration #define X313_IMU_CONFIGURE_ADDR 0x3 ///< IMU logger configuration
#define IMU_CONF(x,y) (((((y) & ((1 << IMUCR__##x##__WIDTH)-1))) | (1 << IMUCR__##x##__WIDTH) ) << IMUCR__##x##__BITNM) #define IMU_CONF(x,y) (((((y) & ((1 << IMUCR__##x##__WIDTH)-1))) | (1 << IMUCR__##x##__WIDTH) ) << IMUCR__##x##__BITNM)
#define IMUCR__IMU_SLOT__BITNM 0 // slot, where 103695 (imu) board is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11) #define IMUCR__IMU_SLOT__BITNM 0 ///< slot, where 103695 (imu) board is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__IMU_SLOT__WIDTH 2 #define IMUCR__IMU_SLOT__WIDTH 2
#define IMUCR__GPS_CONF__BITNM 3 // slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11) #define IMUCR__GPS_CONF__BITNM 3 ///< slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__GPS_CONF__WIDTH 4 // bits 0,1 - slot #, same as for IMU_SLOT, bits 2,3: #define IMUCR__GPS_CONF__WIDTH 4 ///< bits 0,1 - slot #, same as for IMU_SLOT, bits 2,3:
// 0 - ext pulse, leading edge, // 0 - ext pulse, leading edge,
// 1 - ext pulse, trailing edge // 1 - ext pulse, trailing edge
// 2 - start of the first rs232 character after pause // 2 - start of the first rs232 character after pause
// 3 - start of the last "$" character (start of each NMEA sentence) // 3 - start of the last "$" character (start of each NMEA sentence)
#define IMUCR__MSG_CONF__BITNM 8 // source of external pulses to log: #define IMUCR__MSG_CONF__BITNM 8 ///< source of external pulses to log:
#define IMUCR__MSG_CONF__WIDTH 5 // bits 0-3 - number of fpga GPIO input 0..11 (i.e. 0x0a - external optoisolated sync input (J15) #define IMUCR__MSG_CONF__WIDTH 5 ///< bits 0-3 - number of fpga GPIO input 0..11 (i.e. 0x0a - external optoisolated sync input (J15)
// 0x0f - disable MSG module // 0x0f - disable MSG module
// bit 4 - invert polarity: 0 - timestamp leading edge, log at trailing edge, 1 - opposite // bit 4 - invert polarity: 0 - timestamp leading edge, log at trailing edge, 1 - opposite
// software may set (up to 56 bytes) log message before trailing end of the pulse // software may set (up to 56 bytes) log message before trailing end of the pulse
#define IMUCR__SYN_CONF__BITNM 14 // logging frame time stamps (may be synchronized by another camera and have timestamp of that camera) #define IMUCR__SYN_CONF__BITNM 14 ///< logging frame time stamps (may be synchronized by another camera and have timestamp of that camera)
#define IMUCR__SYN_CONF__WIDTH 1 // 0 - disable, 1 - enable #define IMUCR__SYN_CONF__WIDTH 1 ///< 0 - disable, 1 - enable
#define IMUCR__RST_CONF__BITNM 16 // reset module #define IMUCR__RST_CONF__BITNM 16 ///< reset module
#define IMUCR__RST_CONF__WIDTH 1 // 0 - enable, 1 -reset (needs resettimng DMA address in ETRAX also) #define IMUCR__RST_CONF__WIDTH 1 ///< 0 - enable, 1 -reset (needs resettimng DMA address in ETRAX also)
#define IMUCR__DBG_CONF__BITNM 18 // several axtra IMU configuration bits #define IMUCR__DBG_CONF__BITNM 18 ///< several axtra IMU configuration bits
#define IMUCR__DBG_CONF__WIDTH 4 // 0 - config_long_sda_en, 1 -config_late_clk, 2 - config_single_wire, should be set for 103695 rev "A" #define IMUCR__DBG_CONF__WIDTH 4 ///< 0 - config_long_sda_en, 1 -config_late_clk, 2 - config_single_wire, should be set for 103695 rev "A"
#define X313_IMU_REGISTERS_ADDR 0x4 #define X313_IMU_REGISTERS_ADDR 0x4
#define X313_IMU_NMEA_FORMAT_ADDR 0x20 #define X313_IMU_NMEA_FORMAT_ADDR 0x20
#define X313_IMU_MESSAGE_ADDR 0x40 // 40..4f, only first 0xe visible #define X313_IMU_MESSAGE_ADDR 0x40 ///< 40..4f, only first 0xe visible
// offsets in the file (during write) // offsets in the file (during write)
#define X313_IMU_PERIOD_OFFS 0x0 #define X313_IMU_PERIOD_OFFS 0x0
...@@ -177,18 +180,18 @@ ...@@ -177,18 +180,18 @@
#define X313_IMU_NMEA_FORMAT_OFFS 0x30 #define X313_IMU_NMEA_FORMAT_OFFS 0x30
#define X313_IMU_MESSAGE_OFFS 0xB0 // 0xB0..0xE7 #define X313_IMU_MESSAGE_OFFS 0xB0 // 0xB0..0xE7
#define PCA9500_PP_ADDR 0x40 // PCA9500 i2c slave addr for the parallel port (read will be 0x41) #define PCA9500_PP_ADDR 0x40 ///< PCA9500 i2c slave addr for the parallel port (read will be 0x41)
#define DFLT_SLAVE_ADDR 3 // i2c slave addr modifier (0..7) for the IMU (103695) board #define DFLT_SLAVE_ADDR 3 ///< i2c slave addr modifier (0..7) for the IMU (103695) board
#define DFLT_SCLK_FREQ 5000000 // SCLK frequency #define DFLT_SCLK_FREQ 5000000 ///< SCLK frequency
#define DFLT_DIVISOR ( XCLK_RATE / DFLT_SCLK_FREQ /2 ) #define DFLT_DIVISOR ( XCLK_RATE / DFLT_SCLK_FREQ /2 )
#define DFLT_STALL_USEC 2 // stall time in usec #define DFLT_STALL_USEC 2 ///< stall time in usec
#define DFLT_STALL (( DFLT_STALL_USEC * ( XCLK_RATE / DFLT_DIVISOR )) / 1000000 ) // stall time in usec #define DFLT_STALL (( DFLT_STALL_USEC * ( XCLK_RATE / DFLT_DIVISOR )) / 1000000 ) ///< stall time in usec
#define DFLT_SLEEP 30000 // usec, sleep if not ready #define DFLT_SLEEP 30000 ///< usec, sleep if not ready
//#define DFLT_FEQ 300 //#define DFLT_FEQ 300
//#define DFLT_PERIOD ( XCLK_RATE / DFLT_DIVISOR / DFLT_FEQ ) // fixed scan period //#define DFLT_PERIOD ( XCLK_RATE / DFLT_DIVISOR / DFLT_FEQ ) // fixed scan period
#define DFLT_PERIOD 0xFFFFFFFF // read IMU when it is ready #define DFLT_PERIOD 0xFFFFFFFF ///< read IMU when it is ready
#define DFLT_RS232DIV ( XCLK_RATE / 2 / RS232_RATE ) #define DFLT_RS232DIV ( XCLK_RATE / 2 / RS232_RATE )
#if IS_103695_REV_A #if IS_103695_REV_A
...@@ -196,7 +199,7 @@ ...@@ -196,7 +199,7 @@
#else #else
#define EXTRA_CONF 0x0 #define EXTRA_CONF 0x0
#endif #endif
#define SLOW_SPI 0 // set to 1 for slower SPI (not ADIS-16375), it will increase SCLK period that does not end CS active #define SLOW_SPI 0 ///< set to 1 for slower SPI (not ADIS-16375), it will increase SCLK period that does not end CS active
#define DFLT_CONFIG ( IMU_CONF(IMU_SLOT,1) | \ #define DFLT_CONFIG ( IMU_CONF(IMU_SLOT,1) | \
IMU_CONF(GPS_CONF, ( 2 | 8) ) | \ IMU_CONF(GPS_CONF, ( 2 | 8) ) | \
...@@ -219,9 +222,9 @@ ...@@ -219,9 +222,9 @@
#define WHICH_EN_DMA 1024 #define WHICH_EN_DMA 1024
#define WHICH_EN_LOGGER 2048 #define WHICH_EN_LOGGER 2048
#define LSEEK_IMU_NEW 1 // start from the new data, discard buffer #define LSEEK_IMU_NEW 1 ///< start from the new data, discard buffer
#define LSEEK_IMU_STOP 2 // stop DMA1 and IMU #define LSEEK_IMU_STOP 2 ///< stop DMA1 and IMU
#define LSEEK_IMU_START 3 // start IMU and DMA1 (do not modify parameters) #define LSEEK_IMU_START 3 ///< start IMU and DMA1 (do not modify parameters)
static unsigned char dflt_wbuf[]= static unsigned char dflt_wbuf[]=
{ DFLT_PERIOD & 0xff, ( DFLT_PERIOD >> 8 ) & 0xff, ( DFLT_PERIOD >> 16) & 0xff, ( DFLT_PERIOD >> 24 ) & 0xff, { DFLT_PERIOD & 0xff, ( DFLT_PERIOD >> 8 ) & 0xff, ( DFLT_PERIOD >> 16) & 0xff, ( DFLT_PERIOD >> 24 ) & 0xff,
// {0,0,0,0, // period - off // {0,0,0,0, // period - off
...@@ -261,9 +264,9 @@ static unsigned char dflt_wbuf[]= ...@@ -261,9 +264,9 @@ static unsigned char dflt_wbuf[]=
0x70, // time m/s 0x70, // time m/s
0x72, // time d/h 0x72, // time d/h
0x74,// time y/m 0x74,// time y/m
/// NMEA sentences // NMEA sentences
/// first three letters - sentence to log (letters after "$GP"). next "n"/"b" (up to 24 total) - "n" number (will be encoded 4 digits/byte, follwed by "0xF" // first three letters - sentence to log (letters after "$GP"). next "n"/"b" (up to 24 total) - "n" number (will be encoded 4 digits/byte, follwed by "0xF"
/// "b" - byte - all but last will have MSB 0 (& 0x7f), the last one - with MSB set (| 0x80). If there are no characters in the field 0xff will be output // "b" - byte - all but last will have MSB 0 (& 0x7f), the last one - with MSB set (| 0x80). If there are no characters in the field 0xff will be output
'R','M','C','n','b','n','b','n','b','n','n','n','n','b', 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 'R','M','C','n','b','n','b','n','b','n','n','n','n','b', 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','G','A','n','n','b','n','b','n','n','n','n','b','n','b','b','b', 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 'G','G','A','n','n','b','n','b','n','n','n','n','b','n','b','b','b', 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','S','A','b','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n', 0,0,0,0, 0,0,0,0, 0,0,0,0, 'G','S','A','b','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n', 0,0,0,0, 0,0,0,0, 0,0,0,0,
...@@ -274,37 +277,22 @@ static unsigned char dflt_wbuf[]= ...@@ -274,37 +277,22 @@ static unsigned char dflt_wbuf[]=
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
}; };
static unsigned char wbuf[sizeof(dflt_wbuf)]; static unsigned char wbuf[sizeof(dflt_wbuf)];
//static unsigned char brbuf[8192]; /// twice the FPGA FIFO size
//static unsigned long * rbuf= (unsigned long *) brbuf;
/*
#define IMU_MAJOR 141
#define IMU_MINOR 1
*/
static const char fpga_name[] = "imu_control"; static const char fpga_name[] = "imu_control";
static int imu_open (struct inode *inode, struct file *filp); static int imu_open (struct inode *inode, struct file *filp);
static int imu_release(struct inode *inode, struct file *filp); static int imu_release(struct inode *inode, struct file *filp);
//static int imu_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static ssize_t imu_write (struct file * file, const char * buf, size_t count, loff_t *off); static ssize_t imu_write (struct file * file, const char * buf, size_t count, loff_t *off);
static loff_t imu_lseek (struct file * file, loff_t offset, int orig); static loff_t imu_lseek (struct file * file, loff_t offset, int orig);
static ssize_t imu_read (struct file * file, char * buf, size_t count, loff_t *off); static ssize_t imu_read (struct file * file, char * buf, size_t count, loff_t *off);
//static loff_t fpga_lseek(struct file * file, loff_t offset, int orig);
//static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off);
//static int __init fpga_init(void);
#define IMU_MAXMINOR 10 #define IMU_MAXMINOR 10
//static int minors[IMU_MAXMINOR+1]; // each minor can be opened only once static loff_t numBytesRead=0; ///< totalnumber of bytes read from the imu - global pointer (modified when open in write mode)
//static int num_reads; // number of fifo reads (does not advance file position) static loff_t numBytesWritten=0; ///< totalnumber of bytes writtent to the IMU buffer since it was started/restarted
//static int numRecordsRead=0; // number of 64-byte log records read (24 bit, same format as FPGA write counter) static int lastFPGABytes=0; ///< last read FPGA counter (24 bits) << 6
static loff_t numBytesRead=0; // totalnumber of bytes read from the imu - global pointer (modified when open in write mode)
static loff_t numBytesWritten=0; // totalnumber of bytes writtent to the IMU buffer since it was started/restarted
static int lastFPGABytes=0; // last read FPGA counter (24 bits) << 6
//TODO 393: Use allocated 4MB
static unsigned long ccam_dma1_buf[CCAM_DMA1_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE))); static unsigned long ccam_dma1_buf[CCAM_DMA1_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE)));
//!Without "static" system hangs after "Uncompressing Linux... //!Without "static" system hangs after "Uncompressing Linux...
unsigned long * ccam_dma1_buf_ptr = NULL; unsigned long * ccam_dma1_buf_ptr = NULL;
...@@ -318,8 +306,11 @@ void init_ccam_dma1_buf_ptr(void) { ...@@ -318,8 +306,11 @@ void init_ccam_dma1_buf_ptr(void) {
void updateNumBytesWritten(void){ void updateNumBytesWritten(void){
x393_logger_status_t logger_status = x393_logger_status(); x393_logger_status_t logger_status = x393_logger_status();
// int thisFPGABytes=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6; #ifdef NC353
int thisFPGABytes=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
#else
int thisFPGABytes = logger_status.sample << 6; int thisFPGABytes = logger_status.sample << 6;
#endif
int delta=(thisFPGABytes-lastFPGABytes); int delta=(thisFPGABytes-lastFPGABytes);
lastFPGABytes=thisFPGABytes; lastFPGABytes=thisFPGABytes;
if (delta<0) delta+=(IMU_COUNT_OVERFLOW<<6); if (delta<0) delta+=(IMU_COUNT_OVERFLOW<<6);
......
...@@ -38,6 +38,17 @@ struct elphel_buf_t ...@@ -38,6 +38,17 @@ struct elphel_buf_t
void *bidir_vaddr; void *bidir_vaddr;
dma_addr_t bidir_paddr; dma_addr_t bidir_paddr;
ssize_t bidir_size; ssize_t bidir_size;
// Device to host stream DMA buffer for histograms
void *histograms_vaddr;
dma_addr_t histograms_paddr;
ssize_t histograms_size;
// Device to host stream DMA buffer for the logger
void *logger_vaddr;
dma_addr_t logger_paddr;
ssize_t logger_size;
}; };
extern struct elphel_buf_t *pElphel_buf; extern struct elphel_buf_t *pElphel_buf;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment