Commit f99f8986 authored by Tristan Gingold's avatar Tristan Gingold

fw/adc: renaming.

parent 2a853764
......@@ -126,3 +126,4 @@ static int OUT_QUEUE_NAME(out_queue_check_timeout) (struct OUT_QUEUE_STRUCT *q)
#undef OUT_QUEUE_STRUCT
#undef OUT_QUEUE_NAME
#undef OUT_QUEUE_CONCAT
#undef OUT_QUEUE_CONCAT2
/*
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <errno.h>
#include <string.h>
/* ADCIN: trigger coming from the ADC mezzanine. */
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigin.h"
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcin_
#define OUT_QUEUE_SIZE 4
#include "out_queue.h"
#define ADCIN_NUM_CHANNELS 5
struct wrtd_adcin_dev {
uint32_t io_addr;
int idle;
struct adcin_out_queue queue;
/* FIXME: base channel (to create the event id). */
};
static inline int adcin_wr_present(struct wrtd_adcin_dev *fd)
static inline void adcin_writel(const struct wrtd_adcin_dev *dev,
uint32_t value, uint32_t reg)
{
return 1;
dp_writel(value, dev->io_addr + reg);
}
static inline int adcin_wr_link_up(struct wrtd_adcin_dev *fd)
static inline uint32_t adcin_readl(const struct wrtd_adcin_dev *dev, uint32_t reg)
{
return 1;
return dp_readl(dev->io_addr + reg);
}
static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *fd)
static int adcin_init(struct wrtd_adcin_dev *adcin)
{
return 1;
}
pr_debug("%s: Adcin initialization complete\n\r", __func__);
static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *fd)
{
return 1;
}
/* Disable all channels. */
adcin_writel(adcin, 0, ALT_TRIGOUT_CTRL);
static inline int adcin_wr_sync_timeout(void)
{
return 0;
}
static void adcin_wr_enable_lock(struct wrtd_adcin_dev *fd, int enable)
{
return;
}
static inline void adcin_writel(struct wrtd_adcin_dev *dev, uint32_t value,
uint32_t reg)
static inline int adcin_wr_link_up(struct wrtd_adcin_dev *adcin)
{
dp_writel(value, dev->io_addr + reg);
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_LINK;
}
static inline uint32_t adcin_readl (struct wrtd_adcin_dev *dev, uint32_t reg)
static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *adcin)
{
return dp_readl(dev->io_addr + reg);
return 1;
}
/**
* Drop the given enqueued trigger
*/
static void adcin_drop_trigger(struct wrtd_adcin_dev *dev,
struct wrtd_event *ev, unsigned reason)
static void adcin_wr_enable_lock(struct wrtd_adcin_dev *dev, int enable)
{
struct adcin_out_queue *q = &dev->queue;
dev->idle = 1;
if (adcin_out_queue_empty(q))
return;
/* Drop the pulse */
adcin_out_queue_pop(q);
/* Disarm the FD output */
adcin_writel(dev, 0, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, ev, NULL);
return;
}
/**
* Output driving function. Reads pulses from the output queue,
* programs the output and updates the output statistics.
*/
static void adcin_output (struct wrtd_adcin_dev *dev)
static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *adcin)
{
struct adcin_out_queue *q = &dev->queue;
struct wrtd_event *ev = adcin_out_queue_front(q);
uint32_t ctrl = adcin_readl(dev, ALT_TRIGIN_CTRL);
struct wrtd_tstamp *ts;
/* Check if the output has triggered */
if (!dev->idle) {
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if (ctrl & ALT_TRIGIN_CTRL_ENABLE) {
/* Armed but still waiting for trigger */
if (adcin_out_queue_check_timeout (q)) {
/* Will never trigger. Missed. */
adcin_drop_trigger(dev, ev, WRTD_LOG_DISCARD_TIMEOUT);
}
} else {
/* Has been triggered. */
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_DONE, ev, NULL);
adcin_out_queue_pop(q);
dev->idle = 1;
}
return;
}
/* Output is idle: check if there's something in the queue to execute */
if (adcin_out_queue_empty(q))
return;
ev = adcin_out_queue_front(q);
ts = &ev->ts;
if (!wr_is_timing_ok()) {
adcin_drop_trigger(dev, ev, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
/* Program the output start time */
adcin_writel(dev, ts->seconds, ALT_TRIGIN_SECONDS + 0);
adcin_writel(dev, ts->ns / 8, ALT_TRIGIN_CYCLES);
adcin_writel(dev, ALT_TRIGIN_CTRL_ENABLE, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START, ev, NULL);
ts_add2_ns (ts, 8000);
/*
* Store the last programmed timestamp (+ some margin) and mark
* the output as busy
*/
q->last_programmed_sec = ts->seconds;
q->last_programmed_ns = ts->ns;
dev->idle = 0;
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_VALID;
}
static void adcin_local_output(struct wrtd_adcin_dev *dev,
struct wrtd_event *ev, unsigned ch)
static inline int adcin_wr_sync_timeout(void)
{
struct wrtd_event *pq_ev;
pq_ev = adcin_out_queue_push(&dev->queue);
if (!pq_ev) {
/* overflow.
FIXME: stats ? */
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, WRTD_LOG_DISCARD_OVERFLOW,
ev, NULL);
return;
}
*pq_ev = *ev;
return 0;
}
#if 0
/**
* It disable the given channel and clear its internal queue
* Handles input timestamps from all TDC channels.
*
* TODO: tdc config: base address
* first channel number (for sid)
* time offset
*/
static int wrtd_out_disable(struct trtl_fw_msg *msg_i,
struct trtl_fw_msg *msg_o)
{
uint32_t ch = ((uint32_t *)msg_i->payload)[0];
pulse_queue_init(&wrtd_out_channels[ch].queue);
fd_ch_writel(&wrtd_out_channels[ch], FD_DCR_MODE, FD_REG_DCR);
msg_o->header->msg_id = msg_i->header->msg_id;
return 0;
}
#endif
static void adcin_data_init(struct wrtd_adcin_dev *dev)
static void adcin_input(struct wrtd_adcin_dev *adcin)
{
adcin_out_queue_init(&dev->queue);
dev->idle = 1;
uint32_t status = adcin_readl(adcin, ALT_TRIGOUT_STATUS);
uint32_t mask;
struct wrtd_event ev;
int i;
/* Poll the FIFO and read the timestamp */
if(!(status & ALT_TRIGOUT_TS_PRESENT))
return;
/* FIXME: MSB word ? */
ev.ts.seconds = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 0);
mask = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 4);
ev.ts.ns = adcin_readl(adcin, ALT_TRIGOUT_TS_CYCLES) * 8;
ev.ts.frac = 0;
for (i = 0; i < ADCIN_NUM_CHANNELS; i++) {
if (!(mask & ((ALT_TRIGOUT_CH1_MASK >> 32) << i)))
continue;
memset(ev.id, 0, WRTD_ID_LEN);
ev.id[0] = 'A';
ev.id[1] = 'D';
ev.id[2] = 'C';
ev.id[3] = 'I';
ev.id[4] = '1' + i;
ev.flags = 0;
wrtd_log(WRTD_LOG_MSG_EV_GENERATED,
WRTD_LOG_GENERATED_DEVICE + i, &ev, NULL);
/* Pass to wrtd. */
wrtd_route_in(&ev);
}
}
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
/* ADCout: trigger ADC sampling. Output from the WRTD pov. */
#include <errno.h>
#include <string.h>
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigin.h"
#define ADCOUT_NUM_CHANNELS 5
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcout_
#define OUT_QUEUE_SIZE 4
#include "out_queue.h"
struct wrtd_adcout_dev {
uint32_t io_addr;
/* FIXME: base channel (to create the event id). */
int idle;
struct adcout_out_queue queue;
};
static inline void adcout_writel(const struct wrtd_adcout_dev *dev,
uint32_t value, uint32_t reg)
static inline int adcout_wr_present(struct wrtd_adcout_dev *fd)
{
dp_writel(value, dev->io_addr + reg);
return 1;
}
static inline uint32_t adcout_readl(const struct wrtd_adcout_dev *dev, uint32_t reg)
static inline int adcout_wr_link_up(struct wrtd_adcout_dev *fd)
{
return dp_readl(dev->io_addr + reg);
return 1;
}
static int adcout_init(struct wrtd_adcout_dev *adcout)
static inline int adcout_wr_time_locked(struct wrtd_adcout_dev *fd)
{
pr_debug("%s: ADCout initialization complete\n\r", __func__);
return 1;
}
/* Disable all channels. */
adcout_writel(adcout, 0, ALT_TRIGOUT_CTRL);
static inline int adcout_wr_time_ready(struct wrtd_adcout_dev *fd)
{
return 1;
}
static inline int adcout_wr_sync_timeout(void)
{
return 0;
}
static inline int adcout_wr_link_up(struct wrtd_adcout_dev *adcout)
static void adcout_wr_enable_lock(struct wrtd_adcout_dev *fd, int enable)
{
return adcout_readl(adcout, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_LINK;
return;
}
static inline int adcout_wr_time_locked(struct wrtd_adcout_dev *adcout)
static inline void adcout_writel(struct wrtd_adcout_dev *dev, uint32_t value,
uint32_t reg)
{
return 1;
dp_writel(value, dev->io_addr + reg);
}
static void adcout_wr_enable_lock(struct wrtd_adcout_dev *dev, int enable)
static inline uint32_t adcout_readl (struct wrtd_adcout_dev *dev, uint32_t reg)
{
return;
return dp_readl(dev->io_addr + reg);
}
/**
* Drop the given enqueued trigger
*/
static void adcout_drop_trigger(struct wrtd_adcout_dev *dev,
struct wrtd_event *ev, unsigned reason)
{
struct adcout_out_queue *q = &dev->queue;
dev->idle = 1;
if (adcout_out_queue_empty(q))
return;
/* Drop the pulse */
adcout_out_queue_pop(q);
/* Disarm the FD output */
adcout_writel(dev, 0, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, ev, NULL);
}
static inline int adcout_wr_time_ready(struct wrtd_adcout_dev *adcout)
/**
* Output driving function. Reads pulses from the output queue,
* programs the output and updates the output statistics.
*/
static void adcout_output (struct wrtd_adcout_dev *dev)
{
return adcout_readl(adcout, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_VALID;
struct adcout_out_queue *q = &dev->queue;
struct wrtd_event *ev = adcout_out_queue_front(q);
uint32_t ctrl = adcout_readl(dev, ALT_TRIGIN_CTRL);
struct wrtd_tstamp *ts;
/* Check if the output has triggered */
if (!dev->idle) {
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if (ctrl & ALT_TRIGIN_CTRL_ENABLE) {
/* Armed but still waiting for trigger */
if (adcout_out_queue_check_timeout (q)) {
/* Will never trigger. Missed. */
adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_TIMEOUT);
}
} else {
/* Has been triggered. */
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_DONE, ev, NULL);
adcout_out_queue_pop(q);
dev->idle = 1;
}
return;
}
/* Output is idle: check if there's something in the queue to execute */
if (adcout_out_queue_empty(q))
return;
ev = adcout_out_queue_front(q);
ts = &ev->ts;
if (!wr_is_timing_ok()) {
adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
/* Program the output start time */
adcout_writel(dev, ts->seconds, ALT_TRIGIN_SECONDS + 0);
adcout_writel(dev, ts->ns / 8, ALT_TRIGIN_CYCLES);
adcout_writel(dev, ALT_TRIGIN_CTRL_ENABLE, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START, ev, NULL);
ts_add2_ns (ts, 8000);
/*
* Store the last programmed timestamp (+ some margin) and mark
* the output as busy
*/
q->last_programmed_sec = ts->seconds;
q->last_programmed_ns = ts->ns;
dev->idle = 0;
}
static inline int adcout_wr_sync_timeout(void)
static void adcout_local_output(struct wrtd_adcout_dev *dev,
struct wrtd_event *ev, unsigned ch)
{
return 0;
struct wrtd_event *pq_ev;
pq_ev = adcout_out_queue_push(&dev->queue);
if (!pq_ev) {
/* overflow.
FIXME: stats ? */
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, WRTD_LOG_DISCARD_OVERFLOW,
ev, NULL);
return;
}
*pq_ev = *ev;
}
#if 0
/**
* Handles input timestamps from all TDC channels.
*
* TODO: tdc config: base address
* first channel number (for sid)
* time offset
* It disable the given channel and clear its internal queue
*/
static void adcout_input(struct wrtd_adcout_dev *adcout)
static int wrtd_out_disable(struct trtl_fw_msg *msg_i,
struct trtl_fw_msg *msg_o)
{
uint32_t status = adcout_readl(adcout, ALT_TRIGOUT_STATUS);
uint32_t mask;
struct wrtd_event ev;
int i;
/* Poll the FIFO and read the timestamp */
if(!(status & ALT_TRIGOUT_TS_PRESENT))
return;
/* FIXME: MSB word ? */
ev.ts.seconds = adcout_readl(adcout, ALT_TRIGOUT_TS_MASK_SEC + 0);
mask = adcout_readl(adcout, ALT_TRIGOUT_TS_MASK_SEC + 4);
ev.ts.ns = adcout_readl(adcout, ALT_TRIGOUT_TS_CYCLES) * 8;
ev.ts.frac = 0;
for (i = 0; i < ADCOUT_NUM_CHANNELS; i++) {
if (!(mask & ((ALT_TRIGOUT_CH1_MASK >> 32) << i)))
continue;
memset(ev.id, 0, WRTD_ID_LEN);
ev.id[0] = 'A';
ev.id[1] = 'D';
ev.id[2] = 'C';
ev.id[3] = 'O';
ev.id[4] = '1' + i;
ev.flags = 0;
wrtd_log(WRTD_LOG_MSG_EV_GENERATED,
WRTD_LOG_GENERATED_DEVICE + i, &ev, NULL);
/* Pass to wrtd. */
wrtd_route_in(&ev);
}
uint32_t ch = ((uint32_t *)msg_i->payload)[0];
pulse_queue_init(&wrtd_out_channels[ch].queue);
fd_ch_writel(&wrtd_out_channels[ch], FD_DCR_MODE, FD_REG_DCR);
msg_o->header->msg_id = msg_i->header->msg_id;
return 0;
}
#endif
static void adcout_init(struct wrtd_adcout_dev *dev)
{
adcout_out_queue_init(&dev->queue);
dev->idle = 1;
}
......@@ -202,7 +202,7 @@ struct wrtd_io_msg {
#define WRTD_APP_TDC_5CH 0x35D0
#define WRTD_APP_FD_4CH 0x35E0
#define WRTD_APP_ADCIN_5CH 0x35B0
#define WRTD_APP_ADCIO_5CH 0x35B0
enum wrtd_trtl_actions {
/* Always the first one, to get root and version. */
......
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