Skip to content

Commit

Permalink
drivers: ad400x: Add iio driver
Browse files Browse the repository at this point in the history
Add initial IIO support for the ad400x driver.

Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
  • Loading branch information
ahaslam2 committed May 23, 2024
1 parent 142a861 commit 5e09916
Show file tree
Hide file tree
Showing 2 changed files with 322 additions and 0 deletions.
237 changes: 237 additions & 0 deletions drivers/adc/ad400x/iio_ad400x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/***************************************************************************//**
* @file iio_ad400x.c
* @brief Implementation of AD400x IIO Driver.
* @author Axel Haslam (ahaslam@baylibre.com)
********************************************************************************
* Copyright 2024(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include <stdio.h>
#include <math.h>
#include <string.h>

#include "ad400x.h"
#include "iio_ad400x.h"
#include "iio.h"
#include "no_os_util.h"
#include "no_os_alloc.h"
#include "no_os_error.h"

/**
* @brief Read the debug register value
* @param device - Pointer to IIO device instance
* @param reg - Register address to read from
* @param val - Pointer to variable to read data into
* @return 0 in case of success, negative value otherwise
*/
static int32_t iio_ad400x_debug_reg_read(void *device, uint32_t reg,
uint32_t *val)
{
struct ad400x_iio_dev *iio_dev = device;
struct ad400x_dev *dev = iio_dev->ad400x_dev;
int ret;
uint8_t val8;

ret = ad400x_spi_reg_read(dev, &val8);
if (ret)
return ret;

*val = val8;
return 0;
}

/**
* @brief Write the debug register value
* @param device - Pointer to IIO device instance
* @param reg - Register address to read from
* @param val - Pointer to variable to write data into
* @return 0 in case of success, negative value otherwise
*/
static int32_t iio_ad400x_debug_reg_write(void *device, uint32_t reg,
uint32_t val)
{
struct ad400x_iio_dev *iio_dev = device;
struct ad400x_dev *dev = iio_dev->ad400x_dev;

return ad400x_spi_reg_write(dev, (uint8_t)val);
}

static int get_raw(void *device, char *buf, uint32_t len,
const struct iio_ch_info *channel, intptr_t id)
{
struct ad400x_iio_dev *iio_dev = device;
struct ad400x_dev *dev = iio_dev->ad400x_dev;
struct scan_type *scan_type;
uint32_t results;
int32_t results_signed;
int ret;

scan_type = iio_dev->iio_dev->channels[channel->ch_num].scan_type;

ret = ad400x_read_data(dev, &results, 1);
if (ret)
return ret;

if (scan_type->sign == 's') {
results_signed = no_os_sign_extend32(results, scan_type->realbits - 1);
return iio_format_value(buf, len, IIO_VAL_INT, 1, &results_signed);
}

return iio_format_value(buf, len, IIO_VAL_INT, 1, (int32_t *)&results);
}

static int get_scale(void *device, char *buf, uint32_t len,
const struct iio_ch_info *channel, intptr_t id)
{
struct ad400x_iio_dev *iio_dev = device;
struct scan_type *scan_type;
int32_t vals[2];

scan_type = iio_dev->iio_dev->channels[channel->ch_num].scan_type;
vals[0] = iio_dev->ref_voltage_mv;
if (scan_type->sign == 'u')
vals[1] = scan_type->realbits;
else
vals[1] = scan_type->realbits - 1;

return iio_format_value(buf, len, IIO_VAL_FRACTIONAL_LOG2, 2, vals);
}

/**
* @brief Read buffer data corresponding to AD400X IIO device
* @param iio_dev_data - Pointer to IIO device data structure
* @return 0 in case of success, negative error code otherwise
*/
static int32_t iio_ad400x_submit_buffer(struct iio_device_data *iio_dev_data)
{
struct ad400x_iio_dev *iio_dev = iio_dev_data->dev;
struct ad400x_dev *dev = iio_dev->ad400x_dev;
struct iio_buffer *buffer = iio_dev_data->buffer;
void *buff;
int ret;

ret = iio_buffer_get_block(iio_dev_data->buffer, &buff);
if (ret)
return ret;

ret = ad400x_read_data(dev, buff, buffer->samples);
if (ret)
return ret;

return iio_buffer_block_done(buffer);
}

