Skip to content

Commit

Permalink
drivers: ad400x: Move offload to driver code
Browse files Browse the repository at this point in the history
In preparation for iio and making the projects platform independant,
move the offload code to the driver so it is simply enabled or not
by the project code.

Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
  • Loading branch information
ahaslam2 committed May 23, 2024
1 parent 03a06ef commit 142a861
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 58 deletions.
85 changes: 80 additions & 5 deletions drivers/adc/ad400x/ad400x.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,55 @@ int32_t ad400x_spi_reg_write(struct ad400x_dev *dev,
return ret;
}

#if !defined(USE_STANDARD_SPI)
/**
* Read samples using spi offload engine
* @param dev - The device structure.
* @param buf - Buffer to hold the conversion results data
* @param samples - number of samples to read
* @return 0 in case of success, negative error code otherwise.
*/
static int32_t ad400x_read_data_offload(struct ad400x_dev *dev,
uint32_t *buf,
uint16_t samples)
{
struct spi_engine_offload_message msg;
uint32_t commands_data[2] = {0xFF, 0xFF};
int ret;
uint32_t spi_eng_msg_cmds[3] = {
CS_LOW,
READ(2),
CS_HIGH
};

ret = spi_engine_offload_init(dev->spi_desc, dev->offload_init_param);
if (ret)
return ret;

msg.commands = spi_eng_msg_cmds;
msg.no_commands = NO_OS_ARRAY_SIZE(spi_eng_msg_cmds);
msg.rx_addr = buf;
msg.commands_data = commands_data;

ret = spi_engine_offload_transfer(dev->spi_desc, msg, samples * 4);
if (ret)
return ret;

if (dev->dcache_invalidate_range)
dev->dcache_invalidate_range(msg.rx_addr, samples * 4);

return ret;
}
#endif

/**
* Read conversion result from device.
* Read single conversion result from device.
* @param dev - The device structure.
* @param adc_data - The conversion result data
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad400x_spi_single_conversion(struct ad400x_dev *dev,
uint32_t *data)
static int32_t ad400x_spi_single_conversion(struct ad400x_dev *dev,
uint32_t *data)
{
int32_t ret;
uint8_t data_read[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; /* SDI must remain high */
Expand Down Expand Up @@ -216,6 +257,32 @@ int32_t ad400x_spi_single_conversion(struct ad400x_dev *dev,
return 0;
}

/**
* Read conversion results from device.
* @param dev - The device structure.
* @param buf - Buffer to hold the conversion results data
* @param samples - number of samples to read
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad400x_read_data(struct ad400x_dev *dev,
uint32_t *buf,
uint16_t samples)
{
int i, ret;
uint32_t *p;

#if !defined(USE_STANDARD_SPI)
if (dev->offload_enable)
return ad400x_read_data_offload(dev, buf, samples);
#endif
for (i = 0, p = buf; i < samples; i++, p++) {
ret = ad400x_spi_single_conversion(dev, p);
if (ret)
return ret;
}
return ret;
}

/**
* Initialize the device.
* @param device - The device structure.
Expand All @@ -229,6 +296,7 @@ int32_t ad400x_init(struct ad400x_dev **device,
struct ad400x_dev *dev;
int32_t ret;
uint8_t data = 0;
uint16_t transfer_width;

if (!init_param)
return -1;
Expand All @@ -243,6 +311,9 @@ int32_t ad400x_init(struct ad400x_dev **device,

dev->dev_id = init_param->dev_id;
dev->reg_access_speed = init_param->reg_access_speed;
dev->offload_init_param = init_param->offload_init_param;
dev->dcache_invalidate_range = init_param->dcache_invalidate_range;
dev->offload_enable = init_param->offload_enable;

#if defined(USE_STANDARD_SPI)
ret = no_os_gpio_get(&dev->gpio_cnv, init_param->gpio_cnv);
Expand All @@ -253,9 +324,13 @@ int32_t ad400x_init(struct ad400x_dev **device,
if (ret)
goto error;
#else
struct spi_engine_init_param *spi_eng_ip = init_param->spi_init->extra;
transfer_width = ad400x_device_resol[init_param->dev_id];

/* without offload xfer width has to be byte alligned */
if (!dev->offload_enable)
transfer_width = NO_OS_DIV_ROUND_UP(transfer_width, 8) * 8;

spi_engine_set_transfer_width(dev->spi_desc, spi_eng_ip->data_width);
spi_engine_set_transfer_width(dev->spi_desc, transfer_width);
ret = axi_clkgen_init(&dev->clkgen, init_param->clkgen_init);
if (ret)
goto error;
Expand Down
22 changes: 18 additions & 4 deletions drivers/adc/ad400x/ad400x.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ struct ad400x_dev {
uint32_t reg_access_speed;
/* Device Settings */
enum ad400x_supported_dev_ids dev_id;
/** SPI module offload init */
struct spi_engine_offload_init_param *offload_init_param;
/** Invalidate the Data cache for the given address range */
void (*dcache_invalidate_range)(uint32_t address, uint32_t bytes_count);
/* enable offload */
bool offload_enable;
};

