Commit 8924b43d authored by Federico Vaga's avatar Federico Vaga

kernel: add comments to explain driver behavior

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent ebdd9e63
......@@ -152,6 +152,7 @@ static int fd_find_8ns_tap(struct fd_dev *fd, int ch)
* Measure the delay at zero setting, so it can be further
* subtracted to get only the delay part introduced by the
* delay line (ingoring the TDC, FPGA and routing delays).
* Use a binary search of the delay value.
*/
bias = output_delay_ps(fd, ch, 0, FD_CAL_STEPS, NULL);
while( r - l > 1) {
......@@ -174,6 +175,12 @@ static int fd_find_8ns_tap(struct fd_dev *fd, int ch)
}
/**
* fd_calibrate_outputs
* It calibrates the delay line by finding the correct 8ns-tap value
* for each channel. This is done during ACAM initialization, so on driver
* probe.
*/
int fd_calibrate_outputs(struct fd_dev *fd)
{
int ret, ch;
......@@ -206,7 +213,11 @@ int fd_calibrate_outputs(struct fd_dev *fd)
return 0;
}
/* Called from a timer any few seconds */
/**
* fd_update_calibration
* Called from a timer any few seconds. It updates the Delay line tap
* according to the measured temperature
*/
void fd_update_calibration(unsigned long arg)
{
struct fd_dev *fd = (void *)arg;
......
......@@ -41,10 +41,18 @@ module_param_named(show_sdb, fd_show_sdb, int, 0444);
/* FIXME: add parameters "file=" and "wrc=" like wr-nic-core does */
/* The reset function (by Tomasz) */
/**
* fd_do_reset
* The reset function (by Tomasz)
*
* This function can reset the entire mezzanine (FMC) or just
* the fine-delay core (CORE).
* In the reset register 0 means reset, 1 means normal operation.
*/
static void fd_do_reset(struct fd_dev *fd, int hw_reset)
{
if (hw_reset) {
/* clear RSTS_RST_FMC bit, set RSTS_RST_CORE bit*/
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_CORE_MASK,
FD_REG_RSTR);
udelay(10000);
......@@ -55,6 +63,7 @@ static void fd_do_reset(struct fd_dev *fd, int hw_reset)
return;
}
/* clear RSTS_RST_CORE bit, set RSTS_RST_FMC bit */
fd_writel(fd, FD_RSTR_LOCK_W(0xdead) | FD_RSTR_RST_FMC_MASK,
FD_REG_RSTR);
udelay(1000);
......
......@@ -540,40 +540,54 @@ static int __fd_zio_output(struct fd_dev *fd, int index1_4, uint32_t *attrs)
fd->calib.tdc_zero_offset);
}
/* Apply offset to START timestamp */
fd_apply_offset(attrs + FD_ATTR_OUT_START_H,
fd->calib.zero_offset[ch]);
fd_apply_offset(attrs + FD_ATTR_OUT_START_H,
fd->ch_user_offset[ch]);
/* Apply offset to END timestamp */
fd_apply_offset(attrs + FD_ATTR_OUT_END_H,
fd->calib.zero_offset[ch]);
fd_apply_offset(attrs + FD_ATTR_OUT_END_H,
fd->ch_user_offset[ch]);
/* Update Fine Register with calibrated value */
fd_ch_writel(fd, ch, fd->ch[ch].frr_cur, FD_REG_FRR);
/* Write Pulse Start Absolute Time */
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_START_H], FD_REG_U_STARTH);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_START_L], FD_REG_U_STARTL);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_START_COARSE], FD_REG_C_START);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_START_FINE], FD_REG_F_START);
/* Write Pulse End Absolute Time */
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_END_H], FD_REG_U_ENDH);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_END_L], FD_REG_U_ENDL);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_END_COARSE], FD_REG_C_END);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_END_FINE], FD_REG_F_END);
/* Write clock cycles between rasing edges of output pulses */
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_DELTA_L], FD_REG_U_DELTA);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_DELTA_COARSE], FD_REG_C_DELTA);
fd_ch_writel(fd, ch, attrs[FD_ATTR_OUT_DELTA_FINE], FD_REG_F_DELTA);
/*
* Configure the number of repetitions and the operational mode.
* The Fine delay always add an extra pulse to the repetition
* counter, so remove it on our side in order to produce exactly
* the number of pulses requested
*/
if (mode == FD_OUT_MODE_DELAY || mode == FD_OUT_MODE_DISABLED) {
/* Delay Mode */
dcr = 0;
fd_ch_writel(fd, ch, FD_RCR_REP_CNT_W(rep - 1)
| (rep < 0 ? FD_RCR_CONT : 0), FD_REG_RCR);
} else {
dcr = FD_DCR_MODE;
/* Pulse Mode */
dcr = FD_DCR_MODE; /* Set pulse mode */
fd_ch_writel(fd, ch, FD_RCR_REP_CNT_W(rep < 0 ? 0 : rep - 1)
| (rep < 0 ? FD_RCR_CONT : 0), FD_REG_RCR);
}
......@@ -620,13 +634,16 @@ static int __fd_zio_output(struct fd_dev *fd, int index1_4, uint32_t *attrs)
if (delta.tv_sec == 0 && delta.tv_nsec < 200)
dcr |= FD_DCR_NO_FINE;
/* Configure Fine Delay output */
fd_ch_writel(fd, ch, dcr, FD_REG_DCR);
/* Update the time stamps according to start/end registers */
fd_ch_writel(fd, ch, dcr | FD_DCR_UPDATE, FD_REG_DCR);
/* Enable channel output */
if (mode == FD_OUT_MODE_DELAY) {
fd_ch_writel(fd, ch, dcr | FD_DCR_ENABLE, FD_REG_DCR);
fd_ch_writel(fd, ch, dcr | FD_DCR_ENABLE, FD_REG_DCR);
} else if (mode == FD_OUT_MODE_PULSE) {
/* ... and arm the pulse generator */
fd_ch_writel(fd, ch, dcr | FD_DCR_ENABLE | FD_DCR_PG_ARM, FD_REG_DCR);
}
return 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