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 @@
*/
#include <asm/io.h>
#include <linux/dma-mapping.h>
#include "spec.h"
#include "tdc.h"
#include "hw/tdc_regs.h"
......@@ -25,6 +27,11 @@
*/
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 */
writel(src, tdc->base + TDC_DMA_C_START_R);
......
......@@ -104,7 +104,8 @@ static void tdc_fmc_irq_work(struct work_struct *work)
goto dma_out; /* No new events happened */
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)
goto dma_out;
......@@ -162,9 +163,6 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id)
struct spec_tdc *tdc = spec->sub_priv;
u32 irq_code;
/* TODO: fill with everything */
pr_err("tdc: IRQ is coming\n");
/* Check the source of the interrupt */
irq_code = readl(fmc->base + TDC_IRQ_CODE_R);
......@@ -176,6 +174,12 @@ irqreturn_t tdc_fmc_irq_handler(int irq, void *dev_id)
/* DMA interrupt */
if((irq_code & TDC_IRQ_GNUM_CORE_0) ||
(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 */
atomic_set(&fmc_dma_end, 1);
wake_up(&fmc_wait_dma);
......@@ -216,6 +220,15 @@ int tdc_fmc_probe(struct fmc_device *dev)
tdc->gn412x_regs = spec->remap[2]; /* BAR 4 */
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++)
sema_init(&tdc->event[i].lock, 0);
......
......@@ -248,7 +248,7 @@ static int tdc_zio_raw_io(struct zio_cset *cset)
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__);
return 0;
......@@ -260,7 +260,7 @@ static struct zio_driver tdc_zdrv = {
.owner = THIS_MODULE,
},
.id_table = tdc_table,
.probe = tdc_zio_probe, /* TODO: */
.probe = tdc_zio_probe,
};
int tdc_zio_register_device(struct spec_tdc *tdc)
......
......@@ -58,6 +58,7 @@ struct spec_tdc {
unsigned char __iomem *gn412x_regs;
atomic_t busy; /* whether the device is acquiring data */
u32 wr_pointer;
dma_addr_t rx_dma;
struct work_struct irq_work;
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