tdc: now we have events \o/

Signed-off-by: Samuel Iglesias Gonsálvez's avatarSamuel Iglesias Gonsalvez <siglesias@igalia.com>
parent c22f03e3
......@@ -11,6 +11,7 @@
#include <asm/io.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include "spec.h"
#include "tdc.h"
......@@ -29,16 +30,25 @@ int tdc_dma_setup(struct spec_tdc *tdc, unsigned long src, unsigned long dst, in
{
dma_addr_t mapping;
mapping = dma_map_single(&tdc->spec->pdev->dev, (char *)src, size,
mapping = dma_map_single(&tdc->spec->pdev->dev, (char *)dst, size,
DMA_FROM_DEVICE);
tdc->rx_dma = mapping;
if (dma_mapping_error(&tdc->spec->pdev->dev, tdc->rx_dma)) {
dev_err(&tdc->spec->pdev->dev, "dma_map_single Rx failed\n");
return -ENOMEM;
}
/* Write the source and destination addresses */
writel(src, tdc->base + TDC_DMA_C_START_R);
writel(dst & 0x00ffffffff, tdc->base + TDC_DMA_H_START_L_R);
//writel(dst >> 32, tdc->base + TDC_DMA_H_START_H_R);
writel(mapping & 0xffffffff, tdc->base + TDC_DMA_H_START_L_R);
writel((mapping >> 32) & 0x00ffffffff, tdc->base + TDC_DMA_H_START_H_R);
writel(0, tdc->base + TDC_DMA_H_START_H_R);
writel(0, tdc->base + TDC_DMA_NEXT_L_R);
writel(0, tdc->base + TDC_DMA_NEXT_H_R);
/* Write the DMA length */
writel(size, tdc->base + TDC_DMA_LEN_R);
writel(0x1, tdc->base + TDC_DMA_ATTRIB_R);
return 0;
}
......@@ -46,5 +56,7 @@ int tdc_dma_setup(struct spec_tdc *tdc, unsigned long src, unsigned long dst, in
int tdc_dma_start(struct spec_tdc *tdc)
{
writel(0x1, tdc->base + TDC_DMA_CTRL_R);
udelay(50);
writel(0, tdc->base + TDC_DMA_CTRL_R);
return 0;
}
......@@ -56,8 +56,10 @@ static int tdc_fmc_check_lost_events(u32 curr_wr_ptr, u32 prev_wr_ptr, int *coun
dacapo_prev = prev_wr_ptr >> 12;
dacapo_curr = curr_wr_ptr >> 12;
curr_wr_ptr &= 0x0fff; /* Pick last 12 bits */
prev_wr_ptr &= 0x0fff; /* Pick last 12 bits */
curr_wr_ptr &= 0x00fff; /* Pick last 12 bits */
curr_wr_ptr >>= 2; /* Remove last 4 bytes. */
prev_wr_ptr &= 0x00fff; /* Pick last 12 bits */
prev_wr_ptr >>= 2; /* Remove last 4 bytes. */
dacapo_diff = dacapo_curr - dacapo_prev;
switch(dacapo_diff) {
......@@ -105,8 +107,10 @@ static void tdc_fmc_irq_work(struct work_struct *work)
prev_wr_ptr = tdc->wr_pointer;
ret = tdc_dma_setup(tdc, 0, (unsigned long)events,
TDC_EVENT_BUFFER_SIZE*sizeof(struct tdc_event));
if (ret)
if (ret) {
pr_err("tdc: error in DMA setup\n");
goto dma_out;
}
/* Start DMA transfer and wait for it */
tdc_dma_start(tdc);
......@@ -115,8 +119,12 @@ static void tdc_fmc_irq_work(struct work_struct *work)
/* DMA happened */
atomic_set(&fmc_dma_end, 0);
/* Check the status of the DMA */
if(readl(tdc->base + TDC_DMA_STAT_R) & (TDC_DMA_STAT_ERR | TDC_DMA_STAT_ABORT))
if(readl(tdc->base + TDC_DMA_STAT_R) & (TDC_DMA_STAT_ERR | TDC_DMA_STAT_ABORT)) {
pr_err("tdc: error in DMA transfer\n");
mutex_unlock(&fmc_dma_lock);
goto dma_out;
}
mutex_unlock(&fmc_dma_lock);
tdc->wr_pointer = curr_wr_ptr;
......@@ -129,10 +137,12 @@ static void tdc_fmc_irq_work(struct work_struct *work)
/* Start reading in the oldest event */
if(count == TDC_EVENT_BUFFER_SIZE)
rd_ptr = curr_wr_ptr; /* The oldest is curr_wr_ptr */
rd_ptr = (curr_wr_ptr >> 2) & 0x000ff; /* The oldest is curr_wr_ptr */
else
rd_ptr = prev_wr_ptr; /* The oldest is prev_wr_ptr */
rd_ptr = (prev_wr_ptr >> 2) & 0x000ff; /* The oldest is prev_wr_ptr */
pr_err("SIG: %s count %d\n", __func__, count);
for ( ; count > 0; count--) {
tmp_data = &events[rd_ptr];
/* Check which channel to deliver the data */
......@@ -148,12 +158,11 @@ static void tdc_fmc_irq_work(struct work_struct *work)
/* XXX: as it has only one element of data, maybe is better a mutex
* instead of semaphore!
*/
up(&tdc->event[chan].lock);
//up(&tdc->event[chan].lock);
rd_ptr = (rd_ptr + 1) % TDC_EVENT_BUFFER_SIZE;
}
dma_out:
mutex_unlock(&fmc_dma_lock);
kfree(events);
}
......@@ -169,8 +178,9 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id)
/* Tstamp threshold or time threshold */
if((irq_code & TDC_IRQ_TDC_TSTAMP) ||
(irq_code & TDC_IRQ_TDC_TIME_THRESH))
(irq_code & TDC_IRQ_TDC_TIME_THRESH)) {
queue_work(tdc_workqueue, &tdc->irq_work);
}
/* DMA interrupt */
if((irq_code & TDC_IRQ_GNUM_CORE_0) ||
......@@ -284,7 +294,7 @@ int tdc_fmc_probe(struct fmc_device *dev)
/* Request the IRQ */
dev->op->irq_request(dev, tdc_fmc_irq_handler, "spec-tdc", IRQF_SHARED);
/* Enable IRQ */
writel(0xC, tdc->base + TDC_IRQ_ENABLE_REG);
writel(0xF, tdc->base + TDC_IRQ_ENABLE_REG);
return tdc_zio_register_device(tdc);
}
......
......@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/zio.h>
#include <linux/zio-buffer.h>
......@@ -244,17 +245,22 @@ static int tdc_zio_raw_io(struct zio_cset *cset)
zio_chan = cset->chan;
tdc = zdev->priv_d;
chan = cset->index - 1;
chan = cset->index;
/* Wait for data */
#if 0
if(down_interruptible(&tdc->event[chan].lock))
return -ERESTARTSYS;
#else
//mdelay(100);
#endif
/* Check if we have read this data before */
/* XXX: change it if we have more data or use a mutex */
#if 0
if (tdc->event[chan].read)
return -EAGAIN;
tdc->event[chan].read = 1;
#endif
/* Process the data */
ctrl = zio_get_ctrl(zio_chan->active_block);
......@@ -265,7 +271,6 @@ static int tdc_zio_raw_io(struct zio_cset *cset)
ctrl->tstamp.bins = tdc->event[chan].data.fine_time;
ctrl->flags = tdc->event[chan].dacapo_flag; /* XXX: Is it OK here? */
ctrl->reserved = tdc->event[chan].data.metadata;
return 0;
}
......
......@@ -155,8 +155,8 @@ int main(int argc, char **argv)
tdc_set_host_utc_time(b);
tdc_activate_all_channels(b);
tdc_set_active_channels(b, CHAN0 | CHAN1 | CHAN2 | CHAN3 | CHAN4);
tdc_set_time_threshold(b, 1);
tdc_set_timestamp_threshold(b, 10);
tdc_set_time_threshold(b, 10);
tdc_set_timestamp_threshold(b, 100);
tdc_start_acquisition(b);
for (i = 0; i <100; i++) {
/* this should be a blocking read */
......@@ -167,6 +167,7 @@ int main(int argc, char **argv)
} else {
printf("Error reading sample\n");
}
sleep(1);
}
tdc_stop_acquisition(b);
......
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