Commit 1394f372 authored by Dimitris Lampridis's avatar Dimitris Lampridis Committed by Dimitris Lampridis

sw: wip cleanup and comments

parent 1f2cd1f6
...@@ -44,3 +44,16 @@ else ...@@ -44,3 +44,16 @@ else
GIT_VERSION=$(GIT_VERSION) EXCLUDE_FILES=$(EXCLUDE_FILES) BRIEF=$(BRIEF) \ GIT_VERSION=$(GIT_VERSION) EXCLUDE_FILES=$(EXCLUDE_FILES) BRIEF=$(BRIEF) \
OUTPUT=$(DOXY_OUT) doxygen ./doxygen-wrtd-config OUTPUT=$(DOXY_OUT) doxygen ./doxygen-wrtd-config
endif endif
# List of Doxygen folders to consider
DOXINPUT := ../software/lib
DOXINPUT += ../software/include
DOXINPUT += ../software/firmware/common
DOXEXCL := ""
# List of actual Doxygen source files
DOXSRC = $(shell find $(DOXINPUT) -type f -name '*.[chS]')
.doxystamp: $(DOXSRC)
GIT_VERSION=$(GIT_VERSION) DOXINPUT="$(DOXINPUT)" DOXEXCL="$(DOXEXCL)" doxygen ./doxygen-wrtd-config
@touch .doxystamp
Dictionary
==========
The main purpose of this dictionary is to explain the
White-Rabbit Trigger-Distribution terminology.
channel
dead time
delay
input
output
pulse
trigger
trigger condition
\ No newline at end of file
Introduction
============
`Hello` *there* [link](https://ohwr.org)
- item 1
- item 2
[dictionary](dictionary.md)
-include Makefile.specific -include Makefile.specific
DIRS := tdc fd adc DIRS := tdc fd adc
all clean cleanall modules install modules_install: $(DIRS) all clean cleanall modules install modules_install: $(DIRS)
clean: TARGET = clean clean: TARGET = clean
......
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# fmc-svec-carrier fw-01 demo configuration
# #
# #
......
/* /**
* Copyright (C) 2018 CERN (www.cern.ch) * @file wrtd-adcin.c
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch> *
* ADCIN: trigger coming from the ADC mezzanine.
*
* Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
/* ADCIN: trigger coming from the ADC mezzanine. */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
#define ADCIN_NUM_CHANNELS 5 #define ADCIN_NUM_CHANNELS 5
...@@ -17,39 +18,39 @@ struct wrtd_adcin_dev { ...@@ -17,39 +18,39 @@ struct wrtd_adcin_dev {
}; };
static inline void adcin_writel(const struct wrtd_adcin_dev *dev, static inline void adcin_writel(const struct wrtd_adcin_dev *dev,
uint32_t value, uint32_t reg) uint32_t value, uint32_t reg)
{ {
dp_writel(value, dev->io_addr + reg); dp_writel(value, dev->io_addr + reg);
} }
static inline uint32_t adcin_readl(const struct wrtd_adcin_dev *dev, uint32_t reg) static inline uint32_t adcin_readl(const struct wrtd_adcin_dev *dev, uint32_t reg)
{ {
return dp_readl(dev->io_addr + reg); return dp_readl(dev->io_addr + reg);
} }
static inline int adcin_wr_link_up(struct wrtd_adcin_dev *adcin) static inline int adcin_wr_link_up(struct wrtd_adcin_dev *adcin)
{ {
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_LINK; return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_LINK;
} }
static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *adcin) static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *adcin)
{ {
return 1; return 1;
} }
static void adcin_wr_enable_lock(struct wrtd_adcin_dev *dev, int enable) static void adcin_wr_enable_lock(struct wrtd_adcin_dev *dev, int enable)
{ {
return; return;
} }
static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *adcin) static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *adcin)
{ {
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_VALID; return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_VALID;
} }
static inline int adcin_wr_sync_timeout(void) static inline int adcin_wr_sync_timeout(void)
{ {
return 0; return 0;
} }
/** /**
...@@ -68,7 +69,7 @@ static void adcin_input(struct wrtd_adcin_dev *adcin) ...@@ -68,7 +69,7 @@ static void adcin_input(struct wrtd_adcin_dev *adcin)
/* Poll the FIFO and read the timestamp */ /* Poll the FIFO and read the timestamp */
if(!(status & ALT_TRIGOUT_TS_PRESENT)) if(!(status & ALT_TRIGOUT_TS_PRESENT))
return; return;
mask = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 0); mask = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 0);
ev.ts.seconds = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 4); ev.ts.seconds = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 4);
...@@ -77,13 +78,13 @@ static void adcin_input(struct wrtd_adcin_dev *adcin) ...@@ -77,13 +78,13 @@ static void adcin_input(struct wrtd_adcin_dev *adcin)
for (i = 0; i < ADCIN_NUM_CHANNELS; i++) { for (i = 0; i < ADCIN_NUM_CHANNELS; i++) {
/* The last channel is the ext trigger with a different mask */ /* The last channel is the ext trigger with a different mask */
if ( i == ADCIN_NUM_CHANNELS - 1 ) { if ( i == ADCIN_NUM_CHANNELS - 1 ) {
if (!(mask & (ALT_TRIGOUT_EXT_MASK >> 32))) if (!(mask & (ALT_TRIGOUT_EXT_MASK >> 32)))
continue; continue;
} }
else if (!(mask & ((ALT_TRIGOUT_CH1_MASK >> 32) << i))) else if (!(mask & ((ALT_TRIGOUT_CH1_MASK >> 32) << i)))
continue; continue;
memset(ev.id, 0, WRTD_ID_LEN); memset(ev.id, 0, WRTD_ID_LEN);
ev.id[0] = 'L'; ev.id[0] = 'L';
...@@ -104,7 +105,7 @@ static void adcin_input(struct wrtd_adcin_dev *adcin) ...@@ -104,7 +105,7 @@ static void adcin_input(struct wrtd_adcin_dev *adcin)
static int adcin_init(struct wrtd_adcin_dev *adcin) static int adcin_init(struct wrtd_adcin_dev *adcin)
{ {
pr_debug("adcin initialization complete\n\r"); pr_debug("adcin initialization complete\n\r");
return 0; return 0;
} }
/* /**
* Copyright (C) 2013-2018 CERN (www.cern.ch) * @file wrtd-adcin.c
* Author: Federico Vaga <federico.vaga@cern.ch> *
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * ADCout: trigger ADC sampling. Output from the WRTD pov.
*
* Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
/* ADCout: trigger ADC sampling. Output from the WRTD pov. */
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
...@@ -30,44 +30,44 @@ struct wrtd_adcout_dev { ...@@ -30,44 +30,44 @@ struct wrtd_adcout_dev {
static inline int adcout_wr_present(struct wrtd_adcout_dev *fd) static inline int adcout_wr_present(struct wrtd_adcout_dev *fd)
{ {
return 1; return 1;
} }
static inline int adcout_wr_link_up(struct wrtd_adcout_dev *fd) static inline int adcout_wr_link_up(struct wrtd_adcout_dev *fd)
{ {
return 1; return 1;
} }
static inline int adcout_wr_time_locked(struct wrtd_adcout_dev *fd) static inline int adcout_wr_time_locked(struct wrtd_adcout_dev *fd)
{ {
return 1; return 1;
} }
static inline int adcout_wr_time_ready(struct wrtd_adcout_dev *fd) static inline int adcout_wr_time_ready(struct wrtd_adcout_dev *fd)
{ {
return 1; return 1;
} }
static inline int adcout_wr_sync_timeout(void) static inline int adcout_wr_sync_timeout(void)
{ {
return 0; return 0;
} }
static void adcout_wr_enable_lock(struct wrtd_adcout_dev *fd, int enable) static void adcout_wr_enable_lock(struct wrtd_adcout_dev *fd, int enable)
{ {
return; return;
} }
static inline void adcout_writel(struct wrtd_adcout_dev *dev, uint32_t value, static inline void adcout_writel(struct wrtd_adcout_dev *dev, uint32_t value,
uint32_t reg) uint32_t reg)
{ {
dp_writel(value, dev->io_addr + reg); dp_writel(value, dev->io_addr + reg);
} }
static inline uint32_t adcout_readl (struct wrtd_adcout_dev *dev, uint32_t reg) static inline uint32_t adcout_readl (struct wrtd_adcout_dev *dev, uint32_t reg)
{ {
return dp_readl(dev->io_addr + reg); return dp_readl(dev->io_addr + reg);
} }
...@@ -76,24 +76,24 @@ static inline uint32_t adcout_readl (struct wrtd_adcout_dev *dev, uint32_t reg) ...@@ -76,24 +76,24 @@ static inline uint32_t adcout_readl (struct wrtd_adcout_dev *dev, uint32_t reg)
* Drop the given enqueued trigger * Drop the given enqueued trigger
*/ */
static void adcout_drop_trigger(struct wrtd_adcout_dev *dev, static void adcout_drop_trigger(struct wrtd_adcout_dev *dev,
struct wrtd_event *ev, unsigned reason, struct wrtd_event *ev, unsigned reason,
struct wrtd_tstamp *now) struct wrtd_tstamp *now)
{ {
struct adcout_out_queue *q = &dev->queue; struct adcout_out_queue *q = &dev->queue;
dev->idle = 1; dev->idle = 1;
if (adcout_out_queue_empty(q)) { if (adcout_out_queue_empty(q)) {
/* Should never happen. */ /* Should never happen. */
return; return;
} }
/* Drop the pulse */ /* Drop the pulse */
adcout_out_queue_pop(q); adcout_out_queue_pop(q);
/* Disarm the ADC output */ /* Disarm the ADC output */
adcout_writel(dev, 0, ALT_TRIGIN_CTRL); adcout_writel(dev, 0, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, NULL, ev, now); wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, NULL, ev, now);
} }
...@@ -103,91 +103,91 @@ static void adcout_drop_trigger(struct wrtd_adcout_dev *dev, ...@@ -103,91 +103,91 @@ static void adcout_drop_trigger(struct wrtd_adcout_dev *dev,
*/ */
static void adcout_output (struct wrtd_adcout_dev *dev) static void adcout_output (struct wrtd_adcout_dev *dev)
{ {
struct adcout_out_queue *q = &dev->queue; struct adcout_out_queue *q = &dev->queue;
struct wrtd_event *ev = adcout_out_queue_front(q); struct wrtd_event *ev = adcout_out_queue_front(q);
uint32_t ctrl = adcout_readl(dev, ALT_TRIGIN_CTRL); uint32_t ctrl = adcout_readl(dev, ALT_TRIGIN_CTRL);
struct wrtd_tstamp *ts; struct wrtd_tstamp *ts;
/* Check if the output has triggered */ /* Check if the output has triggered */
if (!dev->idle) { if (!dev->idle) {
#if 0 #if 0
if (!wr_is_timing_ok()) { if (!wr_is_timing_ok()) {
/* Timing has been lost. */ /* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC); drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return; return;
} }
#endif #endif
if (ctrl & ALT_TRIGIN_CTRL_ENABLE) { if (ctrl & ALT_TRIGIN_CTRL_ENABLE) {
/* Armed but still waiting for trigger */ /* Armed but still waiting for trigger */
struct wrtd_tstamp now; struct wrtd_tstamp now;
ts_now(&now); ts_now(&now);
if (adcout_out_queue_check_timeout (q, &now)) { if (adcout_out_queue_check_timeout (q, &now)) {
/* Will never trigger. Missed. */ /* Will never trigger. Missed. */
adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_TIMEOUT, &now); adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_TIMEOUT, &now);
} }
} else { } else {
/* Has been triggered. */ /* Has been triggered. */
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, wrtd_log(WRTD_LOG_MSG_EV_CONSUMED,
WRTD_LOG_CONSUMED_DONE, WRTD_LOG_CONSUMED_DONE,
NULL, ev, NULL); NULL, ev, NULL);
adcout_out_queue_pop(q); adcout_out_queue_pop(q);
dev->idle = 1; dev->idle = 1;
} }
return; return;
} }
/* Output is idle: check if there's something in the queue to execute */ /* Output is idle: check if there's something in the queue to execute */
if (adcout_out_queue_empty(q)) if (adcout_out_queue_empty(q))
return; return;
ev = adcout_out_queue_front(q); ev = adcout_out_queue_front(q);
ts = &ev->ts; ts = &ev->ts;
if (!wr_is_timing_ok()) { if (!wr_is_timing_ok()) {
adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_NO_SYNC, NULL); adcout_drop_trigger(dev, ev, WRTD_LOG_DISCARD_NO_SYNC, NULL);
return; return;
} }
/* Program the output start time */ /* Program the output start time */
adcout_writel(dev, 0, ALT_TRIGIN_SECONDS + 0); adcout_writel(dev, 0, ALT_TRIGIN_SECONDS + 0);
adcout_writel(dev, ts->seconds, ALT_TRIGIN_SECONDS + 4); adcout_writel(dev, ts->seconds, ALT_TRIGIN_SECONDS + 4);
adcout_writel(dev, ts->ns / 8, ALT_TRIGIN_CYCLES); adcout_writel(dev, ts->ns / 8, ALT_TRIGIN_CYCLES);
adcout_writel(dev, ALT_TRIGIN_CTRL_ENABLE, ALT_TRIGIN_CTRL); adcout_writel(dev, ALT_TRIGIN_CTRL_ENABLE, ALT_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START, wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START,
NULL, ev, NULL); NULL, ev, NULL);
ts_add2_ns (ts, 8000); ts_add2_ns (ts, 8000);
/* /*
* Store the last programmed timestamp (+ some margin) and mark * Store the last programmed timestamp (+ some margin) and mark
* the output as busy * the output as busy
*/ */
q->last_programmed_sec = ts->seconds; q->last_programmed_sec = ts->seconds;
q->last_programmed_ns = ts->ns; q->last_programmed_ns = ts->ns;
dev->idle = 0; dev->idle = 0;
} }
static int adcout_local_output(struct wrtd_adcout_dev *dev, static int adcout_local_output(struct wrtd_adcout_dev *dev,
struct wrtd_event *ev, unsigned ch) struct wrtd_event *ev, unsigned ch)
{ {
struct wrtd_event *pq_ev; struct wrtd_event *pq_ev;
pq_ev = adcout_out_queue_push(&dev->queue); pq_ev = adcout_out_queue_push(&dev->queue);
if (!pq_ev) { if (!pq_ev) {
return -EOVERFLOW; return -EOVERFLOW;
} }
*pq_ev = *ev; *pq_ev = *ev;
return 0; return 0;
} }
static void adcout_init(struct wrtd_adcout_dev *dev) static void adcout_init(struct wrtd_adcout_dev *dev)
{ {
adcout_out_queue_init(&dev->queue); adcout_out_queue_init(&dev->queue);
dev->idle = 1; dev->idle = 1;
pr_debug("adcout initialization complete\n\r"); pr_debug("adcout initialization complete\n\r");
} }
/* /**
* Copyright (C) 2013-2018 CERN (www.cern.ch) * @file wrtd-rt-adc.c
* Author: Federico Vaga <federico.vaga@cern.ch> *
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
#include "wrtd-common.h" #include "wrtd-common.h"
...@@ -44,35 +43,35 @@ static struct wrtd_adcout_dev adcout0 = ...@@ -44,35 +43,35 @@ static struct wrtd_adcout_dev adcout0 =
static inline int wr_link_up(void) static inline int wr_link_up(void)
{ {
if (!adcin_wr_link_up(&adcin0)) if (!adcin_wr_link_up(&adcin0))
return 0; return 0;
if (!adcout_wr_link_up(&adcout0)) if (!adcout_wr_link_up(&adcout0))
return 0; return 0;
return 1; return 1;
} }
static inline int wr_time_locked(void) static inline int wr_time_locked(void)
{ {
if (!adcin_wr_time_locked(&adcin0)) if (!adcin_wr_time_locked(&adcin0))
return 0; return 0;
if (!adcout_wr_time_locked(&adcout0)) if (!adcout_wr_time_locked(&adcout0))
return 0; return 0;
return 1; return 1;
} }
static inline int wr_time_ready(void) static inline int wr_time_ready(void)
{ {
if (!adcin_wr_time_ready(&adcin0)) if (!adcin_wr_time_ready(&adcin0))
return 0; return 0;
if (!adcout_wr_time_ready(&adcout0)) if (!adcout_wr_time_ready(&adcout0))
return 0; return 0;
return 1; return 1;
} }
static inline void wr_enable_lock(int enable) static inline void wr_enable_lock(int enable)
{ {
adcin_wr_enable_lock(&adcin0, enable); adcin_wr_enable_lock(&adcin0, enable);
adcout_wr_enable_lock(&adcout0, enable); adcout_wr_enable_lock(&adcout0, enable);
} }
static inline int wr_sync_timeout(void) static inline int wr_sync_timeout(void)
...@@ -80,14 +79,14 @@ static inline int wr_sync_timeout(void) ...@@ -80,14 +79,14 @@ static inline int wr_sync_timeout(void)
#ifdef SIMULATION #ifdef SIMULATION
return 0; return 0;
#else #else
int res, val; int res, val;
res = 0; res = 0;
val = adcin_wr_sync_timeout(); val = adcin_wr_sync_timeout();
res = val > res ? val : res; res = val > res ? val : res;
val = adcout_wr_sync_timeout(); val = adcout_wr_sync_timeout();
res = val > res ? val : res; res = val > res ? val : res;
return res; return res;
#endif #endif
} }
...@@ -99,18 +98,18 @@ static int wrtd_local_output(struct wrtd_event *ev, unsigned ch) ...@@ -99,18 +98,18 @@ static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
static int wrtd_user_init(void) static int wrtd_user_init(void)
{ {
adcin_init(&adcin0); adcin_init(&adcin0);
adcout_init(&adcout0); adcout_init(&adcout0);
wr_enable_lock(0); wr_enable_lock(0);
pr_debug("rt-adc firmware initialized.\n\r"); pr_debug("rt-adc firmware initialized.\n\r");
return 0; return 0;
} }
static void wrtd_io(void) static void wrtd_io(void)
{ {
adcin_input(&adcin0); adcin_input(&adcin0);
adcout_output(&adcout0); adcout_output(&adcout0);
} }
/* /**
* acam_gpx.h * @file acam_gpx.h
* *
* Copyright (c) 2012-2013 CERN (http://www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software; you can redistribute it and/or modify it * Copyright (c) 2012-2019 CERN (home.cern)
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation; version 2 of the License. * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#ifndef __ACAM_GPX_H #ifndef __ACAM_GPX_H
...@@ -102,4 +101,3 @@ ...@@ -102,4 +101,3 @@
#define AR12_StartNU (1<<26) #define AR12_StartNU (1<<26)
#endif #endif
/* Generic output queue. /**
User needs to define: * @file out_queue.h
OUT_QUEUE_PREFIX: the prefix (ends with an '_') *
OUT_QUEUE_SIZE: max length of the queue * Generic output queue. Users need to define:
OUT_QUEUE_MAXTIME: maximum time in advance. * - `OUT_QUEUE_PREFIX` : the prefix (must end with an '_')
*/ * - `OUT_QUEUE_SIZE` : max length of the queue
* - `OUT_QUEUE_MAXTIME`: maximum time in advance.
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef OUT_QUEUE_PREFIX #ifndef OUT_QUEUE_PREFIX
#error "OUT_QUEUE_PREFIX not defined" #error "OUT_QUEUE_PREFIX not defined"
...@@ -15,12 +21,12 @@ ...@@ -15,12 +21,12 @@
#define OUT_QUEUE_STRUCT OUT_QUEUE_NAME(out_queue) #define OUT_QUEUE_STRUCT OUT_QUEUE_NAME(out_queue)
struct OUT_QUEUE_STRUCT { struct OUT_QUEUE_STRUCT {
struct wrtd_event events[OUT_QUEUE_SIZE]; struct wrtd_event events[OUT_QUEUE_SIZE];
int head, tail, count; int head, tail, count;
/* Last timestamp value written to output config. */ /* Last timestamp value written to output config. */
uint32_t last_programmed_sec; uint32_t last_programmed_sec;
uint32_t last_programmed_ns; uint32_t last_programmed_ns;
}; };
/** /**
...@@ -28,12 +34,12 @@ struct OUT_QUEUE_STRUCT { ...@@ -28,12 +34,12 @@ struct OUT_QUEUE_STRUCT {
*/ */
static void OUT_QUEUE_NAME(out_queue_init)(struct OUT_QUEUE_STRUCT *p) static void OUT_QUEUE_NAME(out_queue_init)(struct OUT_QUEUE_STRUCT *p)
{ {
p->head = 0; p->head = 0;
p->tail = 0; p->tail = 0;
p->count = 0; p->count = 0;
p->last_programmed_sec = 0; p->last_programmed_sec = 0;
p->last_programmed_ns = 0; p->last_programmed_ns = 0;
} }
...@@ -43,19 +49,19 @@ static void OUT_QUEUE_NAME(out_queue_init)(struct OUT_QUEUE_STRUCT *p) ...@@ -43,19 +49,19 @@ static void OUT_QUEUE_NAME(out_queue_init)(struct OUT_QUEUE_STRUCT *p)
*/ */
static struct wrtd_event *OUT_QUEUE_NAME(out_queue_push)(struct OUT_QUEUE_STRUCT *p) static struct wrtd_event *OUT_QUEUE_NAME(out_queue_push)(struct OUT_QUEUE_STRUCT *p)
{ {
struct wrtd_event *ev; struct wrtd_event *ev;
if (p->count == OUT_QUEUE_SIZE) if (p->count == OUT_QUEUE_SIZE)
return NULL; return NULL;
ev = &p->events[p->head]; ev = &p->events[p->head];
p->count++; p->count++;
p->head++; p->head++;
if (p->head == OUT_QUEUE_SIZE) if (p->head == OUT_QUEUE_SIZE)
p->head = 0; p->head = 0;
return ev; return ev;
} }
...@@ -64,7 +70,7 @@ static struct wrtd_event *OUT_QUEUE_NAME(out_queue_push)(struct OUT_QUEUE_STRUCT ...@@ -64,7 +70,7 @@ static struct wrtd_event *OUT_QUEUE_NAME(out_queue_push)(struct OUT_QUEUE_STRUCT
*/ */
static inline int OUT_QUEUE_NAME(out_queue_empty)(struct OUT_QUEUE_STRUCT *p) static inline int OUT_QUEUE_NAME(out_queue_empty)(struct OUT_QUEUE_STRUCT *p)
{ {
return (p->count == 0); return (p->count == 0);
} }
...@@ -73,9 +79,9 @@ static inline int OUT_QUEUE_NAME(out_queue_empty)(struct OUT_QUEUE_STRUCT *p) ...@@ -73,9 +79,9 @@ static inline int OUT_QUEUE_NAME(out_queue_empty)(struct OUT_QUEUE_STRUCT *p)
*/ */
static struct wrtd_event *OUT_QUEUE_NAME(out_queue_front)(struct OUT_QUEUE_STRUCT *p) static struct wrtd_event *OUT_QUEUE_NAME(out_queue_front)(struct OUT_QUEUE_STRUCT *p)
{ {
if (!p->count) if (!p->count)
return NULL; return NULL;
return &p->events[p->tail]; return &p->events[p->tail];
} }
...@@ -84,11 +90,11 @@ static struct wrtd_event *OUT_QUEUE_NAME(out_queue_front)(struct OUT_QUEUE_STRUC ...@@ -84,11 +90,11 @@ static struct wrtd_event *OUT_QUEUE_NAME(out_queue_front)(struct OUT_QUEUE_STRUC
*/ */
static void OUT_QUEUE_NAME(out_queue_pop)(struct OUT_QUEUE_STRUCT *p) static void OUT_QUEUE_NAME(out_queue_pop)(struct OUT_QUEUE_STRUCT *p)
{ {
p->tail++; p->tail++;
if(p->tail == OUT_QUEUE_SIZE) if(p->tail == OUT_QUEUE_SIZE)
p->tail = 0; p->tail = 0;
p->count--; p->count--;
} }
/** /**
...@@ -96,23 +102,23 @@ static void OUT_QUEUE_NAME(out_queue_pop)(struct OUT_QUEUE_STRUCT *p) ...@@ -96,23 +102,23 @@ static void OUT_QUEUE_NAME(out_queue_pop)(struct OUT_QUEUE_STRUCT *p)
* of timeout * of timeout
*/ */
static int OUT_QUEUE_NAME(out_queue_check_timeout) (struct OUT_QUEUE_STRUCT *q, static int OUT_QUEUE_NAME(out_queue_check_timeout) (struct OUT_QUEUE_STRUCT *q,
struct wrtd_tstamp *now) struct wrtd_tstamp *now)
{ {
int delta; int delta;
if(q->last_programmed_sec > now->seconds + OUT_QUEUE_MAXTIME) { if(q->last_programmed_sec > now->seconds + OUT_QUEUE_MAXTIME) {
pr_error("Enqueued event very far in the future. Dropping."); pr_error("Enqueued event very far in the future. Dropping.");
return 0; return 0;
} }
/* Current time exceeds FD setpoint? */ /* Current time exceeds FD setpoint? */
delta = now->seconds - q->last_programmed_sec; delta = now->seconds - q->last_programmed_sec;
if (delta != 0) if (delta != 0)
return delta > 0; return delta > 0;
delta = now->ns - q->last_programmed_ns; delta = now->ns - q->last_programmed_ns;
return (delta > 0); return (delta > 0);
} }
#undef OUT_QUEUE_STRUCT #undef OUT_QUEUE_STRUCT
......
/* This is a basic linker configuration for WRTD. /**
* @file trtl-memory.ld
*
* This is a basic linker configuration for WRTD.
* *
* It expects that every MT CPU has at least 32KB * It expects that every MT CPU has at least 32KB
* of memory, as well as 2KB of shared memory for * of memory, as well as 2KB of shared memory for
* all CPUS. * all CPUS.
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
MEMORY MEMORY
......
This diff is collapsed.
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# fmc-svec-carrier fw-01 demo configuration
# #
# #
......
This diff is collapsed.
/* /**
* @file fd_calibrate.c
*
* Calibrate the output path. * Calibrate the output path.
* *
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
* *
* This program is free software; you can redistribute it and/or * Copyright (c) 2012-2019 CERN (home.cern)
* modify it under the terms of the GNU Lesser General Public License *
* version 2 as published by the Free Software Foundation or, at your * SPDX-License-Identifier: LGPL-3.0-or-later
* option, any later version.
*/ */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
...@@ -21,10 +22,9 @@ ...@@ -21,10 +22,9 @@
/* This is the same as in ./acam.c: use only at init time */ /* This is the same as in ./acam.c: use only at init time */
static void acam_set_bypass(struct wrtd_fd_dev *fd, int on) static void acam_set_bypass(struct wrtd_fd_dev *fd, int on)
{ {
fd_writel(fd, on ? FD_GCR_BYPASS : 0, FD_REG_GCR); fd_writel(fd, on ? FD_GCR_BYPASS : 0, FD_REG_GCR);
} }
/* /*
* Measures the the FPGA-generated TDC start and the output of one of * Measures the the FPGA-generated TDC start and the output of one of
* the fine delay chips (channel) at a pre-defined number of taps * the fine delay chips (channel) at a pre-defined number of taps
...@@ -36,80 +36,80 @@ static void acam_set_bypass(struct wrtd_fd_dev *fd, int on) ...@@ -36,80 +36,80 @@ static void acam_set_bypass(struct wrtd_fd_dev *fd, int on)
/* Note: channel is the "internal" one: 0..3 */ /* Note: channel is the "internal" one: 0..3 */
static uint64_t output_delay_ps(struct wrtd_fd_dev *fd, int ch, int fine, int n) static uint64_t output_delay_ps(struct wrtd_fd_dev *fd, int ch, int fine, int n)
{ {
int i; int i;
uint64_t acc = 0; uint64_t acc = 0;
/* Disable the output for the channel being calibrated */ /* Disable the output for the channel being calibrated */
fd_gpio_clr(fd, FD_GPIO_OUTPUT_EN(FD_CH_EXT(ch))); fd_gpio_clr(fd, FD_GPIO_OUTPUT_EN(FD_CH_EXT(ch)));
/* Enable the stop input in ACAM for the channel being calibrated */ /* Enable the stop input in ACAM for the channel being calibrated */
acam_writel(fd, AR0_TRiseEn(0) | AR0_TRiseEn(FD_CH_EXT(ch)) acam_writel(fd, AR0_TRiseEn(0) | AR0_TRiseEn(FD_CH_EXT(ch))
| AR0_HQSel | AR0_ROsc, 0); | AR0_HQSel | AR0_ROsc, 0);
/* Program the output delay line setpoint */ /* Program the output delay line setpoint */
fd_drv_ch_writel(fd, ch, fine, FD_REG_FRR); fd_drv_ch_writel(fd, ch, fine, FD_REG_FRR);
fd_drv_ch_writel(fd, ch, FD_DCR_ENABLE | FD_DCR_MODE | FD_DCR_UPDATE, fd_drv_ch_writel(fd, ch, FD_DCR_ENABLE | FD_DCR_MODE | FD_DCR_UPDATE,
FD_REG_DCR); FD_REG_DCR);
fd_drv_ch_writel(fd, ch, FD_DCR_FORCE_DLY | FD_DCR_ENABLE, FD_REG_DCR); fd_drv_ch_writel(fd, ch, FD_DCR_FORCE_DLY | FD_DCR_ENABLE, FD_REG_DCR);
/* /*
* Set the calibration pulse mask to genrate calibration * Set the calibration pulse mask to genrate calibration
* pulses only on one channel at a time. This minimizes the * pulses only on one channel at a time. This minimizes the
* crosstalk in the output buffer which can severely decrease * crosstalk in the output buffer which can severely decrease
* the accuracy of calibration measurements * the accuracy of calibration measurements
*/ */
fd_writel(fd, FD_CALR_PSEL_W(1 << ch), FD_REG_CALR); fd_writel(fd, FD_CALR_PSEL_W(1 << ch), FD_REG_CALR);
udelay(1); udelay(1);
/* Do n_avgs single measurements and average */ /* Do n_avgs single measurements and average */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
uint32_t fr; uint32_t fr;
/* Re-arm the ACAM (it's working in a single-shot mode) */ /* Re-arm the ACAM (it's working in a single-shot mode) */
fd_writel(fd, FD_TDCSR_ALUTRIG, FD_REG_TDCSR); fd_writel(fd, FD_TDCSR_ALUTRIG, FD_REG_TDCSR);
udelay(1); udelay(1);
/* Produce a calib pulse on the TDC start and the output ch */ /* Produce a calib pulse on the TDC start and the output ch */
fd_writel(fd, FD_CALR_CAL_PULSE | fd_writel(fd, FD_CALR_CAL_PULSE |
FD_CALR_PSEL_W(1 << ch), FD_REG_CALR); FD_CALR_PSEL_W(1 << ch), FD_REG_CALR);
udelay(1); udelay(1);
/* read the tag, convert to picoseconds (fixed point: 16.16) */ /* read the tag, convert to picoseconds (fixed point: 16.16) */
fr = acam_readl(fd, 8 /* fifo */) & 0x1ffff; fr = acam_readl(fd, 8 /* fifo */) & 0x1ffff;
//pp_printf("i %d fr %x\n\r", i, fr); //pp_printf("i %d fr %x\n\r", i, fr);
acc += fr * fd->fd_bin_size; acc += fr * fd->fd_bin_size;
} }
fd_drv_ch_writel(fd, ch, 0, FD_REG_DCR); fd_drv_ch_writel(fd, ch, 0, FD_REG_DCR);
/* Calculate avg, min max */ /* Calculate avg, min max */
acc = div_u64((acc + n / 2), n ); acc = div_u64((acc + n / 2), n );
//pp_printf("ch %d avg %08x%08x\n\r", ch, (uint32_t)(acc>>32), (uint32_t)acc); //pp_printf("ch %d avg %08x%08x\n\r", ch, (uint32_t)(acc>>32), (uint32_t)acc);
return acc; return acc;
} }
static int fd_find_8ns_tap(struct wrtd_fd_dev *fd, int ch) static int fd_find_8ns_tap(struct wrtd_fd_dev *fd, int ch)
{ {
int l = 0, mid, r = FD_NUM_TAPS - 1; int l = 0, mid, r = FD_NUM_TAPS - 1;
uint64_t bias, dly; uint64_t bias, dly;
/* /*
* Measure the delay at zero setting, so it can be further * Measure the delay at zero setting, so it can be further
* subtracted to get only the delay part introduced by the * subtracted to get only the delay part introduced by the
* delay line (ingoring the TDC, FPGA and routing delays). * delay line (ingoring the TDC, FPGA and routing delays).
* Use a binary search of the delay value. * Use a binary search of the delay value.
*/ */
bias = output_delay_ps(fd, ch, 0, FD_CAL_STEPS); bias = output_delay_ps(fd, ch, 0, FD_CAL_STEPS);
while( r - l > 1) { while( r - l > 1) {
mid = ( l + r) / 2; mid = ( l + r) / 2;
dly = output_delay_ps(fd, ch, mid, FD_CAL_STEPS) - bias; dly = output_delay_ps(fd, ch, mid, FD_CAL_STEPS) - bias;
if(dly < 8000 << 16) if(dly < 8000 << 16)
l = mid; l = mid;
else else
r = mid; r = mid;
} }
return l; return l;
} }
...@@ -121,17 +121,17 @@ static int fd_find_8ns_tap(struct wrtd_fd_dev *fd, int ch) ...@@ -121,17 +121,17 @@ static int fd_find_8ns_tap(struct wrtd_fd_dev *fd, int ch)
*/ */
int fd_calibrate_outputs(struct wrtd_fd_dev *fd) int fd_calibrate_outputs(struct wrtd_fd_dev *fd)
{ {
int ch; int ch;
int measured; int measured;
acam_set_bypass(fd, 1); /* not useful */ acam_set_bypass(fd, 1); /* not useful */
fd_writel(fd, FD_TDCSR_START_EN | FD_TDCSR_STOP_EN, FD_REG_TDCSR); fd_writel(fd, FD_TDCSR_START_EN | FD_TDCSR_STOP_EN, FD_REG_TDCSR);
for (ch = 0; ch < FD_NUM_CHANNELS; ch++) { for (ch = 0; ch < FD_NUM_CHANNELS; ch++) {
measured = fd_find_8ns_tap(fd, ch); measured = fd_find_8ns_tap(fd, ch);
fd_drv_ch_writel(fd, ch, measured, FD_REG_FRR); fd_drv_ch_writel(fd, ch, measured, FD_REG_FRR);
pr_debug("Channel %d: 8ns @ %i taps.\n\r", ch+1, measured ); pr_debug("Channel %d: 8ns @ %i taps.\n\r", ch+1, measured );
} }
return 0; return 0;
} }
/* /**
* @file fd_gpio.c
*
* SPI access to fine-delay internals * SPI access to fine-delay internals
* *
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* Copyright (c) 2012-2019 CERN (home.cern)
* *
* This program is free software; you can redistribute it and/or * SPDX-License-Identifier: LGPL-3.0-or-later
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/ */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
...@@ -22,58 +23,58 @@ int gpio_writel(struct wrtd_fd_dev *fd, int val, int reg) ...@@ -22,58 +23,58 @@ int gpio_writel(struct wrtd_fd_dev *fd, int val, int reg)
int rval = fd_spi_xfer(fd, FD_CS_GPIO, 24, int rval = fd_spi_xfer(fd, FD_CS_GPIO, 24,
0x4e0000 | (reg << 8) | val, NULL); 0x4e0000 | (reg << 8) | val, NULL);
return rval; return rval;
} }
static int gpio_readl(struct wrtd_fd_dev *fd, int reg) static int gpio_readl(struct wrtd_fd_dev *fd, int reg)
{ {
uint32_t ret; uint32_t ret;
int err; int err;
err = fd_spi_xfer(fd, FD_CS_GPIO, 24, err = fd_spi_xfer(fd, FD_CS_GPIO, 24,
0x4f0000 | (reg << 8), &ret); 0x4f0000 | (reg << 8), &ret);
if (err < 0) if (err < 0)
return err; return err;
return ret & 0xff; return ret & 0xff;
} }
static int gpio_writel_with_retry(struct wrtd_fd_dev *fd, int val, int reg) static int gpio_writel_with_retry(struct wrtd_fd_dev *fd, int val, int reg)
{ {
int retries = SPI_RETRIES, rv; int retries = SPI_RETRIES, rv;
while(retries--) while(retries--)
{ {
gpio_writel(fd, val, reg); gpio_writel(fd, val, reg);
rv = gpio_readl(fd, reg); rv = gpio_readl(fd, reg);
if(rv >= 0 && (rv == val)) if(rv >= 0 && (rv == val))
{ {
if(SPI_RETRIES-1-retries > 0) if(SPI_RETRIES-1-retries > 0)
pr_debug("gpio_writel_with_retry: succeded after %d retries\n", pr_debug("gpio_writel_with_retry: succeded after %d retries\n",
SPI_RETRIES - 1 - retries); SPI_RETRIES - 1 - retries);
return 0; return 0;
} }
} }
return -EIO; return -EIO;
} }
void fd_gpio_dir(struct wrtd_fd_dev *fd, int mask, int dir) void fd_gpio_dir(struct wrtd_fd_dev *fd, int mask, int dir)
{ {
fd->fd_mcp_iodir &= ~mask; fd->fd_mcp_iodir &= ~mask;
if (dir == FD_GPIO_IN) if (dir == FD_GPIO_IN)
fd->fd_mcp_iodir |= mask; fd->fd_mcp_iodir |= mask;
gpio_writel_with_retry(fd, (fd->fd_mcp_iodir & 0xff), FD_MCP_IODIR); gpio_writel_with_retry(fd, (fd->fd_mcp_iodir & 0xff), FD_MCP_IODIR);
gpio_writel_with_retry(fd, (fd->fd_mcp_iodir >> 8), FD_MCP_IODIR+1); gpio_writel_with_retry(fd, (fd->fd_mcp_iodir >> 8), FD_MCP_IODIR+1);
} }
void fd_gpio_val(struct wrtd_fd_dev *fd, int mask, int values) void fd_gpio_val(struct wrtd_fd_dev *fd, int mask, int values)
{ {
fd->fd_mcp_olat &= ~mask; fd->fd_mcp_olat &= ~mask;
fd->fd_mcp_olat |= values; fd->fd_mcp_olat |= values;
gpio_writel_with_retry(fd, (fd->fd_mcp_olat & 0xff), FD_MCP_OLAT); gpio_writel_with_retry(fd, (fd->fd_mcp_olat & 0xff), FD_MCP_OLAT);
gpio_writel_with_retry(fd, (fd->fd_mcp_olat >> 8), FD_MCP_OLAT+1); gpio_writel_with_retry(fd, (fd->fd_mcp_olat >> 8), FD_MCP_OLAT+1);
} }
void fd_gpio_set_clr(struct wrtd_fd_dev *fd, int mask, int set) void fd_gpio_set_clr(struct wrtd_fd_dev *fd, int mask, int set)
...@@ -83,28 +84,28 @@ void fd_gpio_set_clr(struct wrtd_fd_dev *fd, int mask, int set) ...@@ -83,28 +84,28 @@ void fd_gpio_set_clr(struct wrtd_fd_dev *fd, int mask, int set)
int fd_gpio_init(struct wrtd_fd_dev *fd) int fd_gpio_init(struct wrtd_fd_dev *fd)
{ {
int i, val; int i, val;
fd->fd_mcp_iodir = 0xffff; fd->fd_mcp_iodir = 0xffff;
fd->fd_mcp_olat = 0; fd->fd_mcp_olat = 0;
if (gpio_writel(fd, 0x00, FD_MCP_IOCON) < 0) if (gpio_writel(fd, 0x00, FD_MCP_IOCON) < 0)
goto out; goto out;
/* Try to read and write a register to test the SPI connection */ /* Try to read and write a register to test the SPI connection */
for (val = 0xaa; val >= 0; val -= 0x11) { for (val = 0xaa; val >= 0; val -= 0x11) {
if (gpio_writel(fd, val, FD_MCP_IPOL) < 0) if (gpio_writel(fd, val, FD_MCP_IPOL) < 0)
goto out; goto out;
i = gpio_readl(fd, FD_MCP_IPOL); i = gpio_readl(fd, FD_MCP_IPOL);
if (i < 0) if (i < 0)
goto out; goto out;
if (i != val) { if (i != val) {
pr_error("GPIO comm error (got 0x%x, expected 0x%x)\n", i, val); pr_error("GPIO comm error (got 0x%x, expected 0x%x)\n", i, val);
return -EIO; return -EIO;
} }
} }
/* last time we wrote 0, ok */ /* last time we wrote 0, ok */
return 0; return 0;
out: out:
return -EIO; return -EIO;
} }
/* /**
* @file fd_i2c.c
*
* I2C access (on-board EEPROM) * I2C access (on-board EEPROM)
* *
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* Copyright (c) 2012-2019 CERN (home.cern)
* *
* This program is free software; you can redistribute it and/or * SPDX-License-Identifier: LGPL-3.0-or-later
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/ */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
...@@ -18,24 +19,24 @@ ...@@ -18,24 +19,24 @@
static void set_sda(struct wrtd_fd_dev *fd, int val) static void set_sda(struct wrtd_fd_dev *fd, int val)
{ {
uint32_t reg; uint32_t reg;
reg = fd_readl(fd, FD_REG_I2CR) & ~FD_I2CR_SDA_OUT; reg = fd_readl(fd, FD_REG_I2CR) & ~FD_I2CR_SDA_OUT;
if (val) if (val)
reg |= FD_I2CR_SDA_OUT; reg |= FD_I2CR_SDA_OUT;
fd_writel(fd, reg, FD_REG_I2CR); fd_writel(fd, reg, FD_REG_I2CR);
udelay(3); udelay(3);
} }
static void set_scl(struct wrtd_fd_dev *fd, int val) static void set_scl(struct wrtd_fd_dev *fd, int val)
{ {
uint32_t reg; uint32_t reg;
reg = fd_readl(fd, FD_REG_I2CR) & ~FD_I2CR_SCL_OUT; reg = fd_readl(fd, FD_REG_I2CR) & ~FD_I2CR_SCL_OUT;
if (val) if (val)
reg |= FD_I2CR_SCL_OUT; reg |= FD_I2CR_SCL_OUT;
fd_writel(fd, reg, FD_REG_I2CR); fd_writel(fd, reg, FD_REG_I2CR);
udelay(3); udelay(3);
} }
static int get_sda(struct wrtd_fd_dev *fd) static int get_sda(struct wrtd_fd_dev *fd)
...@@ -46,105 +47,105 @@ static int get_sda(struct wrtd_fd_dev *fd) ...@@ -46,105 +47,105 @@ static int get_sda(struct wrtd_fd_dev *fd)
static void mi2c_start(struct wrtd_fd_dev *fd) static void mi2c_start(struct wrtd_fd_dev *fd)
{ {
set_sda(fd, 0); set_sda(fd, 0);
set_scl(fd, 0); set_scl(fd, 0);
} }
static void mi2c_stop(struct wrtd_fd_dev *fd) static void mi2c_stop(struct wrtd_fd_dev *fd)
{ {
set_sda(fd, 0); set_sda(fd, 0);
set_scl(fd, 1); set_scl(fd, 1);
set_sda(fd, 1); set_sda(fd, 1);
} }
int mi2c_put_byte(struct wrtd_fd_dev *fd, int data) int mi2c_put_byte(struct wrtd_fd_dev *fd, int data)
{ {
int i; int i;
int ack; int ack;
for (i = 0; i < 8; i++, data<<=1) { for (i = 0; i < 8; i++, data<<=1) {
set_sda(fd, data & 0x80); set_sda(fd, data & 0x80);
set_scl(fd, 1); set_scl(fd, 1);
set_scl(fd, 0); set_scl(fd, 0);
} }
set_sda(fd, 1); set_sda(fd, 1);
set_scl(fd, 1); set_scl(fd, 1);
ack = get_sda(fd); ack = get_sda(fd);
set_scl(fd, 0); set_scl(fd, 0);
set_sda(fd, 0); set_sda(fd, 0);
return ack ? -EIO : 0; /* ack low == success */ return ack ? -EIO : 0; /* ack low == success */
} }
int mi2c_get_byte(struct wrtd_fd_dev *fd, unsigned char *data, int sendack) int mi2c_get_byte(struct wrtd_fd_dev *fd, unsigned char *data, int sendack)
{ {
int i; int i;
int indata = 0; int indata = 0;
/* assert: scl is low */ /* assert: scl is low */
set_scl(fd, 0); set_scl(fd, 0);
set_sda(fd, 1); set_sda(fd, 1);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
set_scl(fd, 1); set_scl(fd, 1);
indata <<= 1; indata <<= 1;
if (get_sda(fd)) if (get_sda(fd))
indata |= 0x01; indata |= 0x01;
set_scl(fd, 0); set_scl(fd, 0);
} }
set_sda(fd, (sendack ? 0 : 1)); set_sda(fd, (sendack ? 0 : 1));
set_scl(fd, 1); set_scl(fd, 1);
set_scl(fd, 0); set_scl(fd, 0);
set_sda(fd, 0); set_sda(fd, 0);
*data= indata; *data= indata;
return 0; return 0;
} }
void mi2c_init(struct wrtd_fd_dev *fd) void mi2c_init(struct wrtd_fd_dev *fd)
{ {
set_scl(fd, 1); set_scl(fd, 1);
set_sda(fd, 1); set_sda(fd, 1);
} }
void mi2c_scan(struct wrtd_fd_dev *fd) void mi2c_scan(struct wrtd_fd_dev *fd)
{ {
int i; int i;
for(i = 0; i < 256; i += 2) { for(i = 0; i < 256; i += 2) {
mi2c_start(fd); mi2c_start(fd);
if(!mi2c_put_byte(fd, i)) if(!mi2c_put_byte(fd, i))
pr_debug("Found i2c device at 0x%x\n", pr_debug("Found i2c device at 0x%x\n",
i >> 1); i >> 1);
mi2c_stop(fd); mi2c_stop(fd);
} }
} }
/* FIXME: this is very inefficient: read several bytes in a row instead */ /* FIXME: this is very inefficient: read several bytes in a row instead */
int fd_eeprom_read(struct wrtd_fd_dev *fd, int i2c_addr, uint32_t offset, int fd_eeprom_read(struct wrtd_fd_dev *fd, int i2c_addr, uint32_t offset,
void *buf, size_t size) void *buf, size_t size)
{ {
int i; int i;
uint8_t *buf8 = buf; uint8_t *buf8 = buf;
unsigned char c; unsigned char c;
for(i = 0; i < size; i++) { for(i = 0; i < size; i++) {
mi2c_start(fd); mi2c_start(fd);
if(mi2c_put_byte(fd, i2c_addr << 1) < 0) { if(mi2c_put_byte(fd, i2c_addr << 1) < 0) {
mi2c_stop(fd); mi2c_stop(fd);
return -EIO; return -EIO;
} }
mi2c_put_byte(fd, (offset >> 8) & 0xff); mi2c_put_byte(fd, (offset >> 8) & 0xff);
mi2c_put_byte(fd, offset & 0xff); mi2c_put_byte(fd, offset & 0xff);
offset++; offset++;
mi2c_stop(fd); mi2c_stop(fd);
mi2c_start(fd); mi2c_start(fd);
mi2c_put_byte(fd, (i2c_addr << 1) | 1); mi2c_put_byte(fd, (i2c_addr << 1) | 1);
mi2c_get_byte(fd, &c, 0); mi2c_get_byte(fd, &c, 0);
*buf8++ = c; *buf8++ = c;
mi2c_stop(fd); mi2c_stop(fd);
} }
return size; return size;
} }
/* /**
* Copyright (C) 2018 CERN (www.cern.ch) * @file fd_init.c
*
* Author: Federico Vaga <federico.vaga@cern.ch> * Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
...@@ -36,102 +39,102 @@ ...@@ -36,102 +39,102 @@
*/ */
static void fd_do_reset(struct wrtd_fd_dev *fd, int hw_reset) static void fd_do_reset(struct wrtd_fd_dev *fd, int hw_reset)
{ {
if (hw_reset) { if (hw_reset) {
/* clear RSTS_RST_FMC bit, set RSTS_RST_CORE bit*/ /* clear RSTS_RST_FMC bit, set RSTS_RST_CORE bit*/
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_CORE_MASK, fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_CORE_MASK,
FD_REG_RSTR); FD_REG_RSTR);
UDELAY(10000); UDELAY(10000);
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_CORE_MASK fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_CORE_MASK
| FD_RSTR_RST_FMC_MASK, FD_REG_RSTR); | FD_RSTR_RST_FMC_MASK, FD_REG_RSTR);
/* TPS3307 supervisor needs time to de-assert master reset */ /* TPS3307 supervisor needs time to de-assert master reset */
MDELAY(600); MDELAY(600);
return; return;
} }
/* clear RSTS_RST_CORE bit, set RSTS_RST_FMC bit */ /* clear RSTS_RST_CORE bit, set RSTS_RST_FMC bit */
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_FMC_MASK, fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_FMC_MASK,
FD_REG_RSTR); FD_REG_RSTR);
UDELAY(1000); UDELAY(1000);
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_FMC_MASK fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_FMC_MASK
| FD_RSTR_RST_CORE_MASK, FD_REG_RSTR); | FD_RSTR_RST_CORE_MASK, FD_REG_RSTR);
UDELAY(1000); UDELAY(1000);
} }
/* Some init procedures to be intermixed with subsystems */ /* Some init procedures to be intermixed with subsystems */
int fd_gpio_defaults(struct wrtd_fd_dev *fd) int fd_gpio_defaults(struct wrtd_fd_dev *fd)
{ {
fd_gpio_dir(fd, FD_GPIO_TRIG_INTERNAL, FD_GPIO_OUT); fd_gpio_dir(fd, FD_GPIO_TRIG_INTERNAL, FD_GPIO_OUT);
fd_gpio_set(fd, FD_GPIO_TRIG_INTERNAL); fd_gpio_set(fd, FD_GPIO_TRIG_INTERNAL);
fd_gpio_set(fd, FD_GPIO_OUTPUT_MASK); fd_gpio_set(fd, FD_GPIO_OUTPUT_MASK);
fd_gpio_dir(fd, FD_GPIO_OUTPUT_MASK, FD_GPIO_OUT); fd_gpio_dir(fd, FD_GPIO_OUTPUT_MASK, FD_GPIO_OUT);
fd_gpio_dir(fd, FD_GPIO_TERM_EN, FD_GPIO_OUT); fd_gpio_dir(fd, FD_GPIO_TERM_EN, FD_GPIO_OUT);
fd_gpio_clr(fd, FD_GPIO_TERM_EN); fd_gpio_clr(fd, FD_GPIO_TERM_EN);
return 0; return 0;
} }
int fd_reset_again(struct wrtd_fd_dev *fd) int fd_reset_again(struct wrtd_fd_dev *fd)
{ {
/* Reset the FD core once we have proper reference/TDC clocks */ /* Reset the FD core once we have proper reference/TDC clocks */
fd_do_reset(fd, 0 /* not hw */); fd_do_reset(fd, 0 /* not hw */);
MDELAY(10); MDELAY(10);
if (! (fd_readl(fd, FD_REG_GCR) & FD_GCR_DDR_LOCKED) ) if (! (fd_readl(fd, FD_REG_GCR) & FD_GCR_DDR_LOCKED) )
{ {
pr_error("timeout waiting for GCR lock bit\n"); pr_error("timeout waiting for GCR lock bit\n");
return -EIO; return -EIO;
} }
fd_do_reset(fd, 0 /* not hw */); fd_do_reset(fd, 0 /* not hw */);
return 0; return 0;
} }
/* FIXME missing all calibration */ /* FIXME missing all calibration */
int fd_init(struct wrtd_fd_dev *fd) int fd_init(struct wrtd_fd_dev *fd)
{ {
int err, ch; int err, ch;
pr_debug("Initializing the Fine Delay board...\n"); pr_debug("Initializing the Fine Delay board...\n");
fd_do_reset(fd, 1); fd_do_reset(fd, 1);
err = fd_gpio_init(fd); err = fd_gpio_init(fd);
if (err) if (err)
return err; return err;
err = fd_pll_init(fd); err = fd_pll_init(fd);
if (err) if (err)
return err; return err;
fd_gpio_defaults(fd); fd_gpio_defaults(fd);
err = fd_reset_again(fd); err = fd_reset_again(fd);
if (err) if (err)
return err; return err;
err = fd_acam_init(fd); err = fd_acam_init(fd);
if (err) if (err)
return err; return err;
for (ch = 1; ch <= FD_NUM_CHANNELS; ch++) for (ch = 1; ch <= FD_NUM_CHANNELS; ch++)
fd_gpio_set(fd, FD_GPIO_OUTPUT_EN(ch)); fd_gpio_set(fd, FD_GPIO_OUTPUT_EN(ch));
// todo: read offsets from the EEPROM. I2C should be working OK. // todo: read offsets from the EEPROM. I2C should be working OK.
return 0; return 0;
} }
#ifdef SIMULATION #ifdef SIMULATION
int fd_sim_init(struct wrtd_fd_dev *fd) int fd_sim_init(struct wrtd_fd_dev *fd)
{ {
int err; int err;
pr_debug("Initializing the Fine Delay board...\n"); pr_debug("Initializing the Fine Delay board...\n");
fd_do_reset(fd, 1); fd_do_reset(fd, 1);
return 0; return 0;
} }
#endif #endif
This diff is collapsed.
/**
* @file pll_config.h
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
struct ad9516_reg { struct ad9516_reg {
int reg; int reg;
int val; int val;
}; };
const struct ad9516_reg __9516_regs[] = { const struct ad9516_reg __9516_regs[] = {
{0x0000, 0x99}, /* Config SPI */ {0x0000, 0x99}, /* Config SPI */
{0x0001, 0x00}, {0x0001, 0x00},
{0x0002, 0x10}, {0x0002, 0x10},
{0x0003, 0xC3}, {0x0003, 0xC3},
{0x0004, 0x00}, {0x0004, 0x00},
/* PLL */ /* PLL */
{0x0010, 0x7C}, /* PFD and charge pump */ {0x0010, 0x7C}, /* PFD and charge pump */
{0x0011, 0x05}, /* R divider (1) */ {0x0011, 0x05}, /* R divider (1) */
{0x0012, 0x00}, /* R divider (2) */ {0x0012, 0x00}, /* R divider (2) */
{0x0013, 0x0C}, /* A counter */ {0x0013, 0x0C}, /* A counter */
{0x0014, 0x12}, /* B counter (1) */ {0x0014, 0x12}, /* B counter (1) */
{0x0015, 0x00}, /* B counter (2) */ {0x0015, 0x00}, /* B counter (2) */
{0x0016, 0x05}, /* PLL control (1) */ {0x0016, 0x05}, /* PLL control (1) */
{0x0017, 0xb4}, /* PLL control (2) PLL_STATUS = Lock Detect */ {0x0017, 0xb4}, /* PLL control (2) PLL_STATUS = Lock Detect */
{0x0018, 0x07}, /* PLL control (3) */ {0x0018, 0x07}, /* PLL control (3) */
{0x0019, 0x00}, /* PLL control (4) */ {0x0019, 0x00}, /* PLL control (4) */
{0x001A, 0x00}, /* PLL control (5) */ {0x001A, 0x00}, /* PLL control (5) */
{0x001B, 0xE0}, /* PLL control (6) */ {0x001B, 0xE0}, /* PLL control (6) */
{0x001C, 0x02}, /* PLL control (7) */ {0x001C, 0x02}, /* PLL control (7) */
{0x001D, 0x00}, /* PLL control (8) */ {0x001D, 0x00}, /* PLL control (8) */
{0x001E, 0x00}, /* PLL control (9) */ {0x001E, 0x00}, /* PLL control (9) */
{0x001F, 0x0E}, /* PLL readback */ {0x001F, 0x0E}, /* PLL readback */
/* Fine Delay */ /* Fine Delay */
{0x00A0, 0x01}, /* OUT6 Delay bypass */ {0x00A0, 0x01}, /* OUT6 Delay bypass */
{0x00A1, 0x00}, /* OUT6 Delay full-scale */ {0x00A1, 0x00}, /* OUT6 Delay full-scale */
{0x00A2, 0x00}, /* OUT6 Delay fraction */ {0x00A2, 0x00}, /* OUT6 Delay fraction */
{0x00A3, 0x01}, /* OUT7 Delay bypass */ {0x00A3, 0x01}, /* OUT7 Delay bypass */
{0x00A4, 0x00}, /* OUT7 Delay full-scale */ {0x00A4, 0x00}, /* OUT7 Delay full-scale */
{0x00A5, 0x00}, /* OUT7 Delay fraction */ {0x00A5, 0x00}, /* OUT7 Delay fraction */
{0x00A6, 0x01}, /* OUT8 Delay bypass */ {0x00A6, 0x01}, /* OUT8 Delay bypass */
{0x00A7, 0x00}, /* OUT8 Delay full-scale */ {0x00A7, 0x00}, /* OUT8 Delay full-scale */
{0x00A8, 0x00}, /* OUT8 Delay fraction */ {0x00A8, 0x00}, /* OUT8 Delay fraction */
{0x00A9, 0x01}, /* OUT9 Delay bypass */ {0x00A9, 0x01}, /* OUT9 Delay bypass */
{0x00AA, 0x00}, /* OUT9 Delay full-scale */ {0x00AA, 0x00}, /* OUT9 Delay full-scale */
{0x00AB, 0x00}, /* OUT9 Delay fraction */ {0x00AB, 0x00}, /* OUT9 Delay fraction */
/* LVPECL */ /* LVPECL */
{0x00F0, 0x08}, /* OUT0 */ {0x00F0, 0x08}, /* OUT0 */
{0x00F1, 0x08}, /* OUT1 */ {0x00F1, 0x08}, /* OUT1 */
{0x00F2, 0x08}, /* OUT2 */ {0x00F2, 0x08}, /* OUT2 */
{0x00F3, 0x18}, /* OUT3, inverted */ {0x00F3, 0x18}, /* OUT3, inverted */
{0x00F4, 0x00}, /* OUT4 */ {0x00F4, 0x00}, /* OUT4 */
{0x00F5, 0x08}, /* OUT5 */ {0x00F5, 0x08}, /* OUT5 */
/* LVDS/CMOS */ /* LVDS/CMOS */
{0x0140, 0x5A}, /* OUT6 */ {0x0140, 0x5A}, /* OUT6 */
{0x0141, 0x5A}, /* OUT7 */ {0x0141, 0x5A}, /* OUT7 */
{0x0142, 0x5B}, /* OUT8 */ {0x0142, 0x5B}, /* OUT8 */
{0x0143, 0x42}, /* OUT9 */ {0x0143, 0x42}, /* OUT9 */
/* LVPECL Channel divider */ /* LVPECL Channel divider */
{0x0190, 0x00}, /* Divider 0 (1) */ {0x0190, 0x00}, /* Divider 0 (1) */
{0x0191, 0x80}, /* Divider 0 (2) */ {0x0191, 0x80}, /* Divider 0 (2) */
{0x0192, 0x00}, /* Divider 0 (3) */ {0x0192, 0x00}, /* Divider 0 (3) */
{0x0193, 0x00}, /* Divider 1 (1) */ {0x0193, 0x00}, /* Divider 1 (1) */
{0x0194, 0x80}, /* Divider 1 (2) */ {0x0194, 0x80}, /* Divider 1 (2) */
{0x0195, 0x00}, /* Divider 1 (3) */ {0x0195, 0x00}, /* Divider 1 (3) */
{0x0196, 0xFF}, /* Divider 2 (1) */ {0x0196, 0xFF}, /* Divider 2 (1) */
{0x0197, 0x00}, /* Divider 2 (2) */ {0x0197, 0x00}, /* Divider 2 (2) */
{0x0198, 0x00}, /* Divider 2 (3) */ {0x0198, 0x00}, /* Divider 2 (3) */
/* LVDS/CMOS Channel divider */ /* LVDS/CMOS Channel divider */
{0x0199, 0x33}, /* Divider 3 (1) */ {0x0199, 0x33}, /* Divider 3 (1) */
{0x019A, 0x00}, /* Divider 3 (2) */ {0x019A, 0x00}, /* Divider 3 (2) */
{0x019B, 0x11}, /* Divider 3 (3) */ {0x019B, 0x11}, /* Divider 3 (3) */
{0x019C, 0x20}, /* Divider 3 (4) */ {0x019C, 0x20}, /* Divider 3 (4) */
{0x019D, 0x00}, /* Divider 3 (5) */ {0x019D, 0x00}, /* Divider 3 (5) */
{0x019E, 0x00}, /* Divider 4 (1) */ {0x019E, 0x00}, /* Divider 4 (1) */
{0x019F, 0x00}, /* Divider 4 (2) */ {0x019F, 0x00}, /* Divider 4 (2) */
{0x01A0, 0x11}, /* Divider 4 (3) */ {0x01A0, 0x11}, /* Divider 4 (3) */
{0x01A1, 0x20}, /* Divider 4 (4) */ {0x01A1, 0x20}, /* Divider 4 (4) */
{0x01A2, 0x00}, /* Divider 4 (5) */ {0x01A2, 0x00}, /* Divider 4 (5) */
{0x01A3, 0x00}, {0x01A3, 0x00},
/* VCO Divider and CLK Input */ /* VCO Divider and CLK Input */
{0x01E0, 0x04}, /* VCO divider VCODIV = 6 */ {0x01E0, 0x04}, /* VCO divider VCODIV = 6 */
{0x01E1, 0x02}, /* Input Clock */ {0x01E1, 0x02}, /* Input Clock */
/* System */ /* System */
{0x0230, 0x00}, /* Power down and sync */ {0x0230, 0x00}, /* Power down and sync */
{0x0231, 0x00}, {0x0231, 0x00},
/* Update All registers */ /* Update All registers */
{0x0232, 0x00}, /* Update All registers */ {0x0232, 0x00}, /* Update All registers */
}; };
This diff is collapsed.
/**
* @file wrtd-fd.h
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef __FINE_DELAY_WRAPPER_H #ifndef __FINE_DELAY_WRAPPER_H
#define __FINE_DELAY_WRAPPER_H #define __FINE_DELAY_WRAPPER_H
#include "wrtd-common.h" #include "wrtd-common.h"
/* Channels are called 1..4 in all docs. Internally it's 0..3 */ /* Channels are called 1..4 in all docs. Internally it's 0..3 */
#define FD_CH_1 0 #define FD_CH_1 0
#define FD_CH_LAST 3 #define FD_CH_LAST 3
#define FD_NUM_CHANNELS 4 #define FD_NUM_CHANNELS 4
#define FD_CH_EXT(i) ((i) + 1) #define FD_CH_EXT(i) ((i) + 1)
#define FD_NUM_TAPS 1024 /* This is an hardware feature of SY89295U */ #define FD_NUM_TAPS 1024 /* This is an hardware feature of SY89295U */
#define FD_CAL_STEPS 1024 /* This is a parameter: must be power of 2 */ #define FD_CAL_STEPS 1024 /* This is a parameter: must be power of 2 */
#define FD_MAGIC_FPGA 0xf19ede1a /* FD_REG_IDR content */ #define FD_MAGIC_FPGA 0xf19ede1a /* FD_REG_IDR content */
...@@ -20,17 +28,17 @@ ...@@ -20,17 +28,17 @@
/* ACAM TDC operation modes */ /* ACAM TDC operation modes */
enum fd_acam_modes { enum fd_acam_modes {
ACAM_RMODE, ACAM_RMODE,
ACAM_IMODE, ACAM_IMODE,
ACAM_GMODE ACAM_GMODE
}; };
#define FD_GPIO_TERM_EN 0x0001 /* Input terminator enable */ #define FD_GPIO_TERM_EN 0x0001 /* Input terminator enable */
#define FD_GPIO_OUTPUT_EN(x) \ #define FD_GPIO_OUTPUT_EN(x) \
(1 << (6-(x))) /* Output driver enable */ (1 << (6-(x))) /* Output driver enable */
#define FD_GPIO_OUTPUT_MASK 0x003c /* Output driver enable */ #define FD_GPIO_OUTPUT_MASK 0x003c /* Output driver enable */
#define FD_GPIO_TRIG_INTERNAL 0x0040 /* TDC trig (1=in, 1=fpga) */ #define FD_GPIO_TRIG_INTERNAL 0x0040 /* TDC trig (1=in, 1=fpga) */
#define FD_GPIO_CAL_DISABLE 0x0080 /* 0 enables calibration */ #define FD_GPIO_CAL_DISABLE 0x0080 /* 0 enables calibration */
/* /*
...@@ -42,23 +50,23 @@ enum fd_acam_modes { ...@@ -42,23 +50,23 @@ enum fd_acam_modes {
#define ACAM_MASK ((1<<29) - 1) /* 28 bits */ #define ACAM_MASK ((1<<29) - 1) /* 28 bits */
/* SPI Bus chip selects */ /* SPI Bus chip selects */
#define FD_CS_DAC 0 /* DAC for VCXO */ #define FD_CS_DAC 0 /* DAC for VCXO */
#define FD_CS_PLL 1 /* AD9516 PLL */ #define FD_CS_PLL 1 /* AD9516 PLL */
#define FD_CS_GPIO 2 /* MCP23S17 GPIO */ #define FD_CS_GPIO 2 /* MCP23S17 GPIO */
/* MCP23S17 register addresses (only ones which are used by the lib) */ /* MCP23S17 register addresses (only ones which are used by the lib) */
#define FD_MCP_IODIR 0x00 #define FD_MCP_IODIR 0x00
#define FD_MCP_IPOL 0x01 #define FD_MCP_IPOL 0x01
#define FD_MCP_IOCON 0x0a #define FD_MCP_IOCON 0x0a
#define FD_MCP_GPIO 0x12 #define FD_MCP_GPIO 0x12
#define FD_MCP_OLAT 0x14 #define FD_MCP_OLAT 0x14
#define FD_MAX_QUEUE_PULSES 4 #define FD_MAX_QUEUE_PULSES 4
/* Pulse FIFO for a single Fine Delay output */ /* Pulse FIFO for a single Fine Delay output */
struct lrt_pulse_queue { struct lrt_pulse_queue {
struct wrtd_event events[FD_MAX_QUEUE_PULSES]; struct wrtd_event events[FD_MAX_QUEUE_PULSES];
int head, tail, count; int head, tail, count;
}; };
struct wrtd_fd_channel { struct wrtd_fd_channel {
...@@ -109,8 +117,8 @@ int fd_sim_init(struct wrtd_fd_dev *fd); ...@@ -109,8 +117,8 @@ int fd_sim_init(struct wrtd_fd_dev *fd);
#define fd_gpio_set(fd, pin) fd_gpio_set_clr(fd, (pin), 1) #define fd_gpio_set(fd, pin) fd_gpio_set_clr(fd, (pin), 1)
#define fd_gpio_clr(fd, pin) fd_gpio_set_clr(fd, (pin), 0) #define fd_gpio_clr(fd, pin) fd_gpio_set_clr(fd, (pin), 0)
#define FD_GPIO_IN 0 #define FD_GPIO_IN 0
#define FD_GPIO_OUT 1 #define FD_GPIO_OUT 1
static inline void fd_writel(struct wrtd_fd_dev *fd, uint32_t val, uint32_t reg) static inline void fd_writel(struct wrtd_fd_dev *fd, uint32_t val, uint32_t reg)
{ {
...@@ -119,24 +127,24 @@ static inline void fd_writel(struct wrtd_fd_dev *fd, uint32_t val, uint32_t reg) ...@@ -119,24 +127,24 @@ static inline void fd_writel(struct wrtd_fd_dev *fd, uint32_t val, uint32_t reg)
static inline uint32_t fd_readl(struct wrtd_fd_dev *fd, uint32_t reg) static inline uint32_t fd_readl(struct wrtd_fd_dev *fd, uint32_t reg)
{ {
return dp_readl(fd->io_addr + reg); return dp_readl(fd->io_addr + reg);
} }
static inline uint32_t fd_drv_ch_readl(struct wrtd_fd_dev *fd, int ch, static inline uint32_t fd_drv_ch_readl(struct wrtd_fd_dev *fd, int ch,
unsigned long reg) unsigned long reg)
{ {
return fd_readl(fd, 0x100 + ch * 0x100 + reg); return fd_readl(fd, 0x100 + ch * 0x100 + reg);
} }
static inline void fd_drv_ch_writel(struct wrtd_fd_dev *fd, int ch, static inline void fd_drv_ch_writel(struct wrtd_fd_dev *fd, int ch,
uint32_t v, unsigned long reg) uint32_t v, unsigned long reg)
{ {
fd_writel(fd, v, 0x100 + ch * 0x100 + reg); fd_writel(fd, v, 0x100 + ch * 0x100 + reg);
} }
static inline uint64_t div_u64(uint64_t dividend, uint32_t divisor) static inline uint64_t div_u64(uint64_t dividend, uint32_t divisor)
{ {
return dividend / divisor; return dividend / divisor;
} }
......
/* /**
* Copyright (C) 2013-2018 CERN (www.cern.ch) * @file wrtd-rt-fd.c
* Author: Federico Vaga <federico.vaga@cern.ch> *
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
...@@ -74,14 +74,14 @@ static int wrtd_local_output(struct wrtd_event *ev, unsigned ch) ...@@ -74,14 +74,14 @@ static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
*/ */
static int wrtd_user_init(void) static int wrtd_user_init(void)
{ {
if (!fd_wr_present(&fd0)) { if (!fd_wr_present(&fd0)) {
pr_error("WhiteRabbit not found\n\r"); pr_error("WhiteRabbit not found\n\r");
return -EINVAL; return -EINVAL;
} }
wr_enable_lock(0); wr_enable_lock(0);
/* Channels */ /* Channels */
wrtd_fd_data_init(&fd0); wrtd_fd_data_init(&fd0);
#ifdef SIMULATION #ifdef SIMULATION
...@@ -90,9 +90,9 @@ static int wrtd_user_init(void) ...@@ -90,9 +90,9 @@ static int wrtd_user_init(void)
fd_init(&fd0); fd_init(&fd0);
#endif #endif
pr_debug("rt-output firmware initialized.\n\r"); pr_debug("rt-output firmware initialized.\n\r");
return 0; return 0;
} }
static void wrtd_io(void) static void wrtd_io(void)
......
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# fmc-svec-carrier fw-01 demo configuration
# #
# #
......
/* /**
* tdc_registers.h * @file tdc_regs.h
* *
* Copyright (c) 2012 CERN (http://www.cern.ch) * Copyright (c) 2012-2019 CERN (home.cern)
* Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
* *
* This program is free software; you can redistribute it and/or modify it * SPDX-License-Identifier: LGPL-3.0-or-later
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; version 2 of the License.
*/ */
#ifndef __TDC_REGISTERS_H #ifndef __TDC_REGISTERS_H
...@@ -20,116 +17,115 @@ ...@@ -20,116 +17,115 @@
#define TDC_REG_ACAM_CONFIG(index) (0x0000 + (index * 4)) #define TDC_REG_ACAM_CONFIG(index) (0x0000 + (index * 4))
/* TDC core registers */ /* TDC core registers */
#define TDC_REG_START_UTC 0x0080 #define TDC_REG_START_UTC 0x0080
#define TDC_REG_INPUT_ENABLE 0x0084 #define TDC_REG_INPUT_ENABLE 0x0084
#define TDC_REG_IRQ_THRESHOLD 0x0090 #define TDC_REG_IRQ_THRESHOLD 0x0090
#define TDC_REG_IRQ_TIMEOUT 0x0094 #define TDC_REG_IRQ_TIMEOUT 0x0094
#define TDC_REG_DAC_TUNE 0x0098 #define TDC_REG_DAC_TUNE 0x0098
#define TDC_REG_CURRENT_UTC 0x00a0 #define TDC_REG_CURRENT_UTC 0x00a0
#define TDC_REG_BUFFER_PTR 0x00a8 #define TDC_REG_BUFFER_PTR 0x00a8
#define TDC_REG_CTRL 0x00fc #define TDC_REG_CTRL 0x00fc
#define TDC_REG_WR_CTRL 0x00b4 #define TDC_REG_WR_CTRL 0x00b4
#define TDC_REG_WR_STAT 0x00b0 #define TDC_REG_WR_STAT 0x00b0
#define TDC_WR_CTRL_ENABLE BIT(0) #define TDC_WR_CTRL_ENABLE BIT(0)
#define TDC_WR_STAT_ENABLED BIT(6) #define TDC_WR_STAT_ENABLED BIT(6)
#define TDC_WR_STAT_LINK BIT(2) #define TDC_WR_STAT_LINK BIT(2)
#define TDC_WR_STAT_TIME_VALID BIT(8) #define TDC_WR_STAT_TIME_VALID BIT(8)
#define TDC_WR_STAT_AUX_LOCKED BIT(4) #define TDC_WR_STAT_AUX_LOCKED BIT(4)
/* TDC_REG_CTRL bits */ /* TDC_REG_CTRL bits */
#define TDC_CTRL_EN_ACQ BIT(0) #define TDC_CTRL_EN_ACQ BIT(0)
#define TDC_CTRL_DIS_ACQ BIT(1) #define TDC_CTRL_DIS_ACQ BIT(1)
#define TDC_CTRL_LOAD_ACAM_CFG BIT(2) #define TDC_CTRL_LOAD_ACAM_CFG BIT(2)
#define TDC_CTRL_READ_ACAM_CFG BIT(3) #define TDC_CTRL_READ_ACAM_CFG BIT(3)
#define TDC_CTRL_READ_ACAM_STAT BIT(4) #define TDC_CTRL_READ_ACAM_STAT BIT(4)
#define TDC_CTRL_READ_ACAM_IFIFO1 BIT(5) #define TDC_CTRL_READ_ACAM_IFIFO1 BIT(5)
#define TDC_CTRL_READ_ACAM_IFIFO2 BIT(6) #define TDC_CTRL_READ_ACAM_IFIFO2 BIT(6)
#define TDC_CTRL_READ_ACAM_START01_R BIT(7) #define TDC_CTRL_READ_ACAM_START01_R BIT(7)
#define TDC_CTRL_RESET_ACAM BIT(8) #define TDC_CTRL_RESET_ACAM BIT(8)
#define TDC_CTRL_LOAD_UTC BIT(9) #define TDC_CTRL_LOAD_UTC BIT(9)
#define TDC_CTRL_CLEAR_DACAPO_FLAG BIT(10) #define TDC_CTRL_CLEAR_DACAPO_FLAG BIT(10)
#define TDC_CTRL_CONFIG_DAC BIT(11) #define TDC_CTRL_CONFIG_DAC BIT(11)
/* TDC_REG_INPUT_ENABLE bits */ /* TDC_REG_INPUT_ENABLE bits */
#define TDC_INPUT_ENABLE_FLAG BIT(7) #define TDC_INPUT_ENABLE_FLAG BIT(7)
#define TDC_INPUT_ENABLE_CH1 BIT(16) #define TDC_INPUT_ENABLE_CH1 BIT(16)
#define TDC_INPUT_ENABLE_CH2 BIT(17) #define TDC_INPUT_ENABLE_CH2 BIT(17)
#define TDC_INPUT_ENABLE_CH3 BIT(18) #define TDC_INPUT_ENABLE_CH3 BIT(18)
#define TDC_INPUT_ENABLE_CH4 BIT(19) #define TDC_INPUT_ENABLE_CH4 BIT(19)
#define TDC_INPUT_ENABLE_CH5 BIT(20) #define TDC_INPUT_ENABLE_CH5 BIT(20)
#define TDC_INPUT_ENABLE_CH_ALL (TDC_INPUT_ENABLE_CH1 | \ #define TDC_INPUT_ENABLE_CH_ALL (TDC_INPUT_ENABLE_CH1 | \
TDC_INPUT_ENABLE_CH2 | \ TDC_INPUT_ENABLE_CH2 | \
TDC_INPUT_ENABLE_CH3 | \ TDC_INPUT_ENABLE_CH3 | \
TDC_INPUT_ENABLE_CH4 | \ TDC_INPUT_ENABLE_CH4 | \
TDC_INPUT_ENABLE_CH5) TDC_INPUT_ENABLE_CH5)
/* IRQ controler registers */ /* IRQ controler registers */
#define TDC_REG_EIC_IDR 0x0 #define TDC_REG_EIC_IDR 0x0
#define TDC_REG_EIC_IER 0x4 #define TDC_REG_EIC_IER 0x4
#define TDC_REG_EIC_IMR 0x8 #define TDC_REG_EIC_IMR 0x8
#define TDC_REG_EIC_ISR 0xc #define TDC_REG_EIC_ISR 0xc
/* IRQ status/enable bits */ /* IRQ status/enable bits */
#define TDC_IRQ_TDC_TSTAMP BIT(0) #define TDC_IRQ_TDC_TSTAMP BIT(0)
#define TDC_IRQ_TDC_TIME BIT(1) #define TDC_IRQ_TDC_TIME BIT(1)
#define TDC_EVENT_BUFFER_SIZE 256 #define TDC_EVENT_BUFFER_SIZE 256
#define TDC_EVENT_CHANNEL_MASK 0xF #define TDC_EVENT_CHANNEL_MASK 0xF
#define TDC_EVENT_SLOPE_MASK 0xF0 #define TDC_EVENT_SLOPE_MASK 0xF0
#define TDC_EVENT_FIFO_LF_MASK 0xF00 #define TDC_EVENT_FIFO_LF_MASK 0xF00
#define TDC_EVENT_FIFO_EF_MASK 0xF000 #define TDC_EVENT_FIFO_EF_MASK 0xF000
#define TDC_EVENT_DACAPO_FLAG BIT(0) #define TDC_EVENT_DACAPO_FLAG BIT(0)
/* FIFO registers */ /* FIFO registers */
#define TDC_FIFO_OFFSET 0x100 #define TDC_FIFO_OFFSET 0x100
#define TDC_FIFO_LAST 0x0 #define TDC_FIFO_LAST 0x0
#define TDC_FIFO_LAST_N 4 #define TDC_FIFO_LAST_N 4
#define TDC_FIFO_LAST_CSR 0x10 #define TDC_FIFO_LAST_CSR 0x10
#define TDC_FIFO_LAST_CSR_VALID BIT(0) #define TDC_FIFO_LAST_CSR_VALID BIT(0)
#define TDC_FIFO_LAST_CSR_RST_SEQ BIT(1) #define TDC_FIFO_LAST_CSR_RST_SEQ BIT(1)
#define TDC_FIFO_OUT 0x14 #define TDC_FIFO_OUT 0x14
#define TDC_FIFO_OUT_N 4 #define TDC_FIFO_OUT_N 4
#define TDC_FIFO_CSR 0x24 #define TDC_FIFO_CSR 0x24
#define TDC_FIFO_CSR_EMPTY BIT(17) #define TDC_FIFO_CSR_EMPTY BIT(17)
#define TDC_FIFO_CSR_FULL BIT(16) #define TDC_FIFO_CSR_FULL BIT(16)
#define TDC_FIFO_CSR_USEDW #define TDC_FIFO_CSR_USEDW
/* Carrier CSRs */ /* Carrier CSRs */
#define TDC_REG_CARRIER_CTL0 0x0 /* a.k.a. Carrier revision/PCB id reg */ #define TDC_REG_CARRIER_CTL0 0x0 /* a.k.a. Carrier revision/PCB id reg */
#define TDC_REG_CARRIER_STATUS 0x4 #define TDC_REG_CARRIER_STATUS 0x4
#define TDC_REG_CARRIER_CTL1 0x8 #define TDC_REG_CARRIER_CTL1 0x8
#define TDC_REG_CARRIER_RST 0xc #define TDC_REG_CARRIER_RST 0xc
#define TDC_CARRIER_CTL0_PLL_STAT_FMC0 BIT(5) #define TDC_CARRIER_CTL0_PLL_STAT_FMC0 BIT(5)
#define TDC_CARRIER_CTL0_PLL_STAT_FMC1 BIT(6) #define TDC_CARRIER_CTL0_PLL_STAT_FMC1 BIT(6)
#define TDC_CARRIER_CTL1_RSTN_FMC0 BIT(3) #define TDC_CARRIER_CTL1_RSTN_FMC0 BIT(3)
#define TDC_CARRIER_CTL1_RSTN_FMC1 BIT(4) #define TDC_CARRIER_CTL1_RSTN_FMC1 BIT(4)
/* Gennum DMA registers (not defined in the SPEC driver headers) */ /* Gennum DMA registers (not defined in the SPEC driver headers) */
#define TDC_REG_DMA_CTRL 0x0 #define TDC_REG_DMA_CTRL 0x0
#define TDC_REG_DMA_STAT 0x4 #define TDC_REG_DMA_STAT 0x4
#define TDC_REG_DMA_C_START 0x8 #define TDC_REG_DMA_C_START 0x8
#define TDC_REG_DMA_H_START_L 0x0c #define TDC_REG_DMA_H_START_L 0x0c
#define TDC_REG_DMA_H_START_H 0x10 #define TDC_REG_DMA_H_START_H 0x10
#define TDC_REG_DMA_NEXT_L 0x18 #define TDC_REG_DMA_NEXT_L 0x18
#define TDC_REG_DMA_NEXT_H 0x1c #define TDC_REG_DMA_NEXT_H 0x1c
#define TDC_REG_DMA_LEN 0x14 #define TDC_REG_DMA_LEN 0x14
#define TDC_REG_DMA_ATTRIB 0x20 #define TDC_REG_DMA_ATTRIB 0x20
/* TDC_REG_DMA_STAT bits */ /* TDC_REG_DMA_STAT bits */
#define TDC_DMA_STAT_MASK 0x7 #define TDC_DMA_STAT_MASK 0x7
#define TDC_DMA_STAT_DONE 0x1 #define TDC_DMA_STAT_DONE 0x1
#define TDC_DMA_STAT_ERROR 0x3 #define TDC_DMA_STAT_ERROR 0x3
/* TDC core submodule offsets (wrs to the TDC control registers block) */ /* TDC core submodule offsets (wrs to the TDC control registers block) */
#define TDC_MEZZ_ONEWIRE_OFFSET -0x1000
#define TDC_MEZZ_ONEWIRE_OFFSET (-0x1000) #define TDC_MEZZ_EIC_OFFSET 0x1000
#define TDC_MEZZ_EIC_OFFSET (0x1000) #define TDC_MEZZ_I2C_OFFSET 0x2000
#define TDC_MEZZ_I2C_OFFSET (0x2000) #define TDC_MEZZ_MEM_OFFSET 0x3000
#define TDC_MEZZ_MEM_OFFSET (0x3000)
#endif /* __TDC_REGISTERS_H */ #endif /* __TDC_REGISTERS_H */
/* /**
* Copyright (C) 2013-2018 CERN (www.cern.ch) * @file wrtd-rt-tdc.c
* Author: Federico Vaga <federico.vaga@cern.ch> *
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Copyright (c) 2018-2019 CERN (home.cern)
* *
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#include "mockturtle-rt.h" #include "mockturtle-rt.h"
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
#include "wrtd-common.h" #include "wrtd-common.h"
...@@ -75,11 +74,11 @@ static int wrtd_user_init(void) ...@@ -75,11 +74,11 @@ static int wrtd_user_init(void)
{ {
tdc_init(&tdc0); tdc_init(&tdc0);
wr_enable_lock(0); wr_enable_lock(0);
pr_debug("rt-tdc firmware initialized.\n\r"); pr_debug("rt-tdc firmware initialized.\n\r");
return 0; return 0;
} }
static void wrtd_io(void) static void wrtd_io(void)
......
This diff is collapsed.
...@@ -23,24 +23,27 @@ ...@@ -23,24 +23,27 @@
/** /**
* WRTD timestamp format * WRTD timestamp format
*/ */
struct wrtd_tstamp { // TODO: maybe distinguish between UTC and TAI
// TODO: maybe distinguish between UTC and TAI typedef struct wrtd_tstamp {
/** TAI seconds since 1/1/1970 (Unix Epoch Time). */
uint32_t seconds; uint32_t seconds;
/** Number of nanoseconds. Wraps at 10e9. */
uint32_t ns; uint32_t ns;
/** Number of fractional nanoseconds. Unit is 2e-32 ns. */
uint32_t frac; uint32_t frac;
}; } wrtd_tstamp;
struct wrtd_event { struct wrtd_event {
/* Time of the event. */ /** Time of the event. */
struct wrtd_tstamp ts; struct wrtd_tstamp ts;
/* Event id. */ /** Event id. */
char id[WRTD_ID_LEN]; char id[WRTD_ID_LEN];
/* Sequence number. */ /** Sequence number. */
uint32_t seq; uint32_t seq;
/* Associated flags. */ /** Associated flags. */
unsigned char flags; unsigned char flags;
}; };
......
...@@ -38,7 +38,7 @@ enum wrtd_status wrtd_attr_set_alarm_period(struct wrtd_dev *wrtd, ...@@ -38,7 +38,7 @@ enum wrtd_status wrtd_attr_set_alarm_period(struct wrtd_dev *wrtd,
if (value->seconds != 0) if (value->seconds != 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value.seconds", parameter value.seconds",
value->seconds, __func__); value->seconds, __func__);
...@@ -153,7 +153,7 @@ enum wrtd_status wrtd_attr_set_alarm_repeat_count(struct wrtd_dev *wrtd, ...@@ -153,7 +153,7 @@ enum wrtd_status wrtd_attr_set_alarm_repeat_count(struct wrtd_dev *wrtd,
if (value < 0) if (value < 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value", value, __func__); parameter value", value, __func__);
status = wrtd_find_alarm(wrtd, rep_cap_id, &idx, __func__); status = wrtd_find_alarm(wrtd, rep_cap_id, &idx, __func__);
...@@ -194,7 +194,7 @@ enum wrtd_status wrtd_attr_set_rule_repeat_count(struct wrtd_dev *wrtd, ...@@ -194,7 +194,7 @@ enum wrtd_status wrtd_attr_set_rule_repeat_count(struct wrtd_dev *wrtd,
if (value < 0) if (value < 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value", value, __func__); parameter value", value, __func__);
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__); status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
...@@ -409,7 +409,7 @@ enum wrtd_status wrtd_attr_set_rule_delay(struct wrtd_dev *wrtd, ...@@ -409,7 +409,7 @@ enum wrtd_status wrtd_attr_set_rule_delay(struct wrtd_dev *wrtd,
if (value->seconds != 0) if (value->seconds != 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value.seconds", parameter value.seconds",
value->seconds, __func__); value->seconds, __func__);
...@@ -452,7 +452,7 @@ enum wrtd_status wrtd_attr_set_rule_holdoff(struct wrtd_dev *wrtd, ...@@ -452,7 +452,7 @@ enum wrtd_status wrtd_attr_set_rule_holdoff(struct wrtd_dev *wrtd,
if (value->seconds != 0) if (value->seconds != 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value.seconds", parameter value.seconds",
value->seconds, __func__); value->seconds, __func__);
...@@ -495,7 +495,7 @@ enum wrtd_status wrtd_attr_set_rule_resync_period(struct wrtd_dev *wrtd, ...@@ -495,7 +495,7 @@ enum wrtd_status wrtd_attr_set_rule_resync_period(struct wrtd_dev *wrtd,
if (value->seconds != 0) if (value->seconds != 0)
return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE, return wrtd_return_error(wrtd, WRTD_ERROR_INVALID_VALUE,
"Invalid value (%d) for function %s, \ "Invalid value (%d) for function %s, \
parameter value.seconds", parameter value.seconds",
value->seconds, __func__); value->seconds, __func__);
...@@ -850,6 +850,29 @@ enum wrtd_status wrtd_attr_get_rule_send_late(struct wrtd_dev *wrtd, ...@@ -850,6 +850,29 @@ enum wrtd_status wrtd_attr_get_rule_send_late(struct wrtd_dev *wrtd,
return WRTD_SUCCESS; return WRTD_SUCCESS;
} }
enum wrtd_status wrtd_attr_get_sys_time(struct wrtd_dev *wrtd,
struct wrtd_tstamp *value)
{
enum wrtd_status status;
struct wrtd_config_msg msg;
if(wrtd == NULL){
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Always use CPU #0 (it does exist!). */
status = wrtd_msg_get_config(wrtd, 0, &msg, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = msg.now;
return WRTD_SUCCESS;
}
/**
*@} End group Time
*/
enum wrtd_status wrtd_attr_global(struct wrtd_dev *wrtd, enum wrtd_status wrtd_attr_global(struct wrtd_dev *wrtd,
const char *rep_cap_id) const char *rep_cap_id)
{ {
......
...@@ -123,7 +123,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd, ...@@ -123,7 +123,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
} }
/* Clean up errno to be able to distinguish between error cases and /* Clean up errno to be able to distinguish between error cases and
normal behaviour when the function return less messages normal behaviour when the function returns less messages
than expected */ than expected */
errno = 0; errno = 0;
...@@ -135,7 +135,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd, ...@@ -135,7 +135,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
} }
if (ret < 0) if (ret < 0)
return wrtd_return_error return wrtd_return_error
(wrtd, WRTD_ERROR_INTERNAL, "%s/%s: %s", (wrtd, WRTD_ERROR_INTERNAL, "%s/%s(poll): %s",
caller_func, __func__, trtl_strerror(errno)); caller_func, __func__, trtl_strerror(errno));
for (i = 0; i < wrtd->nbr_cpus; ++i) { for (i = 0; i < wrtd->nbr_cpus; ++i) {
...@@ -144,7 +144,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd, ...@@ -144,7 +144,7 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
ret = trtl_msg_async_recv(wrtd->trtl, i, WRTD_HMQ, &msg, 1); ret = trtl_msg_async_recv(wrtd->trtl, i, WRTD_HMQ, &msg, 1);
if (ret <= 0) if (ret <= 0)
return wrtd_return_error return wrtd_return_error
(wrtd, WRTD_ERROR_INTERNAL, "%s/%s: %s", (wrtd, WRTD_ERROR_INTERNAL, "%s/%s(recv): %s",
caller_func, __func__, trtl_strerror(errno)); caller_func, __func__, trtl_strerror(errno));
memcpy(log, msg.data, sizeof(struct wrtd_log_entry)); memcpy(log, msg.data, sizeof(struct wrtd_log_entry));
...@@ -321,17 +321,16 @@ enum wrtd_status wrtd_fill_roots(struct wrtd_dev *wrtd, const char *caller_func) ...@@ -321,17 +321,16 @@ enum wrtd_status wrtd_fill_roots(struct wrtd_dev *wrtd, const char *caller_func)
if (status != WRTD_SUCCESS) if (status != WRTD_SUCCESS)
return status; return status;
if (wrtd->roots[cpu].ver_major != WRTD_VERSION_MAJOR) { if (wrtd->roots[cpu].ver_major != WRTD_VERSION_MAJOR) {
status = wrtd_return_error /* Invalidate root. */
wrtd->roots[cpu].ver_major = 0;
return wrtd_return_error
(wrtd, WRTD_ERROR_VERSION_MISMATCH, (wrtd, WRTD_ERROR_VERSION_MISMATCH,
"%s/%s: incorrect major version (%d instead of %d)", "%s/%s: incorrect major version (%d instead of %d)",
caller_func, __func__, caller_func, __func__,
wrtd->roots[cpu].ver_major, wrtd->roots[cpu].ver_major,
WRTD_VERSION_MAJOR); WRTD_VERSION_MAJOR);
/* Invalidate root. */
wrtd->roots[cpu].ver_major = 0;
return status;
} }
if (wrtd->roots[cpu].ver_minor != WRTD_VERSION_MINOR) { if (wrtd->roots[cpu].ver_minor > WRTD_VERSION_MINOR) {
/* Invalidate root. */ /* Invalidate root. */
wrtd->roots[cpu].ver_major = 0; wrtd->roots[cpu].ver_major = 0;
return wrtd_return_error return wrtd_return_error
...@@ -621,4 +620,3 @@ inline enum wrtd_status wrtd_rule_check_disabled(struct wrtd_dev *wrtd, unsigned ...@@ -621,4 +620,3 @@ inline enum wrtd_status wrtd_rule_check_disabled(struct wrtd_dev *wrtd, unsigned
caller_func, __func__); caller_func, __func__);
return WRTD_SUCCESS; return WRTD_SUCCESS;
} }
...@@ -11,13 +11,6 @@ ...@@ -11,13 +11,6 @@
#define WRTD_RETURN_IF_ERROR(status) if(status != WRTD_SUCCESS) return status #define WRTD_RETURN_IF_ERROR(status) if(status != WRTD_SUCCESS) return status
/* A complete log entry needs 35+1+35+1+9+1+8=90 + 1 for null termination.
1st field: log tstamp in YYYY-MM-DD,hh:mm:ss.xxx.yyy.zzz+fff format.
2nd field: event tstamp in YYYY-MM-DD,hh:mm:ss.xxx.yyy.zzz+fff format.
3rd field: log type, padded with spaces to 9 characters.
4th field: log reason, padded with spaces to 8 characters. */
#define WRTD_LOG_ENTRY_SIZE 91
#define WRTD_DEFAULT_TIMEOUT 1000 #define WRTD_DEFAULT_TIMEOUT 1000
/* Add nanoseconds to an existing wrtd timestamp */ /* Add nanoseconds to an existing wrtd timestamp */
...@@ -302,6 +295,8 @@ enum wrtd_status wrtd_attr_set_rule_send_late(struct wrtd_dev *wrtd, ...@@ -302,6 +295,8 @@ enum wrtd_status wrtd_attr_set_rule_send_late(struct wrtd_dev *wrtd,
enum wrtd_status wrtd_attr_get_rule_send_late(struct wrtd_dev *wrtd, enum wrtd_status wrtd_attr_get_rule_send_late(struct wrtd_dev *wrtd,
const char *rep_cap_id, const char *rep_cap_id,
bool *value); bool *value);
enum wrtd_status wrtd_attr_get_sys_time(struct wrtd_dev *wrtd,
struct wrtd_tstamp *value);
enum wrtd_status wrtd_attr_global(struct wrtd_dev *wrtd, enum wrtd_status wrtd_attr_global(struct wrtd_dev *wrtd,
const char *rep_cap_id); const char *rep_cap_id);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /**
* Copyright (C) 2014-2016 CERN (www.cern.ch) * @file wrtd-internal.h
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* *
* This program is distributed in the hope that it will be useful, * Copyright (c) 2018-2019 CERN (home.cern)
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * SPDX-License-Identifier: LGPL-3.0-or-later
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __WRTD_TOOLS_INTERNAL_H__ #ifndef __WRTD_TOOLS_INTERNAL_H__
...@@ -24,9 +13,9 @@ ...@@ -24,9 +13,9 @@
#include <libwrtd.h> #include <libwrtd.h>
struct wrtd_commands { struct wrtd_commands {
const char *name; const char *name;
const char *parm; const char *parm;
const char *desc; const char *desc;
enum wrtd_status (*handler)(struct wrtd_dev *wrtd, enum wrtd_status (*handler)(struct wrtd_dev *wrtd,
int argc, char **argv); int argc, char **argv);
}; };
......
/* /**
* Copyright (C) 2014-2016 CERN (www.cern.ch) * @file wrtd-logging.c
* Author: Federico Vaga <federico.vaga@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify * Copyright (c) 2018-2019 CERN (home.cern)
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* *
* This program is distributed in the hope that it will be useful, * SPDX-License-Identifier: LGPL-3.0-or-later
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
...@@ -29,21 +19,20 @@ ...@@ -29,21 +19,20 @@
static void help(void) static void help(void)
{ {
fprintf(stderr, "wrtd-logging -D <device>\n"); fprintf(stderr, "wrtd-logging -D <device>\n");
fprintf(stderr, "It shows logging information coming from Real-Time applications\n"); fprintf(stderr, "It shows logging information coming from Real-Time applications\n");
fprintf(stderr, "-D device id\n"); fprintf(stderr, "-D device id\n");
fprintf(stderr, "-n number of messages to read (0 means infinite)\n"); fprintf(stderr, "-n number of messages to read (0 means infinite)\n");
exit(1); exit(1);
} }
static void print_logging (struct wrtd_dev *wrtd, int n_read) static void print_logging (struct wrtd_dev *wrtd, int n_read)
{ {
char log_entry[WRTD_LOG_ENTRY_SIZE]; char log_entry[WRTD_LOG_ENTRY_SIZE];
enum wrtd_status status; enum wrtd_status status;
unsigned int i; unsigned int i;
for(i = 0; i < n_read || n_read == 0; i++) { for(i = 0; i < n_read || n_read == 0; i++) {
do { do {
status = wrtd_get_next_event_log_entry( status = wrtd_get_next_event_log_entry(
wrtd, WRTD_LOG_ENTRY_SIZE, log_entry); wrtd, WRTD_LOG_ENTRY_SIZE, log_entry);
...@@ -63,48 +52,48 @@ static void print_logging (struct wrtd_dev *wrtd, int n_read) ...@@ -63,48 +52,48 @@ static void print_logging (struct wrtd_dev *wrtd, int n_read)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct wrtd_dev *wrtd; struct wrtd_dev *wrtd;
const char *dev_name = NULL; const char *dev_name = NULL;
enum wrtd_status status; enum wrtd_status status;
char *endptr; char *endptr;
int n_read = 0; int n_read = 0;
char c; char c;
while ((c = getopt (argc, argv, "hD:n:")) != -1) { while ((c = getopt (argc, argv, "hD:n:")) != -1) {
switch (c) { switch (c) {
default: default:
help(); help();
break; break;
case 'D': case 'D':
dev_name = optarg; dev_name = optarg;
break; break;
case 'n': case 'n':
n_read = strtoul(optarg, &endptr, 0); n_read = strtoul(optarg, &endptr, 0);
if (*endptr != 0) { if (*endptr != 0) {
fprintf(stderr, "bad value for -n"); fprintf(stderr, "bad value for -n");
exit (1); exit (1);
} }
break; break;
} }
} }
if (dev_name == NULL) { if (dev_name == NULL) {
help(); help();
exit(1); exit(1);
} }
/* Open. */ /* Open. */
status = wrtd_init(dev_name, 0, NULL, &wrtd); status = wrtd_init(dev_name, 0, NULL, &wrtd);
if (status != WRTD_SUCCESS) { if (status != WRTD_SUCCESS) {
char error_message[256]; char error_message[256];
enum wrtd_status error_status; enum wrtd_status error_status;
wrtd_get_error (wrtd, &error_status, 256, error_message); wrtd_get_error (wrtd, &error_status, 256, error_message);
fprintf(stderr, "Cannot open WRTD: %s\n", error_message); fprintf(stderr, "Cannot open WRTD: %s\n", error_message);
return 1; return 1;
} }
print_logging (wrtd, n_read); print_logging (wrtd, n_read);
wrtd_close(wrtd); wrtd_close(wrtd);
exit(0); exit(0);
} }
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