Commit b66c7243 authored by Federico Vaga's avatar Federico Vaga

drv: re-write ADC data pattern code in debugfs

Do not use any calibration data while there is a pattern applied
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 230e2ed6
......@@ -137,8 +137,10 @@ static void fa_calib_adc_config_chan(struct fa_dev *fa, unsigned int chan,
struct fa_calib_stanza *cal = &fa->calib.adc[range];
int32_t delta_temp = temperature - cal->temperature;
int offset = cal->offset[chan];
int gain = fa_calib_adc_gain_fix(range, cal->gain[chan],
delta_temp);
int gain = cal->gain[chan];
if (unlikely(!(fa->flags & FA_DEV_F_PATTERN_DATA)))
gain = fa_calib_adc_gain_fix(range, gain, delta_temp);
dev_dbg(&fa->pdev->dev, "%s: {chan: %d, range: %d, gain: 0x%x, offset: 0x%x}\n",
__func__, chan, range, gain, offset);
......@@ -213,9 +215,12 @@ static int fa_calib_dac_config_chan(struct fa_dev *fa, unsigned int chan,
struct fa_calib_stanza *cal = &fa->calib.dac[range];
int32_t delta_temp = temperature - cal->temperature;
int offset = cal->offset[chan];
int gain = fa_calib_dac_gain_fix(range, cal->gain[chan], delta_temp);
int gain = cal->gain[chan];
int hwval;
if (unlikely(!(fa->flags & FA_DEV_F_PATTERN_DATA)))
gain = fa_calib_dac_gain_fix(range, gain, delta_temp);
dev_dbg(&fa->pdev->dev, "%s: {chan: %d, range: %d, gain: 0x%x, offset: 0x%x}\n",
__func__, chan, range, gain, offset);
hwval = fa_dac_offset_raw_calibrate(off_uv_raw, gain, offset);
......@@ -479,4 +484,5 @@ out:
void fa_calib_exit(struct fa_dev *fa)
{
del_timer_sync(&fa->calib_timer);
fa_identity_calib_set(&fa->calib);
}
......@@ -18,8 +18,6 @@
static int fa_enable_test_data_fpga;
module_param_named(enable_test_data_fpga, fa_enable_test_data_fpga, int, 0444);
int fa_enable_test_data_adc = 0;
module_param_named(enable_test_data_adc, fa_enable_test_data_adc, int, 0444);
#define FA_EEPROM_TYPE "at24c64"
......@@ -154,36 +152,6 @@ int zfad_get_chx_index(unsigned long addr, unsigned int chan)
}
/**
* It enables or disables the pattern data on the ADC
* @fa The ADC device instance
* @pattern the pattern data to get from the ADC
* @enable 0 to disable, 1 to enable
*/
int zfad_pattern_data_enable(struct fa_dev *fa, uint16_t pattern,
unsigned int enable)
{
uint32_t frame_tx;
int err;
frame_tx = 0x0000; /* write mode */
frame_tx |= 0x0400; /* A4 pattern */
frame_tx |= pattern & 0xFF; /* LSB pattern */
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, frame_tx, NULL);
if (err)
return err;
frame_tx = 0x0000; /* write mode */
frame_tx |= 0x0300; /* A3 pattern + enable */
frame_tx |= (pattern & 0xFF00) >> 8; /* MSB pattern */
frame_tx |= (enable ? 0x80 : 0x00); /* Enable the pattern data */
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, frame_tx, NULL);
if (err)
return err;
return 0;
}
/*
* zfad_reset_offset
* @fa: the fmc-adc descriptor
......@@ -234,7 +202,8 @@ int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan,
i = zfad_get_chx_index(ZFA_CHx_CTL_RANGE, chan->index);
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->flags & FA_DEV_F_PATTERN_DATA))
range = FA100M14B4C_RANGE_1V;
else if (range >= FA100M14B4C_RANGE_10V_CAL)
range -= FA100M14B4C_RANGE_10V_CAL;
......@@ -287,6 +256,46 @@ static void fa_fpga_data_pattern_set(struct fa_dev *fa, unsigned int enable)
&zfad_regs[ZFA_CTL_TEST_DATA_EN], enable);
}
/**
* It enables or disables the pattern data on the ADC
* @fa The ADC device instance
* @pattern the pattern data to get from the ADC
* @enable 0 to disable, 1 to enable
*/
int fa_adc_data_pattern_set(struct fa_dev *fa, uint16_t pattern,
unsigned int enable)
{
uint32_t frame_tx;
int err;
dev_dbg(&fa->pdev->dev, "%s {patter: 0x%04x, enable: %d}\n", __func__, pattern, enable);
spin_lock(&fa->zdev->cset->lock);
frame_tx = 0x0000; /* write mode */
frame_tx |= 0x0400; /* A4 pattern */
frame_tx |= pattern & 0xFF; /* LSB pattern */
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, frame_tx, NULL);
if (err)
goto err;
frame_tx = 0x0000; /* write mode */
frame_tx |= 0x0300; /* A3 pattern + enable */
frame_tx |= (pattern & 0xFF00) >> 8; /* MSB pattern */
frame_tx |= (enable ? 0x80 : 0x00); /* Enable the pattern data */
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, frame_tx, NULL);
if (err)
goto err;
if (enable)
fa->flags |= FA_DEV_F_PATTERN_DATA;
else
fa->flags &= ~FA_DEV_F_PATTERN_DATA;
err:
spin_unlock(&fa->zdev->cset->lock);
return err;
}
/*
* zfad_fsm_command
* @fa: the fmc-adc descriptor
......@@ -419,6 +428,8 @@ static int __fa_init(struct fa_dev *fa)
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[ZFAT_SR_UNDER], 1);
/* Set test data register */
fa_fpga_data_pattern_set(fa, fa_enable_test_data_fpga);
/* disable test pattern data in the ADC */
fa_adc_data_pattern_set(fa, 0, 0);
/* Set to single shot mode by default */
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[ZFAT_SHOTS_NB], 1);
......
......@@ -180,6 +180,58 @@ static const struct file_operations fa_trg_sw_ops = {
.write = fa_trg_sw_write,
};
#define FA_ADC_DATA_PATTERN_CMD_SIZE 16UL
static int fa_data_pattern_adc_write(struct fa_dev *fa, const char __user *buf,
size_t count)
{
char buf_l[FA_ADC_DATA_PATTERN_CMD_SIZE];
int err;
memset(buf_l, 0, FA_ADC_DATA_PATTERN_CMD_SIZE);
err = copy_from_user(buf_l, buf, min(count,
FA_ADC_DATA_PATTERN_CMD_SIZE));
if (err)
return -EFAULT;
if ((count == 1 || count == 2)&& buf_l[0] == '0') {
fa_calib_init(fa);
return fa_adc_data_pattern_set(fa, 0, 0);
} else if (count > 2 && buf_l[0] == '1' && buf_l[1] == ' ') {
uint16_t pattern = 0;
err = kstrtou16(buf_l + 2, 0, &pattern);
if (err)
return err;
fa_calib_exit(fa);
pattern &= 0xFFF;
return fa_adc_data_pattern_set(fa, pattern, 1);
} else {
return -EINVAL;
}
}
static ssize_t fa_data_pattern_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct fa_dev *fa = file->private_data;
if (strncmp(buf, "adc ", 4) == 0) {
int err;
err = fa_data_pattern_adc_write(fa, buf + 4, count - 4);
return err ? err : count;
} else {
dev_err(&fa->pdev->dev, "Unknown command \"%s\"\n", buf);
return -EINVAL;
}
}
static const struct file_operations fa_data_pattern_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.write = fa_data_pattern_write,
};
int fa_debug_init(struct fa_dev *fa)
{
......@@ -222,6 +274,14 @@ int fa_debug_init(struct fa_dev *fa)
"Cannot create software trigger file\n");
}
fa->dbg_data_pattern = debugfs_create_file("data_pattern", 0200,
fa->dbg_dir, fa,
&fa_data_pattern_ops);
if (IS_ERR_OR_NULL(fa->dbg_data_pattern)) {
dev_warn(&fa->pdev->dev,
"Cannot create ADC data pattern file\n");
}
return 0;
}
......
......@@ -123,7 +123,6 @@ static struct zio_attribute zfad_cset_ext_zattr[] = {
ZIO_PARAM_EXT("sample-frequency", ZIO_RO_PERM, ZFAT_SAMPLING_HZ, 0),
ZIO_PARAM_EXT("max-sample-mshot", ZIO_RO_PERM, ZFA_MULT_MAX_SAMP, 0),
ZIO_PARAM_EXT("sample-counter", ZIO_RO_PERM, ZFAT_CNT, 0),
ZIO_PARAM_EXT("test-data-pattern", ZIO_RW_PERM, ZFAT_ADC_TST_PATTERN, 0),
};
#if 0 /* FIXME Unused until TLV control will be available */
......@@ -177,7 +176,7 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
struct fa_dev *fa = get_zfadc(dev);
void *baseoff = fa->fa_adc_csr_base;
struct zio_channel *chan;
int i, range, err = 0, reg_index;
int i, range, reg_index;
reg_index = zattr->id;
i = FA100M14B4C_NCHAN;
......@@ -313,24 +312,6 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
break;
case ZFA_CTL_FMS_CMD:
return zfad_fsm_command(fa, usr_val);
case ZFAT_ADC_TST_PATTERN:
if (unlikely(fa_enable_test_data_adc)) {
usr_val &= 0xFFF;
err = zfad_pattern_data_enable(fa, usr_val,
fa_enable_test_data_adc);
if (err)
dev_warn(fa->msgdev,
"Failed to set the ADC test data. Continue without\n");
else if (fa_enable_test_data_adc)
dev_info(fa->msgdev,
"the ADC test data (0x%x) is enabled on all channels\n",
usr_val);
return err;
} else {
dev_err(fa->msgdev,
"Cannot set the ADC test data. The driver is not in test mode\n");
return -EPERM;
}
}
fa_writel(fa, baseoff, &zfad_regs[reg_index], usr_val);
......@@ -374,8 +355,6 @@ static int zfad_info_get(struct device *dev, struct zio_attribute *zattr,
case ZFA_CHx_OFFSET:
*usr_val = fa->user_offset[to_zio_chan(dev)->index];
return 0;
case ZFAT_ADC_TST_PATTERN:
/*fallthrough*/
case ZFA_SW_R_NOADDRES_NBIT:
/*fallthrough*/
case ZFA_SW_R_NOADDERS_AUTO:
......@@ -571,10 +550,6 @@ static int zfad_zio_probe(struct zio_device *zdev)
/* Save also the pointer to the real zio_device */
fa->zdev = zdev;
err = zfad_pattern_data_enable(fa, 0, fa_enable_test_data_adc);
if (err)
return err;
err = device_create_bin_file(&zdev->head.dev, &dev_attr_calibration);
if (err)
return err;
......
......@@ -177,8 +177,6 @@ struct fa_calib {
#define DAC_SAT_LOW -5000000
#define DAC_SAT_UP 5000000
extern int fa_enable_test_data_adc;
#define ADC_DMA 0
enum fa_irq_resource {
......@@ -247,8 +245,6 @@ enum zfadc_dregs_enum {
ZFAT_POST,
/* Sample counter */
ZFAT_CNT,
/* Pattern data for the ADC chip */
ZFAT_ADC_TST_PATTERN,
/* start:declaration block requiring some order */
/* Channel 1 */
ZFA_CH1_CTL_RANGE,
......@@ -385,6 +381,11 @@ enum fa_irq_adc {
mezzanine-specific operations). */
struct fa_dev; /* forward declaration */
/*
* Flag bit set when the ADC uses pattern data
*/
#define FA_DEV_F_PATTERN_DATA BIT(0)
/*
* fa_dev: is the descriptor of the FMC ADC mezzanine
*
......@@ -401,6 +402,7 @@ struct fa_dev; /* forward declaration */
* @zero_offset: necessary offset to push the channel to zero (micro-Volts)
*/
struct fa_dev {
unsigned long flags;
struct device *msgdev; /**< device used to print messages */
/* the pointer to the platform_device generic structure */
struct platform_device *pdev;
......@@ -462,6 +464,7 @@ struct fa_dev {
struct dentry *dbg_reg;
struct dentry *dbg_reg_spi;
struct dentry *dbg_trg_sw;
struct dentry *dbg_data_pattern;
/* Operations */
int (*sg_alloc_table_from_pages)(struct sg_table *sgt,
......@@ -610,14 +613,14 @@ extern int fa_trigger_software(struct fa_dev *fa);
extern int fa_fsm_wait_state(struct fa_dev *fa,
enum fa100m14b4c_fsm_state state,
unsigned int timeout_us);
extern int fa_adc_data_pattern_set(struct fa_dev *fa, uint16_t pattern,
unsigned int enable);
/* Temporarily, user values are the same as hardware values */
extern int zfad_convert_user_range(uint32_t user_val);
extern int zfad_set_range(struct fa_dev *fa, struct zio_channel *chan,
int range);
extern int zfad_get_chx_index(unsigned long addr, unsigned int chan);
extern int zfad_pattern_data_enable(struct fa_dev *fa, uint16_t pattern,
unsigned int enable);
/* Function exported by fa-dma.c */
extern void fa_irq_work(struct work_struct *work);
......
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