AD7768-1 Library Files

Files at this revision

API Documentation at this revision

Comitter:
jngarlitos
Date:
Mon Mar 15 06:51:56 2021 +0000
Parent:
0:3c3bc5b9174a
Commit message:
Initial Commit for AD7768-1 library files

Changed in this revision

AD77681.cpp Show diff for this revision Revisions of this file
AD77681.h Show diff for this revision Revisions of this file
ad77681.c Show annotated file Show diff for this revision Revisions of this file
ad77681.h Show annotated file Show diff for this revision Revisions of this file
diff -r 3c3bc5b9174a -r abe97d9dd504 AD77681.cpp
diff -r 3c3bc5b9174a -r abe97d9dd504 AD77681.h
diff -r 3c3bc5b9174a -r abe97d9dd504 ad77681.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad77681.c	Mon Mar 15 06:51:56 2021 +0000
@@ -0,0 +1,1848 @@
+/***************************************************************************//**
+ *   @file   ad77681.c
+ *   @brief  Implementation of AD7768-1 Driver.
+ *   @author SPopa (stefan.popa@analog.com)
+********************************************************************************
+ * Copyright 2017(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 Files **********************************/
+/******************************************************************************/
+#include "stdio.h"
+#include "stdlib.h"
+#include "stdbool.h"
+#include <string.h>
+#include "ad77681.h"
+#include "error.h"
+#include "delay.h"
+
+/******************************************************************************/
+/************************** Functions Implementation **************************/
+/******************************************************************************/
+/**
+ * Compute CRC8 checksum.
+ * @param data - The data buffer.
+ * @param data_size - The size of the data buffer.
+ * @param init_val - CRC initial value.
+ * @return CRC8 checksum.
+ */
+uint8_t ad77681_compute_crc8(uint8_t *data,
+			     uint8_t data_size,
+			     uint8_t init_val)
+{
+	uint8_t i;
+	uint8_t crc = init_val;
+
+	while (data_size) {
+		for (i = 0x80; i != 0; i >>= 1) {
+			if (((crc & 0x80) != 0) != ((*data & i) != 0)) {
+				crc <<= 1;
+				crc ^= AD77681_CRC8_POLY;
+			} else
+				crc <<= 1;
+		}
+		data++;
+		data_size--;
+	}
+	return crc;
+}
+
+/**
+ * Compute XOR checksum.
+ * @param data - The data buffer.
+ * @param data_size - The size of the data buffer.
+ * @param init_val - CRC initial value.
+ * @return XOR checksum.
+ */
+uint8_t ad77681_compute_xor(uint8_t *data,
+			    uint8_t data_size,
+			    uint8_t init_val)
+{
+	uint8_t crc = init_val;
+	uint8_t buf[3];
+	uint8_t i;
+
+	for (i = 0; i < data_size; i++) {
+		buf[i] = *data;
+		crc ^= buf[i];
+		data++;
+	}
+	return crc;
+}
+
+/**
+ * Read from device.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param reg_data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_reg_read(struct ad77681_dev *dev,
+			     uint8_t reg_addr,
+			     uint8_t *reg_data)
+{
+	int32_t ret;
+	uint8_t crc;
+	uint8_t buf[3], crc_buf[2];
+	uint8_t buf_len = (dev->crc_sel == AD77681_NO_CRC) ? 2 : 3;
+
+	buf[0] = AD77681_REG_READ(reg_addr);
+	buf[1] = 0x00;
+
+	ret = spi_write_and_read(dev->spi_desc, buf, buf_len);
+	if (ret < 0)
+		return ret;
+
+	/* XOR or CRC checksum for read transactions */
+	if (dev->crc_sel != AD77681_NO_CRC) {
+		crc_buf[0] = AD77681_REG_READ(reg_addr);
+		crc_buf[1] = buf[1];
+
+		if (dev->crc_sel == AD77681_XOR)
+			/* INITIAL_CRC is 0, when ADC is not in continuous-read mode */
+			crc = ad77681_compute_xor(crc_buf, 2, INITIAL_CRC);
+		else if(dev->crc_sel == AD77681_CRC)
+			/* INITIAL_CRC is 0, when ADC is not in continuous-read mode */
+			crc = ad77681_compute_crc8(crc_buf, 2, INITIAL_CRC);
+
+		/* In buf[2] is CRC from the ADC */
+		if (crc != buf[2])
+			ret = FAILURE;
+#ifdef CRC_DEBUG
+		printf("\n%x\t%x\tCRC/XOR: %s\n", crc,
+		       buf[2], ((crc !=  buf[2]) ? "FAULT" : "OK"));
+#endif /* CRC_DEBUG */
+	}
+
+	reg_data[0] = AD77681_REG_READ(reg_addr);
+	memcpy(reg_data + 1, buf + 1, ARRAY_SIZE(buf) - 1);
+
+	return ret;
+}
+
+/**
+ * Write to device.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param reg_data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_reg_write(struct ad77681_dev *dev,
+			      uint8_t reg_addr,
+			      uint8_t reg_data)
+{
+	uint8_t buf[3];
+	/* Buffer length in case of checksum usage */
+	uint8_t buf_len = (dev->crc_sel == AD77681_NO_CRC) ? 2 : 3;
+
+	buf[0] = AD77681_REG_WRITE(reg_addr);
+	buf[1] = reg_data;
+
+	/* CRC only for read transactions, CRC and XOR for write transactions*/
+	if (dev->crc_sel != AD77681_NO_CRC)
+		buf[2] = ad77681_compute_crc8(buf, 2, INITIAL_CRC);
+
+	return spi_write_and_read(dev->spi_desc, buf, buf_len);
+}
+
+/**
+ * SPI read from device using a mask.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param mask - The mask.
+ * @param data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_read_mask(struct ad77681_dev *dev,
+			      uint8_t reg_addr,
+			      uint8_t mask,
+			      uint8_t *data)
+{
+	uint8_t reg_data[3];
+	int32_t ret;
+
+	ret = ad77681_spi_reg_read(dev, reg_addr, reg_data);
+	*data = (reg_data[1] & mask);
+
+	return ret;
+}
+
+/**
+ * SPI write to device using a mask.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param mask - The mask.
+ * @param data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_write_mask(struct ad77681_dev *dev,
+			       uint8_t reg_addr,
+			       uint8_t mask,
+			       uint8_t data)
+{
+	uint8_t reg_data[3];
+	int32_t ret;
+
+	ret = ad77681_spi_reg_read(dev, reg_addr, reg_data);
+	reg_data[1] &= ~mask;
+	reg_data[1] |= data;
+	ret |= ad77681_spi_reg_write(dev, reg_addr, reg_data[1]);
+
+	return ret;
+}
+
+/**
+ * Helper function to get the number of rx bytes
+ * @param dev - The device structure.
+ * @return rx_buf_len - the number of rx bytes
+ */
+uint8_t ad77681_get_rx_buf_len(struct ad77681_dev *dev)
+{
+	uint8_t rx_buf_len = 0;
+	uint8_t data_len = 0;
+	uint8_t crc = 0;
+	uint8_t status_bit = 0;
+
+	data_len = 3;
+	crc = (dev->crc_sel == AD77681_NO_CRC) ? 0 : 1; // 1 byte for crc
+	status_bit = dev->status_bit; // one byte for status
+
+	rx_buf_len = data_len + crc + status_bit;
+
+	return rx_buf_len;
+}
+
+/**
+ * Helper function to get the number of SPI 16bit frames for INTERRUPT ADC DATA READ
+ * @param dev - The device structure.
+ * @return frame_16bit - the number of 16 bit SPI frames
+ */
+uint8_t ad77681_get_frame_byte(struct ad77681_dev *dev)
+{
+	/* number of 8bit frames */
+	uint8_t frame_bytes;
+	if (dev->conv_len == AD77681_CONV_24BIT)
+		frame_bytes = 3;
+	else
+		frame_bytes = 2;
+	if (dev->crc_sel != AD77681_NO_CRC)
+		frame_bytes++;
+	if (dev->status_bit)
+		frame_bytes++;
+
+	dev->data_frame_byte = frame_bytes;
+
+	return frame_bytes;
+}
+
+/**
+ * Read conversion result from device.
+ * @param dev - The device structure.
+ * @param adc_data - The conversion result data
+ * @param mode - Data read mode
+ * 		Accepted values: AD77681_REGISTER_DATA_READ
+ *				 AD77681_CONTINUOUS_DATA_READ
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_read_adc_data(struct ad77681_dev *dev,
+				  uint8_t *adc_data,
+				  enum ad77681_data_read_mode mode)
+{
+	uint8_t buf[6], crc_xor, add_buff;
+	int32_t ret;
+
+	if (mode == AD77681_REGISTER_DATA_READ) {
+		buf[0] = AD77681_REG_READ(AD77681_REG_ADC_DATA);
+		add_buff = 1;
+	} else {
+		buf[0] = 0x00;
+		add_buff = 0;
+	}
+	buf[1] = 0x00; /* added 2 more array places for max data length read */
+	buf[2] = 0x00; /* For register data read */
+	buf[3] = 0x00; /* register address + 3 bytes of data (24bit format) + Status bit + CRC */
+	buf[4] = 0x00; /* For continuous data read */
+	buf[5] = 0x00; /* 3 bytes of data (24bit format) + Status bit + CRC */
+
+
+	ret = spi_write_and_read(dev->spi_desc, buf, dev->data_frame_byte + add_buff);
+	if (ret < 0)
+		return ret;
+
+	if (dev->crc_sel != AD77681_NO_CRC) {
+		if (dev->crc_sel == AD77681_CRC)
+			crc_xor = ad77681_compute_crc8(buf + add_buff, dev->data_frame_byte - 1,
+						       INITIAL_CRC_CRC8);
+		else
+			crc_xor = ad77681_compute_xor(buf + add_buff, dev->data_frame_byte - 1,
+						      INITIAL_CRC_XOR);
+
+		if (crc_xor != buf[dev->data_frame_byte - (1 - add_buff)]) {
+			printf("%s: CRC Error.\n", __func__);
+			ret = FAILURE;
+		}
+#ifdef CRC_DEBUG
+		printf("\n%x\t%x\tCRC/XOR: %s\n", crc_xor,
+		       buf[dev->data_frame_byte - (1 - add_buff)],
+		       ((crc_xor != buf[dev->data_frame_byte - (1 - add_buff)]) ? "FAULT" : "OK"));
+#endif /* CRC_DEBUG */
+	}
+
+	/* Fill the adc_data buffer */
+	memcpy(adc_data, buf, ARRAY_SIZE(buf));
+
+	return ret;
+}
+
+/**
+ * CRC and status bit handling after each readout form the ADC
+ * @param dev - The device structure.
+ * @param *data_buffer - 16-bit buffer readed from the ADC containing the CRC,
+ * data and the stattus bit.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_CRC_status_handling(struct ad77681_dev *dev,
+				    uint16_t *data_buffer)
+{
+	int32_t ret = 0;
+	uint8_t status_byte = 0, checksum = 0, checksum_byte = 0, checksum_buf[5],
+		checksum_length = 0, i;
+	char print_buf[50];
+
+	/* Status bit handling */
+	if (dev->status_bit) {
+		/* 24bit ADC data + 8bit of status = 2 16bit frames */
+		if (dev->conv_len == AD77681_CONV_24BIT)
+			status_byte = data_buffer[1] & 0xFF;
+		/* 16bit ADC data + 8bit of status = 2 16bit frames */
+		else
+			status_byte = data_buffer[1] >> 8;
+	}
+
+	/* Checksum bit handling */
+	if (dev->crc_sel != AD77681_NO_CRC) {
+		if ((dev->status_bit == true) & (dev->conv_len == AD77681_CONV_24BIT)) {
+			/* 24bit ADC data + 8bit of status + 8bit of CRC = 3 16bit frames */
+			checksum_byte = data_buffer[2] >> 8;
+			checksum_length = 4;
+		} else if ((dev->status_bit == true) & (dev->conv_len == AD77681_CONV_16BIT)) {
+			/* 16bit ADC data + 8bit of status + 8bit of CRC = 2 16bit frames */
+			checksum_byte = data_buffer[1] & 0xFF;
+			checksum_length = 3;
+		} else if ((dev->status_bit == false) & (dev->conv_len == AD77681_CONV_24BIT)) {
+			/* 24bit ADC data + 8bit of CRC = 2 16bit frames */
+			checksum_byte = data_buffer[1] & 0xFF;
+			checksum_length = 3;
+		} else if ((dev->status_bit == false) & (dev->conv_len == AD77681_CONV_16BIT)) {
+			/* 16bit ADC data + 8bit of CRC = 2 16bit frames */
+			checksum_byte = data_buffer[1] >> 8;
+			checksum_length = 2;
+		}
+
+		for (i = 0; i < checksum_length; i++) {
+			if (i % 2)
+				checksum_buf[i] = data_buffer[i / 2] & 0xFF;
+			else
+				checksum_buf[i] = data_buffer[i / 2] >> 8;
+		}
+
+		if (dev->crc_sel == AD77681_CRC)
+			checksum = ad77681_compute_crc8(checksum_buf, checksum_length,
+							INITIAL_CRC_CRC8);
+		else if (dev->crc_sel == AD77681_XOR)
+			checksum = ad77681_compute_xor(checksum_buf, checksum_length, INITIAL_CRC_XOR);
+
+		if (checksum != checksum_byte)
+			ret = FAILURE;
+
+#ifdef CRC_DEBUG
+
+		char ok[3] = { 'O', 'K' }, fault[6] = { 'F', 'A', 'U', 'L', 'T' };
+		sprintf(print_buf, "\n%x\t%x\t%x\tCRC %s", checksum_byte, checksum, status_byte,
+			((ret == FAILURE) ? (fault) : (ok)));
+		printf(print_buf);
+
+#endif /* CRC_DEBUG */
+	}
+
+	return ret;
+}
+
+/**
+ * Conversion from measured data to voltage
+ * @param dev - The device structure.
+ * @param raw_code - ADC raw code measurements
+ * @param voltage - Converted ADC code to voltage
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_data_to_voltage(struct ad77681_dev *dev,
+				uint32_t *raw_code,
+				double *voltage)
+{
+	int32_t converted_data;
+
+	if (*raw_code & 0x800000)
+		converted_data = (int32_t)((0xFF << 24) | *raw_code);
+	else
+		converted_data = (int32_t)((0x00 << 24) | *raw_code);
+
+	/* ((2*Vref)*code)/2^24	*/
+	*voltage = (double)(((2.0 * (((double)(dev->vref)) / 1000.0)) /
+			     AD7768_FULL_SCALE) * converted_data);
+
+	return SUCCESS;
+}
+
+/**
+ * Update ADCs sample rate depending on MCLK, MCLK_DIV and filter settings
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_update_sample_rate(struct ad77681_dev *dev)
+{
+	uint8_t mclk_div;
+	uint16_t osr;
+
+	/* Finding out MCLK divider */
+	switch (dev->mclk_div) {
+	case AD77681_MCLK_DIV_16:
+		mclk_div = 16;
+		break;
+	case AD77681_MCLK_DIV_8:
+		mclk_div = 8;
+		break;
+	case AD77681_MCLK_DIV_4:
+		mclk_div = 4;
+		break;
+	case AD77681_MCLK_DIV_2:
+		mclk_div = 2;
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	/* Finding out decimation ratio */
+	switch (dev->filter) {
+	case (AD77681_SINC5 | AD77681_FIR):
+		/* Decimation ratio of FIR or SINC5 (x32 to x1024) */
+		switch (dev->decimate) {
+		case AD77681_SINC5_FIR_DECx32:
+			osr = 32;
+			break;
+		case AD77681_SINC5_FIR_DECx64:
+			osr = 64;
+			break;
+		case AD77681_SINC5_FIR_DECx128:
+			osr = 128;
+			break;
+		case AD77681_SINC5_FIR_DECx256:
+			osr = 256;
+			break;
+		case AD77681_SINC5_FIR_DECx512:
+			osr = 512;
+			break;
+		case AD77681_SINC5_FIR_DECx1024:
+			osr = 1024;
+			break;
+		default:
+			return FAILURE;
+			break;
+		}
+		break;
+	/* Decimation ratio of SINC5 x8 */
+	case AD77681_SINC5_DECx8:
+		osr = 8;
+		break;
+	/* Decimation ratio of SINC5 x16 */
+	case AD77681_SINC5_DECx16:
+		osr = 16;
+		break;
+	/* Decimation ratio of SINC3 */
+	case AD77681_SINC3:
+		osr = (dev->sinc3_osr + 1) * 32;
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	/* Sample rate to Hz */
+	dev->sample_rate = (dev->mclk / (osr*mclk_div)) * 1000;
+
+	return SUCCESS;
+}
+
+/**
+ * Get SINC3 filter oversampling ratio register value based on user's inserted
+ * output data rate ODR
+ * @param dev - The device structure.
+ * @param sinc3_dec_reg - Returned closest value of SINC3 register
+ * @param sinc3_odr - Desired output data rage
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_SINC3_ODR(struct ad77681_dev *dev,
+			  uint16_t *sinc3_dec_reg,
+			  float sinc3_odr)
+{
+	uint8_t mclk_div;
+	float	odr;
+
+	if (sinc3_odr < 0)
+		return FAILURE;
+
+	switch (dev->mclk_div) {
+	case AD77681_MCLK_DIV_16:
+		mclk_div = 16;
+		break;
+	case AD77681_MCLK_DIV_8:
+		mclk_div = 8;
+		break;
+	case AD77681_MCLK_DIV_4:
+		mclk_div = 4;
+		break;
+	case AD77681_MCLK_DIV_2:
+		mclk_div = 2;
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	odr = ((float)(dev->mclk * 1000.0) / (sinc3_odr * (float)(32 * mclk_div))) - 1;
+
+	/* Sinc3 oversamplig register has 13 bits, biggest value = 8192 */
+	if (odr < 8193)
+		*sinc3_dec_reg = (uint16_t)(odr);
+	else
+		return FAILURE;
+
+	return SUCCESS;
+}
+
+/**
+ * Set the power consumption mode of the ADC core.
+ * @param dev - The device structure.
+ * @param mode - The power mode.
+ * 					Accepted values: AD77681_ECO
+ *									 AD77681_MEDIAN
+ *									 AD77681_FAST
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_power_mode(struct ad77681_dev *dev,
+			       enum ad77681_power_mode mode)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_POWER_CLOCK,
+				     AD77681_POWER_CLK_PWRMODE_MSK,
+				     AD77681_POWER_CLK_PWRMODE(mode));
+
+	if (ret == SUCCESS)
+		dev->power_mode = mode;
+
+	return ret;
+}
+
+/**
+ * Set the MCLK divider.
+ * @param dev - The device structure.
+ * @param clk_div - The MCLK divider.
+ * 					Accepted values: AD77681_MCLK_DIV_16
+ *									 AD77681_MCLK_DIV_8
+ *									 AD77681_MCLK_DIV_4
+ *									 AD77681_MCLK_DIV_2
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_mclk_div(struct ad77681_dev *dev,
+			     enum ad77681_mclk_div clk_div)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_POWER_CLOCK,
+				     AD77681_POWER_CLK_MCLK_DIV_MSK,
+				     AD77681_POWER_CLK_MCLK_DIV(clk_div));
+
+	if (ret == SUCCESS)
+		dev->mclk_div = clk_div;
+
+	return ret;
+}
+
+/**
+ * Set the VCM output.
+ * @param dev - The device structure.
+ * @param VCM_out - The VCM output voltage.
+ * 			Accepted values: AD77681_VCM_HALF_VCC
+ *					 AD77681_VCM_2_5V
+ *	  				 AD77681_VCM_2_05V
+ *					 AD77681_VCM_1_9V
+ *					 AD77681_VCM_1_65V
+ *					 AD77681_VCM_1_1V
+ *					 AD77681_VCM_0_9V
+ *					 AD77681_VCM_OFF
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_VCM_output(struct ad77681_dev *dev,
+			       enum ad77681_VCM_out VCM_out)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ANALOG2,
+				     AD77681_ANALOG2_VCM_MSK,
+				     AD77681_ANALOG2_VCM(VCM_out));
+
+	if (ret == SUCCESS)
+		dev->VCM_out = VCM_out;
+
+	return ret;
+}
+
+/**
+ * Set the AIN- precharge buffer.
+ * @param dev - The device structure.
+ * @param AINn - The negative analog input precharge buffer selector
+ * 		 Accepted values: AD77681_AINn_ENABLED
+ *				  AD77681_AINn_DISABLED
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_AINn_buffer(struct ad77681_dev *dev,
+				enum ad77681_AINn_precharge AINn)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ANALOG,
+				     AD77681_ANALOG_AIN_BUF_NEG_OFF_MSK,
+				     AD77681_ANALOG_AIN_BUF_NEG_OFF(AINn));
+
+	if (ret == SUCCESS)
+		dev->AINn = AINn;
+
+	return ret;
+}
+
+/**
+ * Set the AIN+ precharge buffer.
+ * @param dev - The device structure.
+ * @param AINp - The positive analog input precharge buffer selector
+ * 		 Accepted values: AD77681_AINp_ENABLED
+ *				  AD77681_AINp_DISABLED
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_AINp_buffer(struct ad77681_dev *dev,
+				enum ad77681_AINp_precharge AINp)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ANALOG,
+				     AD77681_ANALOG_AIN_BUF_POS_OFF_MSK,
+				     AD77681_ANALOG_AIN_BUF_POS_OFF(AINp));
+
+	if (ret == SUCCESS)
+		dev->AINp = AINp;
+
+	return ret;
+}
+
+/**
+ * Set the REF- reference buffer
+ * @param dev - The device structure.
+ * @param REFn - The negative reference buffer selector
+ * 		 Accepted values: AD77681_BUFn_DISABLED
+ *				  AD77681_BUFn_ENABLED
+ *				  AD77681_BUFn_FULL_BUFFER_ON
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_REFn_buffer(struct ad77681_dev *dev,
+				enum ad77681_REFn_buffer REFn)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ANALOG,
+				     AD77681_ANALOG_REF_BUF_NEG_MSK,
+				     AD77681_ANALOG_REF_BUF_NEG(REFn));
+
+	if (ret == SUCCESS)
+		dev->REFn = REFn;
+
+	return ret;
+}
+
+/**
+ * Set the REF+ reference buffer
+ * @param dev -  The device structure.
+ * @param REFp - The positive reference buffer selector
+ * 		 Accepted values: AD77681_BUFp_DISABLED
+ *				  AD77681_BUFp_ENABLED
+ *				  AD77681_BUFp_FULL_BUFFER_ON
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_REFp_buffer(struct ad77681_dev *dev,
+				enum ad77681_REFp_buffer REFp)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ANALOG,
+				     AD77681_ANALOG_REF_BUF_POS_MSK,
+				     AD77681_ANALOG_REF_BUF_POS(REFp));
+
+	if (ret == SUCCESS)
+		dev->REFp = REFp;
+	else
+		return FAILURE;
+
+	return ret;
+}
+
+/**
+ * Set filter type and decimation ratio
+ * @param dev -	The device structure.
+ * @param decimate - Decimation ratio of filter
+ *			Accepted values: AD77681_SINC5_FIR_DECx32
+ *					 AD77681_SINC5_FIR_DECx64
+ *					 AD77681_SINC5_FIR_DECx128
+ *					 AD77681_SINC5_FIR_DECx256
+ *					 AD77681_SINC5_FIR_DECx512
+ *					 AD77681_SINC5_FIR_DECx1024
+ * @param filter - Select filter type
+ *			Accepted values: AD77681_SINC5
+ *					 AD77681_SINC5_DECx8
+ *					 AD77681_SINC5_DECx16
+ *					 AD77681_SINC3
+ *					 AD77681_FIR
+ * @param sinc3_osr - Select decimation ratio for SINC3 filter separately as
+ *			integer from 0 to 8192.
+ *			See the AD7768-1 datasheet for more info
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_filter_type(struct ad77681_dev *dev,
+				enum ad77681_sinc5_fir_decimate decimate,
+				enum ad77681_filter_type filter,
+				uint16_t sinc3_osr)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_reg_write(dev, AD77681_REG_DIGITAL_FILTER, 0x00);
+
+	/* SINC5 for OSR 8x and 16x*/
+	if ((filter == AD77681_SINC5_DECx8) || (filter == AD77681_SINC5_DECx16)) {
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_DIGITAL_FILTER,
+					      AD77681_DIGI_FILTER_FILTER_MSK,
+					      AD77681_DIGI_FILTER_FILTER(filter));
+		/* SINC5 and FIR for osr 32x to 1024x */
+	} else if ((filter == AD77681_SINC5) || (filter == AD77681_FIR)) {
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_DIGITAL_FILTER,
+					      AD77681_DIGI_FILTER_FILTER_MSK,
+					      AD77681_DIGI_FILTER_FILTER(filter));
+
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_DIGITAL_FILTER,
+					      AD77681_DIGI_FILTER_DEC_RATE_MSK,
+					      AD77681_DIGI_FILTER_DEC_RATE(decimate));
+		/* SINC3*/
+	} else {
+		uint8_t sinc3_LSB = 0, sinc3_MSB = 0;
+
+		sinc3_MSB = sinc3_osr >> 8;
+		sinc3_LSB = sinc3_osr & 0x00FF;
+
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_DIGITAL_FILTER,
+					      AD77681_DIGI_FILTER_FILTER_MSK,
+					      AD77681_DIGI_FILTER_FILTER(filter));
+
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_SINC3_DEC_RATE_MSB,
+					      AD77681_SINC3_DEC_RATE_MSB_MSK,
+					      AD77681_SINC3_DEC_RATE_MSB(sinc3_MSB));
+
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_SINC3_DEC_RATE_LSB,
+					      AD77681_SINC3_DEC_RATE_LSB_MSK,
+					      AD77681_SINC3_DEC_RATE_LSB(sinc3_LSB));
+	}
+
+	if ( ret == SUCCESS) {
+		dev->decimate = decimate;
+		dev->filter = filter;
+		/* Sync pulse after each filter change */
+		ret |= ad77681_initiate_sync(dev);
+	}
+
+	return ret;
+}
+
+/**
+ * Enable 50/60 Hz rejection
+ * @param dev -	The device structure.
+ * @param enable - The positive reference buffer selector
+ * 		   Accepted values: true
+ *				    false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_50HZ_rejection(struct ad77681_dev *dev,
+				   uint8_t enable)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_DIGITAL_FILTER,
+				     AD77681_DIGI_FILTER_60HZ_REJ_EN_MSK,
+				     AD77681_DIGI_FILTER_60HZ_REJ_EN(enable));
+
+	return ret;
+}
+
+/**
+ * Set the REF- reference buffer
+ * @param dev - The device structure.
+ * @param continuous_enable - Continous read enable
+ * 		 Accepted values: AD77681_CONTINUOUS_READ_ENABLE
+ *				  AD77681_CONTINUOUS_READ_DISABLE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_continuos_read(struct ad77681_dev *dev,
+				   enum ad77681_continuous_read continuous_enable)
+{
+	int32_t ret;
+
+	if (continuous_enable) {
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_INTERFACE_FORMAT,
+					     AD77681_INTERFACE_CONT_READ_MSK,
+					     AD77681_INTERFACE_CONT_READ_EN(continuous_enable));
+	} else {
+		/* To exit the continuous read mode, a key 0x6C must be
+		written into the device over the SPI*/
+		uint8_t end_key = EXIT_CONT_READ;
+		ret = spi_write_and_read(dev->spi_desc, &end_key, 1);
+	}
+
+	return ret;
+}
+
+/**
+ * Power down / power up the device
+ * @param dev -	The device structure.
+ * @param sleep_wake - Power down, or power up the ADC
+ * 			Accepted values: AD77681_SLEEP
+ *					 AD77681_WAKE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_power_down(struct ad77681_dev *dev,
+			   enum ad77681_sleep_wake sleep_wake)
+{
+	int32_t ret;
+
+	if (sleep_wake == AD77681_SLEEP) {
+		ret = ad77681_spi_reg_write(dev, AD77681_REG_POWER_CLOCK,
+					    AD77681_POWER_CLK_POWER_DOWN);
+	} else {
+		/* Wake up the ADC over SPI, by sending a wake-up sequence:
+		1 followed by 63 zeroes and CS hold low*/
+		uint8_t wake_sequence[8] = { 0 };
+		/* Insert '1' to the beginning of the wake_sequence*/
+		wake_sequence[0] = 0x80;
+		ret = spi_write_and_read(dev->spi_desc, wake_sequence,
+					 ARRAY_SIZE(wake_sequence));
+	}
+
+	return ret;
+}
+
+/**
+ * Conversion mode and source select
+ * @param dev - The device structure.
+ * @param conv_mode - Sets the conversion mode of the ADC
+ * 					  Accepted values: AD77681_CONV_CONTINUOUS
+ *									   AD77681_CONV_ONE_SHOT
+ *									   AD77681_CONV_SINGLE
+ *									   AD77681_CONV_PERIODIC
+ * @param diag_mux_sel - Selects which signal to route through diagnostic mux
+ * 					  Accepted values: AD77681_TEMP_SENSOR
+ *									   AD77681_AIN_SHORT
+ *									   AD77681_POSITIVE_FS
+ *									   AD77681_NEGATIVE_FS
+ * @param conv_diag_sel - Select the input for conversion as AIN or diagnostic mux
+ * 					  Accepted values: true
+ *									   false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_conv_mode(struct ad77681_dev *dev,
+			      enum ad77681_conv_mode conv_mode,
+			      enum ad77681_conv_diag_mux diag_mux_sel,
+			      bool conv_diag_sel)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_CONVERSION,
+				     AD77681_CONVERSION_MODE_MSK,
+				     AD77681_CONVERSION_MODE(conv_mode));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_CONVERSION,
+				      AD77681_CONVERSION_DIAG_MUX_MSK,
+				      AD77681_CONVERSION_DIAG_MUX_SEL(diag_mux_sel));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_CONVERSION,
+				      AD77681_CONVERSION_DIAG_SEL_MSK,
+				      AD77681_CONVERSION_DIAG_SEL(conv_diag_sel));
+
+	if (ret == SUCCESS) {
+		dev->conv_mode = conv_mode;
+		dev->diag_mux_sel = diag_mux_sel;
+		dev->conv_diag_sel = conv_diag_sel;
+	}
+
+	return ret;
+}
+
+/**
+ * Set the Conversion Result Output Length.
+ * @param dev - The device structure.
+ * @param conv_len - The MCLK divider.
+ * 					Accepted values: AD77681_CONV_24BIT
+ *									 AD77681_CONV_16BIT
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_convlen(struct ad77681_dev *dev,
+			    enum ad77681_conv_len conv_len)
+{
+	int32_t ret;
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_INTERFACE_FORMAT,
+				     AD77681_INTERFACE_CONVLEN_MSK,
+				     AD77681_INTERFACE_CONVLEN(conv_len));
+
+	if (ret == SUCCESS) {
+		dev->conv_len = conv_len;
+		ad77681_get_frame_byte(dev);
+	}
+
+	return ret;
+}
+
+/**
+ * Activates CRC on all SPI transactions and
+ * Selects CRC method as XOR or 8-bit polynomial
+ * @param dev - The device structure.
+ * @param crc_sel - The CRC type.
+ * 					Accepted values: AD77681_CRC
+ *									 AD77681_XOR
+ *									 AD77681_NO_CRC
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_crc_sel(struct ad77681_dev *dev,
+			    enum ad77681_crc_sel crc_sel)
+{
+	int32_t ret;
+
+	if (crc_sel == AD77681_NO_CRC) {
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_INTERFACE_FORMAT,
+					     AD77681_INTERFACE_CRC_EN_MSK,
+					     AD77681_INTERFACE_CRC_EN(0));
+	} else {
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_INTERFACE_FORMAT,
+					     AD77681_INTERFACE_CRC_EN_MSK,
+					     AD77681_INTERFACE_CRC_EN(1));
+
+		ret |= ad77681_spi_write_mask(dev,
+					      AD77681_REG_INTERFACE_FORMAT,
+					      AD77681_INTERFACE_CRC_TYPE_MSK,
+					      AD77681_INTERFACE_CRC_TYPE(crc_sel));
+	}
+
+	if (ret == SUCCESS) {
+		dev->crc_sel = crc_sel;
+		ad77681_get_frame_byte(dev);
+	}
+
+	return ret;
+}
+
+/**
+ * Enables Status bits output
+ * @param dev - The device structure.
+ * @param status_bit - enable or disable status bit
+ * 					Accepted values: true
+ *									 false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_status_bit(struct ad77681_dev *dev,
+			       bool status_bit)
+{
+	int32_t ret;
+
+	// Set status bit
+	ret = 	ad77681_spi_write_mask(dev,
+				       AD77681_REG_INTERFACE_FORMAT,
+				       AD77681_INTERFACE_STATUS_EN_MSK,
+				       AD77681_INTERFACE_STATUS_EN(status_bit));
+
+	if (ret == SUCCESS) {
+		dev->status_bit = status_bit;
+		ad77681_get_frame_byte(dev);
+	}
+
+	return ret;
+}
+
+/**
+ * Device reset over SPI.
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_soft_reset(struct ad77681_dev *dev)
+{
+	int32_t ret = 0;
+
+	// Two writes are required to initialize the reset
+	ret |= 	ad77681_spi_write_mask(dev,
+				       AD77681_REG_SYNC_RESET,
+				       AD77681_SYNC_RST_SPI_RESET_MSK,
+				       AD77681_SYNC_RST_SPI_RESET(0x3));
+
+	ret |= 	ad77681_spi_write_mask(dev,
+				       AD77681_REG_SYNC_RESET,
+				       AD77681_SYNC_RST_SPI_RESET_MSK,
+				       AD77681_SYNC_RST_SPI_RESET(0x2));
+
+	return ret;
+}
+
+/**
+ * Initiate a SYNC_OUT pulse over spi
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_initiate_sync(struct ad77681_dev *dev)
+{
+	return ad77681_spi_write_mask(dev,
+				      AD77681_REG_SYNC_RESET,
+				      AD77681_SYNC_RST_SPI_STARTB_MSK,
+				      AD77681_SYNC_RST_SPI_STARTB(0));
+}
+
+/**
+ * Write to offset registers
+ * @param dev 			The device structure.
+ * @param value			The desired value of the whole 24-bit offset register
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_apply_offset(struct ad77681_dev *dev,
+			     uint32_t value)
+{
+	int32_t ret;
+	uint8_t offset_HI = 0, offset_MID = 0, offset_LO = 0;
+
+	offset_HI = (value & 0x00FF0000) >> 16;
+	offset_MID = (value & 0x0000FF00) >> 8;
+	offset_LO = (value & 0x000000FF);
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_OFFSET_HI,
+				     AD77681_OFFSET_HI_MSK,
+				     AD77681_OFFSET_HI(offset_HI));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_OFFSET_MID,
+				      AD77681_OFFSET_MID_MSK,
+				      AD77681_OFFSET_MID(offset_MID));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_OFFSET_LO,
+				      AD77681_OFFSET_LO_MSK,
+				      AD77681_OFFSET_LO(offset_LO));
+
+	return ret;
+}
+
+/**
+ * Write to gain registers
+ * @param dev - The device structure.
+ * @param value - The desired value of the whole 24-bit gain register
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_apply_gain(struct ad77681_dev *dev,
+			   uint32_t value)
+{
+	int32_t ret;
+	uint8_t gain_HI = 0, gain_MID = 0, gain_LO = 0;
+
+	gain_HI = (value & 0x00FF0000) >> 16;
+	gain_MID = (value & 0x0000FF00) >> 8;
+	gain_LO = (value & 0x000000FF);
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_GAIN_HI,
+				     AD77681_GAIN_HI_MSK,
+				     AD77681_GAIN_HI(gain_HI));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_GAIN_MID,
+				      AD77681_GAIN_MID_MSK,
+				      AD77681_GAIN_MID(gain_MID));
+
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_GAIN_LO,
+				      AD77681_GAIN_LOW_MSK,
+				      AD77681_GAIN_LOW(gain_LO));
+
+	return ret;
+}
+
+/**
+ * Upload sequence for Programmamble FIR filter
+ * @param dev - The device structure.
+ * @param coeffs - Pointer to the desired filter coefficients array to be written
+ * @param num_coeffs - Count of active filter coeffs
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_programmable_filter(struct ad77681_dev *dev,
+				    const float *coeffs,
+				    uint8_t num_coeffs)
+{
+	uint8_t coeffs_buf[4], coeffs_index, check_back = 0, i, address;
+	uint32_t twait;
+	int32_t twos_complement, ret;
+	const uint8_t coeff_reg_length = 56;
+
+	/* Specific keys in the upload sequence */
+	const uint8_t key1 = 0xAC, key2 = 0x45, key3 = 0x55;
+	/* Scaling factor for all coefficients 2^22 */
+	const float coeff_scale_factor = (1 << 22);
+	/* Wait time in uS necessary to access the COEFF_CONTROL and */
+	/* COEFF_DATA registers. Twait = 512/MCLK */
+	twait = (uint32_t)(((512.0) / ((float)(dev->mclk))) * 1000.0) + 1;
+
+	/* Set Filter to FIR */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_DIGITAL_FILTER,
+				     AD77681_DIGI_FILTER_FILTER_MSK,
+				     AD77681_DIGI_FILTER_FILTER(AD77681_FIR));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Write the first access key to the ACCESS_KEY register */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ACCESS_KEY,
+				     AD77681_ACCESS_KEY_MSK,
+				     AD77681_ACCESS_KEY(key1));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Write the second access key to the ACCESS_KEY register */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ACCESS_KEY,
+				     AD77681_ACCESS_KEY_MSK,
+				     AD77681_ACCESS_KEY(key2));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Read the the ACCESS_KEY register bit 0, the key bit */
+	ret = ad77681_spi_read_mask(dev,
+				    AD77681_REG_ACCESS_KEY,
+				    AD77681_ACCESS_KEY_CHECK_MSK,
+				    &check_back);
+
+	/* Checks ret and key bit, return FAILURE in case key bit not equal to 1 */
+	if ((ret < 0) || (check_back != 1))
+		return FAILURE;
+
+	/* Set the initial adress to 0 and enable the  write and coefficient access bits */
+	address = AD77681_COEF_CONTROL_COEFFACCESSEN_MSK
+		  | AD77681_COEF_CONTROL_COEFFWRITEEN_MSK;
+
+	/* The COEFF_DATA register has to be filled with 56 coeffs.*/
+	/* In case the number of active filter coefficient is less */
+	/* than 56, zeros will be padded before the desired coeff. */
+	for (i = 0; i < coeff_reg_length; i++) {
+		/* Set the coeff address */
+		ret = ad77681_spi_reg_write(dev,
+					    AD77681_REG_COEFF_CONTROL,
+					    address);
+
+		/* Check return value before proceeding */
+		if (ret < 0)
+			return ret;
+
+		/* Wait for Twait uSeconds*/
+		udelay(twait);
+
+		/* Padding of zeros before the desired coef in case the coef count in less than 56 */
+		if((num_coeffs + i) < coeff_reg_length) {
+			/* wirte zeroes to COEFF_DATA, in case of less coeffs than 56*/
+			coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+			coeffs_buf[1] = 0;
+			coeffs_buf[2] = 0;
+			coeffs_buf[3] = 0;
+		} else {/* Writting of desired filter coefficients */
+			/* Computes the index of coefficients to be uploaded */
+			coeffs_index = (num_coeffs + i) - coeff_reg_length;
+			/* Scaling the coefficient value and converting it to 2's complement */
+			twos_complement = (int32_t)(coeffs[coeffs_index] * coeff_scale_factor);
+
+			/* Write coefficients to COEFF_DATA */
+			coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+			coeffs_buf[1] = (twos_complement & 0xFF0000) >> 16;
+			coeffs_buf[2] = (twos_complement & 0x00FF00) >> 8;
+			coeffs_buf[3] = (twos_complement & 0x0000FF);
+		}
+
+		ret = spi_write_and_read(dev->spi_desc, coeffs_buf, 4);
+
+		/* Check return value before proceeding */
+		if (ret < 0)
+			return ret;
+
+		/* Increment the address*/
+		address++;
+		/* Wait for Twait uSeconds*/
+		udelay(twait);
+	}
+
+	/* Disable coefficient write */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_COEFF_CONTROL,
+				     AD77681_COEF_CONTROL_COEFFWRITEEN_MSK,
+				     AD77681_COEF_CONTROL_COEFFWRITEEN(0x00));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	udelay(twait);
+
+	/* Disable coefficient access */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_COEFF_CONTROL,
+				     AD77681_COEF_CONTROL_COEFFACCESSEN_MSK,
+				     AD77681_COEF_CONTROL_COEFFACCESSEN(0x00));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Toggle the synchronization pulse and to begin reading data */
+	/* Write 0x800000 to COEFF_DATA */
+	coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+	coeffs_buf[1] = 0x80;
+	coeffs_buf[2] = 0x00;
+	coeffs_buf[3] = 0x00;
+
+	ret = spi_write_and_read(dev->spi_desc, coeffs_buf, 4);
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Exit filter upload by wirting specific access key 0x55*/
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_ACCESS_KEY,
+				     AD77681_ACCESS_KEY_MSK,
+				     AD77681_ACCESS_KEY(key3));
+
+	/* Check return value before proceeding */
+	if (ret < 0)
+		return ret;
+
+	/* Send synchronization pulse */
+	ad77681_initiate_sync(dev);
+
+	return ret;
+}
+
+/**
+ * Read value from GPIOs present in AD7768-1 separately, or all GPIOS at once.
+ * @param dev - The device structure.
+ * @param value	- Readed value.
+ * @param gpio_number - Number of GPIO, the value will be written into
+ *			Accepted values: AD77681_GPIO0
+ *					 AD77681_GPIO1
+ *					 AD77681_GPIO2
+ *					 AD77681_GPIO3
+ *					 AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_read(struct ad77681_dev *dev,
+			  uint8_t *value,
+			  enum ad77681_gpios gpio_number)
+{
+	int32_t ret;
+
+	switch (gpio_number) {
+	case AD77681_GPIO0:	/* Read to GPIO0 */
+		ret = ad77681_spi_read_mask(dev,
+					    AD77681_REG_GPIO_READ,
+					    AD77681_GPIO_READ_0_MSK,
+					    value);
+		break;
+	case AD77681_GPIO1:	/* Read to GPIO1 */
+		ret = ad77681_spi_read_mask(dev,
+					    AD77681_REG_GPIO_READ,
+					    AD77681_GPIO_READ_1_MSK,
+					    value);
+		break;
+	case AD77681_GPIO2:	/* Read to GPIO2 */
+		ret = ad77681_spi_read_mask(dev,
+					    AD77681_REG_GPIO_READ,
+					    AD77681_GPIO_READ_2_MSK,
+					    value);
+		break;
+	case AD77681_GPIO3:	/* Read to GPIO3 */
+		ret = ad77681_spi_read_mask(dev,
+					    AD77681_REG_GPIO_READ,
+					    AD77681_GPIO_READ_3_MSK,
+					    value);
+		break;
+	case AD77681_ALL_GPIOS: /* Read to all GPIOs */
+		ret = ad77681_spi_read_mask(dev,
+					    AD77681_REG_GPIO_READ,
+					    AD77681_GPIO_READ_ALL_MSK,
+					    value);
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * Write value to GPIOs present in AD7768-1 separately, or all GPIOS at once.
+ * @param dev - The device structure.
+ * @param value - Value to be written into GPIO
+ *		  Accepted values: GPIO_HIGH
+ *				   GPIO_LOW
+ *				   4-bit value for all gpios
+ * @param gpio_number - Number of GPIO, the value will be written into
+ *			Accepted values: AD77681_GPIO0
+ *					 AD77681_GPIO1
+ *					 AD77681_GPIO2
+ *					 AD77681_GPIO3
+ *					 AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_write(struct ad77681_dev *dev,
+			   uint8_t value,
+			   enum ad77681_gpios gpio_number)
+{
+	int32_t ret;
+
+	switch (gpio_number) {
+	case AD77681_GPIO0:	/* Write to GPIO0 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_WRITE,
+					     AD77681_GPIO_WRITE_0_MSK,
+					     AD77681_GPIO_WRITE_0(value));
+		break;
+	case AD77681_GPIO1:	/* Write to GPIO1 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_WRITE,
+					     AD77681_GPIO_WRITE_1_MSK,
+					     AD77681_GPIO_WRITE_1(value));
+		break;
+	case AD77681_GPIO2: /* Write to GPIO2 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_WRITE,
+					     AD77681_GPIO_WRITE_2_MSK,
+					     AD77681_GPIO_WRITE_2(value));
+		break;
+	case AD77681_GPIO3: /* Write to GPIO3 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_WRITE,
+					     AD77681_GPIO_WRITE_3_MSK,
+					     AD77681_GPIO_WRITE_3(value));
+		break;
+	case AD77681_ALL_GPIOS: /* Write to all GPIOs */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_WRITE,
+					     AD77681_GPIO_WRITE_ALL_MSK,
+					     AD77681_GPIO_WRITE_ALL(value));
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * Set AD7768-1s GPIO as input or output.
+ * @param dev - The device structure.
+ * @param direction - Direction of the GPIO
+ *			Accepted values: GPIO_INPUT
+ *					 GPIO_OUTPUT
+ *					 4-bit value for all gpios
+ * @param gpio_number - Number of GPIO, which will be affected
+ *			Accepted values: AD77681_GPIO0
+ *					 AD77681_GPIO1
+ *					 AD77681_GPIO2
+ *					 AD77681_GPIO3
+ *					 AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_inout(struct ad77681_dev *dev,
+			   uint8_t direction,
+			   enum ad77681_gpios gpio_number)
+{
+	int32_t ret;
+
+	switch (gpio_number) {
+	case AD77681_GPIO0:	/* Set direction of GPIO0 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO0_OP_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO0_OP_EN(direction));
+		break;
+	case AD77681_GPIO1:	/* Set direction of GPIO1 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO1_OP_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO1_OP_EN(direction));
+		break;
+	case AD77681_GPIO2:	/* Set direction of GPIO2 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO2_OP_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO2_OP_EN(direction));
+		break;
+	case AD77681_GPIO3:	/* Set direction of GPIO3 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO3_OP_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO3_OP_EN(direction));
+		break;
+	case AD77681_ALL_GPIOS:	/* Set direction of all GPIOs */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN_MSK,
+					     AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN(direction));
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * Enable global GPIO bit.
+ * This bit must be set high to change GPIO settings.
+ * @param dev - The device structure.
+ * @param gpio_enable - Enable or diable the global GPIO pin
+ *			Accepted values: AD77681_GLOBAL_GPIO_ENABLE
+ *					 AD77681_GLOBAL_GPIO_DISABLE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_global_gpio(struct ad77681_dev *dev,
+			    enum ad77681_gobal_gpio_enable gpio_enable)
+{
+	return ad77681_spi_write_mask(dev,
+				      AD77681_REG_GPIO_CONTROL,
+				      AD77681_GPIO_CNTRL_UGPIO_EN_MSK,
+				      AD77681_GPIO_CNTRL_UGPIO_EN(gpio_enable));
+}
+
+/**
+ * Read and write from ADC scratchpad register to check SPI Communication in
+ * the very beginning, during inicialization.
+ * @param dev - The device structure.
+ * @param sequence - The sequence which will be written into scratchpad and the
+ * 		      readed sequence will be returned
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_scratchpad(struct ad77681_dev *dev,
+			   uint8_t *sequence)
+{
+	int32_t ret;
+	const uint8_t check = *sequence;/* Save the original sequence */
+	uint8_t ret_sequence = 0;/* Return sequence */
+
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_SCRATCH_PAD,
+				     AD77681_SCRATCHPAD_MSK,
+				     AD77681_SCRATCHPAD(check));
+
+	ret |= ad77681_spi_read_mask(dev,
+				     AD77681_REG_SCRATCH_PAD,
+				     AD77681_SCRATCHPAD_MSK,
+				     &ret_sequence);
+
+	if (check != ret_sequence)/* Compare original an returned sequence */
+		return FAILURE;
+
+	return ret;
+}
+
+/**
+ * Set AD7768-1s GPIO output type between strong driver and open drain.
+ * GPIO3 can not be accessed!
+ * @param dev - The device structure.
+ * @param gpio_number - AD7768-1s GPIO to be affected (Only GPIO0, GPIO1 and GPIO2)
+ *			Accepted values: AD77681_GPIO0
+ *					 AD77681_GPIO1
+ *					 AD77681_GPIO2
+ *					 AD77681_ALL_GPIOS
+ *
+ * @param output_type - Output type of the GPIO
+ *			Accepted values: AD77681_GPIO_STRONG_DRIVER
+ *					 AD77681_GPIO_OPEN_DRAIN
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_open_drain(struct ad77681_dev *dev,
+				enum ad77681_gpios gpio_number,
+				enum ad77681_gpio_output_type output_type)
+{
+	int32_t ret;
+
+	switch (gpio_number) {
+	case AD77681_GPIO0: /* Set ouptut type of GPIO0 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO0_OD_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO0_OD_EN(output_type));
+		break;
+	case AD77681_GPIO1: /* Set ouptut type of GPIO1 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO1_OD_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO1_OD_EN(output_type));
+		break;
+	case AD77681_GPIO2: /* Set ouptut type of GPIO2 */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_GPIO2_OD_EN_MSK,
+					     AD77681_GPIO_CNTRL_GPIO2_OD_EN(output_type));
+		break;
+	case AD77681_ALL_GPIOS: /* Set ouptut type of all GPIOs */
+		ret = ad77681_spi_write_mask(dev,
+					     AD77681_REG_GPIO_CONTROL,
+					     AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN_MSK,
+					     AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN(output_type));
+		break;
+	default:
+		return FAILURE;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * Clear all error flags at once
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_clear_error_flags(struct ad77681_dev *dev)
+{
+	int32_t ret;
+
+	/* SPI ignore error CLEAR */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_SPI_DIAG_STATUS,
+				     AD77681_SPI_IGNORE_ERROR_MSK,
+				     AD77681_SPI_IGNORE_ERROR_CLR(ENABLE));
+	/* SPI read error CLEAR */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_STATUS,
+				      AD77681_SPI_READ_ERROR_MSK,
+				      AD77681_SPI_READ_ERROR_CLR(ENABLE));
+	/* SPI write error CLEAR */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_STATUS,
+				      AD77681_SPI_WRITE_ERROR_MSK,
+				      AD77681_SPI_WRITE_ERROR_CLR(ENABLE));
+	/* SPI CRC error CLEAR */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_STATUS,
+				      AD77681_SPI_CRC_ERROR_MSK,
+				      AD77681_SPI_CRC_ERROR_CLR(ENABLE));
+
+	return ret;
+}
+
+/**
+ * Enabling error flags. All error flags enabled by default
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_error_flags_enabe(struct ad77681_dev *dev)
+{
+	int32_t ret;
+
+	/* SPI ERRORS ENABLE */
+	/* SPI ignore error enable */
+	ret = ad77681_spi_write_mask(dev,
+				     AD77681_REG_SPI_DIAG_ENABLE,
+				     AD77681_SPI_DIAG_ERR_SPI_IGNORE_MSK,
+				     AD77681_SPI_DIAG_ERR_SPI_IGNORE(ENABLE));
+	/*  SPI Clock count error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_ENABLE,
+				      AD77681_SPI_DIAG_ERR_SPI_CLK_CNT_MSK,
+				      AD77681_SPI_DIAG_ERR_SPI_CLK_CNT(ENABLE));
+	/* SPI Read error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_ENABLE,
+				      AD77681_SPI_DIAG_ERR_SPI_RD_MSK,
+				      AD77681_SPI_DIAG_ERR_SPI_RD(ENABLE));
+	/* SPI Write error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_SPI_DIAG_ENABLE,
+				      AD77681_SPI_DIAG_ERR_SPI_WR_MSK,
+				      AD77681_SPI_DIAG_ERR_SPI_WR(ENABLE));
+
+	/* ADC DIAG ERRORS ENABLE */
+	/* DLDO PSM error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_ADC_DIAG_ENABLE,
+				      AD77681_ADC_DIAG_ERR_DLDO_PSM_MSK,
+				      AD77681_ADC_DIAG_ERR_DLDO_PSM(ENABLE));
+	/* ALDO PSM error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_ADC_DIAG_ENABLE,
+				      AD77681_ADC_DIAG_ERR_ALDO_PSM_MSK,
+				      AD77681_ADC_DIAG_ERR_ALDO_PSM(ENABLE));
+	/* Filter saturated error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_ADC_DIAG_ENABLE,
+				      AD77681_ADC_DIAG_ERR_FILT_SAT_MSK,
+				      AD77681_ADC_DIAG_ERR_FILT_SAT(ENABLE));
+	/* Filter not settled error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_ADC_DIAG_ENABLE,
+				      AD77681_ADC_DIAG_ERR_FILT_NOT_SET_MSK,
+				      AD77681_ADC_DIAG_ERR_FILT_NOT_SET(ENABLE));
+	/* External clock check error enable */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_ADC_DIAG_ENABLE,
+				      AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL_MSK,
+				      AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL(ENABLE));
+
+	/* DIG DIAG ENABLE */
+	/* Memory map CRC error enabled */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_DIG_DIAG_ENABLE,
+				      AD77681_DIG_DIAG_ERR_MEMMAP_CRC_MSK,
+				      AD77681_DIG_DIAG_ERR_MEMMAP_CRC(ENABLE));
+	/* RAM CRC error enabled */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_DIG_DIAG_ENABLE,
+				      AD77681_DIG_DIAG_ERR_RAM_CRC_MSK,
+				      AD77681_DIG_DIAG_ERR_RAM_CRC(ENABLE));
+	/* FUSE CRC error enabled */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_DIG_DIAG_ENABLE,
+				      AD77681_DIG_DIAG_ERR_FUSE_CRC_MSK,
+				      AD77681_DIG_DIAG_ERR_FUSE_CRC(ENABLE));
+	/* Enable MCLK Counter */
+	ret |= ad77681_spi_write_mask(dev,
+				      AD77681_REG_DIG_DIAG_ENABLE,
+				      AD77681_DIG_DIAG_FREQ_COUNT_EN_MSK,
+				      AD77681_DIG_DIAG_FREQ_COUNT_EN(ENABLE));
+
+	return ret;
+}
+
+/**
+ * Read from all ADC status registers
+ * @param dev - The device structure.
+ * @param status - Structure with all satuts bits
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_status(struct ad77681_dev *dev,
+		       struct ad77681_status_registers *status)
+{
+	int32_t ret;
+	uint8_t buf[3];
+
+	/* Master status register */
+	ret = ad77681_spi_reg_read(dev, AD77681_REG_MASTER_STATUS,buf);
+	status->master_error = buf[1] & AD77681_MASTER_ERROR_MSK;
+	status->adc_error = buf[1] & AD77681_MASTER_ADC_ERROR_MSK;
+	status->dig_error = buf[1] & AD77681_MASTER_DIG_ERROR_MSK;
+	status->adc_err_ext_clk_qual = buf[1] & AD77681_MASTER_DIG_ERR_EXT_CLK_MSK;
+	status->adc_filt_saturated = buf[1] & AD77681_MASTER_FILT_SAT_MSK;
+	status->adc_filt_not_settled = buf[1] & AD77681_MASTER_FILT_NOT_SET_MSK;
+	status->spi_error = buf[1] & AD77681_MASTER_SPI_ERROR_MSK;
+	status->por_flag = buf[1] & AD77681_MASTER_POR_FLAG_MSK;
+	/* SPI diag status register */
+	ret |= ad77681_spi_reg_read(dev, AD77681_REG_SPI_DIAG_STATUS, buf);
+	status->spi_ignore = buf[1] & AD77681_SPI_IGNORE_ERROR_MSK;
+	status->spi_clock_count = buf[1] & AD77681_SPI_CLK_CNT_ERROR_MSK;
+	status->spi_read_error = buf[1] & AD77681_SPI_READ_ERROR_MSK;
+	status->spi_write_error = buf[1] & AD77681_SPI_WRITE_ERROR_MSK;
+	status->spi_crc_error = buf[1] & AD77681_SPI_CRC_ERROR_MSK;
+	/* ADC diag status register */
+	ret |= ad77681_spi_reg_read(dev, AD77681_REG_ADC_DIAG_STATUS,buf);
+	status->dldo_psm_error = buf[1] & AD77681_ADC_DLDO_PSM_ERROR_MSK;
+	status->aldo_psm_error = buf[1] & AD77681_ADC_ALDO_PSM_ERROR_MSK;
+	status->ref_det_error = buf[1] & AD77681_ADC_REF_DET_ERROR_MSK;
+	status->filt_sat_error = buf[1] & AD77681_ADC_FILT_SAT_MSK;
+	status->filt_not_set_error = buf[1] & AD77681_ADC_FILT_NOT_SET_MSK;
+	status->ext_clk_qual_error = buf[1] & AD77681_ADC_DIG_ERR_EXT_CLK_MSK;
+	/* DIG diag status register */
+	ret |= ad77681_spi_reg_read(dev, AD77681_REG_DIG_DIAG_STATUS,buf);
+	status->memoy_map_crc_error = buf[1] & AD77681_DIG_MEMMAP_CRC_ERROR_MSK;
+	status->ram_crc_error = buf[1] & AD77681_DIG_RAM_CRC_ERROR_MSK;
+	status->fuse_crc_error = buf[1] & AD77681_DIG_FUS_CRC_ERROR_MSK;
+
+	return ret;
+}
+
+/**
+ * Initialize the device.
+ * @param device - The device structure.
+ * @param init_param - The structure that contains the device initial
+ * 					   parameters.
+ * @param status - The structure that will contains the ADC status
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_setup(struct ad77681_dev **device,
+		      struct ad77681_init_param init_param,
+		      struct ad77681_status_registers **status)
+{
+	struct ad77681_dev *dev;
+	struct ad77681_status_registers *stat;
+	int32_t ret;
+	uint8_t scratchpad_check = 0xAD;
+
+	dev = (struct ad77681_dev *)malloc(sizeof(*dev));
+	if (!dev) {
+		return -1;
+	}
+
+	stat = (struct ad77681_status_registers *)malloc(sizeof(*stat));
+	if (!stat) {
+		free(dev);
+		return -1;
+	}
+
+	dev->power_mode = init_param.power_mode;
+	dev->mclk_div = init_param.mclk_div;
+	dev->conv_diag_sel = init_param.conv_diag_sel;
+	dev->conv_mode = init_param.conv_mode;
+	dev->diag_mux_sel = init_param.diag_mux_sel;
+	dev->conv_len = init_param.conv_len;
+	dev->crc_sel = AD77681_NO_CRC;
+	dev->status_bit = init_param.status_bit;
+	dev->VCM_out = init_param.VCM_out;
+	dev->AINn = init_param.AINn;
+	dev->AINp = init_param.AINp;
+	dev->REFn = init_param.REFn;
+	dev->REFp = init_param.REFp;
+	dev->filter = init_param.filter;
+	dev->decimate = init_param.decimate;
+	dev->sinc3_osr = init_param.sinc3_osr;
+	dev->vref = init_param.vref;
+	dev->mclk = init_param.mclk;
+	dev->sample_rate = init_param.sample_rate;
+	dev->data_frame_byte = init_param.data_frame_byte;
+
+	ret = spi_init(&dev->spi_desc, &init_param.spi_eng_dev_init);
+	if (ret < 0) {
+		free(dev);
+		free(stat);
+		return ret;
+	}
+
+	ret |= ad77681_soft_reset(dev);
+
+	udelay(200);
+
+	/* Check physical connection using scratchpad*/
+	if (ad77681_scratchpad(dev, &scratchpad_check) == FAILURE) {
+		scratchpad_check = 0xAD;/* If failure, second try */
+		ret |= (ad77681_scratchpad(dev, &scratchpad_check));
+		if(ret == FAILURE) {
+			free(dev);
+			free(stat);
+			return ret;
+		}
+	}
+	ret |= ad77681_set_power_mode(dev, dev->power_mode);
+	ret |= ad77681_set_mclk_div(dev, dev->mclk_div);
+	ret |= ad77681_set_conv_mode(dev,
+				     dev->conv_mode,
+				     dev->diag_mux_sel,
+				     dev->conv_diag_sel);
+	ret |= ad77681_set_convlen(dev, dev->conv_len);
+	ret |= ad77681_set_status_bit(dev, dev->status_bit);
+	ret |= ad77681_set_crc_sel(dev, init_param.crc_sel);
+	ret |= ad77681_set_VCM_output(dev, dev->VCM_out);
+	ret |= ad77681_set_AINn_buffer(dev, dev->AINn);
+	ret |= ad77681_set_AINp_buffer(dev, dev->AINp);
+	ret |= ad77681_set_REFn_buffer(dev, dev->REFn);
+	ret |= ad77681_set_REFp_buffer(dev, dev->REFp);
+	ret |= ad77681_set_filter_type(dev, dev->decimate, dev->filter, dev->sinc3_osr);
+	ret |= ad77681_error_flags_enabe(dev);
+	ret |= ad77681_clear_error_flags(dev);
+	ret |= ad77681_status(dev, stat);
+	ad77681_get_frame_byte(dev);
+	ad77681_update_sample_rate(dev);
+	*status = stat;
+	*device = dev;
+
+	if (!ret)
+		printf("ad77681 successfully initialized\n");
+
+	return ret;
+}
+
+
diff -r 3c3bc5b9174a -r abe97d9dd504 ad77681.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad77681.h	Mon Mar 15 06:51:56 2021 +0000
@@ -0,0 +1,684 @@
+/***************************************************************************//**
+ *   @file   ad77681.h
+ *   @brief  Header file of the AD7768-1 Driver.
+ *   @author SPopa (stefan.popa@analog.com)
+********************************************************************************
+ * Copyright 2017(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 SRC_AD77681_H_
+#define SRC_AD77681_H_
+
+#include "platform_drivers.h"
+
+/******************************************************************************/
+/********************** Macros and Constants Definitions **********************/
+/******************************************************************************/
+#define	AD77681_REG_CHIP_TYPE					0x3
+#define	AD77681_REG_PROD_ID_L					0x4
+#define	AD77681_REG_PROD_ID_H					0x5
+#define	AD77681_REG_CHIP_GRADE					0x6
+#define	AD77681_REG_SCRATCH_PAD					0x0A
+#define	AD77681_REG_VENDOR_L					0x0C
+#define	AD77681_REG_VENDOR_H					0x0D
+#define	AD77681_REG_INTERFACE_FORMAT			0x14
+#define AD77681_REG_POWER_CLOCK					0x15
+#define AD77681_REG_ANALOG						0x16
+#define AD77681_REG_ANALOG2						0x17
+#define AD77681_REG_CONVERSION					0x18
+#define AD77681_REG_DIGITAL_FILTER				0x19
+#define AD77681_REG_SINC3_DEC_RATE_MSB			0x1A
+#define AD77681_REG_SINC3_DEC_RATE_LSB			0x1B
+#define AD77681_REG_DUTY_CYCLE_RATIO			0x1C
+#define AD77681_REG_SYNC_RESET					0x1D
+#define AD77681_REG_GPIO_CONTROL				0x1E
+#define AD77681_REG_GPIO_WRITE					0x1F
+#define AD77681_REG_GPIO_READ					0x20
+#define AD77681_REG_OFFSET_HI					0x21
+#define AD77681_REG_OFFSET_MID					0x22
+#define AD77681_REG_OFFSET_LO					0x23
+#define AD77681_REG_GAIN_HI						0x24
+#define AD77681_REG_GAIN_MID					0x25
+#define AD77681_REG_GAIN_LO						0x26
+#define AD77681_REG_SPI_DIAG_ENABLE				0x28
+#define AD77681_REG_ADC_DIAG_ENABLE				0x29
+#define AD77681_REG_DIG_DIAG_ENABLE				0x2A
+#define	AD77681_REG_ADC_DATA					0x2C
+#define	AD77681_REG_MASTER_STATUS				0x2D
+#define	AD77681_REG_SPI_DIAG_STATUS				0x2E
+#define	AD77681_REG_ADC_DIAG_STATUS				0x2F
+#define	AD77681_REG_DIG_DIAG_STATUS				0x30
+#define	AD77681_REG_MCLK_COUNTER				0x31
+
+/* AD77681_REG_INTERFACE_FORMAT */
+#define AD77681_INTERFACE_CRC_EN_MSK			(0x1 << 6)
+#define AD77681_INTERFACE_CRC_EN(x)				(((x) & 0x1) << 6)
+#define AD77681_INTERFACE_CRC_TYPE_MSK			(0x1 << 5)
+#define AD77681_INTERFACE_CRC_TYPE(x)			(((x) & 0x1) << 5)
+#define AD77681_INTERFACE_STATUS_EN_MSK			(0x1 << 4)
+#define AD77681_INTERFACE_STATUS_EN(x)			(((x) & 0x1) << 4)
+#define AD77681_INTERFACE_CONVLEN_MSK			(0x1 << 3)
+#define AD77681_INTERFACE_CONVLEN(x)			(((x) & 0x1) << 3)
+#define AD77681_INTERFACE_RDY_EN_MSK			(0x1 << 2)
+#define AD77681_INTERFACE_RDY_EN(x)				(((x) & 0x1) << 3)
+#define AD77681_INTERFACE_CONT_READ_MSK			(0x1 << 0)
+#define AD77681_INTERFACE_CONT_READ_EN(x)		(((x) & 0x1) << 0)
+#define AD77681_REG_COEFF_CONTROL				0x32
+#define AD77681_REG_COEFF_DATA					0x33
+#define AD77681_REG_ACCESS_KEY					0x34
+
+/* AD77681_REG_SCRATCH_PAD*/
+#define AD77681_SCRATCHPAD_MSK					(0xFF << 0)
+#define AD77681_SCRATCHPAD(x)					(((x) & 0xFF) << 0)
+
+/* AD77681_REG_POWER_CLOCK */
+#define AD77681_POWER_CLK_PWRMODE_MSK			0x3
+#define AD77681_POWER_CLK_PWRMODE(x)			(((x) & 0x3) << 0)
+#define AD77681_POWER_CLK_MOD_OUT_MSK			(0x1 << 2)
+#define AD77681_POWER_CLK_MOD_OUT(x)			(((x) & 0x1) << 2)
+#define AD77681_POWER_CLK_POWER_DOWN			0x08
+#define AD77681_POWER_CLK_MCLK_DIV_MSK			(0x3 << 4)
+#define AD77681_POWER_CLK_MCLK_DIV(x)			(((x) & 0x3) << 4)
+#define AD77681_POWER_CLK_CLOCK_SEL_MSK			(0x3 << 6)
+#define AD77681_POWER_CLK_CLOCK_SEL(x)			(((x) & 0x3) << 6)
+
+/* AD77681_CONVERSION_REG */
+#define AD77681_CONVERSION_DIAG_MUX_MSK			(0xF << 4)
+#define AD77681_CONVERSION_DIAG_MUX_SEL(x)		(((x) & 0xF) << 4)
+#define AD77681_CONVERSION_DIAG_SEL_MSK			(0x1 << 3)
+#define AD77681_CONVERSION_DIAG_SEL(x)			(((x) & 0x1) << 3)
+#define AD77681_CONVERSION_MODE_MSK				(0x7 << 0)
+#define AD77681_CONVERSION_MODE(x)				(((x) & 0x7) << 0)
+
+/* AD77681_REG_ANALOG */
+#define AD77681_ANALOG_REF_BUF_POS_MSK			(0x3 << 6)
+#define AD77681_ANALOG_REF_BUF_POS(x)			(((x) & 0x3) << 6)
+#define AD77681_ANALOG_REF_BUF_NEG_MSK			(0x3 << 4)
+#define AD77681_ANALOG_REF_BUF_NEG(x)			(((x) & 0x3) << 4)
+#define AD77681_ANALOG_AIN_BUF_POS_OFF_MSK		(0x1 << 1)
+#define AD77681_ANALOG_AIN_BUF_POS_OFF(x)		(((x) & 0x1) << 1)
+#define AD77681_ANALOG_AIN_BUF_NEG_OFF_MSK		(0x1 << 0)
+#define AD77681_ANALOG_AIN_BUF_NEG_OFF(x)		(((x) & 0x1) << 0)
+
+/* AD77681_REG_ANALOG2 */
+#define AD77681_ANALOG2_VCM_MSK					(0x7 << 0)
+#define AD77681_ANALOG2_VCM(x)					(((x) & 0x7) << 0)
+
+/* AD77681_REG_DIGITAL_FILTER */
+#define AD77681_DIGI_FILTER_60HZ_REJ_EN_MSK		(0x1 << 7)
+#define AD77681_DIGI_FILTER_60HZ_REJ_EN(x)		(((x) & 0x1) << 7)
+#define AD77681_DIGI_FILTER_FILTER_MSK			(0x7 << 4)
+#define AD77681_DIGI_FILTER_FILTER(x)			(((x) & 0x7) << 4)
+#define AD77681_DIGI_FILTER_DEC_RATE_MSK		(0x7 << 0)
+#define AD77681_DIGI_FILTER_DEC_RATE(x)			(((x) & 0x7) << 0)
+
+/* AD77681_REG_SINC3_DEC_RATE_MSB */
+#define AD77681_SINC3_DEC_RATE_MSB_MSK			(0x0F << 0)
+#define AD77681_SINC3_DEC_RATE_MSB(x)			(((x) & 0x0F) << 0)
+
+/* AD77681_REG_SINC3_DEC_RATE_LSB */
+#define AD77681_SINC3_DEC_RATE_LSB_MSK			(0xFF << 0)
+#define AD77681_SINC3_DEC_RATE_LSB(x)			(((x) & 0xFF) << 0)
+
+/* AD77681_REG_DUTY_CYCLE_RATIO */
+#define AD77681_DC_RATIO_IDLE_TIME_MSK			(0xFF << 0)
+#define AD77681_DC_RATIO_IDLE_TIME(x)			(((x) & 0xFF) << 0)
+
+/* AD77681_REG_SYNC_RESET */
+#define AD77681_SYNC_RST_SPI_STARTB_MSK			(0x1 << 7)
+#define AD77681_SYNC_RST_SPI_STARTB(x)			(((x) & 0x1) << 7)
+#define AD77681_SYNC_RST_SYNCOUT_EDGE_MSK		(0x1 << 6)
+#define AD77681_SYNC_RST_SYNCOUT_EDGE(x)		(((x) & 0x1) << 6)
+#define AD77681_SYNC_RST_GPIO_START_EN_MSK		(0x1 << 3)
+#define AD77681_SYNC_RST_GPIO_START_EN(x)		(((x) & 0x1) << 3)
+#define AD77681_SYNC_RST_SPI_RESET_MSK			(0x3 << 0)
+#define AD77681_SYNC_RST_SPI_RESET(x)			(((x) & 0x3) << 0)
+
+/* AD77681_REG_GPIO_CONTROL */
+#define AD77681_GPIO_CNTRL_UGPIO_EN_MSK			(0x1 << 7)
+#define AD77681_GPIO_CNTRL_UGPIO_EN(x)			(((x) & 0x1) << 7)
+#define AD77681_GPIO_CNTRL_GPIO2_OD_EN_MSK		(0x1 << 6)
+#define AD77681_GPIO_CNTRL_GPIO2_OD_EN(x)		(((x) & 0x1) << 6)
+#define AD77681_GPIO_CNTRL_GPIO1_OD_EN_MSK		(0x1 << 5)
+#define AD77681_GPIO_CNTRL_GPIO1_OD_EN(x)		(((x) & 0x1) << 5)
+#define AD77681_GPIO_CNTRL_GPIO0_OD_EN_MSK		(0x1 << 4)
+#define AD77681_GPIO_CNTRL_GPIO0_OD_EN(x)		(((x) & 0x1) << 4)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN_MSK	(0x7 << 4)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN(x)	(((x) & 0x7) << 4)
+#define AD77681_GPIO_CNTRL_GPIO3_OP_EN_MSK		(0x1 << 3)
+#define AD77681_GPIO_CNTRL_GPIO3_OP_EN(x)		(((x) & 0x1) << 3)
+#define AD77681_GPIO_CNTRL_GPIO2_OP_EN_MSK		(0x1 << 2)
+#define AD77681_GPIO_CNTRL_GPIO2_OP_EN(x)		(((x) & 0x1) << 2)
+#define AD77681_GPIO_CNTRL_GPIO1_OP_EN_MSK		(0x1 << 1)
+#define AD77681_GPIO_CNTRL_GPIO1_OP_EN(x)		(((x) & 0x1) << 1)
+#define AD77681_GPIO_CNTRL_GPIO0_OP_EN_MSK		(0x1 << 0)
+#define AD77681_GPIO_CNTRL_GPIO0_OP_EN(x)		(((x) & 0x1) << 0)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN_MSK	(0xF << 0)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN(x)	(((x) & 0xF) << 0)
+
+/* AD77681_REG_GPIO_WRITE */
+#define AD77681_GPIO_WRITE_3_MSK				(0x1 << 3)
+#define AD77681_GPIO_WRITE_3(x)					(((x) & 0x1) << 3)
+#define AD77681_GPIO_WRITE_2_MSK				(0x1 << 2)
+#define AD77681_GPIO_WRITE_2(x)					(((x) & 0x1) << 2)
+#define AD77681_GPIO_WRITE_1_MSK				(0x1 << 1)
+#define AD77681_GPIO_WRITE_1(x)					(((x) & 0x1) << 1)
+#define AD77681_GPIO_WRITE_0_MSK				(0x1 << 0)
+#define AD77681_GPIO_WRITE_0(x)					(((x) & 0x1) << 0)
+#define AD77681_GPIO_WRITE_ALL_MSK				(0xF << 0)
+#define AD77681_GPIO_WRITE_ALL(x)				(((x) & 0xF))
+
+/* AD77681_REG_GPIO_READ */
+#define AD77681_GPIO_READ_3_MSK					(0x1 << 3)
+#define AD77681_GPIO_READ_2_MSK					(0x1 << 2)
+#define AD77681_GPIO_READ_1_MSK					(0x1 << 1)
+#define AD77681_GPIO_READ_0_MSK					(0x1 << 0)
+#define AD77681_GPIO_READ_ALL_MSK				(0xF << 0)
+
+/* AD77681_REG_OFFSET_HI */
+#define AD77681_OFFSET_HI_MSK					(0xFF << 0)
+#define	AD77681_OFFSET_HI(x)					(((x) & 0xFF) << 0)
+
+/* AD77681_REG_OFFSET_MID */
+#define AD77681_OFFSET_MID_MSK					(0xFF << 0)
+#define	AD77681_OFFSET_MID(x)					(((x) & 0xFF) << 0)
+
+/* AD77681_REG_OFFSET_LO */
+#define AD77681_OFFSET_LO_MSK					(0xFF << 0)
+#define	AD77681_OFFSET_LO(x)					(((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_HI */
+#define AD77681_GAIN_HI_MSK						(0xFF << 0)
+#define	AD77681_GAIN_HI(x)						(((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_MID */
+#define AD77681_GAIN_MID_MSK					(0xFF << 0)
+#define	AD77681_GAIN_MID(x)						(((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_HI */
+#define AD77681_GAIN_LOW_MSK					(0xFF << 0)
+#define	AD77681_GAIN_LOW(x)						(((x) & 0xFF) << 0)
+
+/* AD77681_REG_SPI_DIAG_ENABLE */
+#define AD77681_SPI_DIAG_ERR_SPI_IGNORE_MSK		(0x1 << 4)
+#define AD77681_SPI_DIAG_ERR_SPI_IGNORE(x)		(((x) & 0x1) << 4)
+#define AD77681_SPI_DIAG_ERR_SPI_CLK_CNT_MSK	(0x1 << 3)
+#define AD77681_SPI_DIAG_ERR_SPI_CLK_CNT(x)		(((x) & 0x1) << 3)
+#define AD77681_SPI_DIAG_ERR_SPI_RD_MSK			(0x1 << 2)
+#define AD77681_SPI_DIAG_ERR_SPI_RD(x)			(((x) & 0x1) << 2)
+#define AD77681_SPI_DIAG_ERR_SPI_WR_MSK			(0x1 << 1)
+#define AD77681_SPI_DIAG_ERR_SPI_WR(x)			(((x) & 0x1) << 1)
+
+/* AD77681_REG_ADC_DIAG_ENABLE */
+#define AD77681_ADC_DIAG_ERR_DLDO_PSM_MSK		(0x1 << 5)
+#define AD77681_ADC_DIAG_ERR_DLDO_PSM(x)		(((x) & 0x1) << 5)
+#define AD77681_ADC_DIAG_ERR_ALDO_PSM_MSK		(0x1 << 4)
+#define AD77681_ADC_DIAG_ERR_ALDO_PSM(x)		(((x) & 0x1) << 4)
+#define AD77681_ADC_DIAG_ERR_FILT_SAT_MSK		(0x1 << 2)
+#define AD77681_ADC_DIAG_ERR_FILT_SAT(x)			(((x) & 0x1) << 2)
+#define AD77681_ADC_DIAG_ERR_FILT_NOT_SET_MSK	(0x1 << 1)
+#define AD77681_ADC_DIAG_ERR_FILT_NOT_SET(x)		(((x) & 0x1) << 1)
+#define AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL_MSK	(0x1 << 0)
+#define AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL(x)	(((x) & 0x1) << 0)
+
+/* AD77681_REG_DIG_DIAG_ENABLE */
+#define AD77681_DIG_DIAG_ERR_MEMMAP_CRC_MSK		(0x1 << 4)
+#define AD77681_DIG_DIAG_ERR_MEMMAP_CRC(x)		(((x) & 0x1) << 4)
+#define AD77681_DIG_DIAG_ERR_RAM_CRC_MSK		(0x1 << 3)
+#define AD77681_DIG_DIAG_ERR_RAM_CRC(x)			(((x) & 0x1) << 3)
+#define AD77681_DIG_DIAG_ERR_FUSE_CRC_MSK		(0x1 << 2)
+#define AD77681_DIG_DIAG_ERR_FUSE_CRC(x)		(((x) & 0x1) << 2)
+#define AD77681_DIG_DIAG_FREQ_COUNT_EN_MSK		(0x1 << 0)
+#define AD77681_DIG_DIAG_FREQ_COUNT_EN(x)		(((x) & 0x1) << 0)
+
+/* AD77681_REG_MASTER_STATUS */
+#define AD77681_MASTER_ERROR_MSK				(0x1 << 7)
+#define AD77681_MASTER_ADC_ERROR_MSK			(0x1 << 6)
+#define AD77681_MASTER_DIG_ERROR_MSK			(0x1 << 5)
+#define AD77681_MASTER_DIG_ERR_EXT_CLK_MSK		(0x1 << 4)
+#define AD77681_MASTER_FILT_SAT_MSK				(0x1 << 3)
+#define AD77681_MASTER_FILT_NOT_SET_MSK			(0x1 << 2)
+#define AD77681_MASTER_SPI_ERROR_MSK			(0x1 << 1)
+#define AD77681_MASTER_POR_FLAG_MSK				(0x1 << 0)
+
+/* AD77681_REG_SPI_DIAG_STATUS */
+#define AD77681_SPI_IGNORE_ERROR_MSK			(0x1 << 4)
+#define AD77681_SPI_IGNORE_ERROR_CLR(x)			(((x) & 0x1) << 4)
+#define AD77681_SPI_CLK_CNT_ERROR_MSK			(0x1 << 3)
+#define AD77681_SPI_READ_ERROR_MSK				(0x1 << 2)
+#define AD77681_SPI_READ_ERROR_CLR(x)			(((x) & 0x1) << 2)
+#define AD77681_SPI_WRITE_ERROR_MSK				(0x1 << 1)
+#define AD77681_SPI_WRITE_ERROR_CLR(x)			(((x) & 0x1) << 1)
+#define AD77681_SPI_CRC_ERROR_MSK				(0x1 << 0)
+#define AD77681_SPI_CRC_ERROR_CLR(x)			(((x) & 0x1) << 0)
+
+/* AD77681_REG_ADC_DIAG_STATUS */
+#define AD77681_ADC_DLDO_PSM_ERROR_MSK			(0x1 << 5)
+#define AD77681_ADC_ALDO_PSM_ERROR_MSK			(0x1 << 4)
+#define AD77681_ADC_REF_DET_ERROR_MSK           (0x1 << 3)
+#define AD77681_ADC_FILT_SAT_MSK				(0x1 << 2)
+#define AD77681_ADC_FILT_NOT_SET_MSK			(0x1 << 1)
+#define AD77681_ADC_DIG_ERR_EXT_CLK_MSK			(0x1 << 0)
+
+/* AD77681_REG_DIG_DIAG_STATUS */
+#define AD77681_DIG_MEMMAP_CRC_ERROR_MSK		(0x1 << 4)
+#define AD77681_DIG_RAM_CRC_ERROR_MSK			(0x1 << 3)
+#define AD77681_DIG_FUS_CRC_ERROR_MSK			(0x1 << 2)
+
+/* AD77681_REG_MCLK_COUNTER */
+#define AD77681_MCLK_COUNTER_MSK				(0xFF << 0)
+#define	AD77681_MCLK_COUNTER(x)					(((x) & 0xFF) << 0)
+
+/* AD77681_REG_COEFF_CONTROL */
+#define AD77681_COEF_CONTROL_COEFFACCESSEN_MSK	(0x1 << 7)
+#define AD77681_COEF_CONTROL_COEFFACCESSEN(x)	(((x) & 0x1) << 7)
+#define AD77681_COEF_CONTROL_COEFFWRITEEN_MSK	(0x1 << 6)
+#define AD77681_COEF_CONTROL_COEFFWRITEEN(x)	(((x) & 0x1) << 6)
+#define AD77681_COEF_CONTROL_COEFFADDR_MSK		(0x3F << 5)
+#define AD77681_COEF_CONTROL_COEFFADDR(x)		(((x) & 0x3F) << 5)
+
+/* AD77681_REG_COEFF_DATA */
+#define AD77681_COEFF_DATA_USERCOEFFEN_MSK		(0x1 << 23)
+#define	AD77681_COEFF_DATA_USERCOEFFEN(x)		(((x) & 0x1) << 23)
+#define AD77681_COEFF_DATA_COEFFDATA_MSK		(0x7FFFFF << 22)
+#define	AD77681_COEFF_DATA_COEFFDATA(x)			(((x) & 0x7FFFFF) << 22)
+
+/* AD77681_REG_ACCESS_KEY */
+#define AD77681_ACCESS_KEY_MSK					(0xFF << 0)
+#define	AD77681_ACCESS_KEY(x)					(((x) & 0xFF) << 0)
+#define AD77681_ACCESS_KEY_CHECK_MSK			(0x1 << 0)
+
+#define AD77681_REG_READ(x)						( (1 << 6) | (x & 0xFF) )		// Read from register x
+#define AD77681_REG_WRITE(x)					( (~(1 << 6)) & (x & 0xFF) )  	// Write to register x
+
+/* 8-bits wide checksum generated using the polynomial */
+#define AD77681_CRC8_POLY	0x07 // x^8 + x^2 + x^1 + x^0
+
+/* Initial CRC for continuous read mode */
+#define INITIAL_CRC_CRC8						0x03
+#define INITIAL_CRC_XOR							0x6C
+#define INITIAL_CRC								0x00
+
+#define CRC_DEBUG
+
+/* AD7768-1 */
+/* A special key for exit the contiuous read mode, taken from the AD7768-1 datasheet */
+#define EXIT_CONT_READ							0x6C
+/* Bit resolution of the AD7768-1 */
+#define AD7768_N_BITS							24
+/* Full scale of the AD7768-1 = 2^24 = 16777216 */
+#define AD7768_FULL_SCALE						(1 << AD7768_N_BITS)
+/* Half scale of the AD7768-1 = 2^23 = 8388608 */
+#define AD7768_HALF_SCALE						(1 << (AD7768_N_BITS - 1))
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define ENABLE		1
+#define DISABLE		0
+
+/*****************************************************************************/
+/*************************** Types Declarations *******************************/
+/******************************************************************************/
+enum ad77681_power_mode {
+	AD77681_ECO = 0,
+	AD77681_MEDIAN = 2,
+	AD77681_FAST = 3,
+};
+
+enum ad77681_mclk_div {
+	AD77681_MCLK_DIV_16 = 0,
+	AD77681_MCLK_DIV_8 = 1,
+	AD77681_MCLK_DIV_4 = 2,
+	AD77681_MCLK_DIV_2 = 3
+};
+
+enum ad77681_conv_mode {
+	AD77681_CONV_CONTINUOUS = 0,
+	AD77681_CONV_ONE_SHOT = 1,
+	AD77681_CONV_SINGLE = 2,
+	AD77681_CONV_PERIODIC = 3,
+	AD77681_CONV_STANDBY = 4
+};
+
+enum ad77681_conv_len {
+	AD77681_CONV_24BIT = 0,
+	AD77681_CONV_16BIT = 1
+};
+
+enum ad77681_rdy_dout {
+	AD77681_RDY_DOUT_EN,
+	AD77681_RDY_DOUT_DIS
+};
+
+enum ad77681_conv_diag_mux {
+	AD77681_TEMP_SENSOR = 0x0,
+	AD77681_AIN_SHORT= 0x8,
+	AD77681_POSITIVE_FS = 0x9,
+	AD77681_NEGATIVE_FS = 0xA
+};
+
+enum ad77681_crc_sel {
+	AD77681_CRC,
+	AD77681_XOR,
+	AD77681_NO_CRC
+};
+
+/* Filter tye FIR, SINC3, SINC5 */
+enum ad77681_filter_type {
+	AD77681_SINC5			= 0,
+	AD77681_SINC5_DECx8		= 1,
+	AD77681_SINC5_DECx16	= 2,
+	AD77681_SINC3			= 3,
+	AD77681_FIR				= 4
+};
+
+/* Dectimation ratios for SINC5 and FIR */
+enum ad77681_sinc5_fir_decimate {
+	AD77681_SINC5_FIR_DECx32	= 0,
+	AD77681_SINC5_FIR_DECx64	= 1,
+	AD77681_SINC5_FIR_DECx128	= 2,
+	AD77681_SINC5_FIR_DECx256	= 3,
+	AD77681_SINC5_FIR_DECx512	= 4,
+	AD77681_SINC5_FIR_DECx1024	= 5
+};
+
+/* Sleep / Power up */
+enum ad77681_sleep_wake {
+	AD77681_SLEEP   = 1,
+	AD77681_WAKE = 0
+};
+
+/* Reset option */
+enum ad7761_reset_option {
+	AD77681_SOFT_RESET,
+	AD77681_HARD_RESET
+};
+/* AIN- precharge */
+enum ad77681_AINn_precharge {
+	AD77681_AINn_ENABLED   = 0,
+	AD77681_AINn_DISABLED  = 1
+};
+
+/* AIN+ precharge */
+enum ad77681_AINp_precharge {
+	AD77681_AINp_ENABLED  = 0,
+	AD77681_AINp_DISABLED = 1
+};
+
+/* REF- buffer */
+enum ad77681_REFn_buffer {
+	AD77681_BUFn_ENABLED        = 0,
+	AD77681_BUFn_DISABLED       = 1,
+	AD77681_BUFn_FULL_BUFFER_ON = 2
+};
+
+/* REF+ buffer */
+enum ad77681_REFp_buffer {
+	AD77681_BUFp_ENABLED        = 0,
+	AD77681_BUFp_DISABLED       = 1,
+	AD77681_BUFp_FULL_BUFFER_ON = 2
+};
+
+/* VCM output voltage */
+enum ad77681_VCM_out {
+	AD77681_VCM_HALF_VCC	= 0,
+	AD77681_VCM_2_5V		= 1,
+	AD77681_VCM_2_05V   	= 2,
+	AD77681_VCM_1_9V		= 3,
+	AD77681_VCM_1_65V		= 4,
+	AD77681_VCM_1_1V		= 5,
+	AD77681_VCM_0_9V		= 6,
+	AD77681_VCM_OFF  		= 7
+};
+
+/* Global GPIO enable/disable */
+enum ad77681_gobal_gpio_enable {
+	AD77681_GLOBAL_GPIO_ENABLE		= 1,
+	AD77681_GLOBAL_GPIO_DISABLE		= 0
+};
+
+/* ADCs GPIO numbering */
+enum ad77681_gpios {
+	AD77681_GPIO0					= 0,
+	AD77681_GPIO1					= 1,
+	AD77681_GPIO2					= 2,
+	AD77681_GPIO3					= 3,
+	AD77681_ALL_GPIOS				= 4
+};
+
+enum ad77681_gpio_output_type {
+	AD77681_GPIO_STRONG_DRIVER		= 0,
+	AD77681_GPIO_OPEN_DRAIN			= 1
+};
+
+/* Continuous ADC read */
+enum ad77681_continuous_read {
+	AD77681_CONTINUOUS_READ_ENABLE = 1,
+	AD77681_CONTINUOUS_READ_DISABLE = 0,
+};
+
+/* ADC data read mode */
+enum ad77681_data_read_mode {
+	AD77681_REGISTER_DATA_READ = 0,
+	AD77681_CONTINUOUS_DATA_READ = 1,
+};
+
+/* ADC data structure */
+struct adc_data {
+	bool		finish;
+	uint16_t	count;
+	uint16_t	samples;
+	uint32_t	raw_data[4096];
+};
+/* ADC status registers structure */
+struct ad77681_status_registers {
+	bool							master_error;
+	bool							adc_error;
+	bool							dig_error;
+	bool							adc_err_ext_clk_qual;
+	bool							adc_filt_saturated;
+	bool							adc_filt_not_settled;
+	bool							spi_error;
+	bool							por_flag;
+	bool							spi_ignore;
+	bool							spi_clock_count;
+	bool							spi_read_error;
+	bool							spi_write_error;
+	bool							spi_crc_error;
+	bool							dldo_psm_error;
+	bool							aldo_psm_error;
+	bool                            ref_det_error;
+	bool                            filt_sat_error;
+	bool                            filt_not_set_error;
+	bool                            ext_clk_qual_error;
+	bool							memoy_map_crc_error;
+	bool							ram_crc_error;
+	bool							fuse_crc_error;
+};
+
+struct ad77681_dev {
+	/* SPI */
+	spi_desc			*spi_desc;
+	/* Configuration */
+	enum ad77681_power_mode		power_mode;
+	enum ad77681_mclk_div		mclk_div;
+	enum ad77681_conv_mode 		conv_mode;
+	enum ad77681_conv_diag_mux 	diag_mux_sel;
+	bool 					conv_diag_sel;
+	enum ad77681_conv_len		conv_len;
+	enum ad77681_crc_sel 		crc_sel;
+	uint8_t					status_bit;
+	enum ad77681_VCM_out            VCM_out;
+	enum ad77681_AINn_precharge     AINn;
+	enum ad77681_AINp_precharge     AINp;
+	enum ad77681_REFn_buffer        REFn;
+	enum ad77681_REFp_buffer        REFp;
+	enum ad77681_filter_type        filter;
+	enum ad77681_sinc5_fir_decimate decimate;
+	uint16_t                        sinc3_osr;
+	uint16_t                        vref;               /* Reference voltage*/
+	uint16_t                        mclk;               /* Mater clock*/
+	uint32_t                        sample_rate;        /* Sample rate*/
+	uint8_t                         data_frame_byte;    /* SPI 8bit frames*/
+};
+
+struct ad77681_init_param {
+	/* SPI */
+	spi_init_param			spi_eng_dev_init;
+	/* Configuration */
+	enum ad77681_power_mode		power_mode;
+	enum ad77681_mclk_div		mclk_div;
+	enum ad77681_conv_mode 		conv_mode;
+	enum ad77681_conv_diag_mux 	diag_mux_sel;
+	bool 					conv_diag_sel;
+	enum ad77681_conv_len		conv_len;
+	enum ad77681_crc_sel 		crc_sel;
+	uint8_t					status_bit;
+	enum ad77681_VCM_out            VCM_out;
+	enum ad77681_AINn_precharge     AINn;
+	enum ad77681_AINp_precharge     AINp;
+	enum ad77681_REFn_buffer        REFn;
+	enum ad77681_REFp_buffer        REFp;
+	enum ad77681_filter_type        filter;
+	enum ad77681_sinc5_fir_decimate decimate;
+	uint16_t                        sinc3_osr;
+	uint16_t                        vref;
+	uint16_t                        mclk;
+	uint32_t                        sample_rate;
+	uint8_t                         data_frame_byte;
+};
+
+/******************************************************************************/
+/************************ Functions Declarations ******************************/
+/******************************************************************************/
+uint8_t ad77681_compute_crc8(uint8_t *data,
+			     uint8_t data_size,
+			     uint8_t init_val);
+uint8_t ad77681_compute_xor(uint8_t *data,
+			    uint8_t data_size,
+			    uint8_t init_val);
+int32_t ad77681_setup(struct ad77681_dev **device,
+		      struct ad77681_init_param init_param,
+		      struct ad77681_status_registers **status);
+int32_t ad77681_spi_reg_read(struct ad77681_dev *dev,
+			     uint8_t reg_addr,
+			     uint8_t *reg_data);
+int32_t ad77681_spi_read_mask(struct ad77681_dev *dev,
+			      uint8_t reg_addr,
+			      uint8_t mask,
+			      uint8_t *data);
+int32_t ad77681_spi_reg_write(struct ad77681_dev *dev,
+			      uint8_t reg_addr,
+			      uint8_t reg_data);
+int32_t ad77681_spi_write_mask(struct ad77681_dev *dev,
+			       uint8_t reg_addr,
+			       uint8_t mask,
+			       uint8_t data);
+int32_t ad77681_set_power_mode(struct ad77681_dev *dev,
+			       enum ad77681_power_mode mode);
+int32_t ad77681_set_mclk_div(struct ad77681_dev *dev,
+			     enum ad77681_mclk_div clk_div);
+int32_t ad77681_spi_read_adc_data(struct ad77681_dev *dev,
+				  uint8_t *adc_data,
+				  enum ad77681_data_read_mode mode);
+int32_t ad77681_set_conv_mode(struct ad77681_dev *dev,
+			      enum ad77681_conv_mode conv_mode,
+			      enum ad77681_conv_diag_mux diag_mux_sel,
+			      bool conv_diag_sel);
+int32_t ad77681_set_convlen(struct ad77681_dev *dev,
+			    enum ad77681_conv_len conv_len);
+int32_t ad77681_soft_reset(struct ad77681_dev *dev);
+int32_t ad77681_initiate_sync(struct ad77681_dev *dev);
+int32_t ad77681_programmable_filter(struct ad77681_dev *dev,
+				    const float *coeffs,
+				    uint8_t num_coeffs);
+int32_t ad77681_gpio_read(struct ad77681_dev *dev,
+			  uint8_t *value,
+			  enum ad77681_gpios gpio_number);
+int32_t ad77681_apply_offset(struct ad77681_dev *dev,
+			     uint32_t value);
+int32_t ad77681_apply_gain(struct ad77681_dev *dev,
+			   uint32_t value);
+int32_t ad77681_set_crc_sel(struct ad77681_dev *dev,
+			    enum ad77681_crc_sel crc_sel);
+int32_t ad77681_gpio_open_drain(struct ad77681_dev *dev,
+				enum ad77681_gpios gpio_number,
+				enum ad77681_gpio_output_type output_type);
+int32_t ad77681_set_continuos_read(struct ad77681_dev *dev,
+				   enum ad77681_continuous_read continuous_enable);
+int32_t ad77681_clear_error_flags(struct ad77681_dev *dev);
+int32_t ad77681_data_to_voltage(struct ad77681_dev *dev,
+				uint32_t *raw_code,
+				double *voltage);
+int32_t ad77681_CRC_status_handling(struct ad77681_dev *dev,
+				    uint16_t *data_buffer);
+int32_t ad77681_set_AINn_buffer(struct ad77681_dev *dev,
+				enum ad77681_AINn_precharge AINn);
+int32_t ad77681_set_AINp_buffer(struct ad77681_dev *dev,
+				enum ad77681_AINp_precharge AINp);
+int32_t ad77681_set_REFn_buffer(struct ad77681_dev *dev,
+				enum ad77681_REFn_buffer REFn);
+int32_t ad77681_set_REFp_buffer(struct ad77681_dev *dev,
+				enum ad77681_REFp_buffer REFp);
+int32_t ad77681_set_filter_type(struct ad77681_dev *dev,
+				enum ad77681_sinc5_fir_decimate decimate,
+				enum ad77681_filter_type filter,
+				uint16_t sinc3_osr);
+int32_t ad77681_set_50HZ_rejection(struct ad77681_dev *dev,
+				   uint8_t enable);
+int32_t ad77681_power_down(struct ad77681_dev *dev,
+			   enum ad77681_sleep_wake sleep_wake);
+int32_t ad77681_set_status_bit(struct ad77681_dev *dev,
+			       bool status_bit);
+int32_t ad77681_set_VCM_output(struct ad77681_dev *dev,
+			       enum ad77681_VCM_out VCM_out);
+int32_t ad77681_gpio_write(struct ad77681_dev *dev,
+			   uint8_t value,
+			   enum ad77681_gpios gpio_number);
+int32_t ad77681_gpio_inout(struct ad77681_dev *dev,
+			   uint8_t direction,
+			   enum ad77681_gpios gpio_number);
+int32_t ad77681_global_gpio(struct ad77681_dev *devices,
+			    enum ad77681_gobal_gpio_enable gpio_enable);
+int32_t ad77681_scratchpad(struct ad77681_dev *dev,
+			   uint8_t *sequence);
+int32_t ad77681_error_flags_enabe(struct ad77681_dev *dev);
+int32_t ad77681_update_sample_rate(struct ad77681_dev *dev);
+int32_t ad77681_SINC3_ODR(struct ad77681_dev *dev,
+			  uint16_t *sinc3_dec_reg,
+			  float sinc3_odr);
+int32_t ad77681_status(struct ad77681_dev *dev,
+		       struct ad77681_status_registers *status);
+#endif /* SRC_AD77681_H_ */
+