tdc: added better DMA support

Signed-off-by: Samuel Iglesias Gonsálvez's avatarSamuel Iglesias Gonsálvez <siglesias@igalia.com>
parent 44638da3
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
*/ */
#include <asm/io.h> #include <asm/io.h>
#include <linux/dma-mapping.h>
#include "spec.h"
#include "tdc.h" #include "tdc.h"
#include "hw/tdc_regs.h" #include "hw/tdc_regs.h"
...@@ -25,6 +27,11 @@ ...@@ -25,6 +27,11 @@
*/ */
int tdc_dma_setup(struct spec_tdc *tdc, unsigned long src, unsigned long dst, int size) int tdc_dma_setup(struct spec_tdc *tdc, unsigned long src, unsigned long dst, int size)
{ {
dma_addr_t mapping;
mapping = dma_map_single(&tdc->spec->pdev->dev, (char *)src, size,
DMA_FROM_DEVICE);
tdc->rx_dma = mapping;
/* Write the source and destination addresses */ /* Write the source and destination addresses */
writel(src, tdc->base + TDC_DMA_C_START_R); writel(src, tdc->base + TDC_DMA_C_START_R);
......
...@@ -104,7 +104,8 @@ static void tdc_fmc_irq_work(struct work_struct *work) ...@@ -104,7 +104,8 @@ static void tdc_fmc_irq_work(struct work_struct *work)
goto dma_out; /* No new events happened */ goto dma_out; /* No new events happened */
prev_wr_ptr = tdc->wr_pointer; prev_wr_ptr = tdc->wr_pointer;
ret = tdc_dma_setup(tdc, 0, (unsigned long)events, 1024*sizeof(struct tdc_event)); ret = tdc_dma_setup(tdc, 0, (unsigned long)events,
TDC_EVENT_BUFFER_SIZE*sizeof(struct tdc_event));
if (ret) if (ret)
goto dma_out; goto dma_out;
...@@ -162,9 +163,6 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id) ...@@ -162,9 +163,6 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id)
struct spec_tdc *tdc = spec->sub_priv; struct spec_tdc *tdc = spec->sub_priv;
u32 irq_code; u32 irq_code;
/* TODO: fill with everything */
pr_err("tdc: IRQ is coming\n");
/* Check the source of the interrupt */ /* Check the source of the interrupt */
irq_code = readl(fmc->base + TDC_IRQ_CODE_R); irq_code = readl(fmc->base + TDC_IRQ_CODE_R);
...@@ -176,6 +174,12 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id) ...@@ -176,6 +174,12 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id)
/* DMA interrupt */ /* DMA interrupt */
if((irq_code & TDC_IRQ_GNUM_CORE_0) || if((irq_code & TDC_IRQ_GNUM_CORE_0) ||
(irq_code & TDC_IRQ_GNUM_CORE_1)) { (irq_code & TDC_IRQ_GNUM_CORE_1)) {
dma_sync_single_for_cpu(&spec->pdev->dev, tdc->rx_dma,
TDC_EVENT_BUFFER_SIZE*sizeof(struct tdc_event),
DMA_FROM_DEVICE);
dma_unmap_single(&spec->pdev->dev, tdc->rx_dma,
TDC_EVENT_BUFFER_SIZE*sizeof(struct tdc_event),
DMA_FROM_DEVICE);
/* Wake up the threads waiting for the DMA transfer */ /* Wake up the threads waiting for the DMA transfer */
atomic_set(&fmc_dma_end, 1); atomic_set(&fmc_dma_end, 1);
wake_up(&fmc_wait_dma); wake_up(&fmc_wait_dma);
...@@ -216,6 +220,15 @@ int tdc_fmc_probe(struct fmc_device *dev) ...@@ -216,6 +220,15 @@ int tdc_fmc_probe(struct fmc_device *dev)
tdc->gn412x_regs = spec->remap[2]; /* BAR 4 */ tdc->gn412x_regs = spec->remap[2]; /* BAR 4 */
tdc->wr_pointer = 0; tdc->wr_pointer = 0;
/* XXX: Not implemented yet. Do we needed it? */
#if 0
/* Check if the device is DMA capable on 32 bits. */
if (pci_set_dma_mask(spec->pdev, DMA_BIT_MASK(32)) < 0 ||
pci_set_consistent_dma_mask(spec->pdev, DMA_BIT_MASK(32)) < 0) {
pr_err("error setting 32-bit DMA mask.\n");
return -ENXIO;
}
#endif
for(i = 0; i < TDC_CHAN_NUMBER; i++) for(i = 0; i < TDC_CHAN_NUMBER; i++)
sema_init(&tdc->event[i].lock, 0); sema_init(&tdc->event[i].lock, 0);
......
...@@ -248,7 +248,7 @@ static int tdc_zio_raw_io(struct zio_cset *cset) ...@@ -248,7 +248,7 @@ static int tdc_zio_raw_io(struct zio_cset *cset)
static int tdc_zio_probe(struct zio_device *zdev) static int tdc_zio_probe(struct zio_device *zdev)
{ {
/* TODO */ /* TODO: implement something if needed. If not, delete this function */
pr_err("%s: register new device\n", __func__); pr_err("%s: register new device\n", __func__);
return 0; return 0;
...@@ -260,7 +260,7 @@ static struct zio_driver tdc_zdrv = { ...@@ -260,7 +260,7 @@ static struct zio_driver tdc_zdrv = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.id_table = tdc_table, .id_table = tdc_table,
.probe = tdc_zio_probe, /* TODO: */ .probe = tdc_zio_probe,
}; };
int tdc_zio_register_device(struct spec_tdc *tdc) int tdc_zio_register_device(struct spec_tdc *tdc)
......
...@@ -58,6 +58,7 @@ struct spec_tdc { ...@@ -58,6 +58,7 @@ struct spec_tdc {
unsigned char __iomem *gn412x_regs; unsigned char __iomem *gn412x_regs;
atomic_t busy; /* whether the device is acquiring data */ atomic_t busy; /* whether the device is acquiring data */
u32 wr_pointer; u32 wr_pointer;
dma_addr_t rx_dma;
struct work_struct irq_work; struct work_struct irq_work;
struct tdc_event_buffer event[TDC_CHAN_NUMBER]; struct tdc_event_buffer event[TDC_CHAN_NUMBER];
}; };
......
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