Commit 98e64175 authored by Alessandro Rubini's avatar Alessandro Rubini

calibrate: added timer_temp (renamed timer_fifo)

parent 62903999
...@@ -15,10 +15,14 @@ ...@@ -15,10 +15,14 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/moduleparam.h>
#include "fine-delay.h" #include "fine-delay.h"
#include "hw/fd_main_regs.h" #include "hw/fd_main_regs.h"
#include "hw/acam_gpx.h" #include "hw/acam_gpx.h"
int fd_calib_period_s = 30;
module_param_named(calib_s, fd_calib_period_s, int, 0444);
/* /*
* Calculation is fixed point: picoseconds and 16 decimals (i.e. ps << 16). * Calculation is fixed point: picoseconds and 16 decimals (i.e. ps << 16).
* We know the bin is small, but the Tref is several nanos so we need 64 bits * We know the bin is small, but the Tref is several nanos so we need 64 bits
...@@ -331,10 +335,15 @@ int fd_acam_init(struct spec_fd *fd) ...@@ -331,10 +335,15 @@ int fd_acam_init(struct spec_fd *fd)
fd_writel(fd, 3 * fd->calib.acam_start_offset, FD_REG_ASOR); fd_writel(fd, 3 * fd->calib.acam_start_offset, FD_REG_ASOR);
fd_writel(fd, fd->calib.atmcr_val, FD_REG_ATMCR); fd_writel(fd, fd->calib.atmcr_val, FD_REG_ATMCR);
/* Prepare the timely recalibration */
setup_timer(&fd->temp_timer, fd_update_calibration, (unsigned long)fd);
if (fd_calib_period_s)
mod_timer(&fd->temp_timer, jiffies + HZ * fd_calib_period_s);
return 0; return 0;
} }
void fd_acam_exit(struct spec_fd *fd) void fd_acam_exit(struct spec_fd *fd)
{ {
/* nothing to do */ del_timer_sync(&fd->temp_timer);
} }
...@@ -179,25 +179,55 @@ static int fd_find_8ns_tap(struct spec_fd *fd, int ch) ...@@ -179,25 +179,55 @@ static int fd_find_8ns_tap(struct spec_fd *fd, int ch)
int fd_calibrate_outputs(struct spec_fd *fd) int fd_calibrate_outputs(struct spec_fd *fd)
{ {
int ret, ch; int ret, ch;
int measured, fitted; int measured, fitted, new;
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);
if ((ret = acam_test_delay_transfer_function(fd)) < 0) if ((ret = acam_test_delay_transfer_function(fd)) < 0)
return ret; return ret;
fd_read_temp(fd, 0);
fitted = fd_eval_polynomial(fd); fitted = fd_eval_polynomial(fd);
for (ch = FD_CH_1; ch <= FD_CH_LAST; ch++) { for (ch = FD_CH_1; ch <= FD_CH_LAST; ch++) {
fd_read_temp(fd, 0);
measured = fd_find_8ns_tap(fd, ch); measured = fd_find_8ns_tap(fd, ch);
fd->ch[ch].frr_cur = measured; new = measured;
fd->ch[ch].frr_offset = measured - fitted; fd->ch[ch].frr_offset = new - fitted;
pr_info("%s: ch %i: 8ns @ %i (f %i, offset %i, t %i.%02i)\n", fd_ch_writel(fd, ch, new, FD_REG_FRR);
__func__, FD_CH_EXT(ch), fd->ch[ch].frr_cur = new;
fd->ch[ch].frr_cur, fitted, fd->ch[ch].frr_offset, if (1) {
fd->temp / 16, (fd->temp & 0xf) * 100 / 16); pr_info("%s: ch%i: 8ns @%i (f %i, off %i, t %i.%02i)\n",
__func__, FD_CH_EXT(ch),
new, fitted, fd->ch[ch].frr_offset,
fd->temp / 16, (fd->temp & 0xf) * 100 / 16);
}
} }
return 0; return 0;
} }
/* Called from a timer any few seconds */
void fd_update_calibration(unsigned long arg)
{
struct spec_fd *fd = (void *)arg;
int ch, fitted, new;
fd_read_temp(fd, 0 /* not verbose */);
fitted = fd_eval_polynomial(fd);
for (ch = FD_CH_1; ch <= FD_CH_LAST; ch++) {
new = fitted + fd->ch[ch].frr_offset;
fd_ch_writel(fd, ch, new, FD_REG_FRR);
fd->ch[ch].frr_cur = new;
if (0) {
pr_info("%s: ch%i: 8ns @%i (f %i, off %i, t %i.%02i)\n",
__func__, FD_CH_EXT(ch),
new, fitted, fd->ch[ch].frr_offset,
fd->temp / 16, (fd->temp & 0xf) * 100 / 16);
}
}
mod_timer(&fd->temp_timer, jiffies + HZ * fd_calib_period_s);
}
...@@ -275,6 +275,12 @@ The following parameters are used: ...@@ -275,6 +275,12 @@ The following parameters are used:
polling code. The interval by default is 10ms and currently polling code. The interval by default is 10ms and currently
only one timestamp is retrieved at each timer execution. only one timestamp is retrieved at each timer execution.
@item calib_s=
The period, in seconds, of temperature measurement to recalibrate
the output delays. Defaults to 30. If set to zero, the timer is
not activated.
@end table @end table
@c ########################################################################## @c ##########################################################################
......
...@@ -304,7 +304,7 @@ static void fd_timer_fn(unsigned long arg) ...@@ -304,7 +304,7 @@ static void fd_timer_fn(unsigned long arg)
} }
out: out:
mod_timer(&fd->timer, jiffies + fd_timer_period_jiffies); mod_timer(&fd->fifo_timer, jiffies + fd_timer_period_jiffies);
} }
static int fd_output(struct zio_cset *cset) static int fd_output(struct zio_cset *cset)
...@@ -490,15 +490,15 @@ int fd_zio_init(struct spec_fd *fd) ...@@ -490,15 +490,15 @@ int fd_zio_init(struct spec_fd *fd)
return err; return err;
} }
setup_timer(&fd->timer, fd_timer_fn, (unsigned long)fd); setup_timer(&fd->fifo_timer, fd_timer_fn, (unsigned long)fd);
if (fd_timer_period_ms) if (fd_timer_period_ms)
mod_timer(&fd->timer, jiffies + fd_timer_period_jiffies); mod_timer(&fd->fifo_timer, jiffies + fd_timer_period_jiffies);
return 0; return 0;
} }
void fd_zio_exit(struct spec_fd *fd) void fd_zio_exit(struct spec_fd *fd)
{ {
del_timer_sync(&fd->timer); del_timer_sync(&fd->fifo_timer);
zio_unregister_device(fd->hwzdev); zio_unregister_device(fd->hwzdev);
zio_free_device(fd->hwzdev); zio_free_device(fd->hwzdev);
} }
...@@ -93,7 +93,8 @@ struct spec_fd { ...@@ -93,7 +93,8 @@ struct spec_fd {
unsigned long flags; unsigned long flags;
struct spec_dev *spec; struct spec_dev *spec;
struct zio_device *zdev, *hwzdev; struct zio_device *zdev, *hwzdev;
struct timer_list timer; struct timer_list fifo_timer;
struct timer_list temp_timer;
struct fd_calib calib; struct fd_calib calib;
struct fd_ch ch[FD_CH_NUMBER]; struct fd_ch ch[FD_CH_NUMBER];
unsigned char __iomem *base; /* regs files are byte-oriented */ unsigned char __iomem *base; /* regs files are byte-oriented */
...@@ -240,6 +241,9 @@ extern void acam_writel(struct spec_fd *fd, int val, int reg); ...@@ -240,6 +241,9 @@ extern void acam_writel(struct spec_fd *fd, int val, int reg);
/* Functions exported by calibrate.c, called within acam.c */ /* Functions exported by calibrate.c, called within acam.c */
extern int fd_calibrate_outputs(struct spec_fd *fd); extern int fd_calibrate_outputs(struct spec_fd *fd);
extern void fd_update_calibration(unsigned long arg);
extern int fd_calib_period_s;
/* Functions exported by gpio.c */ /* Functions exported by gpio.c */
extern int fd_gpio_init(struct spec_fd *fd); extern int fd_gpio_init(struct spec_fd *fd);
......
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