Skip to content

Commit

Permalink
iio: frequency: cf_axi_dds: Support for EXT SYNC
Browse files Browse the repository at this point in the history
This patch adds a new device attributes 'sync_start_enable' and
'sync_start_enable_available' reading the later returns the available
modes which depend on HDL core synthesis parameters.
The options are explained below. Reading 'sync_start_enable' returns
either 'arm' while waiting for the external synchronization signal
or 'disarm' otherwise.

 - arm: Setting this bit will arm the trigger mechanism sensitive to an
	external sync signal. Once the external sync signal goes high
	it synchronizes channels within a DAC, and across multiple
	instances. This bit has an effect only the EXT_SYNC
	synthesis parameter is set. This bit self clears.

 - disarm: Setting this bit will disarm the trigger mechanism
	sensitive to an external sync signal. This bit has an
	effect only the EXT_SYNC synthesis parameter is set.
	This bit self clears.

 - trigger_manual: Setting this bit will issue an external sync event
	if it is hooked up inside the fabric. This bit has an effect
	only the EXT_SYNC synthesis parameter is set.
	This bit self clears.

Signed-off-by: Michael Hennerich <[email protected]>
  • Loading branch information
mhennerich authored and dbogdan committed Feb 2, 2022
1 parent 0792eac commit 9a09ba3
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 12 deletions.
80 changes: 69 additions & 11 deletions drivers/iio/frequency/cf_axi_dds.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct cf_axi_dds_state {
enum fifo_ctrl dma_fifo_ctrl_bypass;
bool dma_fifo_ctrl_oneshot;
bool issue_sync_en;
bool ext_sync_avail;

struct iio_info iio_info;
struct iio_dev *indio_dev;
Expand Down Expand Up @@ -552,37 +553,91 @@ static ssize_t cf_axi_sampling_frequency_available(struct device *dev,
return ret;
}

static ssize_t cf_axi_sync_start(struct device *dev,

static const char * const axidds_sync_ctrls[] = {
"arm", "disarm", "trigger_manual",
};

static ssize_t axidds_sync_start_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct cf_axi_dds_state *st = iio_priv(indio_dev);
bool state;
int ret;

ret = strtobool(buf, &state);
ret = sysfs_match_string(axidds_sync_ctrls, buf);
if (ret < 0)
return ret;

if (state)
mutex_lock(&indio_dev->mlock);
if (st->ext_sync_avail) {
switch (ret) {
case 0:
dds_write(st, ADI_REG_CNTRL_1, ADI_EXT_SYNC_ARM);
break;
case 1:
dds_write(st, ADI_REG_CNTRL_1, ADI_EXT_SYNC_DISARM);
break;
case 2:
dds_write(st, ADI_REG_CNTRL_1, ADI_MANUAL_SYNC_REQUEST);
break;
default:
ret = -EINVAL;
}
} else if (ret == 0) {
cf_axi_dds_start_sync(st, 0);
}
mutex_unlock(&indio_dev->mlock);

return len;
return ret < 0 ? ret : len;
}

static IIO_DEVICE_ATTR(out_voltage_sampling_frequency_available, 0444,
cf_axi_sampling_frequency_available,
NULL,
static ssize_t axidds_sync_start_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct cf_axi_dds_state *st = iio_priv(indio_dev);
u32 reg;

switch ((u32)this_attr->address) {
case 0:
reg = dds_read(st, ADI_REG_SYNC_STATUS);

return sprintf(buf, "%s\n", reg & ADI_ADC_SYNC_STATUS ?
axidds_sync_ctrls[0] : axidds_sync_ctrls[1]);
case 1:
if (st->ext_sync_avail)
return sprintf(buf, "arm disarm trigger_manual\n");
else
return sprintf(buf, "arm\n");
default:
return -EINVAL;
}

return -EINVAL;
}

static IIO_DEVICE_ATTR(sync_start_enable, 0644,
axidds_sync_start_show,
axidds_sync_start_store,
0);

static IIO_DEVICE_ATTR(sync_start_enable, 0200,
static IIO_DEVICE_ATTR(sync_start_enable_available, 0444,
axidds_sync_start_show,
NULL,
1);

static IIO_DEVICE_ATTR(out_voltage_sampling_frequency_available, 0444,
cf_axi_sampling_frequency_available,
NULL,
cf_axi_sync_start,
0);

static struct attribute *cf_axi_attributes[] = {
&iio_dev_attr_sync_start_enable.dev_attr.attr,
&iio_dev_attr_sync_start_enable_available.dev_attr.attr,
&iio_dev_attr_out_voltage_sampling_frequency_available.dev_attr.attr,
NULL,
};
Expand Down Expand Up @@ -2082,7 +2137,7 @@ static int cf_axi_dds_probe(struct platform_device *pdev)
struct cf_axi_dds_state *st;
struct iio_dev *indio_dev;
struct resource *res;
unsigned int ctrl_2;
unsigned int ctrl_2, config;
unsigned int rate;
unsigned int drp_status;
int timeout = 100;
Expand Down Expand Up @@ -2190,6 +2245,9 @@ static int cf_axi_dds_probe(struct platform_device *pdev)
st->issue_sync_en = info->issue_sync_en;
st->standalone = info->standalone;
st->version = dds_read(st, ADI_AXI_REG_VERSION);

config = dds_read(st, ADI_REG_CONFIG);
st->ext_sync_avail = !!(config & ADI_EXT_SYNC);
st->dp_disable = false; /* FIXME: resolve later which reg & bit to read for this */

if (ADI_AXI_PCORE_VER_MAJOR(st->version) >
Expand Down
8 changes: 7 additions & 1 deletion drivers/iio/frequency/cf_axi_dds.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define ADI_PPS_RECEIVER_ENABLE (1 << 8)
#define ADI_SCALECORRECTION_ONLY (1 << 9)
#define ADI_XBAR_ENABLE (1 << 10)
#define ADI_EXT_SYNC (1 << 12)

/* DAC COMMON */

Expand All @@ -33,8 +34,10 @@
#define ADI_MMCM_RSTN (1 << 1)

#define ADI_REG_CNTRL_1 0x0044
#define ADI_ENABLE (1 << 0) /* v7.0 */
#define ADI_SYNC (1 << 0) /* v8.0 */
#define ADI_EXT_SYNC_ARM (1 << 1)
#define ADI_EXT_SYNC_DISARM (1 << 2)
#define ADI_MANUAL_SYNC_REQUEST (1 << 8)

#define ADI_REG_CNTRL_2 0x0048
#define ADI_PAR_TYPE (1 << 7)
Expand Down Expand Up @@ -78,6 +81,9 @@ enum dds_data_select {
#define ADI_REG_STATUS 0x005C
#define ADI_STATUS (1 << 0)

#define ADI_REG_SYNC_STATUS 0x0068
#define ADI_ADC_SYNC_STATUS (1 << 0)

#define ADI_REG_DRP_CNTRL 0x0070
#define ADI_DRP_SEL (1 << 29)
#define ADI_DRP_RWN (1 << 28)
Expand Down

0 comments on commit 9a09ba3

Please sign in to comment.