struct ad400x_init_param {
Expand All @@ -110,6 +116,15 @@ struct ad400x_init_param {
uint32_t reg_access_speed;
/* Device Settings */
enum ad400x_supported_dev_ids dev_id;
/** SPI module offload init */
struct spi_engine_offload_init_param *offload_init_param;
/** Invalidate the Data cache for the given address range */
void (*dcache_invalidate_range)(uint32_t address, uint32_t bytes_count);
/* buffer to store data samples */
uint32_t *buffer;
/* buffer size */
uint32_t buffer_size;
bool offload_enable;
bool turbo_mode;
bool high_z_mode;
bool span_compression;
Expand All @@ -123,8 +138,7 @@ int32_t ad400x_spi_reg_write(struct ad400x_dev *dev,
int32_t ad400x_init(struct ad400x_dev **device,
struct ad400x_init_param *init_param);
int32_t ad400x_remove(struct ad400x_dev *dev);
/* Execute a single conversion */
int32_t ad400x_spi_single_conversion(struct ad400x_dev *dev,
uint32_t *data);

/* read data samples */
int32_t ad400x_read_data(struct ad400x_dev *dev, uint32_t *buf,
uint16_t samples);
#endif /* SRC_AD400X_H_ */
67 changes: 18 additions & 49 deletions projects/ad400x-fmcz/src/ad400x_fmcz.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,15 @@ static void print_output_data(uint32_t adc_data, uint16_t res, char sign)
int main()
{
struct ad400x_dev *dev;
uint32_t *offload_data;
uint32_t adc_data;
uint32_t *adc_data = 0x800000;
int32_t ret, i;
enum ad400x_supported_dev_ids dev_id = ID_AD4020;
uint16_t res = ad400x_device_resol[dev_id];

struct spi_engine_offload_init_param spi_engine_offload_init_param = {
.offload_config = OFFLOAD_RX_EN,
.rx_dma_baseaddr = AD400X_DMA_BASEADDR,
};
struct spi_engine_offload_message msg;
uint32_t commands_data[2] = {0xFF, 0xFF};
int32_t ret, i;
enum ad400x_supported_dev_ids dev_id = ID_AD4020;
uint16_t res = ad400x_device_resol[dev_id];

struct spi_engine_init_param spi_eng_init_param = {
.ref_clk_hz = 160000000,
Expand Down Expand Up @@ -104,6 +102,13 @@ int main()
.axi_clkgen_rate = 160000000,
.reg_access_speed = 1000000,
.dev_id = dev_id,
.offload_init_param = &spi_engine_offload_init_param,
.dcache_invalidate_range = Xil_DCacheInvalidateRange,
#if (SPI_ENGINE_OFFLOAD_EXAMPLE == 1)
.offload_enable = 1,
#else
.offload_enable = 0,
#endif
.turbo_mode = 1,
.high_z_mode = 0,
.span_compression = 0,
Expand All @@ -112,55 +117,19 @@ int main()

print("Test\n\r");

uint32_t spi_eng_msg_cmds[3] = {
CS_LOW,
READ(2),
CS_HIGH
};

Xil_ICacheEnable();
Xil_DCacheEnable();

/* data must be byte alligned when offload is disabled */
if (SPI_ENGINE_OFFLOAD_EXAMPLE == 0)
spi_eng_init_param.data_width =
NO_OS_DIV_ROUND_UP(spi_eng_init_param.data_width, 8) * 8;

ret = ad400x_init(&dev, &ad400x_init_param);
if (ret < 0)
return ret;

if (SPI_ENGINE_OFFLOAD_EXAMPLE == 0) {
while(1) {
ad400x_spi_single_conversion(dev, &adc_data);
print_output_data(adc_data, res, ad400x_device_sign[dev_id]);
}
}
/* Offload example */
else {
ret = spi_engine_offload_init(dev->spi_desc, &spi_engine_offload_init_param);
if (ret != 0)
return -1;

msg.commands = spi_eng_msg_cmds;
msg.no_commands = NO_OS_ARRAY_SIZE(spi_eng_msg_cmds);
msg.rx_addr = 0x800000;
msg.tx_addr = 0xA000000;
msg.commands_data = commands_data;

ret = spi_engine_offload_transfer(dev->spi_desc, msg, AD400x_EVB_SAMPLE_NO * 2);
if (ret != 0)
return ret;

no_os_mdelay(2000);
Xil_DCacheInvalidateRange(0x800000, AD400x_EVB_SAMPLE_NO * 4);
offload_data = (uint32_t *)msg.rx_addr;

for(i = 0; i < AD400x_EVB_SAMPLE_NO; i++) {
print_output_data(*offload_data, res, ad400x_device_sign[dev_id]);
offload_data += 1;
}
}
ret = ad400x_read_data(dev, adc_data, AD400x_EVB_SAMPLE_NO);
if (ret)
return ret;

for(i = 0, adc_data = 0x800000; i < AD400x_EVB_SAMPLE_NO; i++, adc_data++)
print_output_data(*adc_data, res, ad400x_device_sign[dev_id]);

print("Success\n\r");

Expand Down

0 comments on commit 142a861

Please sign in to comment.