Commit 23090067 authored by Federico Vaga's avatar Federico Vaga

drv: add offset-zero value

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent bb859ef7
...@@ -131,22 +131,23 @@ static int zfad_offset_to_dac(struct zio_channel *chan, ...@@ -131,22 +131,23 @@ static int zfad_offset_to_dac(struct zio_channel *chan,
/* /*
* zfad_apply_user_offset * zfad_apply_user_offset
* @fa: the fmc-adc descriptor
* @chan: the channel where apply offset * @chan: the channel where apply offset
* @usr_val: the offset value to apply, expressed as millivolts (-5000..5000)
* *
* Apply user offset to the channel input. Before apply the user offset it must * Apply user offset to the channel input. Before apply the user offset it must
* be corrected with offset and gain calibration value. An open input does not * be corrected with offset and gain calibration value.
* need any correction. *
* Offset values are taken from `struct fa_dev`, so they must be there before
* calling this function
*/ */
int zfad_apply_user_offset(struct fa_dev *fa, struct zio_channel *chan, int zfad_apply_offset(struct zio_channel *chan)
uint32_t usr_val)
{ {
struct fa_dev *fa = get_zfadc(&chan->cset->zdev->head.dev);
uint32_t range_reg; uint32_t range_reg;
int32_t uval = (int32_t)usr_val; int32_t off_uv;
int hwval, i, range; int hwval, i, range;
if (uval < -5000000 || uval > 5000000) off_uv = fa->user_offset[chan->index] + fa->zero_offset[chan->index];
if (off_uv < -5000000 || off_uv > 5000000)
return -EINVAL; return -EINVAL;
i = zfad_get_chx_index(ZFA_CHx_CTL_RANGE, chan); i = zfad_get_chx_index(ZFA_CHx_CTL_RANGE, chan);
...@@ -159,7 +160,7 @@ int zfad_apply_user_offset(struct fa_dev *fa, struct zio_channel *chan, ...@@ -159,7 +160,7 @@ int zfad_apply_user_offset(struct fa_dev *fa, struct zio_channel *chan,
if (range == FA100M14B4C_RANGE_OPEN || fa_enable_test_data_adc) if (range == FA100M14B4C_RANGE_OPEN || fa_enable_test_data_adc)
range = FA100M14B4C_RANGE_1V; range = FA100M14B4C_RANGE_1V;
hwval = zfad_offset_to_dac(chan, usr_val, range); hwval = zfad_offset_to_dac(chan, off_uv, range);
return zfad_dac_set(chan, hwval); return zfad_dac_set(chan, hwval);
} }
...@@ -173,8 +174,11 @@ void zfad_reset_offset(struct fa_dev *fa) ...@@ -173,8 +174,11 @@ void zfad_reset_offset(struct fa_dev *fa)
{ {
int i; int i;
for (i = 0; i < FA100M14B4C_NCHAN; ++i) for (i = 0; i < FA100M14B4C_NCHAN; ++i) {
zfad_apply_user_offset(fa, &fa->zdev->cset->chan[i], 0); fa->user_offset[i] = 0;
fa->zero_offset[i] = 0;
zfad_apply_offset(&fa->zdev->cset->chan[i]);
}
} }
/* /*
...@@ -210,25 +214,18 @@ int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan, ...@@ -210,25 +214,18 @@ int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan,
i = zfad_get_chx_index(ZFA_CHx_CTL_RANGE, chan); i = zfad_get_chx_index(ZFA_CHx_CTL_RANGE, chan);
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i], zfad_hw_range[range]); fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i], zfad_hw_range[range]);
if (range == FA100M14B4C_RANGE_OPEN || fa_enable_test_data_adc) { if (range == FA100M14B4C_RANGE_OPEN || fa_enable_test_data_adc)
/* range = FA100M14B4C_RANGE_1V;
* With OPEN range we do not use calibration values
* if (range < 0 || range > ARRAY_SIZE(fa->calib.adc)) {
* In test mode we do not apply the gain/offset because dev_info(fa->msgdev, "Invalid range %i or ch %i\n",
* this compromises the test pattern range, chan->index);
*/ return -EINVAL;
offset = FA_CAL_NO_OFFSET;
gain = FA_CAL_NO_GAIN;
} else {
if (range < 0 || range > ARRAY_SIZE(fa->calib.adc)) {
dev_info(fa->msgdev, "Invalid range %i or ch %i\n",
range, chan->index);
return -EINVAL;
}
offset = fa->calib.adc[range].offset[chan->index];
gain = fa->calib.adc[range].gain[chan->index];
} }
offset = fa->calib.adc[range].offset[chan->index];
gain = fa->calib.adc[range].gain[chan->index];
i = zfad_get_chx_index(ZFA_CHx_OFFSET, chan); i = zfad_get_chx_index(ZFA_CHx_OFFSET, chan);
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i], fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i],
offset & 0xffff /* prevent warning */); offset & 0xffff /* prevent warning */);
...@@ -236,7 +233,7 @@ int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan, ...@@ -236,7 +233,7 @@ int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan,
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i], gain); fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[i], gain);
/* recalculate user offset for the new range */ /* recalculate user offset for the new range */
zfad_apply_user_offset(fa, chan, fa->user_offset[chan->index]); zfad_apply_offset(chan);
return 0; return 0;
} }
......
...@@ -47,6 +47,11 @@ static struct zio_attribute zfad_cset_ext_zattr[] = { ...@@ -47,6 +47,11 @@ static struct zio_attribute zfad_cset_ext_zattr[] = {
ZIO_ATTR_EXT("ch2-offset", ZIO_RW_PERM, ZFA_CH3_OFFSET, 0), ZIO_ATTR_EXT("ch2-offset", ZIO_RW_PERM, ZFA_CH3_OFFSET, 0),
ZIO_ATTR_EXT("ch3-offset", ZIO_RW_PERM, ZFA_CH4_OFFSET, 0), ZIO_ATTR_EXT("ch3-offset", ZIO_RW_PERM, ZFA_CH4_OFFSET, 0),
ZIO_ATTR_EXT("ch0-offset-zero", ZIO_RW_PERM, ZFA_SW_CH1_OFFSET_ZERO, 0),
ZIO_ATTR_EXT("ch1-offset-zero", ZIO_RW_PERM, ZFA_SW_CH2_OFFSET_ZERO, 0),
ZIO_ATTR_EXT("ch2-offset-zero", ZIO_RW_PERM, ZFA_SW_CH3_OFFSET_ZERO, 0),
ZIO_ATTR_EXT("ch3-offset-zero", ZIO_RW_PERM, ZFA_SW_CH4_OFFSET_ZERO, 0),
ZIO_ATTR_EXT("ch0-vref", ZIO_RW_PERM, ZFA_CH1_CTL_RANGE, 0), ZIO_ATTR_EXT("ch0-vref", ZIO_RW_PERM, ZFA_CH1_CTL_RANGE, 0),
ZIO_ATTR_EXT("ch1-vref", ZIO_RW_PERM, ZFA_CH2_CTL_RANGE, 0), ZIO_ATTR_EXT("ch1-vref", ZIO_RW_PERM, ZFA_CH2_CTL_RANGE, 0),
ZIO_ATTR_EXT("ch2-vref", ZIO_RW_PERM, ZFA_CH3_CTL_RANGE, 0), ZIO_ATTR_EXT("ch2-vref", ZIO_RW_PERM, ZFA_CH3_CTL_RANGE, 0),
...@@ -168,6 +173,7 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr, ...@@ -168,6 +173,7 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
unsigned int baseoff = fa->fa_adc_csr_base; unsigned int baseoff = fa->fa_adc_csr_base;
struct zio_channel *chan; struct zio_channel *chan;
int i, range, err = 0, reg_index; int i, range, err = 0, reg_index;
uint32_t off;
reg_index = zattr->id; reg_index = zattr->id;
i = FA100M14B4C_NCHAN; i = FA100M14B4C_NCHAN;
...@@ -186,6 +192,21 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr, ...@@ -186,6 +192,21 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
case ZFA_SW_R_NOADDERS_AUTO: case ZFA_SW_R_NOADDERS_AUTO:
fa->enable_auto_start = usr_val; fa->enable_auto_start = usr_val;
return 0; return 0;
case ZFA_SW_CH1_OFFSET_ZERO:
i--;
case ZFA_SW_CH2_OFFSET_ZERO:
i--;
case ZFA_SW_CH3_OFFSET_ZERO:
i--;
case ZFA_SW_CH4_OFFSET_ZERO:
i--;
chan = to_zio_cset(dev)->chan + i;
fa->zero_offset[i] = usr_val;
err = zfad_apply_offset(chan);
if (err == -EIO)
fa->zero_offset[chan->index] = 0;
return err;
case ZFA_CHx_SAT: case ZFA_CHx_SAT:
/* TODO when TLV */ /* TODO when TLV */
break; break;
...@@ -209,21 +230,20 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr, ...@@ -209,21 +230,20 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
i--; i--;
case ZFA_CH4_OFFSET: case ZFA_CH4_OFFSET:
i--; i--;
chan = to_zio_cset(dev)->chan + i; chan = to_zio_cset(dev)->chan + i;
err = zfad_apply_user_offset(fa, chan, usr_val);
if (err)
return err;
fa->user_offset[chan->index] = usr_val; fa->user_offset[chan->index] = usr_val;
return 0; err = zfad_apply_offset(chan);
if (err == -EIO)
fa->user_offset[chan->index] = 0;
return err;
case ZFA_CHx_OFFSET: case ZFA_CHx_OFFSET:
chan = to_zio_chan(dev), chan = to_zio_chan(dev),
err = zfad_apply_user_offset(fa, chan, usr_val);
if (err)
return err;
fa->user_offset[chan->index] = usr_val; fa->user_offset[chan->index] = usr_val;
return 0; err = zfad_apply_offset(chan);
if (err == -EIO)
fa->user_offset[chan->index] = 0;
return err;
case ZFA_CTL_DAC_CLR_N: case ZFA_CTL_DAC_CLR_N:
zfad_reset_offset(fa); zfad_reset_offset(fa);
return 0; return 0;
...@@ -341,6 +361,16 @@ static int zfad_info_get(struct device *dev, struct zio_attribute *zattr, ...@@ -341,6 +361,16 @@ static int zfad_info_get(struct device *dev, struct zio_attribute *zattr,
*usr_val = fa_read_temp(fa, 0); *usr_val = fa_read_temp(fa, 0);
*usr_val = (*usr_val * 1000 + 8) / 16; *usr_val = (*usr_val * 1000 + 8) / 16;
return 0; return 0;
case ZFA_SW_CH1_OFFSET_ZERO:
i--;
case ZFA_SW_CH2_OFFSET_ZERO:
i--;
case ZFA_SW_CH3_OFFSET_ZERO:
i--;
case ZFA_SW_CH4_OFFSET_ZERO:
i--;
*usr_val = fa->zero_offset[i];
return 0;
case ZFA_CHx_SAT: case ZFA_CHx_SAT:
case ZFA_CHx_CTL_TERM: case ZFA_CHx_CTL_TERM:
case ZFA_CHx_CTL_RANGE: case ZFA_CHx_CTL_RANGE:
......
...@@ -303,6 +303,10 @@ enum fa_sw_param_id { ...@@ -303,6 +303,10 @@ enum fa_sw_param_id {
ZFA_SW_R_NOADDRES_TEMP, ZFA_SW_R_NOADDRES_TEMP,
ZFA_SW_R_NOADDERS_AUTO, ZFA_SW_R_NOADDERS_AUTO,
ZFA_SW_CH1_OFFSET_ZERO,
ZFA_SW_CH2_OFFSET_ZERO,
ZFA_SW_CH3_OFFSET_ZERO,
ZFA_SW_CH4_OFFSET_ZERO,
ZFA_SW_PARAM_COMMON_LAST, ZFA_SW_PARAM_COMMON_LAST,
}; };
...@@ -366,7 +370,8 @@ struct fa_calib { ...@@ -366,7 +370,8 @@ struct fa_calib {
* @n_fires: number of trigger fire occurred within an acquisition * @n_fires: number of trigger fire occurred within an acquisition
* *
* @n_dma_err: number of errors * @n_dma_err: number of errors
* * @user_offset: user offset (micro-Volts)
* @zero_offset: necessary offset to push the channel to zero (micro-Volts)
*/ */
struct fa_dev { struct fa_dev {
struct device *msgdev; /**< device used to print messages */ struct device *msgdev; /**< device used to print messages */
...@@ -410,8 +415,8 @@ struct fa_dev { ...@@ -410,8 +415,8 @@ struct fa_dev {
unsigned int n_dma_err; unsigned int n_dma_err;
/* Configuration */ /* Configuration */
int user_offset[4]; /* one per channel */ int32_t user_offset[4]; /* one per channel */
int32_t zero_offset[FA100M14B4C_NCHAN];
/* one-wire */ /* one-wire */
uint8_t ds18_id[8]; uint8_t ds18_id[8];
unsigned long next_t; unsigned long next_t;
...@@ -545,8 +550,7 @@ extern const struct zfa_field_desc zfad_regs[]; ...@@ -545,8 +550,7 @@ extern const struct zfa_field_desc zfad_regs[];
/* Functions exported by fa-core.c */ /* Functions exported by fa-core.c */
extern int zfad_fsm_command(struct fa_dev *fa, uint32_t command); extern int zfad_fsm_command(struct fa_dev *fa, uint32_t command);
extern int zfad_apply_user_offset(struct fa_dev *fa, struct zio_channel *chan, extern int zfad_apply_offset(struct zio_channel *chan);
uint32_t usr_val);
extern void zfad_reset_offset(struct fa_dev *fa); extern void zfad_reset_offset(struct fa_dev *fa);
extern int zfad_convert_hw_range(uint32_t bitmask); extern int zfad_convert_hw_range(uint32_t bitmask);
extern int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan, extern int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan,
......
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