static struct iio_attribute ad400x_iio_ch_attributes[] = {
{ .name = "raw", .show = get_raw },
{ .name = "scale", .show = get_scale, },
END_ATTRIBUTES_ARRAY
};

static struct iio_channel ad400x_channel = {
.name = "voltage0",
.ch_type = IIO_VOLTAGE,
.ch_out = IIO_DIRECTION_INPUT,
.indexed = true,
.channel = 0,
.scan_index = 0,
.attributes = ad400x_iio_ch_attributes,
};

static struct iio_device ad400x_iio_device_template = {
.num_ch = 1,
.channels = &ad400x_channel,
.debug_reg_read = iio_ad400x_debug_reg_read,
.debug_reg_write= iio_ad400x_debug_reg_write,
.submit = iio_ad400x_submit_buffer,
};

/**
* @brief Initialize AD400X for IIO interfacing
* @param dev - The device structure.
* @param iio_init_param - IIO init parameter structure
* @return 0 on success, an error code otherwise
*/
int ad400x_iio_init(struct ad400x_iio_dev **dev,
struct ad400x_iio_init_param *iio_init_param)
{
struct ad400x_iio_dev *desc;
enum ad400x_supported_dev_ids dev_id;
int ret;

desc = no_os_calloc(1, sizeof(*desc));
if (!desc)
return -ENOMEM;

desc->iio_dev = &ad400x_iio_device_template;
desc->ref_voltage_mv = iio_init_param->ref_voltage_mv;

dev_id = iio_init_param->init_param->dev_id;

/* fill scan_type based on device id */
desc->scan_type.sign = ad400x_device_sign[dev_id];
desc->scan_type.realbits = ad400x_device_resol[dev_id];
desc->scan_type.storagebits = 32;
desc->scan_type.is_big_endian = false;
desc->scan_type.shift = 0;


desc->iio_dev->channels[0].scan_type = &desc->scan_type;

ret = ad400x_init(&desc->ad400x_dev, iio_init_param->init_param);
if (ret)
goto error_setup;

*dev = desc;

return 0;

error_setup:
no_os_free(desc);
return ret;
}

/**
* @brief Release resources.
* @param iio_dev - iio device.
* @return 0 in case of success, error otherwise.
*/
int ad400x_iio_remove(struct ad400x_iio_dev *iio_dev)
{
if (!iio_dev)
return -EINVAL;

ad400x_remove(iio_dev->ad400x_dev);

no_os_free(iio_dev);
return 0;
}
85 changes: 85 additions & 0 deletions drivers/adc/ad400x/iio_ad400x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/***************************************************************************//**
* @file iio_ad400x.h
* @brief Header file for AD400X IIO interface
* @author Axel Haslam (ahaslam@baylibre.com)
********************************************************************************
* Copyright 2024(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#ifndef _AD400X_IIO_H_
#define _AD400X_IIO_H_

/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include <stdint.h>

#include "iio.h"
#include "iio_types.h"
#include "ad400x.h"

/******************************************************************************/
/********************** Public/Extern Declarations ****************************/
/******************************************************************************/
/**
* @struct ad400x_iio_dev
* @brief AD400x IIO device structure
*/
struct ad400x_iio_dev {
/** AD400x driver handler */
struct ad400x_dev *ad400x_dev;
/** Generic IIO device handler */
struct iio_device *iio_dev;
/* Voltage reference */
uint32_t ref_voltage_mv;
/* scan type */
struct scan_type scan_type;
};

/**
* @struct ad400x_iio_init_param
* @brief AD400x IIO initialization structure
*/
struct ad400x_iio_init_param {
struct ad400x_init_param *init_param;
/* Voltage reference */
uint32_t ref_voltage_mv;
};

/** Allocate memory for AD400x IIO handler. */
int ad400x_iio_init(struct ad400x_iio_dev **dev,
struct ad400x_iio_init_param *iio_init_param);
/** Free memory allocated by iio_ad400x_init(). */
int ad400x_iio_remove(struct ad400x_iio_dev *dev);
#endif /* __AD400X_IIO_H__ */

0 comments on commit 5e09916

Please sign in to comment.