Commit 097d22f4 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

kernel: made support for VIC and SDB carrier-independent

parent cedaf701
......@@ -87,9 +87,6 @@ struct ft_carrier_specific {
int (*reset_core) (struct fmctdc_dev *);
int (*copy_timestamps) (struct fmctdc_dev *, int base_addr, int size,
void *dst);
int (*setup_irqs) (struct fmctdc_dev *, irq_handler_t handler);
int (*disable_irqs) (struct fmctdc_dev *);
int (*ack_irq) (struct fmctdc_dev *, int irq_id);
void (*exit) (struct fmctdc_dev *);
};
......@@ -145,6 +142,7 @@ struct fmctdc_dev {
int ft_dma_base;
int ft_carrier_base;
int ft_irq_base;
int ft_buffer_base;
/* IRQ base index (for SVEC) */
struct fmc_device *fmc;
struct zio_device *zdev, *hwzdev;
......
......@@ -282,33 +282,30 @@ int ft_probe(struct fmc_device *fmc)
ft->ft_carrier_base =
fmc_find_sdb_device(fmc->sdb, 0xce42, 0x603, NULL);
/* fixme: use SDB */
ft->ft_irq_base = ft->ft_core_base + 0x2000;
ft->ft_irq_base =
fmc_find_sdb_device_ext(fmc->sdb, 0xce42, 0x605, fmc->slot_id,
NULL);
/* FIXME/UGLY HACK: enumerate sub-cores via SDB (requires some HDL cleanup:
at least the whole Wishbone interconnect must be clocked before we proceed
with enumeration) */
/* the 0th onewire controller is the carrier one */
ft->ft_owregs_base =
fmc_find_sdb_device_ext(fmc->sdb, 0xce42, 0x602, fmc->slot_id + 1,
NULL);
if (!strcmp(fmc->carrier_name, "SPEC")) {
ft->ft_owregs_base =
fmc_find_sdb_device(fmc->sdb, 0xce42, 0x602, NULL);
ft->ft_dma_base =
fmc_find_sdb_device(fmc->sdb, 0xce42, 0x601, NULL);
ft->ft_dma_base = fmc_find_sdb_device(fmc->sdb, 0xce42, 0x601, NULL);
} else {
ft->ft_owregs_base = ft->ft_core_base + 0x1000;
}
ft->ft_buffer_base =
fmc_find_sdb_device_ext(fmc->sdb, 0xce42, 0x601, fmc->slot_id,
NULL);
if (ft_verbose) {
dev_info(dev,
"Base addrs: core 0x%x, carrier_csr 0x%x, irq 0x%x, 1wire 0x%x\n",
"Base addrs: core 0x%x, carrier_csr 0x%x, irq 0x%x, 1wire 0x%x, buffer/DMA 0x%X\n",
ft->ft_core_base, ft->ft_carrier_base, ft->ft_irq_base,
ft->ft_owregs_base);
ft->ft_owregs_base, ft->ft_buffer_base);
}
spin_lock_init(&ft->lock);
/* Retrieve calibration from the eeprom, and validate */
ret = ft_handle_eeprom_calibration(ft);
if (ret < 0)
......@@ -335,7 +332,7 @@ int ft_probe(struct fmc_device *fmc)
ft->initialized = 1;
return 0;
err:
err:
while (--m, --i >= 0)
if (m->exit)
m->exit(ft);
......
......@@ -23,7 +23,7 @@
#include <linux/zio.h>
#include <linux/zio-trigger.h>
#include <linux/zio-buffer.h>
#include <linux/zio-buffer.h>
#include "fmc-tdc.h"
#include "hw/tdc_regs.h"
......@@ -154,9 +154,8 @@ static inline void process_timestamp(struct fmctdc_dev *ft,
(diff.seconds || diff.coarse > 12
|| (diff.coarse == 12 && diff.frac >= 2048))) {
ft_ts_apply_offset(&ts,
ft->
calib.zero_offset[channel -
1]);
ft->calib.
zero_offset[channel - 1]);
if (st->user_offset)
ft_ts_apply_offset(&ts,
......@@ -187,15 +186,14 @@ static irqreturn_t ft_irq_handler(int irq, void *dev_id)
struct fmc_device *fmc = dev_id;
struct fmctdc_dev *ft = fmc->mezzanine_data;
uint32_t irq_stat;
irq_stat = fmc_readl(ft->fmc, ft->ft_irq_base + TDC_REG_EIC_ISR); /* clear the IRQ */
if( likely (irq_stat & TDC_IRQ_TDC_TSTAMP))
{
tasklet_schedule(&ft->readout_tasklet);
return IRQ_HANDLED;
irq_stat = fmc_readl(ft->fmc, ft->ft_irq_base + TDC_REG_EIC_ISR); /* clear the IRQ */
if (likely(irq_stat & TDC_IRQ_TDC_TSTAMP)) {
tasklet_schedule(&ft->readout_tasklet);
return IRQ_HANDLED;
}
return 0;
}
......@@ -286,14 +284,17 @@ static void ft_readout_tasklet(unsigned long arg)
}
}
out:
out:
/* ack the irq */
fmc_writel(ft->fmc, TDC_IRQ_TDC_TSTAMP, ft->ft_irq_base + TDC_REG_EIC_ISR);
fmc_writel(ft->fmc, TDC_IRQ_TDC_TSTAMP,
ft->ft_irq_base + TDC_REG_EIC_ISR);
fmc->op->irq_ack(fmc);
}
int ft_irq_init(struct fmctdc_dev *ft)
{
int ret;
tasklet_init(&ft->readout_tasklet, ft_readout_tasklet,
(unsigned long)ft);
......@@ -301,16 +302,28 @@ int ft_irq_init(struct fmctdc_dev *ft)
ft_writel(ft, 1, TDC_REG_IRQ_THRESHOLD);
ft_writel(ft, 0, TDC_REG_IRQ_TIMEOUT);
/* enable timestamp readout irq */
fmc_writel(ft->fmc, TDC_IRQ_TDC_TSTAMP, ft->ft_irq_base + TDC_REG_EIC_IER);
/* enable timestamp readout IRQ */
fmc_writel(ft->fmc, TDC_IRQ_TDC_TSTAMP,
ft->ft_irq_base + TDC_REG_EIC_IER);
/* pass the core's base addr as the VIC IRQ vector. */
/* fixme: vector table points to the bridge instead of the core's base address */
ft->fmc->irq = ft->ft_core_base - 0x10000;
ret = ft->fmc->op->irq_request(ft->fmc, ft_irq_handler, "fmc-tdc", 0);
/* configure the actual handler via a carrier-specific mechanism */
return ft->carrier_specific->setup_irqs(ft, ft_irq_handler);
if (ret < 0) {
dev_err(&ft->fmc->dev, "Request interrupt failed: %d\n", ret);
return ret;
}
/* kick off the interrupts (fixme: possible issue with the HDL) */
ft->fmc->op->irq_ack(ft->fmc);
return 0;
}
void ft_irq_exit(struct fmctdc_dev *ft)
{
fmc_writel(ft->fmc, ~0, ft->ft_irq_base + TDC_REG_EIC_IDR);
ft->carrier_specific->disable_irqs(ft);
ft->fmc->op->irq_free(ft->fmc);
}
......@@ -138,54 +138,6 @@ static int ft_spec_copy_timestamps(struct fmctdc_dev *ft, int base_addr,
return ret;
}
/* Unfortunately, on the spec this is GPIO9, i.e. IRQ(1) */
static struct fmc_gpio ft_gpio_on[] = {
{
.gpio = FMC_GPIO_IRQ(1),
.mode = GPIOF_DIR_IN,
.irqmode = IRQF_TRIGGER_RISING,
}
};
static struct fmc_gpio ft_gpio_off[] = {
{
.gpio = FMC_GPIO_IRQ(1),
.mode = GPIOF_DIR_IN,
.irqmode = 0,
}
};
static int ft_spec_setup_irqs(struct fmctdc_dev *ft, irq_handler_t handler)
{
struct fmc_device *fmc = ft->fmc;
int ret;
ret = fmc->op->irq_request(fmc, handler, "fmc-tdc", IRQF_SHARED);
if (ret < 0) {
dev_err(&fmc->dev, "Request interrupt failed: %d\n", ret);
return ret;
}
fmc->op->gpio_config(fmc, ft_gpio_on, ARRAY_SIZE(ft_gpio_on));
return 0;
}
static int ft_spec_disable_irqs(struct fmctdc_dev *ft)
{
struct fmc_device *fmc = ft->fmc;
fmc->op->gpio_config(fmc, ft_gpio_off, ARRAY_SIZE(ft_gpio_off));
fmc->op->irq_free(fmc);
return 0;
}
static int ft_spec_ack_irq(struct fmctdc_dev *ft, int irq_id)
{
return 0;
}
static void ft_spec_exit(struct fmctdc_dev *ft)
{
kfree(ft->carrier_data);
......@@ -196,8 +148,5 @@ struct ft_carrier_specific ft_carrier_spec = {
ft_spec_init,
ft_spec_reset,
ft_spec_copy_timestamps,
ft_spec_setup_irqs,
ft_spec_disable_irqs,
ft_spec_ack_irq,
ft_spec_exit,
};
......@@ -77,7 +77,7 @@ static int ft_svec_copy_timestamps(struct fmctdc_dev *ft, int base_addr,
return -EIO;
/* FIXME: use SDB to determine buffer base address (after fixing the HDL) */
addr = ft->ft_core_base + 0x4000 + base_addr;
addr = ft->ft_buffer_base + base_addr;
for (i = 0, dptr = (uint32_t *) dst; i < size / 4; i++, dptr++)
*dptr = fmc_readl(ft->fmc, addr + i * 4);
......@@ -85,36 +85,6 @@ static int ft_svec_copy_timestamps(struct fmctdc_dev *ft, int base_addr,
return 0;
}
static int ft_svec_setup_irqs(struct fmctdc_dev *ft, irq_handler_t handler)
{
int ret;
/* pass the core's base addr as the VIC IRQ vector. */
/* fixme: vector table points to the bridge instead of the core's base address */
ft->fmc->irq = ft->ft_core_base - 0x10000;
ret = ft->fmc->op->irq_request(ft->fmc, handler, "fmc-tdc", 0);
if (ret < 0) {
dev_err(&ft->fmc->dev, "Request interrupt failed: %d\n", ret);
return ret;
}
return 0;
}
static int ft_svec_disable_irqs(struct fmctdc_dev *ft)
{
return ft->fmc->op->irq_free(ft->fmc);
}
static int ft_svec_ack_irq(struct fmctdc_dev *ft, int irq_id)
{
ft->fmc->op->irq_ack(ft->fmc);
return 0;
}
static void ft_svec_exit(struct fmctdc_dev *ft)
{
}
......@@ -124,8 +94,5 @@ struct ft_carrier_specific ft_carrier_svec = {
ft_svec_init,
ft_svec_reset,
ft_svec_copy_timestamps,
ft_svec_setup_irqs,
ft_svec_disable_irqs,
ft_svec_ack_irq,
ft_svec_exit
};
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